@superpanel-sdk/runtime 0.2.2 → 0.5.0

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 (274) hide show
  1. package/README.md +28 -8
  2. package/dist/builder/codegen/emit.d.ts +29 -11
  3. package/dist/builder/codegen/emit.js +328 -61
  4. package/dist/builder/codegen/generate.d.ts +21 -0
  5. package/dist/builder/codegen/generate.js +152 -20
  6. package/dist/builder/company-import-graph.d.ts +2 -0
  7. package/dist/builder/company-import-graph.js +40 -8
  8. package/dist/builder/company-imports.d.ts +24 -0
  9. package/dist/builder/company-imports.js +114 -0
  10. package/dist/builder/compile/compile-sequence.d.ts +59 -8
  11. package/dist/builder/compile/compile-sequence.js +279 -77
  12. package/dist/builder/compile/function-code.d.ts +12 -2
  13. package/dist/builder/compile/function-code.js +87 -39
  14. package/dist/builder/compile/registry.d.ts +7 -3
  15. package/dist/builder/compile/registry.js +24 -23
  16. package/dist/builder/load.d.ts +70 -10
  17. package/dist/builder/load.js +250 -61
  18. package/dist/builder/paths.d.ts +3 -0
  19. package/dist/builder/paths.js +16 -0
  20. package/dist/builder/schedules.d.ts +23 -0
  21. package/dist/builder/schedules.js +102 -0
  22. package/dist/builder/slot-schema-validation.d.ts +4 -0
  23. package/dist/builder/slot-schema-validation.js +10 -0
  24. package/dist/builder/typecheck.d.ts +8 -0
  25. package/dist/builder/typecheck.js +105 -0
  26. package/dist/builder/types.d.ts +91 -19
  27. package/dist/builder/types.js +2 -1
  28. package/dist/cli/auth/auth.d.ts +37 -0
  29. package/dist/cli/auth/auth.js +211 -0
  30. package/dist/cli/auth/backend-url.d.ts +5 -0
  31. package/dist/cli/auth/backend-url.js +25 -0
  32. package/dist/cli/auth/clipboard.d.ts +9 -0
  33. package/dist/cli/auth/clipboard.js +38 -0
  34. package/dist/cli/auth/http.d.ts +20 -0
  35. package/dist/cli/auth/http.js +27 -0
  36. package/dist/cli/auth/index.d.ts +10 -0
  37. package/dist/cli/auth/index.js +27 -0
  38. package/dist/cli/auth/progress.d.ts +12 -0
  39. package/dist/cli/auth/progress.js +15 -0
  40. package/dist/cli/auth/serve-login.d.ts +8 -0
  41. package/dist/cli/auth/serve-login.js +24 -0
  42. package/dist/cli/compile/index.js +3 -0
  43. package/dist/cli/config.d.ts +10 -0
  44. package/dist/cli/config.js +52 -0
  45. package/dist/cli/index.js +28 -8
  46. package/dist/cli/serve/index.d.ts +73 -3
  47. package/dist/cli/serve/index.js +410 -113
  48. package/dist/cli/type-gen/index.js +9 -8
  49. package/dist/compiler.d.ts +7 -0
  50. package/dist/compiler.js +7 -0
  51. package/dist/compute-host/compute-host.d.ts +15 -23
  52. package/dist/compute-host/compute-host.js +25 -28
  53. package/dist/compute-host/index.d.ts +2 -2
  54. package/dist/compute-host/index.js +1 -1
  55. package/dist/compute-host/source-compute-host.d.ts +11 -9
  56. package/dist/compute-host/source-compute-host.js +50 -31
  57. package/dist/core/case-orchestrator/contact-hours.d.ts +50 -0
  58. package/dist/core/case-orchestrator/contact-hours.js +108 -0
  59. package/dist/core/case-orchestrator/follow-ups.d.ts +31 -0
  60. package/dist/core/case-orchestrator/follow-ups.js +103 -0
  61. package/dist/core/case-orchestrator/index.d.ts +6 -0
  62. package/dist/core/case-orchestrator/index.js +6 -0
  63. package/dist/core/case-orchestrator/render.d.ts +75 -0
  64. package/dist/core/case-orchestrator/render.js +239 -0
  65. package/dist/core/case-orchestrator/time.d.ts +11 -0
  66. package/dist/core/case-orchestrator/time.js +29 -0
  67. package/dist/core/case-orchestrator/tools.d.ts +29 -0
  68. package/dist/core/case-orchestrator/tools.js +31 -0
  69. package/dist/core/case-orchestrator/types.d.ts +753 -0
  70. package/dist/core/case-orchestrator/types.js +46 -0
  71. package/dist/core/case-orchestrator/validate.d.ts +11 -0
  72. package/dist/core/case-orchestrator/validate.js +63 -0
  73. package/dist/core/context/call.d.ts +291 -0
  74. package/dist/core/context/call.js +94 -0
  75. package/dist/core/context/channels.d.ts +60 -0
  76. package/dist/core/context/channels.js +35 -0
  77. package/dist/core/context/contact.d.ts +96 -6
  78. package/dist/core/context/contact.js +48 -2
  79. package/dist/core/context/email-message.d.ts +159 -0
  80. package/dist/core/context/email-message.js +59 -0
  81. package/dist/core/context/email.d.ts +97 -0
  82. package/dist/core/context/email.js +91 -0
  83. package/dist/core/context/exchanges.d.ts +142 -0
  84. package/dist/core/context/exchanges.js +63 -0
  85. package/dist/core/context/instances.d.ts +278 -0
  86. package/dist/core/context/instances.js +123 -0
  87. package/dist/core/context/kv.d.ts +113 -0
  88. package/dist/core/context/kv.js +60 -0
  89. package/dist/core/context/platform-registry.d.ts +509 -4
  90. package/dist/core/context/platform-registry.js +14 -2
  91. package/dist/core/context/platform.d.ts +2 -1
  92. package/dist/core/context/sms.d.ts +147 -0
  93. package/dist/core/context/sms.js +57 -0
  94. package/dist/core/context/types.d.ts +51 -30
  95. package/dist/core/context/types.js +1 -7
  96. package/dist/core/conversation/index.d.ts +31 -0
  97. package/dist/core/conversation/index.js +14 -0
  98. package/dist/core/functions/define/bind.d.ts +25 -0
  99. package/dist/core/functions/define/bind.js +14 -0
  100. package/dist/core/functions/define/case.d.ts +9 -0
  101. package/dist/core/functions/define/case.js +13 -0
  102. package/dist/core/functions/define/events.d.ts +20 -0
  103. package/dist/core/functions/define/events.js +21 -0
  104. package/dist/core/functions/define/no-case.d.ts +4 -0
  105. package/dist/core/functions/define/no-case.js +9 -0
  106. package/dist/core/functions/events.d.ts +247 -0
  107. package/dist/core/functions/events.js +32 -0
  108. package/dist/core/functions/func-ref.d.ts +11 -2
  109. package/dist/core/functions/schedules.d.ts +51 -0
  110. package/dist/core/functions/schedules.js +20 -0
  111. package/dist/core/functions/types.d.ts +62 -51
  112. package/dist/core/functions/types.js +6 -1
  113. package/dist/core/office-hours/index.d.ts +39 -0
  114. package/dist/core/office-hours/index.js +187 -0
  115. package/dist/core/page/define.d.ts +834 -0
  116. package/dist/core/page/define.js +477 -0
  117. package/dist/core/page/ops.d.ts +58 -0
  118. package/dist/core/page/ops.js +220 -0
  119. package/dist/core/page/render.d.ts +253 -0
  120. package/dist/core/page/render.js +840 -0
  121. package/dist/core/page/time-format.d.ts +19 -0
  122. package/dist/core/page/time-format.js +41 -0
  123. package/dist/core/page/timeline.d.ts +40 -0
  124. package/dist/core/page/timeline.js +2 -0
  125. package/dist/core/page/typed.d.ts +642 -0
  126. package/dist/core/page/typed.js +2 -0
  127. package/dist/core/page/workspace.d.ts +33 -0
  128. package/dist/core/page/workspace.js +231 -0
  129. package/dist/core/party/index.d.ts +3 -0
  130. package/dist/core/party/index.js +3 -0
  131. package/dist/core/party/schema.d.ts +137 -0
  132. package/dist/core/party/schema.js +80 -0
  133. package/dist/core/party/types.d.ts +40 -0
  134. package/dist/core/party/types.js +15 -0
  135. package/dist/core/sequence/define.d.ts +57 -0
  136. package/dist/core/sequence/define.js +10 -0
  137. package/dist/core/sequence/index.d.ts +63 -0
  138. package/dist/core/sequence/index.js +231 -0
  139. package/dist/core/slot/binding.d.ts +40 -0
  140. package/dist/core/slot/binding.js +2 -0
  141. package/dist/core/slot/company-metadata.d.ts +113 -0
  142. package/dist/core/slot/company-metadata.js +563 -0
  143. package/dist/core/slot/compile-schema.d.ts +19 -13
  144. package/dist/core/slot/compile-schema.js +51 -248
  145. package/dist/core/slot/contact-timezone.d.ts +110 -0
  146. package/dist/core/slot/contact-timezone.js +186 -0
  147. package/dist/core/slot/field.d.ts +2 -24
  148. package/dist/core/slot/field.js +0 -69
  149. package/dist/core/slot/id-ref.d.ts +17 -2
  150. package/dist/core/slot/id-ref.js +16 -8
  151. package/dist/core/slot/index.d.ts +12 -13
  152. package/dist/core/slot/index.js +11 -12
  153. package/dist/core/slot/naming.d.ts +15 -0
  154. package/dist/core/slot/naming.js +96 -0
  155. package/dist/core/slot/platform-fields.d.ts +119 -0
  156. package/dist/core/slot/platform-fields.js +121 -0
  157. package/dist/core/slot/ref.d.ts +16 -0
  158. package/dist/core/slot/ref.js +14 -0
  159. package/dist/core/slot/row.d.ts +2 -9
  160. package/dist/core/slot/row.js +13 -23
  161. package/dist/core/slot/schema-compat.d.ts +16 -0
  162. package/dist/core/slot/schema-compat.js +112 -0
  163. package/dist/core/slot/schema.d.ts +409 -76
  164. package/dist/core/slot/schema.js +178 -10
  165. package/dist/core/slot/types.d.ts +27 -92
  166. package/dist/core/slot/value.d.ts +26 -3
  167. package/dist/core/slot/value.js +89 -57
  168. package/dist/dev-overlay/protocol.d.ts +41 -8
  169. package/dist/fn-context/build-context.d.ts +3 -1
  170. package/dist/fn-context/build-context.js +20 -10
  171. package/dist/fn-context/fake/empty-api.js +9 -28
  172. package/dist/fn-context/fake/index.d.ts +11 -4
  173. package/dist/fn-context/fake/index.js +27 -2
  174. package/dist/fn-context/fn-params.d.ts +6 -0
  175. package/dist/fn-context/fn-params.js +13 -0
  176. package/dist/fn-context/index.d.ts +5 -5
  177. package/dist/fn-context/index.js +4 -4
  178. package/dist/fn-context/log.js +2 -2
  179. package/dist/fn-context/make-ctx.d.ts +11 -0
  180. package/dist/fn-context/make-ctx.js +18 -8
  181. package/dist/fn-context/rpc/case-orchestrator-tools.d.ts +24 -0
  182. package/dist/fn-context/rpc/case-orchestrator-tools.js +13 -0
  183. package/dist/fn-context/rpc/index.d.ts +3 -1
  184. package/dist/fn-context/rpc/index.js +3 -1
  185. package/dist/fn-context/rpc/integration/index.d.ts +4 -4
  186. package/dist/fn-context/rpc/integration/index.js +1 -1
  187. package/dist/fn-context/rpc/integration/list-surfaces.d.ts +21 -0
  188. package/dist/fn-context/rpc/integration/{list-bindings.js → list-surfaces.js} +4 -4
  189. package/dist/fn-context/rpc/platform.d.ts +2 -2
  190. package/dist/fn-context/rpc/platform.js +1 -1
  191. package/dist/fn-context/rpc/records.d.ts +78 -0
  192. package/dist/fn-context/rpc/records.js +26 -0
  193. package/dist/fn-context/rpc/trpc-client.d.ts +2 -2
  194. package/dist/fn-context/rpc/trpc-client.js +89 -5
  195. package/dist/fn-context/rpc/trpc-init.d.ts +2 -2
  196. package/dist/fn-context/rpc/trpc-router-factory.d.ts +49 -3
  197. package/dist/fn-context/rpc/trpc-router-factory.js +2 -0
  198. package/dist/fn-context/run-scope.d.ts +4 -0
  199. package/dist/fn-context/run-scope.js +9 -0
  200. package/dist/fn-context/types.d.ts +36 -3
  201. package/dist/index.d.ts +37 -46
  202. package/dist/index.js +33 -33
  203. package/dist/logger.d.ts +7 -0
  204. package/dist/logger.js +41 -0
  205. package/dist/platform.d.ts +76 -0
  206. package/dist/platform.js +56 -0
  207. package/dist/voice-service/actions.d.ts +71 -4
  208. package/dist/voice-service/types.d.ts +42 -2
  209. package/dist/worker.d.ts +10 -0
  210. package/dist/worker.js +10 -0
  211. package/package.json +38 -19
  212. package/dist/builder/compile/compile-agenda.d.ts +0 -15
  213. package/dist/builder/compile/compile-agenda.js +0 -59
  214. package/dist/builder/merge.d.ts +0 -4
  215. package/dist/builder/merge.js +0 -19
  216. package/dist/core/context/db.d.ts +0 -69
  217. package/dist/core/context/db.js +0 -44
  218. package/dist/core/context/docusign.d.ts +0 -134
  219. package/dist/core/context/docusign.js +0 -108
  220. package/dist/core/context/filevine.d.ts +0 -323
  221. package/dist/core/context/filevine.js +0 -254
  222. package/dist/core/context/http.d.ts +0 -9
  223. package/dist/core/context/http.js +0 -4
  224. package/dist/core/context/hubspot.d.ts +0 -250
  225. package/dist/core/context/hubspot.js +0 -191
  226. package/dist/core/context/twilio.d.ts +0 -50
  227. package/dist/core/context/twilio.js +0 -42
  228. package/dist/core/functions/define/case-context.d.ts +0 -14
  229. package/dist/core/functions/define/case-context.js +0 -15
  230. package/dist/core/functions/define/compute.d.ts +0 -7
  231. package/dist/core/functions/define/compute.js +0 -17
  232. package/dist/core/functions/define/custom.d.ts +0 -4
  233. package/dist/core/functions/define/custom.js +0 -8
  234. package/dist/core/functions/define/system.d.ts +0 -7
  235. package/dist/core/functions/define/system.js +0 -12
  236. package/dist/core/slot/deps.d.ts +0 -15
  237. package/dist/core/slot/deps.js +0 -88
  238. package/dist/core/slot/derived.d.ts +0 -32
  239. package/dist/core/slot/derived.js +0 -115
  240. package/dist/core/slot/platform-session-fields.d.ts +0 -38
  241. package/dist/core/slot/platform-session-fields.js +0 -48
  242. package/dist/core/slot/sf-schema.d.ts +0 -23
  243. package/dist/core/slot/sf-schema.js +0 -125
  244. package/dist/core/slot/sf-validate.d.ts +0 -14
  245. package/dist/core/slot/sf-validate.js +0 -132
  246. package/dist/core/slot/snapshot.d.ts +0 -18
  247. package/dist/core/slot/snapshot.js +0 -138
  248. package/dist/core/slot/write.d.ts +0 -41
  249. package/dist/core/slot/write.js +0 -319
  250. package/dist/core/stage/builders.d.ts +0 -36
  251. package/dist/core/stage/builders.js +0 -28
  252. package/dist/core/stage/condition.d.ts +0 -17
  253. package/dist/core/stage/condition.js +0 -198
  254. package/dist/core/stage/drive.d.ts +0 -43
  255. package/dist/core/stage/drive.js +0 -77
  256. package/dist/core/stage/finish-when.d.ts +0 -20
  257. package/dist/core/stage/finish-when.js +0 -82
  258. package/dist/core/stage/flatten.d.ts +0 -27
  259. package/dist/core/stage/flatten.js +0 -464
  260. package/dist/core/stage/index.d.ts +0 -11
  261. package/dist/core/stage/index.js +0 -10
  262. package/dist/core/stage/simulate.d.ts +0 -24
  263. package/dist/core/stage/simulate.js +0 -33
  264. package/dist/core/stage/transfer-fields.d.ts +0 -14
  265. package/dist/core/stage/transfer-fields.js +0 -88
  266. package/dist/core/stage/types.d.ts +0 -177
  267. package/dist/core/stage/types.js +0 -2
  268. package/dist/core/stage/validate.d.ts +0 -11
  269. package/dist/core/stage/validate.js +0 -226
  270. package/dist/core/stage/walk.d.ts +0 -34
  271. package/dist/core/stage/walk.js +0 -96
  272. package/dist/fn-context/rpc/integration/list-bindings.d.ts +0 -21
  273. package/dist/fn-context/system-args.d.ts +0 -6
  274. package/dist/fn-context/system-args.js +0 -14
@@ -0,0 +1,102 @@
1
+ import { pathToFileURL } from 'node:url';
2
+ import { CronExpressionParser } from 'cron-parser';
3
+ import { SCHEDULE_FUNCTION_PREFIX, SCHEDULES_MODULE, scheduleFunctionName, } from '../core/functions/schedules.js';
4
+ import { compileScheduleModuleCode } from './compile/function-code.js';
5
+ import { companyImportGraphHref } from './company-import-graph.js';
6
+ import { findTsModule } from './paths.js';
7
+ /** A job name: an identifier, so `schedule.<name>` stays one plain function name. */
8
+ const SCHEDULE_NAME = /^[A-Za-z][A-Za-z0-9_]{0,63}$/;
9
+ function isPlainObject(value) {
10
+ return value != null && typeof value === 'object' && !Array.isArray(value);
11
+ }
12
+ /** Whether `timezone` is an IANA name this runtime knows. */
13
+ function knownTimezone(timezone) {
14
+ try {
15
+ new Intl.DateTimeFormat('en-US', { timeZone: timezone });
16
+ return true;
17
+ }
18
+ catch {
19
+ return false;
20
+ }
21
+ }
22
+ /**
23
+ * Why one job's `cron` / `timezone` cannot run, or `null`. The cron is read by the same parser the
24
+ * worker's job scheduler uses (BullMQ's cron-parser); five fields only, so nothing runs every second.
25
+ */
26
+ export function scheduleTimingIssue(cron, timezone) {
27
+ if (typeof timezone !== 'string' || !knownTimezone(timezone)) {
28
+ return `timezone ${JSON.stringify(timezone)} is not an IANA timezone (e.g. 'UTC', 'America/Phoenix')`;
29
+ }
30
+ if (typeof cron !== 'string' || cron.trim().split(/\s+/).length !== 5) {
31
+ return `cron ${JSON.stringify(cron)} must have five fields: minute hour day-of-month month day-of-week (e.g. '0 2 * * *')`;
32
+ }
33
+ try {
34
+ CronExpressionParser.parse(cron.trim(), { tz: timezone }).next();
35
+ }
36
+ catch (error) {
37
+ return `cron ${JSON.stringify(cron)} is not valid: ${error instanceof Error ? error.message : String(error)}`;
38
+ }
39
+ return null;
40
+ }
41
+ /** Read a `schedules` export: every job named, timed and runnable, else one error listing what is wrong. */
42
+ export function parseSchedules(value, where) {
43
+ if (!isPlainObject(value)) {
44
+ throw new Error(`${where}: export const schedules = defineSchedules({ name: { cron, timezone, run } })`);
45
+ }
46
+ const issues = [];
47
+ for (const [name, entry] of Object.entries(value)) {
48
+ if (!SCHEDULE_NAME.test(name)) {
49
+ issues.push(`'${name}': a job name is letters, digits and _ starting with a letter (at most 64)`);
50
+ continue;
51
+ }
52
+ if (!isPlainObject(entry)) {
53
+ issues.push(`'${name}': expected { cron, timezone, run }`);
54
+ continue;
55
+ }
56
+ if (typeof entry.run !== 'function')
57
+ issues.push(`'${name}': run must be an async function (ctx) => { … }`);
58
+ const timing = scheduleTimingIssue(entry.cron, entry.timezone);
59
+ if (timing)
60
+ issues.push(`'${name}': ${timing}`);
61
+ }
62
+ if (issues.length > 0)
63
+ throw new Error(`${where}: ${issues.join('; ')} (25 §6.4)`);
64
+ return value;
65
+ }
66
+ async function importSchedules(modulePath, where) {
67
+ const mod = (await import(companyImportGraphHref(pathToFileURL(modulePath).href)));
68
+ const fromDefault = isPlainObject(mod.default) && Object.hasOwn(mod.default, 'schedules') ? mod.default.schedules : mod.default;
69
+ return parseSchedules(mod.schedules ?? fromDefault, where);
70
+ }
71
+ /** Load and check `<dir>/schedules.ts`; `where` names it in errors (`schedules.ts`, `sequences/pi/schedules.ts`). */
72
+ export async function loadSchedules(dir, where) {
73
+ const modulePath = findTsModule(dir, SCHEDULES_MODULE);
74
+ if (!modulePath)
75
+ return null;
76
+ const schedules = await importSchedules(modulePath, where);
77
+ const functions = {};
78
+ const manifest = {};
79
+ for (const [name, { cron, timezone, run }] of Object.entries(schedules)) {
80
+ functions[scheduleFunctionName(name)] = { kind: 'noCase', main: run };
81
+ manifest[name] = { cron: cron.trim(), timezone };
82
+ }
83
+ return { path: modulePath, functions, manifest };
84
+ }
85
+ /** The build's registry entries of the jobs: `schedule.<name>` (`code` left out on the serve overlay). */
86
+ export async function scheduleRegistry(loaded, includeCode) {
87
+ const entries = await Promise.all(Object.keys(loaded.manifest).map(async (name) => [
88
+ scheduleFunctionName(name),
89
+ includeCode
90
+ ? { kind: 'noCase', code: await compileScheduleModuleCode(loaded.path, name) }
91
+ : { kind: 'noCase' },
92
+ ]));
93
+ return Object.fromEntries(entries);
94
+ }
95
+ /** Authored functions must leave `schedule.*` to `schedules.ts`. */
96
+ export function assertNoScheduleNames(names, where) {
97
+ const taken = names.filter((name) => name.startsWith(SCHEDULE_FUNCTION_PREFIX));
98
+ if (taken.length > 0) {
99
+ throw new Error(`${where} must not define ${taken.map((n) => `'${n}'`).join(', ')}: ${SCHEDULE_FUNCTION_PREFIX}* names are the jobs of ${SCHEDULES_MODULE}.ts`);
100
+ }
101
+ }
102
+ //# sourceMappingURL=schedules.js.map
@@ -0,0 +1,4 @@
1
+ import type { ValidationIssue } from '../core/slot/types.js';
2
+ /** The issues that stop codegen and compile: all but {@link WARNING_SLOT_SCHEMA_CODES}. */
3
+ export declare function fatalSlotSchemaIssues(issues: ValidationIssue[]): ValidationIssue[];
4
+ //# sourceMappingURL=slot-schema-validation.d.ts.map
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Slot schema issues that only warn. Every other issue fails codegen and compile: a new issue code
3
+ * blocks the build unless it is listed here on purpose. None warns today.
4
+ */
5
+ const WARNING_SLOT_SCHEMA_CODES = new Set([]);
6
+ /** The issues that stop codegen and compile: all but {@link WARNING_SLOT_SCHEMA_CODES}. */
7
+ export function fatalSlotSchemaIssues(issues) {
8
+ return issues.filter((issue) => !WARNING_SLOT_SCHEMA_CODES.has(issue.code));
9
+ }
10
+ //# sourceMappingURL=slot-schema-validation.js.map
@@ -0,0 +1,8 @@
1
+ /**
2
+ * The repository's type check, as `pnpm typecheck` runs it locally: `type:gen`, then `tsc --noEmit`
3
+ * with the repo's own `tsconfig.json`. With no sequence it writes only the root `__gen` (the local
4
+ * `type:gen` needs a sequence). The compile runs it itself, so a type error blocks a release in every
5
+ * environment; the platform never calls the repo's `typecheck` script.
6
+ */
7
+ export declare function typecheckRepo(repoRoot: string, onLog?: (text: string) => void): Promise<void>;
8
+ //# sourceMappingURL=typecheck.d.ts.map
@@ -0,0 +1,105 @@
1
+ import { spawn } from 'node:child_process';
2
+ import { existsSync, readFileSync, realpathSync } from 'node:fs';
3
+ import { createRequire } from 'node:module';
4
+ import path from 'node:path';
5
+ import { generateAll, generateCompany, listSequenceIds } from './codegen/generate.js';
6
+ import { RUNTIME_PACKAGE, isCompanyApiFile } from './company-imports.js';
7
+ /**
8
+ * The TypeScript this runtime pins: the check never depends on whether, or which, `typescript` the repo
9
+ * lists. The types it reads (`@types/node`) are the repo's own devDependencies, which a release installs too.
10
+ */
11
+ function pinnedTypescript() {
12
+ const require = createRequire(import.meta.url);
13
+ const pkgPath = require.resolve('typescript/package.json');
14
+ const pkg = JSON.parse(readFileSync(pkgPath, 'utf8'));
15
+ const bin = typeof pkg.bin === 'string' ? pkg.bin : pkg.bin.tsc;
16
+ return { version: pkg.version, tsc: path.join(path.dirname(pkgPath), bin) };
17
+ }
18
+ function runTsc(tsc, args, cwd) {
19
+ return new Promise((resolve, reject) => {
20
+ const child = spawn(process.execPath, [tsc, ...args], { cwd, stdio: ['ignore', 'pipe', 'pipe'] });
21
+ let output = '';
22
+ child.stdout.setEncoding('utf8');
23
+ child.stderr.setEncoding('utf8');
24
+ child.stdout.on('data', (chunk) => {
25
+ output += chunk;
26
+ });
27
+ child.stderr.on('data', (chunk) => {
28
+ output += chunk;
29
+ });
30
+ child.once('error', reject);
31
+ child.once('close', (status) => resolve({ status, output }));
32
+ });
33
+ }
34
+ /** Whether a `paths` key (`@scope/*`, `*`, an exact name) can match an import of `@superpanel-sdk/…`. */
35
+ function mapsSdkImports(key) {
36
+ const star = key.indexOf('*');
37
+ if (star === -1)
38
+ return key.startsWith('@superpanel-sdk/');
39
+ const prefix = key.slice(0, star);
40
+ return '@superpanel-sdk/'.startsWith(prefix) || prefix.startsWith('@superpanel-sdk/');
41
+ }
42
+ /**
43
+ * Why the repository's tsconfig would let its types see more than the company API (09-runtime-compat §6):
44
+ * `customConditions` resolve the platform's entries, and a `paths` entry can point a runtime import at
45
+ * any file. The one mapping it may have is `@superpanel-sdk/runtime` to a runtime's company API (the
46
+ * runtime's own fixtures map it to its source). Null when the config does neither.
47
+ */
48
+ async function tsconfigImportIssue(tsc, root) {
49
+ // The effective config, `extends` applied. A config tsc cannot read fails the type check itself.
50
+ const { status, output } = await runTsc(tsc, ['-p', path.join(root, 'tsconfig.json'), '--showConfig'], root);
51
+ if (status !== 0)
52
+ return null;
53
+ let options;
54
+ try {
55
+ options = JSON.parse(output).compilerOptions ?? {};
56
+ }
57
+ catch {
58
+ return null;
59
+ }
60
+ if (options.customConditions && options.customConditions.length > 0) {
61
+ return `customConditions (${options.customConditions.join(', ')}) can change how ${RUNTIME_PACKAGE} resolves; company code gets it as it resolves by default`;
62
+ }
63
+ const base = options.baseUrl ? path.resolve(root, options.baseUrl) : root;
64
+ for (const [key, targets] of Object.entries(options.paths ?? {})) {
65
+ if (!mapsSdkImports(key))
66
+ continue;
67
+ if (key === RUNTIME_PACKAGE && targets.every((target) => isCompanyApiFile(path.resolve(base, target))))
68
+ continue;
69
+ return `paths maps '${key}': company code imports ${RUNTIME_PACKAGE} as the package resolves it`;
70
+ }
71
+ return null;
72
+ }
73
+ /**
74
+ * The repository's type check, as `pnpm typecheck` runs it locally: `type:gen`, then `tsc --noEmit`
75
+ * with the repo's own `tsconfig.json`. With no sequence it writes only the root `__gen` (the local
76
+ * `type:gen` needs a sequence). The compile runs it itself, so a type error blocks a release in every
77
+ * environment; the platform never calls the repo's `typecheck` script.
78
+ */
79
+ export async function typecheckRepo(repoRoot, onLog) {
80
+ const tsconfig = path.join(repoRoot, 'tsconfig.json');
81
+ if (!existsSync(tsconfig)) {
82
+ throw new Error('tsconfig.json is required: the compile type-checks the repository with it');
83
+ }
84
+ // type:gen first. A repository with no sequence still releases its company code (22 §11): only the
85
+ // root __gen is written then, which its root code's `ctx.api.db` is typed by.
86
+ if (listSequenceIds(repoRoot).length > 0)
87
+ await generateAll(repoRoot);
88
+ else
89
+ await generateCompany(repoRoot);
90
+ const { version, tsc } = pinnedTypescript();
91
+ onLog?.(`Type checking with TypeScript ${version}...`);
92
+ // tsc names files relative to its working directory, which is the real path (macOS's /var is a link):
93
+ // run it there, so the output names `sequences/…` as the repository has them.
94
+ const root = realpathSync(repoRoot);
95
+ const configIssue = await tsconfigImportIssue(tsc, root);
96
+ if (configIssue)
97
+ throw new Error(`Type check failed: tsconfig.json ${configIssue} (AGENTS.md, "Imports")`);
98
+ // Plain output whatever the terminal: the compile log is text.
99
+ const { status, output } = await runTsc(tsc, ['-p', path.join(root, 'tsconfig.json'), '--noEmit', '--pretty', 'false'], root);
100
+ if (status !== 0) {
101
+ throw new Error(`Type check failed (tsc --noEmit):\n${output.trim()}`);
102
+ }
103
+ onLog?.('Type check passed');
104
+ }
105
+ //# sourceMappingURL=typecheck.js.map
@@ -1,36 +1,108 @@
1
- import type { CaseContextViewRegistryEntry, FunctionRegistry } from '../core/functions/types.js';
2
- import type { CompanySchema, EffectiveSchema } from '../core/slot/schema.js';
1
+ import type { CaseOrchestratorManifest } from '../core/case-orchestrator/types.js';
2
+ import type { ScheduleManifest } from '../core/functions/schedules.js';
3
+ import type { FunctionRegistry } from '../core/functions/types.js';
4
+ import type { OfficeHours } from '../core/office-hours/index.js';
5
+ import type { CompiledExperiments, CompiledVariables } from '../core/sequence/index.js';
3
6
  import type { CompiledSlotSchema } from '../core/slot/types.js';
4
- import type { CompiledAgenda } from '../core/stage/types.js';
5
7
  export type RuntimePackageSource = 'local-file' | 'npm';
6
8
  /**
7
- * Compiled sequence artifact (Manual §9 subset; grows over time).
8
- * Omitted for now: paramsDefaults, schedulers, caseManual.
9
+ * Deterministic compiled sequence artifact (22 §4.1; grows over time).
10
+ * Omitted for now: caseManual.
9
11
  *
10
12
  * Published builds include per-fn `code`. Local serve overlay uses the same
11
13
  * type but omits `code` — functions run on the laptop via WebSocket.
14
+ * Compilation time belongs to the database row's `createdAt`, never this artifact.
15
+ *
16
+ * Contract: the company repo's own runtime writes this, and the platform engine (always the
17
+ * newest runtime) reads it, for as long as that runtime version is supported.
18
+ *
19
+ * From launch on (docs/impl/09-runtime-compat.md), grow it only: never rename or remove a field,
20
+ * and give every new field a default the engine applies when an older build lacks it. A breaking
21
+ * change needs a new major runtime plus an announced end-of-support date for the old one. Before
22
+ * launch there are no older builds to read, so fields are added as required, with no defaults.
12
23
  */
13
24
  export type SequenceBuild = {
25
+ /** The directory name under `sequences/`: the sequence's identity (22 §10.2). */
14
26
  sequenceId: string;
15
- sha: string;
27
+ /** What people see: `defineSequence({ meta: { label } })`, else the directory name. Synced on release. */
28
+ label: string;
29
+ /** Version of the runtime whose compiler produced this build (the company repo's runtime). */
16
30
  engineVersion: string;
17
31
  /** Installed @superpanel-sdk/runtime version resolved from the company repo. */
18
- runtimeVersion?: string;
19
- /** Dependency source declared by the company repo. Optional for legacy persisted builds. */
20
- runtimeSource?: RuntimePackageSource;
21
- compiledAt: string;
22
- companySchemaSnapshot: CompanySchema;
23
- /** SlotEngine runtime schema (tables + derivedOrder / reverseDeps). */
24
- schema: CompiledSlotSchema;
25
- effectiveSchema: EffectiveSchema;
32
+ runtimeVersion: string;
33
+ /** Dependency source declared by the company repo. */
34
+ runtimeSource: RuntimePackageSource;
35
+ /** The company table each run is about (`defineSequence({ subject })`, 14-sequence-instance §4.5). */
36
+ subject: string;
37
+ /** Run variables from `variables.ts` (14 §4.4); `{}` without the file. */
38
+ variables: CompiledVariables;
39
+ /** Experiments from `variables.ts`: how runs that do not set a variable are split. */
40
+ experiments: CompiledExperiments;
26
41
  /** Per-function registry. `code` omitted on local overlay. */
27
42
  functions: FunctionRegistry;
43
+ /** Platform event handlers keyed by event name; kind fixed by the event table. */
44
+ events: FunctionRegistry;
45
+ /**
46
+ * Sequence office hours from `sequences/<id>/office-hours.ts`. `null` when the sequence has no
47
+ * file (always open).
48
+ */
49
+ officeHours: OfficeHours | null;
50
+ /**
51
+ * The Case Orchestrator entry point (`orchestrator` in `functions`). `null` / absent when the
52
+ * sequence has no orchestrator.ts (older builds lack the field).
53
+ */
54
+ orchestrator?: CaseOrchestratorManifest | null;
55
+ /**
56
+ * The conversation's page script (`sequences/<id>/context.page.ts`, 15 §10.2), bundled: evaluates to
57
+ * the entry that renders the page or runs one of its actions. Always carries its code, the serve
58
+ * overlay included: the platform runs it next to the database. Every sequence has one. `channels`:
59
+ * the channels it has a page function for (17b §9.1).
60
+ */
61
+ contextPage: {
62
+ code: string;
63
+ channels: string[];
64
+ };
65
+ /**
66
+ * The sequence's recurring jobs (`sequences/<id>/schedules.ts`, 25 §6.4), by name; each one's code is
67
+ * `functions['schedule.<name>']`. Absent: none.
68
+ */
69
+ schedules?: ScheduleManifest;
70
+ };
71
+ /**
72
+ * The company build (22-sequence-as-business-unit §4.1): one release compiles the whole repository
73
+ * into it, and one Cloudflare Worker serves all of it. Same contract as {@link SequenceBuild}.
74
+ */
75
+ export type CompanyBuild = {
76
+ /** The company's own code, outside any sequence (§5). */
77
+ company: CompanyPart;
78
+ /** Every sequence's build, keyed by its directory name under `sequences/`. */
79
+ sequences: Record<string, SequenceBuild>;
80
+ };
81
+ /**
82
+ * Company-level functions (`resolve.ts` and `webhook.ts` at the repository root): they run with no
83
+ * sequence. In the company Worker they are named `@company/<name>`; `@` keeps them apart from any
84
+ * sequence's directory.
85
+ */
86
+ export type CompanyPart = {
87
+ /**
88
+ * `companyResolve`, `webhook.received` when the repository has `webhook.ts`, and `schedule.<name>`
89
+ * for each job of `schedules.ts`. `code` omitted on the local serve overlay.
90
+ */
91
+ functions: FunctionRegistry;
92
+ /** The company's recurring jobs (root `schedules.ts`, 25 §6.4), by name. Absent: none. */
93
+ schedules?: ScheduleManifest;
94
+ /**
95
+ * The company schema: what every function, page and the Orchestrator read and write, in every
96
+ * sequence (28 §2: a sequence has no schema of its own, only its `subject`).
97
+ */
98
+ schema: CompiledSlotSchema;
28
99
  /**
29
- * Optional CaseContext projector. `null` when sequence has no view.ts
30
- * (functions receive Slots / identity CaseContext).
100
+ * The runtime the repository installs, which the company Worker runs (every sequence compiles
101
+ * against the same one): known with no sequence at all (22 §11).
31
102
  */
32
- caseContextView: CaseContextViewRegistryEntry | null;
33
- /** Flattened agendas keyed by agenda id. Empty when the sequence has no agendas module. */
34
- agendas: Record<string, CompiledAgenda>;
103
+ runtimeVersion: string;
104
+ runtimeSource: RuntimePackageSource;
35
105
  };
106
+ /** Where company-level functions live, in place of a sequence's directory name. */
107
+ export declare const COMPANY_SCOPE = "@company";
36
108
  //# sourceMappingURL=types.d.ts.map
@@ -1,2 +1,3 @@
1
- export {};
1
+ /** Where company-level functions live, in place of a sequence's directory name. */
2
+ export const COMPANY_SCOPE = '@company';
2
3
  //# sourceMappingURL=types.js.map
@@ -0,0 +1,37 @@
1
+ export type ServeAuthorization = {
2
+ token: string;
3
+ user: {
4
+ id: string;
5
+ email: string;
6
+ };
7
+ companyId: string;
8
+ companyName: string | null;
9
+ };
10
+ export declare function resolveBackendUrl(repoRoot: string, optionUrl?: string): string;
11
+ export declare function loadCachedServeAuthorization(backendUrl: string, file?: string): Promise<ServeAuthorization | null>;
12
+ export declare function cacheServeAuthorization(backendUrl: string, authorization: ServeAuthorization, file?: string): Promise<void>;
13
+ export declare function clearCachedServeAuthorization(backendUrl: string, token: string, file?: string): Promise<void>;
14
+ export declare function removeCachedServeAuthorization(backendUrl: string, file?: string): Promise<boolean>;
15
+ export type ServeAuthorizationStatus = {
16
+ loggedIn: false;
17
+ } | {
18
+ loggedIn: true;
19
+ authorization: ServeAuthorization;
20
+ expiresAt: number;
21
+ expired: boolean;
22
+ };
23
+ export declare function readServeAuthorizationStatus(backendUrl: string, file?: string): Promise<ServeAuthorizationStatus>;
24
+ export type ServeEnvironment = {
25
+ id: string;
26
+ name: string;
27
+ };
28
+ /** The backend rejected the serve token (revoked, re-keyed, or the user lost access): log in again. */
29
+ export declare class ServeAuthorizationRejectedError extends Error {
30
+ constructor(message: string);
31
+ }
32
+ /** Non-prod environments the serve token's company can overlay. */
33
+ export declare function listServeEnvironments(backendUrl: string, token: string): Promise<ServeEnvironment[]>;
34
+ export declare function authorizeServe(backendUrl: string, options?: {
35
+ openBrowser?: boolean;
36
+ }): Promise<ServeAuthorization>;
37
+ //# sourceMappingURL=auth.d.ts.map
@@ -0,0 +1,211 @@
1
+ import { spawn } from 'node:child_process';
2
+ import { chmod, mkdir, readFile, rename, writeFile } from 'node:fs/promises';
3
+ import { homedir } from 'node:os';
4
+ import path from 'node:path';
5
+ import { readCompanyRepoConfig } from '../config.js';
6
+ import { toHttpUrl } from './backend-url.js';
7
+ import { copyToClipboard } from './clipboard.js';
8
+ import { apiUrl, getJson, postJson } from './http.js';
9
+ import { progressIndicator } from './progress.js';
10
+ function env(name) {
11
+ const value = process.env[name];
12
+ return value && value.length > 0 ? value : undefined;
13
+ }
14
+ export function resolveBackendUrl(repoRoot, optionUrl) {
15
+ const resolved = optionUrl?.trim() || env('SUPERPANEL_SDK_BACKEND_URL') || readCompanyRepoConfig(repoRoot)?.backendUrl || undefined;
16
+ if (!resolved) {
17
+ throw new Error('No backend URL configured. Pass --url <backend-url>, set SUPERPANEL_SDK_BACKEND_URL, or configure .superpanel/config.json.');
18
+ }
19
+ return resolved;
20
+ }
21
+ function backendCacheKey(backendUrl) {
22
+ const url = toHttpUrl(backendUrl);
23
+ url.pathname = url.pathname.replace(/\/$/, '');
24
+ url.search = '';
25
+ url.hash = '';
26
+ return url.toString();
27
+ }
28
+ function authorizationCachePath() {
29
+ return path.join(homedir(), '.superpanel', 'credentials.json');
30
+ }
31
+ function tokenExpiresAt(token) {
32
+ const body = token.split('.')[1];
33
+ if (!body)
34
+ return null;
35
+ try {
36
+ const claims = JSON.parse(Buffer.from(body, 'base64url').toString('utf8'));
37
+ return claims.purpose === 'serve' && typeof claims.exp === 'number' ? claims.exp * 1000 : null;
38
+ }
39
+ catch {
40
+ return null;
41
+ }
42
+ }
43
+ function isServeAuthorization(value) {
44
+ if (!value || typeof value !== 'object')
45
+ return false;
46
+ const record = value;
47
+ const user = record.user;
48
+ return (typeof record.token === 'string' &&
49
+ typeof record.companyId === 'string' &&
50
+ (record.companyName === null || typeof record.companyName === 'string') &&
51
+ Boolean(user) &&
52
+ typeof user === 'object' &&
53
+ typeof user.id === 'string' &&
54
+ typeof user.email === 'string');
55
+ }
56
+ async function readAuthorizationCache(file = authorizationCachePath()) {
57
+ try {
58
+ const raw = JSON.parse(await readFile(file, 'utf8'));
59
+ if (raw.version !== 1 || !raw.credentials || typeof raw.credentials !== 'object') {
60
+ return { version: 1, credentials: {} };
61
+ }
62
+ const credentials = {};
63
+ for (const [key, value] of Object.entries(raw.credentials)) {
64
+ if (isServeAuthorization(value))
65
+ credentials[key] = value;
66
+ }
67
+ return { version: 1, credentials };
68
+ }
69
+ catch (error) {
70
+ const code = error && typeof error === 'object' && 'code' in error ? error.code : undefined;
71
+ if (code === 'ENOENT' || error instanceof SyntaxError)
72
+ return { version: 1, credentials: {} };
73
+ throw error;
74
+ }
75
+ }
76
+ async function writeAuthorizationCache(cache, file = authorizationCachePath()) {
77
+ const directory = path.dirname(file);
78
+ await mkdir(directory, { recursive: true, mode: 0o700 });
79
+ const temporary = `${file}.${process.pid}.tmp`;
80
+ await writeFile(temporary, `${JSON.stringify(cache, null, 2)}\n`, { mode: 0o600 });
81
+ await rename(temporary, file);
82
+ await chmod(file, 0o600);
83
+ }
84
+ export async function loadCachedServeAuthorization(backendUrl, file = authorizationCachePath()) {
85
+ const authorization = (await readAuthorizationCache(file)).credentials[backendCacheKey(backendUrl)];
86
+ if (!authorization)
87
+ return null;
88
+ const expiresAt = tokenExpiresAt(authorization.token);
89
+ return expiresAt !== null && expiresAt > Date.now() + 30_000 ? authorization : null;
90
+ }
91
+ export async function cacheServeAuthorization(backendUrl, authorization, file = authorizationCachePath()) {
92
+ const cache = await readAuthorizationCache(file);
93
+ cache.credentials[backendCacheKey(backendUrl)] = authorization;
94
+ await writeAuthorizationCache(cache, file);
95
+ }
96
+ export async function clearCachedServeAuthorization(backendUrl, token, file = authorizationCachePath()) {
97
+ const cache = await readAuthorizationCache(file);
98
+ const key = backendCacheKey(backendUrl);
99
+ if (cache.credentials[key]?.token !== token)
100
+ return;
101
+ delete cache.credentials[key];
102
+ await writeAuthorizationCache(cache, file);
103
+ }
104
+ export async function removeCachedServeAuthorization(backendUrl, file = authorizationCachePath()) {
105
+ const cache = await readAuthorizationCache(file);
106
+ const key = backendCacheKey(backendUrl);
107
+ if (!(key in cache.credentials))
108
+ return false;
109
+ delete cache.credentials[key];
110
+ await writeAuthorizationCache(cache, file);
111
+ return true;
112
+ }
113
+ export async function readServeAuthorizationStatus(backendUrl, file = authorizationCachePath()) {
114
+ const authorization = (await readAuthorizationCache(file)).credentials[backendCacheKey(backendUrl)];
115
+ if (!authorization)
116
+ return { loggedIn: false };
117
+ const expiresAt = tokenExpiresAt(authorization.token);
118
+ if (expiresAt === null)
119
+ return { loggedIn: false };
120
+ return { loggedIn: true, authorization, expiresAt, expired: expiresAt <= Date.now() };
121
+ }
122
+ /** The backend rejected the serve token (revoked, re-keyed, or the user lost access): log in again. */
123
+ export class ServeAuthorizationRejectedError extends Error {
124
+ constructor(message) {
125
+ super(message);
126
+ this.name = 'ServeAuthorizationRejectedError';
127
+ }
128
+ }
129
+ /** Non-prod environments the serve token's company can overlay. */
130
+ export async function listServeEnvironments(backendUrl, token) {
131
+ const { response, payload } = await getJson(apiUrl(backendUrl, 'cli-auth/environments'), token);
132
+ if (response.status === 401) {
133
+ throw new ServeAuthorizationRejectedError(payload.error ?? 'serve authorization rejected');
134
+ }
135
+ if (!response.ok) {
136
+ throw new Error(payload.error ?? `could not list environments (${response.status})`);
137
+ }
138
+ if (!Array.isArray(payload.environments)) {
139
+ throw new Error('malformed response from the backend (missing environments list)');
140
+ }
141
+ return payload.environments;
142
+ }
143
+ function openBrowser(url) {
144
+ const command = process.platform === 'darwin'
145
+ ? { file: 'open', args: [url] }
146
+ : process.platform === 'win32'
147
+ ? { file: 'rundll32', args: ['url.dll,FileProtocolHandler', url] }
148
+ : { file: 'xdg-open', args: [url] };
149
+ const child = spawn(command.file, command.args, { detached: true, stdio: 'ignore' });
150
+ child.once('error', () => undefined);
151
+ child.unref();
152
+ }
153
+ function wait(ms) {
154
+ return new Promise((resolve) => setTimeout(resolve, ms));
155
+ }
156
+ export async function authorizeServe(backendUrl, options = {}) {
157
+ const starting = progressIndicator();
158
+ starting.start('Starting browser authorization…');
159
+ let created;
160
+ try {
161
+ created = await postJson(apiUrl(backendUrl, 'cli-auth/device'), {});
162
+ if (!created.response.ok) {
163
+ throw new Error(created.payload.error ?? `could not start browser authorization (${created.response.status})`);
164
+ }
165
+ }
166
+ catch (error) {
167
+ starting.error('Could not start browser authorization.');
168
+ throw error;
169
+ }
170
+ starting.stop('Browser authorization started.');
171
+ const device = created.payload;
172
+ const progress = progressIndicator();
173
+ if (options.openBrowser === false) {
174
+ try {
175
+ copyToClipboard(device.verificationUrl);
176
+ progress.start(`Authorization URL copied to your clipboard. Paste it into a browser to continue:\n ${device.verificationUrl}`);
177
+ }
178
+ catch (error) {
179
+ progress.start(`Could not copy the authorization URL (${error instanceof Error ? error.message : String(error)}). Open it manually:\n ${device.verificationUrl}`);
180
+ }
181
+ }
182
+ else {
183
+ openBrowser(device.verificationUrl);
184
+ progress.start(`Opening your browser to continue — if it doesn't open within a few seconds, open this URL yourself:\n ${device.verificationUrl}`);
185
+ }
186
+ try {
187
+ const expiresAt = Date.now() + device.expiresIn * 1000;
188
+ let delaySeconds = Math.max(1, device.interval);
189
+ while (Date.now() < expiresAt) {
190
+ await wait(delaySeconds * 1000);
191
+ const polled = await postJson(apiUrl(backendUrl, 'cli-auth/token'), { deviceCode: device.deviceCode });
192
+ if (polled.response.ok && 'token' in polled.payload) {
193
+ progress.stop('Authorized. You can close the browser tab now.');
194
+ return polled.payload;
195
+ }
196
+ if (polled.response.status === 202 || polled.response.status === 429) {
197
+ delaySeconds = Math.max(1, 'retryAfter' in polled.payload ? (polled.payload.retryAfter ?? delaySeconds) : delaySeconds);
198
+ continue;
199
+ }
200
+ if (polled.response.status === 410)
201
+ throw new Error('browser authorization expired');
202
+ throw new Error(polled.payload.error ?? `browser authorization failed (${polled.response.status})`);
203
+ }
204
+ throw new Error('browser authorization expired');
205
+ }
206
+ catch (error) {
207
+ progress.error('Browser authorization failed.');
208
+ throw error;
209
+ }
210
+ }
211
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1,5 @@
1
+ /** Parses `raw` and rewrites its protocol to the ws/wss equivalent (http→ws, https→wss). */
2
+ export declare function toWsUrl(raw: string): URL;
3
+ /** Parses `raw` and rewrites its protocol to the http/https equivalent (ws→http, wss→https). */
4
+ export declare function toHttpUrl(raw: string): URL;
5
+ //# sourceMappingURL=backend-url.d.ts.map
@@ -0,0 +1,25 @@
1
+ /** Parses `raw` and rewrites its protocol to the ws/wss equivalent (http→ws, https→wss). */
2
+ export function toWsUrl(raw) {
3
+ const url = new URL(raw);
4
+ if (url.protocol === 'http:')
5
+ url.protocol = 'ws:';
6
+ else if (url.protocol === 'https:')
7
+ url.protocol = 'wss:';
8
+ else if (url.protocol !== 'ws:' && url.protocol !== 'wss:') {
9
+ throw new Error(`unsupported backend url: ${raw}`);
10
+ }
11
+ return url;
12
+ }
13
+ /** Parses `raw` and rewrites its protocol to the http/https equivalent (ws→http, wss→https). */
14
+ export function toHttpUrl(raw) {
15
+ const url = new URL(raw);
16
+ if (url.protocol === 'ws:')
17
+ url.protocol = 'http:';
18
+ else if (url.protocol === 'wss:')
19
+ url.protocol = 'https:';
20
+ else if (url.protocol !== 'http:' && url.protocol !== 'https:') {
21
+ throw new Error(`unsupported backend url: ${raw}`);
22
+ }
23
+ return url;
24
+ }
25
+ //# sourceMappingURL=backend-url.js.map
@@ -0,0 +1,9 @@
1
+ export type ClipboardCommand = {
2
+ file: string;
3
+ args: string[];
4
+ };
5
+ /** Native clipboard commands, in preference order for the current platform. */
6
+ export declare function clipboardCommands(platform: NodeJS.Platform): ClipboardCommand[];
7
+ /** Copy text without invoking a shell, so an authorization URL is always treated as plain input. */
8
+ export declare function copyToClipboard(text: string, platform?: NodeJS.Platform): void;
9
+ //# sourceMappingURL=clipboard.d.ts.map