@superpanel-sdk/runtime 0.2.3 → 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 (282) 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 +365 -116
  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 -4
  54. package/dist/compute-host/index.js +1 -2
  55. package/dist/compute-host/source-compute-host.d.ts +11 -9
  56. package/dist/compute-host/source-compute-host.js +46 -32
  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 -48
  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 -94
  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 +88 -7
  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 -5
  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 -64
  214. package/dist/builder/merge.d.ts +0 -4
  215. package/dist/builder/merge.js +0 -19
  216. package/dist/compute-host/read-only-cache.d.ts +0 -20
  217. package/dist/compute-host/read-only-cache.js +0 -61
  218. package/dist/core/context/db.d.ts +0 -69
  219. package/dist/core/context/db.js +0 -44
  220. package/dist/core/context/docusign.d.ts +0 -134
  221. package/dist/core/context/docusign.js +0 -108
  222. package/dist/core/context/filevine.d.ts +0 -323
  223. package/dist/core/context/filevine.js +0 -254
  224. package/dist/core/context/http.d.ts +0 -9
  225. package/dist/core/context/http.js +0 -4
  226. package/dist/core/context/hubspot.d.ts +0 -250
  227. package/dist/core/context/hubspot.js +0 -191
  228. package/dist/core/context/twilio.d.ts +0 -50
  229. package/dist/core/context/twilio.js +0 -42
  230. package/dist/core/functions/define/case-context.d.ts +0 -14
  231. package/dist/core/functions/define/case-context.js +0 -15
  232. package/dist/core/functions/define/compute.d.ts +0 -7
  233. package/dist/core/functions/define/compute.js +0 -17
  234. package/dist/core/functions/define/custom.d.ts +0 -4
  235. package/dist/core/functions/define/custom.js +0 -8
  236. package/dist/core/functions/define/system.d.ts +0 -7
  237. package/dist/core/functions/define/system.js +0 -12
  238. package/dist/core/slot/deps.d.ts +0 -15
  239. package/dist/core/slot/deps.js +0 -88
  240. package/dist/core/slot/derived.d.ts +0 -32
  241. package/dist/core/slot/derived.js +0 -115
  242. package/dist/core/slot/platform-session-fields.d.ts +0 -38
  243. package/dist/core/slot/platform-session-fields.js +0 -48
  244. package/dist/core/slot/sf-schema.d.ts +0 -23
  245. package/dist/core/slot/sf-schema.js +0 -125
  246. package/dist/core/slot/sf-validate.d.ts +0 -14
  247. package/dist/core/slot/sf-validate.js +0 -132
  248. package/dist/core/slot/snapshot.d.ts +0 -18
  249. package/dist/core/slot/snapshot.js +0 -138
  250. package/dist/core/slot/write.d.ts +0 -48
  251. package/dist/core/slot/write.js +0 -426
  252. package/dist/core/stage/builders.d.ts +0 -54
  253. package/dist/core/stage/builders.js +0 -31
  254. package/dist/core/stage/condition.d.ts +0 -17
  255. package/dist/core/stage/condition.js +0 -198
  256. package/dist/core/stage/drive.d.ts +0 -43
  257. package/dist/core/stage/drive.js +0 -78
  258. package/dist/core/stage/finish-when.d.ts +0 -20
  259. package/dist/core/stage/finish-when.js +0 -82
  260. package/dist/core/stage/flatten.d.ts +0 -27
  261. package/dist/core/stage/flatten.js +0 -466
  262. package/dist/core/stage/index.d.ts +0 -15
  263. package/dist/core/stage/index.js +0 -13
  264. package/dist/core/stage/interrupts.d.ts +0 -28
  265. package/dist/core/stage/interrupts.js +0 -120
  266. package/dist/core/stage/ivr-fields.d.ts +0 -9
  267. package/dist/core/stage/ivr-fields.js +0 -75
  268. package/dist/core/stage/simulate.d.ts +0 -24
  269. package/dist/core/stage/simulate.js +0 -33
  270. package/dist/core/stage/transfer-fields.d.ts +0 -19
  271. package/dist/core/stage/transfer-fields.js +0 -129
  272. package/dist/core/stage/transfer-spec.d.ts +0 -48
  273. package/dist/core/stage/transfer-spec.js +0 -113
  274. package/dist/core/stage/types.d.ts +0 -208
  275. package/dist/core/stage/types.js +0 -2
  276. package/dist/core/stage/validate.d.ts +0 -11
  277. package/dist/core/stage/validate.js +0 -330
  278. package/dist/core/stage/walk.d.ts +0 -39
  279. package/dist/core/stage/walk.js +0 -119
  280. package/dist/fn-context/rpc/integration/list-bindings.d.ts +0 -21
  281. package/dist/fn-context/system-args.d.ts +0 -6
  282. package/dist/fn-context/system-args.js +0 -14
@@ -1,28 +1,22 @@
1
1
  import { mkdirSync, readFileSync, writeFileSync } from 'node:fs';
2
2
  import path from 'node:path';
3
3
  import { fileURLToPath } from 'node:url';
4
- import { resolveCaseContextViewFn } from '../../core/functions/define/case-context.js';
5
- import { resolveFuncName } from '../../core/functions/func-ref.js';
6
4
  import { compileSlotSchema } from '../../core/slot/compile-schema.js';
5
+ import { compileCompanyMetadata, subjectTableIssues } from '../../core/slot/company-metadata.js';
6
+ import { ensureCompanyStub, ensureStub } from '../codegen/generate.js';
7
7
  import { withCompanyImportGraph } from '../company-import-graph.js';
8
- import { listSequenceIds, loadCompanySchema, loadSequenceAgendas, loadSequenceCaseContextView, loadSequenceFunctions, loadSequenceSlots, } from '../load.js';
9
- import { findTsModule, resolveTsModule } from '../paths.js';
10
- import { compileSequenceAgendas, fatalAgendaIssues } from './compile-agenda.js';
11
- import { toCaseContextViewRegistry, toFunctionRegistry } from './registry.js';
12
- const FATAL_CODES = new Set([
13
- 'unknown-table',
14
- 'unknown-field',
15
- 'missing-compute-fn',
16
- 'cyclic-dependency',
17
- 'multi-derived-forbidden',
18
- 'session-derived-forbidden',
19
- 'unknown-ref-table',
20
- 'invalid-id-field',
21
- 'missing-id-field',
22
- 'id-cannot-ref',
23
- 'reserved-table-name',
24
- ]);
25
- /** SequenceBuild / SequenceConfigBuild cache key. Bump when compiled `code` shape changes. */
8
+ import { ORCHESTRATOR_CONTACTS_FUNCTION, ORCHESTRATOR_FUNCTION, } from '../../core/case-orchestrator/types.js';
9
+ import { COMPANY_RESOLVE_FUNCTION, RESOLVE_FUNCTION, RESOLVE_MODULE } from '../../core/party/types.js';
10
+ import { compileVariables } from '../../core/sequence/index.js';
11
+ import { WEBHOOK_RECEIVED_FUNCTION } from '../../core/functions/events.js';
12
+ import { isPlatformName, listSequenceIds, loadCompanySchema, loadCompanyWebhook, WEBHOOK_MODULE, loadOfficeHours, loadSequenceCaseOrchestrator, loadSequenceEvents, loadSequenceFunctions, loadSequenceDefinition, loadCompanyResolver, loadSequenceResolver, loadSequenceVariables, loadPageChannels, loadSessionSchema, assertNoSlotsModule, assertNoChannelsModule, } from '../load.js';
13
+ import { findTsModule, requireCompanyResolveModule, requireResolveModule, resolveTsModule } from '../paths.js';
14
+ import { fatalSlotSchemaIssues } from '../slot-schema-validation.js';
15
+ import { typecheckRepo } from '../typecheck.js';
16
+ import { compileExportModuleCode, compilePageModuleCode } from './function-code.js';
17
+ import { assertNoScheduleNames, loadSchedules, scheduleRegistry } from '../schedules.js';
18
+ import { toEventRegistry, toFunctionRegistry } from './registry.js';
19
+ /** SequenceBuild cache key. Bump when compiled `code` shape changes. */
26
20
  export function runtimePackageVersion() {
27
21
  const pkgPath = path.join(path.dirname(fileURLToPath(import.meta.url)), '..', '..', '..', 'package.json');
28
22
  const pkg = JSON.parse(readFileSync(pkgPath, 'utf8'));
@@ -40,101 +34,309 @@ export function runtimePackageSource(repoRoot) {
40
34
  return 'npm';
41
35
  }
42
36
  }
43
- /** Deep-clone company schema with derived computeFn normalized to string names. */
44
- export function snapshotCompanySchema(company, functions) {
45
- const tables = {};
46
- for (const [tableName, table] of Object.entries(company)) {
47
- const fields = {};
48
- for (const [fieldName, field] of Object.entries(table.fields)) {
49
- if (field.derived) {
50
- fields[fieldName] = {
51
- ...field,
52
- computeFn: resolveFuncName(field.computeFn, functions),
53
- };
54
- }
55
- else {
56
- fields[fieldName] = { ...field };
57
- }
58
- }
59
- tables[tableName] = { ...table, fields };
60
- }
61
- return tables;
62
- }
63
37
  export function sequenceBuildPath(repoRoot, sequenceId) {
64
38
  return path.join(repoRoot, 'sequences', sequenceId, 'build', 'sequence-build.json');
65
39
  }
40
+ async function loadCompanySchemas(repoRoot) {
41
+ const schemaPath = resolveTsModule(repoRoot, 'schema', `No company schema found. Expected schema.ts or schema/index.ts under ${repoRoot}`);
42
+ return { company: await loadCompanySchema(schemaPath), session: await loadSessionSchema(repoRoot) };
43
+ }
44
+ function compileMetadata({ company, session }) {
45
+ const result = compileCompanyMetadata(company, session);
46
+ if (!result.validation.ok || !result.metadata) {
47
+ throw new Error(result.validation.ok
48
+ ? 'invalid company metadata'
49
+ : result.validation.issues.map((issue) => issue.message).join('; '));
50
+ }
51
+ return result.metadata;
52
+ }
53
+ export async function compileCompanyMetadataFromRepo(repoRoot) {
54
+ return withCompanyImportGraph(repoRoot, async () => compileMetadata(await loadCompanySchemas(repoRoot)));
55
+ }
66
56
  export async function compileSequence(repoRoot, sequenceId, options = {}) {
67
- return withCompanyImportGraph(repoRoot, () => compileSequenceInGraph(repoRoot, sequenceId, options));
57
+ return withCompanyImportGraph(repoRoot, async () => {
58
+ const result = await compileSequenceInGraph(repoRoot, sequenceId, options);
59
+ const { schemas, ...build } = result;
60
+ return { ...build, companyMetadata: compileMetadata(schemas) };
61
+ });
62
+ }
63
+ export async function compileSequenceBuild(repoRoot, sequenceId, options = {}) {
64
+ return withCompanyImportGraph(repoRoot, async () => {
65
+ const { schemas: _, ...result } = await compileSequenceInGraph(repoRoot, sequenceId, options);
66
+ return result;
67
+ });
68
68
  }
69
69
  async function compileSequenceInGraph(repoRoot, sequenceId, options) {
70
- const schemaPath = resolveTsModule(repoRoot, 'schema', `No company schema found. Expected schema.ts or schema/index.ts under ${repoRoot}`);
70
+ // The directory name is the sequence's identity in every environment (22 §10.2).
71
+ if (!isPlatformName(sequenceId)) {
72
+ throw new Error(`sequences/${sequenceId}: a sequence directory is named with letters, numbers and hyphens (at most 40)`);
73
+ }
71
74
  const sequenceDir = path.join(repoRoot, 'sequences', sequenceId);
72
- const slotsPath = resolveTsModule(sequenceDir, 'slots', `No sequence slots found. Expected sequences/${sequenceId}/slots.ts or sequences/${sequenceId}/slots/index.ts`);
75
+ assertNoSlotsModule(sequenceDir, sequenceId);
73
76
  const functionsPath = findTsModule(sequenceDir, 'functions');
74
77
  if (!functionsPath) {
75
78
  throw new Error(`No sequence functions found. Expected sequences/${sequenceId}/functions.ts or sequences/${sequenceId}/functions/index.ts`);
76
79
  }
77
- const company = await loadCompanySchema(schemaPath);
78
- const slots = await loadSequenceSlots(slotsPath);
79
- const functions = await loadSequenceFunctions(functionsPath);
80
- const viewPath = findTsModule(sequenceDir, 'view');
81
- const caseContextView = viewPath ? await loadSequenceCaseContextView(viewPath) : undefined;
82
- if (viewPath && !resolveCaseContextViewFn(caseContextView)) {
83
- throw new Error(`sequences/${sequenceId}/view.ts did not export a caseContextView function`);
84
- }
85
- const { schema, validation } = compileSlotSchema(company, slots, {
86
- functions,
87
- computeFns: new Set(Object.keys(functions)),
88
- });
80
+ // `__gen/` is gitignored in company repos, so a fresh checkout (server-side compile from a git
81
+ // archive) has no `__gen/index.ts` — which functions.ts / events.ts import at runtime. Write the
82
+ // missing generated files first; existing ones are left untouched.
83
+ ensureStub(repoRoot, sequenceId);
84
+ const schemas = await loadCompanySchemas(repoRoot);
85
+ const { company, session } = schemas;
86
+ const authored = await loadSequenceFunctions(functionsPath);
87
+ // The conversation follows the page (17b): what to do next is worked out from it, not from an agenda.
88
+ for (const removed of ['agenda', 'agendas']) {
89
+ if (findTsModule(sequenceDir, removed)) {
90
+ throw new Error(`sequences/${sequenceId}/${removed}.ts is no longer supported: the conversation follows the page — write one page function per channel in context.page.ts`);
91
+ }
92
+ }
93
+ const caseOrchestratorPath = findTsModule(sequenceDir, 'orchestrator');
94
+ for (const reserved of [ORCHESTRATOR_FUNCTION, ORCHESTRATOR_CONTACTS_FUNCTION]) {
95
+ if (Object.hasOwn(authored, reserved)) {
96
+ throw new Error(`functions must not define '${reserved}'; it is the Case Orchestrator's, from orchestrator.ts`);
97
+ }
98
+ }
99
+ for (const reserved of [RESOLVE_FUNCTION, COMPANY_RESOLVE_FUNCTION]) {
100
+ if (Object.hasOwn(authored, reserved)) {
101
+ throw new Error(`functions must not define '${reserved}'; it is a resolver in ${RESOLVE_MODULE}.ts`);
102
+ }
103
+ }
104
+ assertNoScheduleNames(Object.keys(authored), `sequences/${sequenceId}/functions`);
105
+ // The sequence's recurring jobs (25 §6.4): `schedule.<name>` functions, timed by `schedules`.
106
+ const schedules = await loadSchedules(sequenceDir, `sequences/${sequenceId}/schedules.ts`);
107
+ if (findTsModule(sequenceDir, 'party')) {
108
+ throw new Error(`sequences/${sequenceId}/party.ts is no longer supported: export ${RESOLVE_FUNCTION} from sequences/${sequenceId}/${RESOLVE_MODULE}.ts`);
109
+ }
110
+ const resolvePath = requireResolveModule(sequenceDir, sequenceId);
111
+ const resolver = await loadSequenceResolver(resolvePath);
112
+ const caseOrchestratorFn = caseOrchestratorPath ? await loadSequenceCaseOrchestrator(caseOrchestratorPath) : null;
113
+ const functions = {
114
+ ...authored,
115
+ [RESOLVE_FUNCTION]: resolver,
116
+ ...(caseOrchestratorFn
117
+ ? {
118
+ [ORCHESTRATOR_FUNCTION]: { kind: 'orchestrator', main: caseOrchestratorFn.orchestrator },
119
+ [ORCHESTRATOR_CONTACTS_FUNCTION]: { kind: 'orchestrator', main: caseOrchestratorFn.contacts },
120
+ }
121
+ : {}),
122
+ };
123
+ const eventsPath = findTsModule(sequenceDir, 'events');
124
+ const events = eventsPath ? await loadSequenceEvents(eventsPath) : {};
125
+ const collisions = Object.keys(functions).filter((name) => Object.hasOwn(events, name));
126
+ if (collisions.length > 0) {
127
+ throw new Error(`functions and events must not share names: ${collisions.join(', ')}`);
128
+ }
129
+ // The Orchestrator reads with `ctx.api.db` (15 §10.16): no view.
130
+ if (findTsModule(sequenceDir, 'view')) {
131
+ throw new Error(`sequences/${sequenceId}/view.ts is no longer supported: the Orchestrator reads with ctx.api.db, and names who a Run may contact with contacts in orchestrator.ts`);
132
+ }
133
+ // The conversation's page is the page script, always (15 §10.2): no default page.
134
+ const pagePath = findTsModule(sequenceDir, 'context.page');
135
+ if (!pagePath) {
136
+ throw new Error(`sequences/${sequenceId}: context.page.ts is required (the conversation's page, 15 §10.2)`);
137
+ }
138
+ // The FAQ is the page's (24 §7): `faq` in definePage, called when the conversation starts.
139
+ if (findTsModule(sequenceDir, 'knowledge')) {
140
+ throw new Error(`sequences/${sequenceId}/knowledge.ts is no longer supported: return the FAQ from definePage({ faq: (ctx) => [...] }) in context.page.ts (24 §7)`);
141
+ }
142
+ const { subject, label } = await loadSequenceDefinition(sequenceDir);
143
+ // One schema for the whole company (28 §2): the sequence only names its subject.
144
+ const { schema, validation } = compileSlotSchema(company, { session });
145
+ const subjectIssues = subjectTableIssues(company, subject);
146
+ if (subjectIssues.length > 0)
147
+ throw new Error(subjectIssues.map((i) => i.message).join('; '));
89
148
  if (!validation.ok) {
90
- const fatal = validation.issues.filter((i) => FATAL_CODES.has(i.code));
149
+ const fatal = fatalSlotSchemaIssues(validation.issues);
91
150
  if (fatal.length > 0) {
92
151
  throw new Error(fatal.map((i) => i.message).join('; '));
93
152
  }
94
153
  }
95
- const agendasPath = findTsModule(sequenceDir, 'agendas');
96
- const rawAgendas = agendasPath ? await loadSequenceAgendas(agendasPath) : null;
97
- const compiledAgendas = compileSequenceAgendas(schema, rawAgendas, { functions });
98
- const fatalAgenda = fatalAgendaIssues(compiledAgendas.issues);
99
- if (fatalAgenda.length > 0) {
100
- throw new Error(fatalAgenda.map((i) => i.message).join('; '));
154
+ const declared = await loadSequenceVariables(sequenceDir);
155
+ const variables = compileVariables(declared.variables, declared.experiments);
156
+ if (variables.issues.length > 0) {
157
+ throw new Error(`sequences/${sequenceId}/variables.ts: ${variables.issues.join('; ')}`);
158
+ }
159
+ // The declarative load was removed (15 §10.15): the conversation reads in context.page.ts.
160
+ if (findTsModule(sequenceDir, 'load')) {
161
+ throw new Error(`sequences/${sequenceId}/load.ts: declarative load is no longer supported; read with db in context.page.ts`);
101
162
  }
163
+ const orchestrator = caseOrchestratorFn
164
+ ? { fn: ORCHESTRATOR_FUNCTION, contactsFn: ORCHESTRATOR_CONTACTS_FUNCTION }
165
+ : null;
102
166
  const includeCode = options.includeCode ?? true;
103
- const [functionsRegistry, caseContextViewEntry] = await Promise.all([
104
- toFunctionRegistry(functions, { includeCode, modulePath: functionsPath }),
105
- toCaseContextViewRegistry(caseContextView, { includeCode, modulePath: viewPath }),
167
+ const [functionsRegistry, resolveCode, caseOrchestratorCode, caseOrchestratorContactsCode, eventsRegistry, pageCode, schedulesRegistry,] = await Promise.all([
168
+ toFunctionRegistry(authored, { includeCode, modulePath: functionsPath }),
169
+ includeCode ? compileExportModuleCode(resolvePath, RESOLVE_FUNCTION) : Promise.resolve(undefined),
170
+ caseOrchestratorPath && includeCode
171
+ ? compileExportModuleCode(caseOrchestratorPath, ORCHESTRATOR_FUNCTION)
172
+ : Promise.resolve(undefined),
173
+ caseOrchestratorPath && includeCode ? compileExportModuleCode(caseOrchestratorPath, 'contacts') : Promise.resolve(undefined),
174
+ toEventRegistry(events, { includeCode, modulePath: eventsPath }),
175
+ compilePageModuleCode(pagePath),
176
+ schedules ? scheduleRegistry(schedules, includeCode) : Promise.resolve({}),
106
177
  ]);
178
+ const channels = loadPageChannels(pageCode, sequenceId);
179
+ const runtimeVersion = runtimePackageVersion();
107
180
  const build = {
108
181
  sequenceId,
109
- sha: options.sha ?? 'local',
110
- engineVersion: runtimePackageVersion(),
182
+ label: typeof label === 'string' && label.trim() ? label.trim() : sequenceId,
183
+ engineVersion: runtimeVersion,
184
+ runtimeVersion,
111
185
  runtimeSource: options.runtimeSource ?? runtimePackageSource(repoRoot),
112
- compiledAt: new Date().toISOString(),
113
- companySchemaSnapshot: snapshotCompanySchema(company, functions),
114
- schema: compiledAgendas.schema,
115
- effectiveSchema: compiledAgendas.effectiveSchema,
116
- functions: functionsRegistry,
117
- caseContextView: caseContextViewEntry,
118
- agendas: compiledAgendas.agendas,
186
+ subject: subject,
187
+ variables: variables.variables,
188
+ experiments: variables.experiments,
189
+ functions: {
190
+ ...functionsRegistry,
191
+ [RESOLVE_FUNCTION]: resolveCode === undefined ? { kind: 'noCase' } : { kind: 'noCase', code: resolveCode },
192
+ ...(caseOrchestratorPath
193
+ ? {
194
+ [ORCHESTRATOR_FUNCTION]: caseOrchestratorCode === undefined
195
+ ? { kind: 'orchestrator' }
196
+ : { kind: 'orchestrator', code: caseOrchestratorCode },
197
+ [ORCHESTRATOR_CONTACTS_FUNCTION]: caseOrchestratorContactsCode === undefined
198
+ ? { kind: 'orchestrator' }
199
+ : { kind: 'orchestrator', code: caseOrchestratorContactsCode },
200
+ }
201
+ : {}),
202
+ ...schedulesRegistry,
203
+ },
204
+ events: eventsRegistry,
205
+ officeHours: await loadOfficeHours(sequenceDir),
206
+ orchestrator,
207
+ contextPage: { code: pageCode, channels },
208
+ ...(schedules ? { schedules: schedules.manifest } : {}),
119
209
  };
120
210
  const outPath = sequenceBuildPath(repoRoot, sequenceId);
121
211
  if (!options.dryRun) {
122
212
  mkdirSync(path.dirname(outPath), { recursive: true });
123
213
  writeFileSync(outPath, `${JSON.stringify(build, null, 2)}\n`, 'utf8');
124
214
  }
125
- return { sequenceId, outPath, build, wrote: !options.dryRun };
215
+ return { sequenceId, outPath, build, schema, schemas, wrote: !options.dryRun };
126
216
  }
127
217
  export async function compileAll(repoRoot, options = {}) {
128
218
  return withCompanyImportGraph(repoRoot, async () => {
129
219
  const ids = options.sequenceIds ?? listSequenceIds(repoRoot);
130
220
  if (ids.length === 0) {
131
- throw new Error(`No sequences with slots found under ${path.join(repoRoot, 'sequences')} (expected slots.ts or slots/index.ts)`);
221
+ throw new Error(`No sequences found under ${path.join(repoRoot, 'sequences')} (a sequence is a directory with index.ts)`);
132
222
  }
223
+ const companyMetadata = compileMetadata(await loadCompanySchemas(repoRoot));
133
224
  const results = [];
134
225
  for (const sequenceId of ids) {
135
- results.push(await compileSequence(repoRoot, sequenceId, options));
226
+ const { schemas: _, ...result } = await compileSequenceInGraph(repoRoot, sequenceId, options);
227
+ results.push({ ...result, companyMetadata });
136
228
  }
137
229
  return results;
138
230
  });
139
231
  }
232
+ /**
233
+ * The company part of the company build (22 §5): the root `resolve.ts` as `companyResolve`, the root
234
+ * `webhook.ts` as `webhook.received`, the root `schedules.ts` as `schedule.<name>` (25 §6.4), and the
235
+ * company schema with no subject. An error in it fails the
236
+ * whole compile.
237
+ */
238
+ export async function compileCompanyPart(repoRoot, options = {}) {
239
+ return withCompanyImportGraph(repoRoot, async () => {
240
+ const includeCode = options.includeCode ?? true;
241
+ // `resolve.ts` and `webhook.ts` import the root `__gen/`, which a fresh checkout does not have.
242
+ ensureCompanyStub(repoRoot);
243
+ const { company, session } = await loadCompanySchemas(repoRoot);
244
+ const companyResolvePath = requireCompanyResolveModule(repoRoot);
245
+ await loadCompanyResolver(companyResolvePath);
246
+ assertNoChannelsModule(repoRoot);
247
+ const webhookPath = findTsModule(repoRoot, WEBHOOK_MODULE);
248
+ if (webhookPath)
249
+ await loadCompanyWebhook(webhookPath);
250
+ const schedules = await loadSchedules(repoRoot, 'schedules.ts');
251
+ const [resolveCode, webhookCode, schedulesRegistry] = await Promise.all([
252
+ includeCode ? compileExportModuleCode(companyResolvePath, RESOLVE_FUNCTION) : Promise.resolve(undefined),
253
+ includeCode && webhookPath ? compileExportModuleCode(webhookPath, 'received') : Promise.resolve(undefined),
254
+ schedules ? scheduleRegistry(schedules, includeCode) : Promise.resolve({}),
255
+ ]);
256
+ const entry = (code) => (code === undefined ? { kind: 'noCase' } : { kind: 'noCase', code });
257
+ const { schema } = compileSlotSchema(company, { session });
258
+ return {
259
+ functions: {
260
+ [COMPANY_RESOLVE_FUNCTION]: entry(resolveCode),
261
+ ...(webhookPath ? { [WEBHOOK_RECEIVED_FUNCTION]: entry(webhookCode) } : {}),
262
+ ...schedulesRegistry,
263
+ },
264
+ ...(schedules ? { schedules: schedules.manifest } : {}),
265
+ schema,
266
+ runtimeVersion: runtimePackageVersion(),
267
+ runtimeSource: options.runtimeSource ?? runtimePackageSource(repoRoot),
268
+ };
269
+ });
270
+ }
271
+ export const COMPILE_CONCURRENCY = 4;
272
+ export const COMPILE_SEQUENCE_TIMEOUT_MS = 5 * 60_000;
273
+ function withDeadline(work, ms, message) {
274
+ return new Promise((resolve, reject) => {
275
+ const timer = setTimeout(() => reject(new Error(message)), ms);
276
+ work.then((value) => {
277
+ clearTimeout(timer);
278
+ resolve(value);
279
+ }, (error) => {
280
+ clearTimeout(timer);
281
+ reject(error);
282
+ });
283
+ });
284
+ }
285
+ async function mapPool(items, limit, run) {
286
+ if (items.length === 0)
287
+ return;
288
+ let cursor = 0;
289
+ const workers = Array.from({ length: Math.min(limit, items.length) }, async () => {
290
+ while (cursor < items.length) {
291
+ const item = items[cursor];
292
+ cursor += 1;
293
+ if (item === undefined)
294
+ return;
295
+ await run(item);
296
+ }
297
+ });
298
+ await Promise.all(workers);
299
+ }
300
+ /**
301
+ * Compile company metadata once, then every named sequence in this process, then type-check the
302
+ * repository. A sequence error is collected; a company schema error or a type error rejects the whole
303
+ * call, a type error with the tsc output as its message.
304
+ */
305
+ export async function compileRepo(repoRoot, options) {
306
+ return withCompanyImportGraph(repoRoot, async () => {
307
+ const companyMetadata = compileMetadata(await loadCompanySchemas(repoRoot));
308
+ const runtimeSource = options.runtimeSource ?? runtimePackageSource(repoRoot);
309
+ const company = await compileCompanyPart(repoRoot, { includeCode: true, runtimeSource });
310
+ options.onEvent?.({
311
+ type: 'log',
312
+ text: `Repo build runtime: ${runtimePackageVersion()} (${runtimeSource})`,
313
+ });
314
+ const timeoutMs = options.sequenceTimeoutMs ?? COMPILE_SEQUENCE_TIMEOUT_MS;
315
+ const sequences = {};
316
+ await mapPool(options.sequences, options.concurrency ?? COMPILE_CONCURRENCY, async (sequenceId) => {
317
+ options.onEvent?.({ type: 'sequence-started', sequence: sequenceId });
318
+ options.onEvent?.({ type: 'log', sequence: sequenceId, text: `Compiling ${sequenceId}...` });
319
+ try {
320
+ const result = await withDeadline(compileSequenceInGraph(repoRoot, sequenceId, {
321
+ dryRun: true,
322
+ runtimeSource,
323
+ includeCode: true,
324
+ }), timeoutMs, `compile timed out after ${Math.round(timeoutMs / 60_000)} minutes`);
325
+ sequences[sequenceId] = { ok: true, build: result.build };
326
+ options.onEvent?.({ type: 'log', sequence: sequenceId, text: `Compiled ${sequenceId}` });
327
+ options.onEvent?.({ type: 'sequence-finished', sequence: sequenceId, ok: true });
328
+ }
329
+ catch (error) {
330
+ const message = error instanceof Error ? error.message : String(error);
331
+ sequences[sequenceId] = { ok: false, error: message };
332
+ options.onEvent?.({ type: 'sequence-finished', sequence: sequenceId, ok: false, error: message });
333
+ }
334
+ });
335
+ // A failed sequence already fails the release, and type:gen would only repeat its error.
336
+ if (Object.values(sequences).every((outcome) => outcome.ok)) {
337
+ await typecheckRepo(repoRoot, (text) => options.onEvent?.({ type: 'log', text }));
338
+ }
339
+ return { companyMetadata, company, sequences };
340
+ });
341
+ }
140
342
  //# sourceMappingURL=compile-sequence.js.map
@@ -5,6 +5,16 @@
5
5
  export declare function compileFunctionCode(fn: (...args: never[]) => unknown): Promise<string>;
6
6
  /** Bundle one registered function with module-local helpers and constants. */
7
7
  export declare function compileFunctionModuleCode(modulePath: string, functionName: string): Promise<string>;
8
- /** Bundle caseContextView with module-local helpers and constants. */
9
- export declare function compileCaseContextViewModuleCode(modulePath: string): Promise<string>;
8
+ /** Bundle one event handler (a plain function under the `events` export) with module-local helpers. */
9
+ export declare function compileEventModuleCode(modulePath: string, eventName: string): Promise<string>;
10
+ /** Bundle one job's `run` of a `schedules.ts` (25 §6.4) with module-local helpers. */
11
+ export declare function compileScheduleModuleCode(modulePath: string, scheduleName: string): Promise<string>;
12
+ /** Bundle a module's named export (a plain function, or a `define*` result's `main`) with its helpers. */
13
+ export declare function compileExportModuleCode(modulePath: string, exportName: string): Promise<string>;
14
+ /**
15
+ * Bundle a sequence's page script (`context.page.ts`, 15 §10.2) with its helpers and the page module:
16
+ * the result evaluates to `pageEntry(module)`, which renders the page or runs one of its actions
17
+ * (`core/page/define.ts`).
18
+ */
19
+ export declare function compilePageModuleCode(modulePath: string): Promise<string>;
10
20
  //# sourceMappingURL=function-code.d.ts.map
@@ -1,35 +1,62 @@
1
1
  import * as esbuild from 'esbuild';
2
+ import { existsSync } from 'node:fs';
2
3
  import path from 'node:path';
3
- const RUNTIME_SHIM_NAMESPACE = 'superpanel-runtime-shim';
4
- const RUNTIME_SHIM = `
5
- export function defineComputeFunc(main, options) {
6
- return { kind: 'compute', main, ...options };
7
- }
8
- export function defineBoolComputeFunc(main, options) {
9
- return { kind: 'boolCompute', main, ...options };
10
- }
11
- export function defineCustomFunc(main, options) {
12
- return { kind: 'custom', main, ...options };
13
- }
14
- export function defineSystemFunc(main, options) {
15
- return { kind: 'system', main, ...options };
16
- }
17
- export function defineCaseContext(main) {
18
- return Object.assign(main, { kind: 'caseContextView', main });
4
+ import { fileURLToPath } from 'node:url';
5
+ import { companyRepoRoot } from '../company-import-graph.js';
6
+ import { RUNTIME_PACKAGE, companyImportError, packageRootOf, realPath, resolvedIssue, specifierIssue, } from '../company-imports.js';
7
+ /**
8
+ * A module of this runtime as a bundle takes it: `<name>.js` next to this module in the published
9
+ * package, `<name>.ts` in the source tree.
10
+ */
11
+ function runtimeModule(name) {
12
+ const base = path.resolve(path.dirname(fileURLToPath(import.meta.url)), `../../${name}`);
13
+ return existsSync(`${base}.js`) ? `${base}.js` : `${base}.ts`;
19
14
  }
20
- `;
21
- function runtimeShimPlugin() {
15
+ /** The bundle's entry: the compile's own code next to the company module, importing it. */
16
+ const ENTRY_FILE = 'superpanel-function-entry.ts';
17
+ /** Marks a resolve the plugin asked for itself, so it does not check its own request. */
18
+ const CHECKED = Symbol('company import checked');
19
+ /**
20
+ * Checks every import a company file makes (company-imports.ts) and bundles `@superpanel-sdk/runtime` as
21
+ * this runtime's own company API (`src/index.ts`): a code string carries the helpers of the runtime that
22
+ * compiled it, whichever copy the repository would resolve, and keeps of them only what it uses.
23
+ */
24
+ function companyImportsPlugin(repoRoot, entryFile) {
25
+ const root = realPath(repoRoot);
26
+ const isCompanyFile = (file) => {
27
+ // The entry is the compile's own (it picks the export and the page's `pageEntry`), not the company's.
28
+ if (!path.isAbsolute(file) || file === entryFile)
29
+ return false;
30
+ const relative = path.relative(root, realPath(file));
31
+ return relative !== '' && !relative.startsWith('..') && !path.isAbsolute(relative) && !relative.split(path.sep).includes('node_modules');
32
+ };
22
33
  return {
23
- name: 'superpanel-runtime-shim',
34
+ name: 'superpanel-company-imports',
24
35
  setup(build) {
25
- build.onResolve({ filter: /^@superpanel-sdk\/runtime$/ }, () => ({
26
- path: 'runtime',
27
- namespace: RUNTIME_SHIM_NAMESPACE,
28
- }));
29
- build.onLoad({ filter: /.*/, namespace: RUNTIME_SHIM_NAMESPACE }, () => ({
30
- contents: RUNTIME_SHIM,
31
- loader: 'js',
32
- }));
36
+ build.onResolve({ filter: /.*/ }, async (args) => {
37
+ if (args.pluginData === CHECKED || !isCompanyFile(args.importer))
38
+ return undefined;
39
+ const refuse = (issue) => ({
40
+ errors: [{ text: companyImportError(args.importer, repoRoot, issue).message }],
41
+ });
42
+ const issue = specifierIssue(args.path);
43
+ if (issue)
44
+ return refuse(issue);
45
+ if (args.path === RUNTIME_PACKAGE)
46
+ return { path: runtimeModule('index') };
47
+ const resolved = await build.resolve(args.path, {
48
+ kind: args.kind,
49
+ importer: args.importer,
50
+ resolveDir: args.resolveDir,
51
+ pluginData: CHECKED,
52
+ });
53
+ if (resolved.errors.length > 0)
54
+ return { errors: resolved.errors };
55
+ const resolvedProblem = resolvedIssue(args.path, resolved.path, repoRoot);
56
+ if (resolvedProblem)
57
+ return refuse(resolvedProblem);
58
+ return { path: resolved.path, namespace: resolved.namespace, sideEffects: resolved.sideEffects, suffix: resolved.suffix };
59
+ });
33
60
  },
34
61
  };
35
62
  }
@@ -48,11 +75,10 @@ export async function compileFunctionCode(fn) {
48
75
  });
49
76
  const text = result.code.trim();
50
77
  if (text.includes('@superpanel-sdk/runtime') ||
51
- text.includes('defineComputeFunc') ||
52
- text.includes('defineCustomFunc') ||
53
- text.includes('defineBoolComputeFunc') ||
54
- text.includes('defineSystemFunc') ||
55
- text.includes('defineCaseContext')) {
78
+ text.includes('defineCaseFunc') ||
79
+ text.includes('defineNoCaseFunc') ||
80
+ text.includes('defineEvents') ||
81
+ text.includes('bindDefines')) {
56
82
  throw new Error('compiled function code still references define* / @superpanel-sdk/runtime');
57
83
  }
58
84
  const m = /^export\s+default\s*/.exec(text);
@@ -61,14 +87,18 @@ export async function compileFunctionCode(fn) {
61
87
  }
62
88
  return text.slice(m[0].length).replace(/;?\s*$/, '');
63
89
  }
64
- async function compileModuleSelection(modulePath, selection) {
90
+ async function compileModuleSelection(modulePath, selection, imports = '') {
91
+ // The compile bundles inside its import graph; a caller outside one (a test) bundles within the module's package.
92
+ const repoRoot = companyRepoRoot() ?? packageRootOf(modulePath);
93
+ const entryFile = path.join(path.dirname(modulePath), ENTRY_FILE);
65
94
  const result = await esbuild.build({
66
95
  stdin: {
67
96
  contents: `import * as mod from ${JSON.stringify(modulePath)};
97
+ ${imports}
68
98
  const selected = ${selection};
69
99
  export default selected;`,
70
100
  resolveDir: path.dirname(modulePath),
71
- sourcefile: 'superpanel-function-entry.ts',
101
+ sourcefile: ENTRY_FILE,
72
102
  loader: 'ts',
73
103
  },
74
104
  bundle: true,
@@ -79,7 +109,7 @@ export default selected;`,
79
109
  target: 'es2022',
80
110
  minify: true,
81
111
  logLevel: 'silent',
82
- plugins: [runtimeShimPlugin()],
112
+ plugins: [companyImportsPlugin(repoRoot, entryFile)],
83
113
  });
84
114
  const output = result.outputFiles[0]?.text.trim();
85
115
  if (!output) {
@@ -92,9 +122,27 @@ export function compileFunctionModuleCode(modulePath, functionName) {
92
122
  const registry = `(mod.functions ?? mod.default?.functions ?? mod.default)`;
93
123
  return compileModuleSelection(modulePath, `${registry}[${JSON.stringify(functionName)}].main`);
94
124
  }
95
- /** Bundle caseContextView with module-local helpers and constants. */
96
- export function compileCaseContextViewModuleCode(modulePath) {
97
- const view = `(mod.caseContextView ?? mod.default?.caseContextView ?? mod.default)`;
98
- return compileModuleSelection(modulePath, `(${view}.main ?? ${view})`);
125
+ /** Bundle one event handler (a plain function under the `events` export) with module-local helpers. */
126
+ export function compileEventModuleCode(modulePath, eventName) {
127
+ const registry = `(mod.events ?? mod.default?.events ?? mod.default)`;
128
+ return compileModuleSelection(modulePath, `${registry}[${JSON.stringify(eventName)}]`);
129
+ }
130
+ /** Bundle one job's `run` of a `schedules.ts` (25 §6.4) with module-local helpers. */
131
+ export function compileScheduleModuleCode(modulePath, scheduleName) {
132
+ const registry = `(mod.schedules ?? mod.default?.schedules ?? mod.default)`;
133
+ return compileModuleSelection(modulePath, `${registry}[${JSON.stringify(scheduleName)}].run`);
134
+ }
135
+ /** Bundle a module's named export (a plain function, or a `define*` result's `main`) with its helpers. */
136
+ export function compileExportModuleCode(modulePath, exportName) {
137
+ const entry = `(mod[${JSON.stringify(exportName)}] ?? mod.default)`;
138
+ return compileModuleSelection(modulePath, `(${entry}.main ?? ${entry})`);
139
+ }
140
+ /**
141
+ * Bundle a sequence's page script (`context.page.ts`, 15 §10.2) with its helpers and the page module:
142
+ * the result evaluates to `pageEntry(module)`, which renders the page or runs one of its actions
143
+ * (`core/page/define.ts`).
144
+ */
145
+ export function compilePageModuleCode(modulePath) {
146
+ return compileModuleSelection(modulePath, 'pageEntry(mod)', `import { pageEntry } from ${JSON.stringify(runtimeModule('core/page/define'))};`);
99
147
  }
100
148
  //# sourceMappingURL=function-code.js.map
@@ -1,4 +1,5 @@
1
- import type { CaseContextViewRegistryEntry, FuncMap, FunctionRegistry } from '../../core/functions/types.js';
1
+ import { type AnyEventHandlers } from '../../core/functions/events.js';
2
+ import type { FuncMap, FunctionRegistry } from '../../core/functions/types.js';
2
3
  export type BuildRegistryOptions = {
3
4
  /** When false, skip esbuild and omit `code` (local serve overlay). Default true. */
4
5
  includeCode?: boolean;
@@ -10,6 +11,9 @@ export type BuildRegistryOptions = {
10
11
  * Published builds include per-function compiled `code`; overlay omits it.
11
12
  */
12
13
  export declare function toFunctionRegistry(functions: FuncMap, options?: BuildRegistryOptions): Promise<FunctionRegistry>;
13
- /** Compile optional caseContextView to registry entry. */
14
- export declare function toCaseContextViewRegistry(view: unknown, options?: BuildRegistryOptions): Promise<CaseContextViewRegistryEntry | null>;
14
+ /**
15
+ * Project the company `events` export → JSON-safe registry. The kind of each
16
+ * handler is fixed by the platform event table (`case` / `noCase`), not by the author.
17
+ */
18
+ export declare function toEventRegistry(events: AnyEventHandlers, options?: BuildRegistryOptions): Promise<FunctionRegistry>;
15
19
  //# sourceMappingURL=registry.d.ts.map