@ratio-app/cli 0.1.1

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.
Files changed (182) hide show
  1. package/README.md +504 -0
  2. package/bin/run.mjs +5 -0
  3. package/dist/commands/__test__/throw.d.ts +25 -0
  4. package/dist/commands/__test__/throw.js +238 -0
  5. package/dist/commands/__test__/throw.js.map +1 -0
  6. package/dist/commands/app/create.d.ts +55 -0
  7. package/dist/commands/app/create.js +609 -0
  8. package/dist/commands/app/create.js.map +1 -0
  9. package/dist/commands/app/deploy.d.ts +14 -0
  10. package/dist/commands/app/deploy.js +179 -0
  11. package/dist/commands/app/deploy.js.map +1 -0
  12. package/dist/commands/app/dev.d.ts +28 -0
  13. package/dist/commands/app/dev.js +701 -0
  14. package/dist/commands/app/dev.js.map +1 -0
  15. package/dist/commands/app/generate.d.ts +14 -0
  16. package/dist/commands/app/generate.js +179 -0
  17. package/dist/commands/app/generate.js.map +1 -0
  18. package/dist/commands/app/info.d.ts +14 -0
  19. package/dist/commands/app/info.js +179 -0
  20. package/dist/commands/app/info.js.map +1 -0
  21. package/dist/commands/app/link.d.ts +118 -0
  22. package/dist/commands/app/link.js +1120 -0
  23. package/dist/commands/app/link.js.map +1 -0
  24. package/dist/commands/auth/login.d.ts +43 -0
  25. package/dist/commands/auth/login.js +987 -0
  26. package/dist/commands/auth/login.js.map +1 -0
  27. package/dist/commands/auth/logout.d.ts +15 -0
  28. package/dist/commands/auth/logout.js +486 -0
  29. package/dist/commands/auth/logout.js.map +1 -0
  30. package/dist/commands/auth/whoami.d.ts +16 -0
  31. package/dist/commands/auth/whoami.js +531 -0
  32. package/dist/commands/auth/whoami.js.map +1 -0
  33. package/dist/commands/dev/listen.d.ts +84 -0
  34. package/dist/commands/dev/listen.js +1187 -0
  35. package/dist/commands/dev/listen.js.map +1 -0
  36. package/dist/commands/dev/trigger.d.ts +88 -0
  37. package/dist/commands/dev/trigger.js +729 -0
  38. package/dist/commands/dev/trigger.js.map +1 -0
  39. package/dist/index.d.ts +14 -0
  40. package/dist/index.js +617 -0
  41. package/dist/index.js.map +1 -0
  42. package/dist/lib/auth/authorize-code-exchange.d.ts +50 -0
  43. package/dist/lib/auth/authorize-code-exchange.js +114 -0
  44. package/dist/lib/auth/authorize-code-exchange.js.map +1 -0
  45. package/dist/lib/auth/authorize-url.d.ts +42 -0
  46. package/dist/lib/auth/authorize-url.js +35 -0
  47. package/dist/lib/auth/authorize-url.js.map +1 -0
  48. package/dist/lib/auth/browser.d.ts +16 -0
  49. package/dist/lib/auth/browser.js +48 -0
  50. package/dist/lib/auth/browser.js.map +1 -0
  51. package/dist/lib/auth/config.d.ts +41 -0
  52. package/dist/lib/auth/config.js +21 -0
  53. package/dist/lib/auth/config.js.map +1 -0
  54. package/dist/lib/auth/http-refresher.d.ts +30 -0
  55. package/dist/lib/auth/http-refresher.js +103 -0
  56. package/dist/lib/auth/http-refresher.js.map +1 -0
  57. package/dist/lib/auth/identity.d.ts +26 -0
  58. package/dist/lib/auth/identity.js +10 -0
  59. package/dist/lib/auth/identity.js.map +1 -0
  60. package/dist/lib/auth/index.d.ts +13 -0
  61. package/dist/lib/auth/index.js +527 -0
  62. package/dist/lib/auth/index.js.map +1 -0
  63. package/dist/lib/auth/loopback-server.d.ts +65 -0
  64. package/dist/lib/auth/loopback-server.js +245 -0
  65. package/dist/lib/auth/loopback-server.js.map +1 -0
  66. package/dist/lib/auth/manual-prompt.d.ts +17 -0
  67. package/dist/lib/auth/manual-prompt.js +20 -0
  68. package/dist/lib/auth/manual-prompt.js.map +1 -0
  69. package/dist/lib/auth/pkce.d.ts +24 -0
  70. package/dist/lib/auth/pkce.js +15 -0
  71. package/dist/lib/auth/pkce.js.map +1 -0
  72. package/dist/lib/auth/state.d.ts +20 -0
  73. package/dist/lib/auth/state.js +19 -0
  74. package/dist/lib/auth/state.js.map +1 -0
  75. package/dist/lib/auth/verbose-trace.d.ts +25 -0
  76. package/dist/lib/auth/verbose-trace.js +17 -0
  77. package/dist/lib/auth/verbose-trace.js.map +1 -0
  78. package/dist/lib/credentials/clock.d.ts +18 -0
  79. package/dist/lib/credentials/clock.js +10 -0
  80. package/dist/lib/credentials/clock.js.map +1 -0
  81. package/dist/lib/credentials/index.d.ts +5 -0
  82. package/dist/lib/credentials/index.js +340 -0
  83. package/dist/lib/credentials/index.js.map +1 -0
  84. package/dist/lib/credentials/path.d.ts +26 -0
  85. package/dist/lib/credentials/path.js +32 -0
  86. package/dist/lib/credentials/path.js.map +1 -0
  87. package/dist/lib/credentials/refresher.d.ts +26 -0
  88. package/dist/lib/credentials/refresher.js +34 -0
  89. package/dist/lib/credentials/refresher.js.map +1 -0
  90. package/dist/lib/credentials/schema.d.ts +138 -0
  91. package/dist/lib/credentials/schema.js +85 -0
  92. package/dist/lib/credentials/schema.js.map +1 -0
  93. package/dist/lib/credentials/store.d.ts +102 -0
  94. package/dist/lib/credentials/store.js +337 -0
  95. package/dist/lib/credentials/store.js.map +1 -0
  96. package/dist/lib/credentials/types.d.ts +65 -0
  97. package/dist/lib/credentials/types.js +1 -0
  98. package/dist/lib/credentials/types.js.map +1 -0
  99. package/dist/lib/dev-store-gate.d.ts +66 -0
  100. package/dist/lib/dev-store-gate.js +15 -0
  101. package/dist/lib/dev-store-gate.js.map +1 -0
  102. package/dist/lib/errors.d.ts +60 -0
  103. package/dist/lib/errors.js +101 -0
  104. package/dist/lib/errors.js.map +1 -0
  105. package/dist/lib/manifest/index.d.ts +2 -0
  106. package/dist/lib/manifest/index.js +144 -0
  107. package/dist/lib/manifest/index.js.map +1 -0
  108. package/dist/lib/manifest/read-manifest.d.ts +32 -0
  109. package/dist/lib/manifest/read-manifest.js +87 -0
  110. package/dist/lib/manifest/read-manifest.js.map +1 -0
  111. package/dist/lib/manifest/write-client-id.d.ts +33 -0
  112. package/dist/lib/manifest/write-client-id.js +94 -0
  113. package/dist/lib/manifest/write-client-id.js.map +1 -0
  114. package/dist/lib/messages.d.ts +15 -0
  115. package/dist/lib/messages.js +16 -0
  116. package/dist/lib/messages.js.map +1 -0
  117. package/dist/lib/orchestrator/child-runner.d.ts +140 -0
  118. package/dist/lib/orchestrator/child-runner.js +471 -0
  119. package/dist/lib/orchestrator/child-runner.js.map +1 -0
  120. package/dist/lib/preview/index.d.ts +11 -0
  121. package/dist/lib/preview/index.js +17 -0
  122. package/dist/lib/preview/index.js.map +1 -0
  123. package/dist/lib/preview/types.d.ts +16 -0
  124. package/dist/lib/preview/types.js +11 -0
  125. package/dist/lib/preview/types.js.map +1 -0
  126. package/dist/lib/ratio-command.d.ts +52 -0
  127. package/dist/lib/ratio-command.js +141 -0
  128. package/dist/lib/ratio-command.js.map +1 -0
  129. package/dist/lib/relay/index.d.ts +7 -0
  130. package/dist/lib/relay/index.js +362 -0
  131. package/dist/lib/relay/index.js.map +1 -0
  132. package/dist/lib/relay/relay-client.d.ts +91 -0
  133. package/dist/lib/relay/relay-client.js +362 -0
  134. package/dist/lib/relay/relay-client.js.map +1 -0
  135. package/dist/lib/relay/types.d.ts +71 -0
  136. package/dist/lib/relay/types.js +1 -0
  137. package/dist/lib/relay/types.js.map +1 -0
  138. package/dist/lib/render-error.d.ts +35 -0
  139. package/dist/lib/render-error.js +115 -0
  140. package/dist/lib/render-error.js.map +1 -0
  141. package/dist/lib/verbose-flag.d.ts +12 -0
  142. package/dist/lib/verbose-flag.js +17 -0
  143. package/dist/lib/verbose-flag.js.map +1 -0
  144. package/dist/render-CrHGqTPH.d.ts +115 -0
  145. package/dist/templates/.gitkeep +0 -0
  146. package/dist/templates/minimal/.env.example.tmpl +4 -0
  147. package/dist/templates/minimal/README.md.tmpl +26 -0
  148. package/dist/templates/minimal/gitignore +5 -0
  149. package/dist/templates/minimal/manifest.json +5 -0
  150. package/dist/templates/minimal/package.json.tmpl +25 -0
  151. package/dist/templates/minimal/ratio.config.jsonc.tmpl +17 -0
  152. package/dist/templates/minimal/src/index.ts.tmpl +26 -0
  153. package/dist/templates/minimal/src/install.ts.tmpl +37 -0
  154. package/dist/templates/minimal/src/webhooks.ts.tmpl +57 -0
  155. package/dist/templates/minimal/tsconfig.json +17 -0
  156. package/dist/templates/serverless/README.md.tmpl +28 -0
  157. package/dist/templates/serverless/gitignore +6 -0
  158. package/dist/templates/serverless/manifest.json +5 -0
  159. package/dist/templates/serverless/package.json.tmpl +22 -0
  160. package/dist/templates/serverless/ratio.config.jsonc.tmpl +17 -0
  161. package/dist/templates/serverless/src/index.ts.tmpl +20 -0
  162. package/dist/templates/serverless/src/install.ts.tmpl +20 -0
  163. package/dist/templates/serverless/src/webhooks.ts.tmpl +36 -0
  164. package/dist/templates/serverless/tsconfig.json +18 -0
  165. package/dist/templates/serverless/wrangler.toml.tmpl +9 -0
  166. package/dist/templates/with-admin-ui/.env.example.tmpl +4 -0
  167. package/dist/templates/with-admin-ui/README.md.tmpl +28 -0
  168. package/dist/templates/with-admin-ui/gitignore +6 -0
  169. package/dist/templates/with-admin-ui/manifest.json +5 -0
  170. package/dist/templates/with-admin-ui/package.json.tmpl +31 -0
  171. package/dist/templates/with-admin-ui/ratio.config.jsonc.tmpl +17 -0
  172. package/dist/templates/with-admin-ui/src/admin/app/globals.css +19 -0
  173. package/dist/templates/with-admin-ui/src/admin/app/layout.tsx.tmpl +13 -0
  174. package/dist/templates/with-admin-ui/src/admin/app/page.tsx.tmpl +8 -0
  175. package/dist/templates/with-admin-ui/src/admin/next-env.d.ts.tmpl +5 -0
  176. package/dist/templates/with-admin-ui/src/admin/next.config.mjs +3 -0
  177. package/dist/templates/with-admin-ui/src/admin/tsconfig.json +20 -0
  178. package/dist/templates/with-admin-ui/src/index.ts.tmpl +26 -0
  179. package/dist/templates/with-admin-ui/src/install.ts.tmpl +37 -0
  180. package/dist/templates/with-admin-ui/src/webhooks.ts.tmpl +57 -0
  181. package/dist/templates/with-admin-ui/tsconfig.json +17 -0
  182. package/package.json +78 -0
@@ -0,0 +1,103 @@
1
+ // src/lib/auth/http-refresher.ts
2
+ import { z } from "zod";
3
+
4
+ // src/lib/errors.ts
5
+ var RatioCLIError = class extends Error {
6
+ code;
7
+ exitCode;
8
+ hint;
9
+ docsUrl;
10
+ constructor(opts) {
11
+ super(opts.message);
12
+ this.name = new.target.name;
13
+ this.code = opts.code;
14
+ this.exitCode = opts.exitCode;
15
+ if (opts.hint !== void 0) this.hint = opts.hint;
16
+ if (opts.docsUrl !== void 0) this.docsUrl = opts.docsUrl;
17
+ }
18
+ };
19
+ var TokenExpiredError = class extends RatioCLIError {
20
+ constructor(message, hint = "Run 'ratio auth login' to refresh your session.") {
21
+ super({ code: "TOKEN_EXPIRED", exitCode: 3, message, hint });
22
+ }
23
+ };
24
+ var NetworkError = class extends RatioCLIError {
25
+ constructor(message, hint = "Check your network and retry.") {
26
+ super({ code: "NETWORK_ERROR", exitCode: 5, message, hint });
27
+ }
28
+ };
29
+
30
+ // src/lib/auth/verbose-trace.ts
31
+ var noopTracer = () => {
32
+ };
33
+
34
+ // src/lib/auth/http-refresher.ts
35
+ var RefreshResponseSchema = z.object({
36
+ access_token: z.string().min(1),
37
+ refresh_token: z.string().min(1),
38
+ expires_in: z.number().int().positive()
39
+ });
40
+ var HttpTokenRefresher = class {
41
+ serverUrl;
42
+ clientId;
43
+ fetchImpl;
44
+ trace;
45
+ constructor(opts) {
46
+ this.serverUrl = opts.serverUrl;
47
+ this.clientId = opts.clientId;
48
+ this.fetchImpl = opts.fetchImpl ?? fetch;
49
+ this.trace = opts.trace ?? noopTracer;
50
+ }
51
+ async refresh(refreshToken) {
52
+ const body = {
53
+ grant_type: "refresh_token",
54
+ refresh_token: refreshToken,
55
+ clientId: this.clientId
56
+ };
57
+ this.trace("refresh: fired (access token expired or expiring)");
58
+ const startedAt = Date.now();
59
+ let response;
60
+ try {
61
+ response = await this.fetchImpl(`${this.serverUrl}/oauth/token`, {
62
+ method: "POST",
63
+ headers: { "Content-Type": "application/json" },
64
+ body: JSON.stringify(body)
65
+ });
66
+ } catch {
67
+ this.trace(`POST /oauth/token \u2192 network error (${Date.now() - startedAt}ms)`);
68
+ throw new NetworkError("Failed to reach the Ratio server during token refresh.");
69
+ }
70
+ this.trace(`POST /oauth/token \u2192 ${response.status} (${Date.now() - startedAt}ms)`);
71
+ if (response.status >= 400 && response.status < 500) {
72
+ throw new TokenExpiredError(
73
+ "Your session has expired and could not be refreshed."
74
+ );
75
+ }
76
+ if (response.status >= 500 || !response.ok) {
77
+ throw new NetworkError("The Ratio server returned an error during token refresh.");
78
+ }
79
+ let raw;
80
+ try {
81
+ raw = await response.json();
82
+ } catch {
83
+ throw new NetworkError("Token refresh response was not valid JSON.");
84
+ }
85
+ const parsed = RefreshResponseSchema.safeParse(raw);
86
+ if (!parsed.success) {
87
+ throw new TokenExpiredError(
88
+ "Your session has expired and could not be refreshed."
89
+ );
90
+ }
91
+ const data = parsed.data;
92
+ const expiresAt = new Date(Date.now() + data.expires_in * 1e3).toISOString();
93
+ return {
94
+ accessToken: data.access_token,
95
+ refreshToken: data.refresh_token,
96
+ expiresAt
97
+ };
98
+ }
99
+ };
100
+ export {
101
+ HttpTokenRefresher
102
+ };
103
+ //# sourceMappingURL=http-refresher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/lib/auth/http-refresher.ts","../../../src/lib/errors.ts","../../../src/lib/auth/verbose-trace.ts"],"sourcesContent":["/**\n * HTTP implementation of the TokenRefresher interface.\n *\n * POSTs to /oauth/token with grant_type=refresh_token.\n * Maps 4xx → TokenExpiredError, 5xx/network → NetworkError.\n * Never logs or echoes the token value in any error message.\n */\n\nimport { z } from 'zod';\nimport { NetworkError, TokenExpiredError } from '../errors.js';\nimport type { TokenRefresher, TokenSet } from '../credentials/index.js';\nimport { RATIO_CLI_CLIENT_ID } from './config.js';\nimport { noopTracer } from './verbose-trace.js';\nimport type { VerboseTracer } from './verbose-trace.js';\n\n/** Refresh response envelope — subset of the full token response. */\nconst RefreshResponseSchema = z.object({\n access_token: z.string().min(1),\n refresh_token: z.string().min(1),\n expires_in: z.number().int().positive(),\n});\n\nexport interface HttpTokenRefresherOptions {\n readonly serverUrl: string;\n readonly clientId: typeof RATIO_CLI_CLIENT_ID;\n readonly fetchImpl?: typeof fetch; // injectable for tests\n /** Verbose diagnostic sink — never receives the refresh token value. */\n readonly trace?: VerboseTracer;\n}\n\nexport class HttpTokenRefresher implements TokenRefresher {\n private readonly serverUrl: string;\n private readonly clientId: string;\n private readonly fetchImpl: typeof fetch;\n private readonly trace: VerboseTracer;\n\n constructor(opts: HttpTokenRefresherOptions) {\n this.serverUrl = opts.serverUrl;\n this.clientId = opts.clientId;\n this.fetchImpl = opts.fetchImpl ?? fetch;\n this.trace = opts.trace ?? noopTracer;\n }\n\n async refresh(refreshToken: string): Promise<TokenSet> {\n const body = {\n grant_type: 'refresh_token',\n refresh_token: refreshToken,\n clientId: this.clientId,\n };\n\n this.trace('refresh: fired (access token expired or expiring)');\n const startedAt = Date.now();\n\n let response: Response;\n try {\n response = await this.fetchImpl(`${this.serverUrl}/oauth/token`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n });\n } catch {\n this.trace(`POST /oauth/token → network error (${Date.now() - startedAt}ms)`);\n throw new NetworkError('Failed to reach the Ratio server during token refresh.');\n }\n\n this.trace(`POST /oauth/token → ${response.status} (${Date.now() - startedAt}ms)`);\n\n if (response.status >= 400 && response.status < 500) {\n throw new TokenExpiredError(\n 'Your session has expired and could not be refreshed.',\n );\n }\n\n if (response.status >= 500 || !response.ok) {\n throw new NetworkError('The Ratio server returned an error during token refresh.');\n }\n\n let raw: unknown;\n try {\n raw = await response.json();\n } catch {\n throw new NetworkError('Token refresh response was not valid JSON.');\n }\n\n const parsed = RefreshResponseSchema.safeParse(raw);\n if (!parsed.success) {\n throw new TokenExpiredError(\n 'Your session has expired and could not be refreshed.',\n );\n }\n\n const data = parsed.data;\n const expiresAt = new Date(Date.now() + data.expires_in * 1000).toISOString();\n\n return {\n accessToken: data.access_token,\n refreshToken: data.refresh_token,\n expiresAt,\n };\n }\n}\n","/**\n * Error hierarchy for the Ratio CLI. Every error thrown from a command's\n * run() is expected to be an instance of RatioCLIError so the global\n * render-error handler can map it to a deterministic stderr line and exit\n * code. Uncaught Error subclasses render as \"INTERNAL: <msg>\" with exit 1.\n *\n * No import from @oclif/core — this file is dependency-free so tests\n * can import it without oclif overhead.\n */\n\nexport class RatioCLIError extends Error {\n readonly code: string;\n readonly exitCode: number;\n readonly hint?: string;\n readonly docsUrl?: string;\n\n constructor(opts: {\n code: string;\n exitCode: number;\n message: string;\n hint?: string;\n docsUrl?: string;\n }) {\n super(opts.message);\n this.name = new.target.name;\n this.code = opts.code;\n this.exitCode = opts.exitCode;\n if (opts.hint !== undefined) this.hint = opts.hint;\n if (opts.docsUrl !== undefined) this.docsUrl = opts.docsUrl;\n }\n}\n\n/** Coming-soon stub UX. Renders on stdout with exit 0. */\nexport class ComingSoonError extends RatioCLIError {\n constructor(message: string) {\n super({ code: 'COMING_SOON', exitCode: 0, message });\n }\n}\n\n/** User has no credentials and command requires auth. */\nexport class NotLoggedInError extends RatioCLIError {\n constructor(\n message: string,\n hint: string = \"Run 'ratio auth login' to sign in.\",\n ) {\n super({ code: 'NOT_LOGGED_IN', exitCode: 3, message, hint });\n }\n}\n\nexport class TokenExpiredError extends RatioCLIError {\n constructor(\n message: string,\n hint: string = \"Run 'ratio auth login' to refresh your session.\",\n ) {\n super({ code: 'TOKEN_EXPIRED', exitCode: 3, message, hint });\n }\n}\n\nexport class ScopeDeniedError extends RatioCLIError {\n constructor(message: string, hint?: string) {\n const opts: { code: string; exitCode: number; message: string; hint?: string } = {\n code: 'SCOPE_DENIED',\n exitCode: 4,\n message,\n };\n if (hint !== undefined) opts.hint = hint;\n super(opts);\n }\n}\n\nexport class NetworkError extends RatioCLIError {\n constructor(message: string, hint: string = 'Check your network and retry.') {\n super({ code: 'NETWORK_ERROR', exitCode: 5, message, hint });\n }\n}\n\nexport class RelayConnectError extends RatioCLIError {\n constructor(\n message: string,\n hint: string = 'Verify the tunnel URL and that the auth-server is reachable.',\n ) {\n super({ code: 'RELAY_CONNECT', exitCode: 6, message, hint });\n }\n}\n\nexport class TemplateExistsError extends RatioCLIError {\n constructor(\n message: string,\n hint: string = 'Choose a different name or remove the existing directory.',\n ) {\n super({ code: 'TEMPLATE_EXISTS', exitCode: 7, message, hint });\n }\n}\n\nexport class ValidationError extends RatioCLIError {\n constructor(message: string, hint?: string) {\n const opts: { code: string; exitCode: number; message: string; hint?: string } = {\n code: 'VALIDATION_ERROR',\n exitCode: 8,\n message,\n };\n if (hint !== undefined) opts.hint = hint;\n super(opts);\n }\n}\n\nexport class RelayResumeGapError extends RatioCLIError {\n constructor(\n message: string,\n hint: string = 'Reconnect from the current cursor; older events are outside the buffer window.',\n ) {\n super({ code: 'RELAY_RESUME_GAP', exitCode: 9, message, hint });\n }\n}\n\nexport class OrchestratorSpawnError extends RatioCLIError {\n constructor(\n message: string,\n hint: string = \"Could not start your app's dev command — check that the command in ratio.config.jsonc runs from this directory.\",\n ) {\n super({ code: 'ORCHESTRATOR_SPAWN', exitCode: 10, message, hint });\n }\n}\n\nexport class OrchestratorDrainTimeoutError extends RatioCLIError {\n constructor(\n message: string,\n hint: string = 'Your dev command did not exit cleanly within 5 seconds — it was forcibly terminated.',\n ) {\n super({ code: 'ORCHESTRATOR_DRAIN', exitCode: 11, message, hint });\n }\n}\n\nexport function isRatioCLIError(err: unknown): err is RatioCLIError {\n return err instanceof RatioCLIError;\n}\n","/**\n * Minimal verbose diagnostic seam for the auth flow.\n *\n * When `--verbose` is on, the auth HTTP/loopback boundaries emit ONE line\n * per boundary crossing (method, path, status, timing, flow events) so a\n * failing login/refresh can be diagnosed from the CLI transcript alone.\n *\n * Safety contract (enforced by tests):\n * - Lines go to STDERR only — never stdout — so `--json` consumers and\n * shell pipelines are never corrupted.\n * - NO secret material is ever passed to a tracer: no access/refresh\n * token, no authorization code, no code_verifier, no state value.\n * Only method, path, HTTP status, port numbers, and durations.\n */\n\n/** A tracer receives one pre-formatted diagnostic message per event. */\nexport type VerboseTracer = (msg: string) => void;\n\n/** Shared no-op used when `--verbose` is off (default everywhere). */\nexport const noopTracer: VerboseTracer = () => {};\n\n/**\n * Build a tracer. Returns the shared no-op unless `verbose` is true.\n * Output sink is injectable for tests; defaults to process.stderr.\n */\nexport function createVerboseTracer(\n verbose: boolean,\n write: (line: string) => void = (line) => {\n process.stderr.write(line);\n },\n): VerboseTracer {\n if (!verbose) return noopTracer;\n return (msg: string) => {\n write(`[verbose] ${msg}\\n`);\n };\n}\n"],"mappings":";AAQA,SAAS,SAAS;;;ACEX,IAAM,gBAAN,cAA4B,MAAM;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAET,YAAY,MAMT;AACD,UAAM,KAAK,OAAO;AAClB,SAAK,OAAO,WAAW;AACvB,SAAK,OAAO,KAAK;AACjB,SAAK,WAAW,KAAK;AACrB,QAAI,KAAK,SAAS,OAAW,MAAK,OAAO,KAAK;AAC9C,QAAI,KAAK,YAAY,OAAW,MAAK,UAAU,KAAK;AAAA,EACtD;AACF;AAmBO,IAAM,oBAAN,cAAgC,cAAc;AAAA,EACnD,YACE,SACA,OAAe,mDACf;AACA,UAAM,EAAE,MAAM,iBAAiB,UAAU,GAAG,SAAS,KAAK,CAAC;AAAA,EAC7D;AACF;AAcO,IAAM,eAAN,cAA2B,cAAc;AAAA,EAC9C,YAAY,SAAiB,OAAe,iCAAiC;AAC3E,UAAM,EAAE,MAAM,iBAAiB,UAAU,GAAG,SAAS,KAAK,CAAC;AAAA,EAC7D;AACF;;;ACvDO,IAAM,aAA4B,MAAM;AAAC;;;AFHhD,IAAM,wBAAwB,EAAE,OAAO;AAAA,EACrC,cAAc,EAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EAC9B,eAAe,EAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EAC/B,YAAY,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS;AACxC,CAAC;AAUM,IAAM,qBAAN,MAAmD;AAAA,EACvC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEjB,YAAY,MAAiC;AAC3C,SAAK,YAAY,KAAK;AACtB,SAAK,WAAW,KAAK;AACrB,SAAK,YAAY,KAAK,aAAa;AACnC,SAAK,QAAQ,KAAK,SAAS;AAAA,EAC7B;AAAA,EAEA,MAAM,QAAQ,cAAyC;AACrD,UAAM,OAAO;AAAA,MACX,YAAY;AAAA,MACZ,eAAe;AAAA,MACf,UAAU,KAAK;AAAA,IACjB;AAEA,SAAK,MAAM,mDAAmD;AAC9D,UAAM,YAAY,KAAK,IAAI;AAE3B,QAAI;AACJ,QAAI;AACF,iBAAW,MAAM,KAAK,UAAU,GAAG,KAAK,SAAS,gBAAgB;AAAA,QAC/D,QAAQ;AAAA,QACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,QAC9C,MAAM,KAAK,UAAU,IAAI;AAAA,MAC3B,CAAC;AAAA,IACH,QAAQ;AACN,WAAK,MAAM,2CAAsC,KAAK,IAAI,IAAI,SAAS,KAAK;AAC5E,YAAM,IAAI,aAAa,wDAAwD;AAAA,IACjF;AAEA,SAAK,MAAM,4BAAuB,SAAS,MAAM,KAAK,KAAK,IAAI,IAAI,SAAS,KAAK;AAEjF,QAAI,SAAS,UAAU,OAAO,SAAS,SAAS,KAAK;AACnD,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAEA,QAAI,SAAS,UAAU,OAAO,CAAC,SAAS,IAAI;AAC1C,YAAM,IAAI,aAAa,0DAA0D;AAAA,IACnF;AAEA,QAAI;AACJ,QAAI;AACF,YAAM,MAAM,SAAS,KAAK;AAAA,IAC5B,QAAQ;AACN,YAAM,IAAI,aAAa,4CAA4C;AAAA,IACrE;AAEA,UAAM,SAAS,sBAAsB,UAAU,GAAG;AAClD,QAAI,CAAC,OAAO,SAAS;AACnB,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAEA,UAAM,OAAO,OAAO;AACpB,UAAM,YAAY,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,aAAa,GAAI,EAAE,YAAY;AAE5E,WAAO;AAAA,MACL,aAAa,KAAK;AAAA,MAClB,cAAc,KAAK;AAAA,MACnB;AAAA,IACF;AAAA,EACF;AACF;","names":[]}
@@ -0,0 +1,26 @@
1
+ export { TokenDerivedIdentity } from './authorize-code-exchange.js';
2
+ import '../credentials/types.js';
3
+ import './config.js';
4
+ import './verbose-trace.js';
5
+
6
+ /**
7
+ * Identity helpers for the auth flow.
8
+ *
9
+ * A-29 adjudication: the backend token envelope does not expose developerId/email.
10
+ * Identity is therefore token-derived: {clientId, merchantId, scopes}.
11
+ *
12
+ * This file re-exports the TokenDerivedIdentity type from authorize-code-exchange
13
+ * so consumers have a single import point. It is a null-object for the POST-token
14
+ * identity fetch originally envisioned (no GET /developer/me endpoint
15
+ * exists yet). The appName optional field is added if GET /oauth/app-info returns it.
16
+ */
17
+
18
+ /** Rendered display string for the identity in whoami / login success. */
19
+ declare function renderIdentity(identity: {
20
+ clientId: string;
21
+ merchantId: string;
22
+ scopes: readonly string[];
23
+ appName?: string;
24
+ }): string;
25
+
26
+ export { renderIdentity };
@@ -0,0 +1,10 @@
1
+ // src/lib/auth/identity.ts
2
+ function renderIdentity(identity) {
3
+ const scopePart = identity.scopes.length > 0 ? ` scopes=[${identity.scopes.join(", ")}]` : "";
4
+ const appPart = identity.appName ? ` app="${identity.appName}"` : "";
5
+ return `clientId=${identity.clientId} merchantId=${identity.merchantId}${appPart}${scopePart}`;
6
+ }
7
+ export {
8
+ renderIdentity
9
+ };
10
+ //# sourceMappingURL=identity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/lib/auth/identity.ts"],"sourcesContent":["/**\n * Identity helpers for the auth flow.\n *\n * A-29 adjudication: the backend token envelope does not expose developerId/email.\n * Identity is therefore token-derived: {clientId, merchantId, scopes}.\n *\n * This file re-exports the TokenDerivedIdentity type from authorize-code-exchange\n * so consumers have a single import point. It is a null-object for the POST-token\n * identity fetch originally envisioned (no GET /developer/me endpoint\n * exists yet). The appName optional field is added if GET /oauth/app-info returns it.\n */\n\nexport type { TokenDerivedIdentity } from './authorize-code-exchange.js';\n\n/** Rendered display string for the identity in whoami / login success. */\nexport function renderIdentity(identity: {\n clientId: string;\n merchantId: string;\n scopes: readonly string[];\n appName?: string;\n}): string {\n const scopePart = identity.scopes.length > 0\n ? ` scopes=[${identity.scopes.join(', ')}]`\n : '';\n const appPart = identity.appName ? ` app=\"${identity.appName}\"` : '';\n return `clientId=${identity.clientId} merchantId=${identity.merchantId}${appPart}${scopePart}`;\n}\n"],"mappings":";AAeO,SAAS,eAAe,UAKpB;AACT,QAAM,YAAY,SAAS,OAAO,SAAS,IACvC,YAAY,SAAS,OAAO,KAAK,IAAI,CAAC,MACtC;AACJ,QAAM,UAAU,SAAS,UAAU,SAAS,SAAS,OAAO,MAAM;AAClE,SAAO,YAAY,SAAS,QAAQ,eAAe,SAAS,UAAU,GAAG,OAAO,GAAG,SAAS;AAC9F;","names":[]}
@@ -0,0 +1,13 @@
1
+ export { PkcePair, computeS256Challenge, generatePkcePair } from './pkce.js';
2
+ export { generateState, timingSafeEqualState } from './state.js';
3
+ export { DEFAULT_SERVER_URL, RATIO_CLI_CLIENT_ID, RATIO_CLI_MERCHANT_ID, ResolveServerUrlOptions, ServerConfig, resolveServerUrl } from './config.js';
4
+ export { AuthorizeUrlBrowserOptions, AuthorizeUrlManualOptions, buildBrowserAuthorizeUrl, buildManualAuthorizeUrl } from './authorize-url.js';
5
+ export { CodeExchangeInput, CodeExchangeOutput, TokenDerivedIdentity, exchangeCodeForTokens } from './authorize-code-exchange.js';
6
+ export { HttpTokenRefresher, HttpTokenRefresherOptions } from './http-refresher.js';
7
+ export { LoopbackAwaitOptions, LoopbackAwaitResult, LoopbackSession, awaitLoopbackCallback, buildLoopbackRedirectUri, startLoopbackSession } from './loopback-server.js';
8
+ export { BrowserOpener, defaultBrowserOpener } from './browser.js';
9
+ export { StdinPrompt, defaultStdinPrompt } from './manual-prompt.js';
10
+ export { renderIdentity } from './identity.js';
11
+ export { VerboseTracer, createVerboseTracer, noopTracer } from './verbose-trace.js';
12
+ import '../credentials/types.js';
13
+ import '../credentials/refresher.js';