Session

This page documents the Session model.

Data Shape

Gadget's database stores Session records by storing and retrieving each of the fields defined on the model in the Gadget Editor to a managed database. Gadget has generated a GraphQL type matching the configured fields for Session:

1export interface Session {
2 __typename: "Session";
3
4 /** The globally unique, unchanging identifier for this record. Assigned and managed by Gadget. */
5 id: Scalars["GadgetID"];
6
7 /** The time at which this record was first created. Set once upon record creation and never changed. Managed by Gadget. */
8 createdAt: Scalars["DateTime"];
9
10 /** The time at which this record was last changed. Set each time the record is successfully acted upon by an action. Managed by Gadget. */
11 updatedAt: Scalars["DateTime"];
12
13 /** The current state this record is in. Changed by invoking actions. Managed by Gadget. */
14 state: Scalars["RecordState"];
15
16 user: User | null;
17
18 userId: Scalars["GadgetID"] | null;
19
20 roles: Role[];
21
22 shop: ShopifyShop | null;
23
24 shopId: Scalars["GadgetID"] | null;
25
26 shopifySID: Scalars["String"] | null;
27
28 /** Get all the fields for this record. Useful for not having to list out all the fields you want to retrieve, but slower. */
29 _all: Scalars["JSONObject"];
30}
1type Session {
2 """
3 The globally unique, unchanging identifier for this record. Assigned and managed by Gadget.
4 """
5 id: GadgetID!
6
7 """
8 The time at which this record was first created. Set once upon record creation and never changed. Managed by Gadget.
9 """
10 createdAt: DateTime!
11
12 """
13 The time at which this record was last changed. Set each time the record is successfully acted upon by an action. Managed by Gadget.
14 """
15 updatedAt: DateTime!
16
17 """
18 The current state this record is in. Changed by invoking actions. Managed by Gadget.
19 """
20 state: RecordState!
21 user: User
22 userId: GadgetID
23 roles: [Role!]
24 shop: ShopifyShop
25 shopId: GadgetID
26 shopifySID: String
27
28 """
29 Get all the fields for this record. Useful for not having to list out all the fields you want to retrieve, but slower.
30 """
31 _all: JSONObject!
32}

You can preview what a real record's shape looks like by fetching it using the alida-quiz-app-2 API Playground.

Any fetched Session record will have this same Session type, and expose the same data by default, regardless of where it comes from. This means you can select any of the record's fields wherever you like in a GraphQL query according to the use case at hand.

Session for Session Storage and Authentication

The Session powers session functionality for the alida-quiz-app-2 app. Sessions store transient data specific to one browser interacting with the application, like which user is currently logged in, if a banner message has been shown, or anything else that needs to be specific to each session someone has with alida-quiz-app-2.

alida-quiz-app-2 uses Session to power user authentication using actions on Session. Each user's current Session is accessible using special GraphQL fields for querying and mutating. Session are stored in the Gadget platform similarly to other models, but have this extra functionality for convenient access to the current Session.

Because of this, Session does not have normal findOne, maybeFindOne, findMany, findFirst, maybeFindFirst, or create actions. The Gadget platform manages the lifecycle of Session records, and uses cookies to associate them with browser requests as needed.

Session can still be managed like other models using the Internal API .

Retrieving the current Session record

The current Session record for a request can be retrieved using the currentSession GraphQL field, or the .currentSession.get() JS client function. You can also return only some fields, or extra fields beyond what Gadget retrieves by default, using the select option.

The findOne, maybeFindOne, findMany, findFirst, and maybeFindFirst record readers do not exist for Session. If you need to change arbitrary records, or iterate the list of Session, you can use the Internal API for Session.

const record = await api.currentSession.get();
console.log(record.id); //=> a string
console.log(record.state); //=> a state value like { "created": "loggedOut" }
console.log(record.createdAt); //=> a Date object
const [result, refresh] = useGet(api.currentSession);
const { data, error, fetching } = result;
console.log(result.data?.id); //=> a string
console.log(result.data?.state); //=> a state value like { "created": "loggedOut" }
console.log(result.data?.createdAt); //=> a Date object
1query GetCurrentSession {
2 currentSession {
3 id
4 state
5 createdAt
6 }
7}
Variables
json
{}

Invoking Actions

Session records are changed by invoking Actions. Action are the things that "do" stuff -- logging a user in, logging a user out, making API calls to other services, etc. Actions each have one corresponding GraphQL mutation and a corresponding function available in the API client libraries.

Actions for Session are executed on the currentSession GraphQL field, or the .currentSession JS client ModelManager object. Each of these automatically refers to the Session for the current browser session.

Action Result format

Each API action returns results in the same format that includes a success indicator, errors, and the actual result if the action succeeded. The result is the record that was acted on for a model action, or a list of records for a bulk action, or a JSON blob for Global Actions. Model actions that delete the record don't return the record.

The success field returns a boolean indicating if the action executed as expected. Any execution errors are returned in the errors object, which will always be null if success is true or contain ExecutionError objects if success is false.

ExecutionError objects always have a message describing what error prevented the action from succeeding, as well as a code attribute that gives a stable, searchable, human readable error class code for referencing this specific error. Details on each error code can be found in the Errors documentation. All ExecutionError object types returned by the GraphQL object can be one of many types of error, where some types have extra data that is useful for remedying the error. All error types will always have message and code properties, but some, like InvalidRecordError have extra fields for use by clients.

Errors when using the generated client

The generated JavaScript client automatically interprets errors from invoking actions and throws JavaScript Error instances if the action didn't succeed. The Error objects it throws are rich, and expose extra error properties beyond just message and code if they exist.

Errors thrown by the JavaScript client are easiest to catch by using a try/catch statement around an await, like so:

JavaScript
1import {
2 GadgetOperationError,
3 InvalidRecordError,
4} from "@gadget-client/example-app";
5
6// must be in an async function to use `await` syntax
7const runAction = async () => {
8 try {
9 return await api.exampleModel.create(
10 {
11 exampleModel: {
12 name: "example record name",
13 },
14 }
15 );
16 } catch (error) {
17 if (
18 error instanceof
19 GadgetOperationError
20 ) {
21 // a recognized general error has occurred, retry the operation or inspect error.code`
22 console.error(error);
23 } else if (
24 error instanceof
25 InvalidRecordError
26 ) {
27 // the submitted input data for the action was invalid, inspect the invalid fields which `InvalidRecordError` exposes
28 console.error(
29 error.validationErrors
30 );
31 } else {
32 // an unrecognized error occurred, like an HTTP connection interrupted error or a syntax error. Re-throw it because it's not clear what to do to fix ti
33 throw error;
34 }
35 }
36};

For more information on error codes, consult the Errors documentation.

Session Log In Via Email

The Log In Via Email action transitions a Session from Logged Out to Logged In.

Input

Log In Via Email operates on the current Session for the API client making a request. The Gadget platform manages which Session is available, and no `id` parameter should be passed. The Log In Via Email action takes this input:

Example Invocation
const record = await api.currentSession.logInViaEmail({
// action input data
});
console.log(record.id); //=> a string
console.log(record.state); //=> a state value, like { "created": "loggedOut" }
1const [result, logInViaEmailCurrentSession] = useAction(
2 api.currentSession.logInViaEmail
3);
4const { data, error, fetching } = result;
5await logInViaEmailCurrentSession({
6 // action input data
7});
8console.log(data?.id); //=> a string
9console.log(data?.state); //=> a state value, like { "created": "loggedOut" }
1mutation ($email: LogInViaEmailEmailInput, $password: String) {
2 logInViaEmail(email: $email, password: $password) {
3 success
4 errors {
5 message
6 ... on InvalidRecordError {
7 validationErrors {
8 apiIdentifier
9 message
10 }
11 record
12 model {
13 apiIdentifier
14 }
15 }
16 }
17 session {
18 __typename
19 id
20 state
21 createdAt
22 roles {
23 key
24 name
25 }
26 shop {
27 id
28 state
29 accessToken
30 address1
31 address2
32 checkoutApiSupported
33 city
34 cookieConsentLevel
35 country
36 countryCode
37 countryName
38 countyTaxes
39 createdAt
40 currency
41 customerEmail
42 domain
43 eligibleForCardReaderGiveaway
44 eligibleForPayments
45 email
46 enabledPresentmentCurrencies
47 finances
48 forceSsl
49 googleAppsDomain
50 googleAppsLoginEnabled
51 grantedScopes
52 hasDiscounts
53 hasGiftCards
54 hasStorefront
55 ianaTimezone
56 installedViaApiKey
57 latitude
58 longitude
59 moneyFormat
60 moneyInEmailsFormat
61 moneyWithCurrencyFormat
62 moneyWithCurrencyInEmailsFormat
63 multiLocationEnabled
64 myshopifyDomain
65 name
66 passwordEnabled
67 phone
68 planDisplayName
69 planName
70 preLaunchEnabled
71 primaryLocale
72 province
73 provinceCode
74 registeredWebhooks
75 requiresExtraPaymentsAgreement
76 setupRequired
77 shopOwner
78 shopifyCreatedAt
79 shopifyUpdatedAt
80 source
81 taxShipping
82 taxesIncluded
83 timezone
84 updatedAt
85 weightUnit
86 zipCode
87 }
88 shopifySID
89 updatedAt
90 user {
91 id
92 state
93 createdAt
94 email
95 roles {
96 key
97 name
98 }
99 updatedAt
100 }
101 }
102 }
103}
Variables
json
{
"session": {}
}
Output

Log In Via Email returns data in the action result format, which includes the record if the action was successful. The fields returned for the record can be controlled with the select option.

1export interface LogInViaEmailSessionResult {
2 __typename: "LogInViaEmailSessionResult";
3
4 success: Scalars["Boolean"];
5
6 errors: ExecutionError[];
7
8 session: Session | null;
9}
type LogInViaEmailSessionResult {
success: Boolean!
errors: [ExecutionError!]
session: Session
}

Session Log Out

The Log Out action transitions a Session from Logged In to Logged Out.

Input

Log Out operates on the current Session for the API client making a request. The Gadget platform manages which Session is available, and no `id` parameter should be passed. The Log Out action takes this input:

Example Invocation
const record = await api.currentSession.logOut();
console.log(record.id); //=> a string
console.log(record.state); //=> a state value, like { "created": "loggedOut" }
const [result, logOutCurrentSession] = useAction(api.currentSession.logOut);
const { data, error, fetching } = result;
await logOutCurrentSession();
console.log(data?.id); //=> a string
console.log(data?.state); //=> a state value, like { "created": "loggedOut" }
1mutation {
2 logOut {
3 success
4 errors {
5 message
6 ... on InvalidRecordError {
7 validationErrors {
8 apiIdentifier
9 message
10 }
11 record
12 model {
13 apiIdentifier
14 }
15 }
16 }
17 session {
18 __typename
19 id
20 state
21 createdAt
22 roles {
23 key
24 name
25 }
26 shop {
27 id
28 state
29 accessToken
30 address1
31 address2
32 checkoutApiSupported
33 city
34 cookieConsentLevel
35 country
36 countryCode
37 countryName
38 countyTaxes
39 createdAt
40 currency
41 customerEmail
42 domain
43 eligibleForCardReaderGiveaway
44 eligibleForPayments
45 email
46 enabledPresentmentCurrencies
47 finances
48 forceSsl
49 googleAppsDomain
50 googleAppsLoginEnabled
51 grantedScopes
52 hasDiscounts
53 hasGiftCards
54 hasStorefront
55 ianaTimezone
56 installedViaApiKey
57 latitude
58 longitude
59 moneyFormat
60 moneyInEmailsFormat
61 moneyWithCurrencyFormat
62 moneyWithCurrencyInEmailsFormat
63 multiLocationEnabled
64 myshopifyDomain
65 name
66 passwordEnabled
67 phone
68 planDisplayName
69 planName
70 preLaunchEnabled
71 primaryLocale
72 province
73 provinceCode
74 registeredWebhooks
75 requiresExtraPaymentsAgreement
76 setupRequired
77 shopOwner
78 shopifyCreatedAt
79 shopifyUpdatedAt
80 source
81 taxShipping
82 taxesIncluded
83 timezone
84 updatedAt
85 weightUnit
86 zipCode
87 }
88 shopifySID
89 updatedAt
90 user {
91 id
92 state
93 createdAt
94 email
95 roles {
96 key
97 name
98 }
99 updatedAt
100 }
101 }
102 }
103}
Variables
json
{}
Output

Log Out returns data in the action result format, which includes the record if the action was successful. The fields returned for the record can be controlled with the select option.

1export interface LogOutSessionResult {
2 __typename: "LogOutSessionResult";
3
4 success: Scalars["Boolean"];
5
6 errors: ExecutionError[];
7
8 session: Session | null;
9}
type LogOutSessionResult {
success: Boolean!
errors: [ExecutionError!]
session: Session
}