castle-web-cli 0.4.64 → 0.4.66

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -35,6 +35,7 @@ export type PlatformHandler = (
35
35
  export interface HostCapabilities {
36
36
  graphqlFetch: GraphqlFetch;
37
37
  platformHandler?: PlatformHandler;
38
+ localPassGrant?: (passId: string) => boolean;
38
39
  }
39
40
 
40
41
  export interface SerializedCommandError {
@@ -94,7 +94,7 @@ function runCommand(ctx, command, params, caps) {
94
94
  case "time.getServerTime":
95
95
  return timeGetServerTime(gql);
96
96
  case "pass.has":
97
- return passHas(ctx, params, gql);
97
+ return passHas(ctx, params, caps);
98
98
  // Platform commands are handled above; listed here to keep the switch
99
99
  // exhaustive over CommandName.
100
100
  case "pass.offer":
@@ -114,10 +114,13 @@ async function runPlatformCommand(ctx, command, params, caps) {
114
114
  return unavailableOutcome(command);
115
115
  }
116
116
  }
117
- async function passHas(ctx, params, gql) {
118
- const deckId = requireDeckId(ctx, "pass.has");
117
+ async function passHas(ctx, params, caps) {
119
118
  const passId = asString(params.passId, "passId", "pass.has");
120
- const data = await graphql(gql, PASSES_FOR_DECK_QUERY, { deckId }, "pass.has");
119
+ if (caps.localPassGrant?.(passId) === true) {
120
+ return { hasPass: true };
121
+ }
122
+ const deckId = requireDeckId(ctx, "pass.has");
123
+ const data = await graphql(caps.graphqlFetch, PASSES_FOR_DECK_QUERY, { deckId }, "pass.has");
121
124
  const match = (data.passesForDeck ?? []).find((p) => p?.passId === passId);
122
125
  return { hasPass: match?.isActive === true };
123
126
  }
@@ -127,6 +130,8 @@ async function passesOffer(ctx, params, caps) {
127
130
  // unavailable, never an error or a thrown MISSING_DECK_ID.
128
131
  if (!caps.platformHandler)
129
132
  return { status: "unavailable" };
133
+ if (caps.localPassGrant?.(passId) === true)
134
+ return { status: "alreadyOwned" };
130
135
  // Real transaction path (mobile native sheet; web upsell): the pass belongs
131
136
  // to a deck, so a trusted deckId is required before handing off.
132
137
  const deckId = requireDeckId(ctx, "pass.offer");
package/dist/config.js CHANGED
@@ -32,11 +32,16 @@ function writeConfig(updates) {
32
32
  const configFilePath = path.join(configDir, 'config.json');
33
33
  fs.writeFileSync(configFilePath, JSON.stringify(existing, null, 2), 'utf-8');
34
34
  }
35
+ // Env overrides on-disk config so a caller can act as a user without writing the token to disk.
35
36
  export function getToken() {
37
+ if (process.env.CASTLE_TOKEN)
38
+ return process.env.CASTLE_TOKEN;
36
39
  const c = readConfigFile('config.json');
37
40
  return c && typeof c.token === 'string' ? c.token : null;
38
41
  }
39
42
  export function getUserId() {
43
+ if (process.env.CASTLE_USER_ID)
44
+ return process.env.CASTLE_USER_ID;
40
45
  const c = readConfigFile('config.json');
41
46
  return c && typeof c.userId === 'string' ? c.userId : null;
42
47
  }