primitive-admin 1.0.62 → 1.0.64

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 (344) hide show
  1. package/README.md +132 -42
  2. package/assets/skill/skills/primitive-platform/SKILL.md +142 -661
  3. package/dist/bin/primitive.js +121 -41
  4. package/dist/bin/primitive.js.map +1 -1
  5. package/dist/src/commands/admins.js +37 -50
  6. package/dist/src/commands/admins.js.map +1 -1
  7. package/dist/src/commands/analytics.js +178 -9
  8. package/dist/src/commands/analytics.js.map +1 -1
  9. package/dist/src/commands/apps.js +17 -7
  10. package/dist/src/commands/apps.js.map +1 -1
  11. package/dist/src/commands/auth-sessions.d.ts +7 -0
  12. package/dist/src/commands/auth-sessions.js +144 -0
  13. package/dist/src/commands/auth-sessions.js.map +1 -0
  14. package/dist/src/commands/auth.js +76 -116
  15. package/dist/src/commands/auth.js.map +1 -1
  16. package/dist/src/commands/blob-buckets.js +2 -1
  17. package/dist/src/commands/blob-buckets.js.map +1 -1
  18. package/dist/src/commands/catalog.js +26 -10
  19. package/dist/src/commands/catalog.js.map +1 -1
  20. package/dist/src/commands/collection-type-configs.js +3 -10
  21. package/dist/src/commands/collection-type-configs.js.map +1 -1
  22. package/dist/src/commands/collections.js +736 -19
  23. package/dist/src/commands/collections.js.map +1 -1
  24. package/dist/src/commands/config.js +13 -27
  25. package/dist/src/commands/config.js.map +1 -1
  26. package/dist/src/commands/connections.js +8 -9
  27. package/dist/src/commands/connections.js.map +1 -1
  28. package/dist/src/commands/cron-triggers.js +2 -1
  29. package/dist/src/commands/cron-triggers.js.map +1 -1
  30. package/dist/src/commands/database-type-configs.js +5 -12
  31. package/dist/src/commands/database-type-configs.js.map +1 -1
  32. package/dist/src/commands/databases.js +59 -72
  33. package/dist/src/commands/databases.js.map +1 -1
  34. package/dist/src/commands/documents.d.ts +58 -0
  35. package/dist/src/commands/documents.js +1623 -95
  36. package/dist/src/commands/documents.js.map +1 -1
  37. package/dist/src/commands/email-templates.js +5 -4
  38. package/dist/src/commands/email-templates.js.map +1 -1
  39. package/dist/src/commands/env.d.ts +1 -1
  40. package/dist/src/commands/env.js +106 -44
  41. package/dist/src/commands/env.js.map +1 -1
  42. package/dist/src/commands/feature-flags.js +2 -1
  43. package/dist/src/commands/feature-flags.js.map +1 -1
  44. package/dist/src/commands/functions.d.ts +20 -0
  45. package/dist/src/commands/functions.js +1630 -0
  46. package/dist/src/commands/functions.js.map +1 -0
  47. package/dist/src/commands/group-type-configs.js +2 -1
  48. package/dist/src/commands/group-type-configs.js.map +1 -1
  49. package/dist/src/commands/groups.js +30 -17
  50. package/dist/src/commands/groups.js.map +1 -1
  51. package/dist/src/commands/guides.js +17 -11
  52. package/dist/src/commands/guides.js.map +1 -1
  53. package/dist/src/commands/init.d.ts +24 -12
  54. package/dist/src/commands/init.js +198 -110
  55. package/dist/src/commands/init.js.map +1 -1
  56. package/dist/src/commands/integrations.js +65 -26
  57. package/dist/src/commands/integrations.js.map +1 -1
  58. package/dist/src/commands/locks.js +17 -2
  59. package/dist/src/commands/locks.js.map +1 -1
  60. package/dist/src/commands/metadata-category-configs.js +2 -1
  61. package/dist/src/commands/metadata-category-configs.js.map +1 -1
  62. package/dist/src/commands/metadata.js +8 -1
  63. package/dist/src/commands/metadata.js.map +1 -1
  64. package/dist/src/commands/prompts.js +106 -59
  65. package/dist/src/commands/prompts.js.map +1 -1
  66. package/dist/src/commands/rule-sets.js +3 -10
  67. package/dist/src/commands/rule-sets.js.map +1 -1
  68. package/dist/src/commands/scripts.d.ts +10 -0
  69. package/dist/src/commands/scripts.js +159 -25
  70. package/dist/src/commands/scripts.js.map +1 -1
  71. package/dist/src/commands/secrets.js +2 -1
  72. package/dist/src/commands/secrets.js.map +1 -1
  73. package/dist/src/commands/sessions.js +10 -9
  74. package/dist/src/commands/sessions.js.map +1 -1
  75. package/dist/src/commands/sync-app-settings.js +3 -5
  76. package/dist/src/commands/sync-app-settings.js.map +1 -1
  77. package/dist/src/commands/sync.d.ts +391 -44
  78. package/dist/src/commands/sync.js +2622 -534
  79. package/dist/src/commands/sync.js.map +1 -1
  80. package/dist/src/commands/tokens.js +2 -1
  81. package/dist/src/commands/tokens.js.map +1 -1
  82. package/dist/src/commands/users.js +19 -10
  83. package/dist/src/commands/users.js.map +1 -1
  84. package/dist/src/commands/vars.js +2 -1
  85. package/dist/src/commands/vars.js.map +1 -1
  86. package/dist/src/commands/waitlist.js +2 -1
  87. package/dist/src/commands/waitlist.js.map +1 -1
  88. package/dist/src/commands/webhooks.d.ts +29 -0
  89. package/dist/src/commands/webhooks.js +135 -64
  90. package/dist/src/commands/webhooks.js.map +1 -1
  91. package/dist/src/commands/workflows.d.ts +1 -29
  92. package/dist/src/commands/workflows.js +113 -179
  93. package/dist/src/commands/workflows.js.map +1 -1
  94. package/dist/src/lib/api-client.d.ts +628 -14
  95. package/dist/src/lib/api-client.js +776 -70
  96. package/dist/src/lib/api-client.js.map +1 -1
  97. package/dist/src/lib/app-settings-descriptor.d.ts +1 -1
  98. package/dist/src/lib/app-settings-descriptor.js +9 -1
  99. package/dist/src/lib/app-settings-descriptor.js.map +1 -1
  100. package/dist/src/lib/block-selector.d.ts +58 -0
  101. package/dist/src/lib/block-selector.js +92 -0
  102. package/dist/src/lib/block-selector.js.map +1 -0
  103. package/dist/src/lib/codegen-shared/resolveCodegenSourceDir.d.ts +24 -54
  104. package/dist/src/lib/codegen-shared/resolveCodegenSourceDir.js +31 -153
  105. package/dist/src/lib/codegen-shared/resolveCodegenSourceDir.js.map +1 -1
  106. package/dist/src/lib/collection-export.d.ts +184 -0
  107. package/dist/src/lib/collection-export.js +252 -0
  108. package/dist/src/lib/collection-export.js.map +1 -0
  109. package/dist/src/lib/config-json-field.d.ts +28 -0
  110. package/dist/src/lib/config-json-field.js +56 -0
  111. package/dist/src/lib/config-json-field.js.map +1 -0
  112. package/dist/src/lib/config-object-descriptor.js +88 -6
  113. package/dist/src/lib/config-object-descriptor.js.map +1 -1
  114. package/dist/src/lib/config-payload.d.ts +8 -1
  115. package/dist/src/lib/config-payload.js +49 -4
  116. package/dist/src/lib/config-payload.js.map +1 -1
  117. package/dist/src/lib/config-surface.d.ts +12 -1
  118. package/dist/src/lib/config-surface.js +71 -3
  119. package/dist/src/lib/config-surface.js.map +1 -1
  120. package/dist/src/lib/config.d.ts +31 -13
  121. package/dist/src/lib/config.js +34 -70
  122. package/dist/src/lib/config.js.map +1 -1
  123. package/dist/src/lib/credentials-store.d.ts +37 -22
  124. package/dist/src/lib/credentials-store.js +103 -97
  125. package/dist/src/lib/credentials-store.js.map +1 -1
  126. package/dist/src/lib/db-codegen/dbTypeIR.js +8 -0
  127. package/dist/src/lib/db-codegen/dbTypeIR.js.map +1 -1
  128. package/dist/src/lib/deprecation.d.ts +22 -0
  129. package/dist/src/lib/deprecation.js +43 -0
  130. package/dist/src/lib/deprecation.js.map +1 -0
  131. package/dist/src/lib/document-export-permissions.d.ts +30 -0
  132. package/dist/src/lib/document-export-permissions.js +54 -0
  133. package/dist/src/lib/document-export-permissions.js.map +1 -0
  134. package/dist/src/lib/document-ingest-artifact.d.ts +120 -0
  135. package/dist/src/lib/document-ingest-artifact.js +505 -0
  136. package/dist/src/lib/document-ingest-artifact.js.map +1 -0
  137. package/dist/src/lib/document-ingest-input.d.ts +51 -0
  138. package/dist/src/lib/document-ingest-input.js +132 -0
  139. package/dist/src/lib/document-ingest-input.js.map +1 -0
  140. package/dist/src/lib/document-ingest-rows.d.ts +137 -0
  141. package/dist/src/lib/document-ingest-rows.js +181 -0
  142. package/dist/src/lib/document-ingest-rows.js.map +1 -0
  143. package/dist/src/lib/document-ingest.d.ts +101 -0
  144. package/dist/src/lib/document-ingest.js +384 -0
  145. package/dist/src/lib/document-ingest.js.map +1 -0
  146. package/dist/src/lib/env-resolver-core.d.ts +128 -17
  147. package/dist/src/lib/env-resolver-core.js +204 -22
  148. package/dist/src/lib/env-resolver-core.js.map +1 -1
  149. package/dist/src/lib/env-resolver.d.ts +18 -3
  150. package/dist/src/lib/env-resolver.js +23 -3
  151. package/dist/src/lib/env-resolver.js.map +1 -1
  152. package/dist/src/lib/function-bundle.d.ts +147 -0
  153. package/dist/src/lib/function-bundle.js +341 -0
  154. package/dist/src/lib/function-bundle.js.map +1 -0
  155. package/dist/src/lib/function-collect.d.ts +123 -0
  156. package/dist/src/lib/function-collect.js +610 -0
  157. package/dist/src/lib/function-collect.js.map +1 -0
  158. package/dist/src/lib/function-db-types.d.ts +202 -0
  159. package/dist/src/lib/function-db-types.js +870 -0
  160. package/dist/src/lib/function-db-types.js.map +1 -0
  161. package/dist/src/lib/function-document-types.d.ts +144 -0
  162. package/dist/src/lib/function-document-types.js +370 -0
  163. package/dist/src/lib/function-document-types.js.map +1 -0
  164. package/dist/src/lib/function-grants-preflight.d.ts +64 -0
  165. package/dist/src/lib/function-grants-preflight.js +105 -0
  166. package/dist/src/lib/function-grants-preflight.js.map +1 -0
  167. package/dist/src/lib/function-log-lines.d.ts +76 -0
  168. package/dist/src/lib/function-log-lines.js +160 -0
  169. package/dist/src/lib/function-log-lines.js.map +1 -0
  170. package/dist/src/lib/function-log-row.d.ts +29 -0
  171. package/dist/src/lib/function-log-row.js +73 -0
  172. package/dist/src/lib/function-log-row.js.map +1 -0
  173. package/dist/src/lib/function-log-tail.d.ts +132 -0
  174. package/dist/src/lib/function-log-tail.js +262 -0
  175. package/dist/src/lib/function-log-tail.js.map +1 -0
  176. package/dist/src/lib/function-run.d.ts +289 -0
  177. package/dist/src/lib/function-run.js +389 -0
  178. package/dist/src/lib/function-run.js.map +1 -0
  179. package/dist/src/lib/function-schema-codegen.d.ts +143 -0
  180. package/dist/src/lib/function-schema-codegen.js +420 -0
  181. package/dist/src/lib/function-schema-codegen.js.map +1 -0
  182. package/dist/src/lib/function-sync.d.ts +459 -0
  183. package/dist/src/lib/function-sync.js +1258 -0
  184. package/dist/src/lib/function-sync.js.map +1 -0
  185. package/dist/src/lib/function-trigger-listing.d.ts +27 -0
  186. package/dist/src/lib/function-trigger-listing.js +70 -0
  187. package/dist/src/lib/function-trigger-listing.js.map +1 -0
  188. package/dist/src/lib/function-typecheck.d.ts +86 -0
  189. package/dist/src/lib/function-typecheck.js +370 -0
  190. package/dist/src/lib/function-typecheck.js.map +1 -0
  191. package/dist/src/lib/function-versions.d.ts +122 -0
  192. package/dist/src/lib/function-versions.js +182 -0
  193. package/dist/src/lib/function-versions.js.map +1 -0
  194. package/dist/src/lib/generated-allowlist.js +4 -0
  195. package/dist/src/lib/generated-allowlist.js.map +1 -1
  196. package/dist/src/lib/generated-config-surfaces.d.ts +2332 -78
  197. package/dist/src/lib/generated-config-surfaces.js +6979 -468
  198. package/dist/src/lib/generated-config-surfaces.js.map +1 -1
  199. package/dist/src/lib/generated-sdk-types.d.ts +12 -0
  200. package/dist/src/lib/generated-sdk-types.js +13 -0
  201. package/dist/src/lib/generated-sdk-types.js.map +1 -0
  202. package/dist/src/lib/init-adopt.js +2 -2
  203. package/dist/src/lib/init-adopt.js.map +1 -1
  204. package/dist/src/lib/init-assets.js +3 -3
  205. package/dist/src/lib/init-client-platforms.d.ts +14 -0
  206. package/dist/src/lib/init-client-platforms.js +71 -0
  207. package/dist/src/lib/init-client-platforms.js.map +1 -0
  208. package/dist/src/lib/init-config.d.ts +1 -1
  209. package/dist/src/lib/init-email-redirect-uris.d.ts +37 -0
  210. package/dist/src/lib/init-email-redirect-uris.js +46 -0
  211. package/dist/src/lib/init-email-redirect-uris.js.map +1 -0
  212. package/dist/src/lib/init-ios-links.d.ts +41 -0
  213. package/dist/src/lib/init-ios-links.js +67 -1
  214. package/dist/src/lib/init-ios-links.js.map +1 -1
  215. package/dist/src/lib/init-plan.d.ts +1 -1
  216. package/dist/src/lib/init-plan.js +1 -1
  217. package/dist/src/lib/init-xcode.d.ts +6 -5
  218. package/dist/src/lib/init-xcode.js +34 -10
  219. package/dist/src/lib/init-xcode.js.map +1 -1
  220. package/dist/src/lib/integration-selector.d.ts +42 -0
  221. package/dist/src/lib/integration-selector.js +46 -0
  222. package/dist/src/lib/integration-selector.js.map +1 -0
  223. package/dist/src/lib/ios-app-id.d.ts +34 -0
  224. package/dist/src/lib/ios-app-id.js +69 -0
  225. package/dist/src/lib/ios-app-id.js.map +1 -0
  226. package/dist/src/lib/list-options.d.ts +68 -0
  227. package/dist/src/lib/list-options.js +89 -0
  228. package/dist/src/lib/list-options.js.map +1 -0
  229. package/dist/src/lib/local-state.d.ts +1 -1
  230. package/dist/src/lib/local-state.js +1 -1
  231. package/dist/src/lib/local-test-cases.d.ts +63 -0
  232. package/dist/src/lib/local-test-cases.js +136 -0
  233. package/dist/src/lib/local-test-cases.js.map +1 -0
  234. package/dist/src/lib/log-inspection.d.ts +152 -5
  235. package/dist/src/lib/log-inspection.js +179 -2
  236. package/dist/src/lib/log-inspection.js.map +1 -1
  237. package/dist/src/lib/logout-admin-session.d.ts +33 -0
  238. package/dist/src/lib/logout-admin-session.js +70 -0
  239. package/dist/src/lib/logout-admin-session.js.map +1 -0
  240. package/dist/src/lib/output.d.ts +15 -0
  241. package/dist/src/lib/output.js +28 -0
  242. package/dist/src/lib/output.js.map +1 -1
  243. package/dist/src/lib/paginate.d.ts +15 -0
  244. package/dist/src/lib/paginate.js +17 -0
  245. package/dist/src/lib/paginate.js.map +1 -1
  246. package/dist/src/lib/project-config.d.ts +46 -21
  247. package/dist/src/lib/project-config.js +74 -47
  248. package/dist/src/lib/project-config.js.map +1 -1
  249. package/dist/src/lib/prompt-cost-format.d.ts +11 -0
  250. package/dist/src/lib/prompt-cost-format.js +41 -0
  251. package/dist/src/lib/prompt-cost-format.js.map +1 -0
  252. package/dist/src/lib/prompt-schema-codegen.d.ts +147 -0
  253. package/dist/src/lib/prompt-schema-codegen.js +462 -0
  254. package/dist/src/lib/prompt-schema-codegen.js.map +1 -0
  255. package/dist/src/lib/refresh-admin-credentials.d.ts +9 -1
  256. package/dist/src/lib/refresh-admin-credentials.js +22 -2
  257. package/dist/src/lib/refresh-admin-credentials.js.map +1 -1
  258. package/dist/src/lib/resolve-owner.d.ts +19 -0
  259. package/dist/src/lib/resolve-owner.js +20 -0
  260. package/dist/src/lib/resolve-owner.js.map +1 -0
  261. package/dist/src/lib/skill-installer.d.ts +49 -3
  262. package/dist/src/lib/skill-installer.js +275 -100
  263. package/dist/src/lib/skill-installer.js.map +1 -1
  264. package/dist/src/lib/snapshot-audit-source.d.ts +45 -0
  265. package/dist/src/lib/snapshot-audit-source.js +58 -0
  266. package/dist/src/lib/snapshot-audit-source.js.map +1 -0
  267. package/dist/src/lib/snapshot-audit-store.d.ts +52 -0
  268. package/dist/src/lib/snapshot-audit-store.js +196 -0
  269. package/dist/src/lib/snapshot-audit-store.js.map +1 -0
  270. package/dist/src/lib/snapshot-audit.d.ts +207 -0
  271. package/dist/src/lib/snapshot-audit.js +431 -0
  272. package/dist/src/lib/snapshot-audit.js.map +1 -0
  273. package/dist/src/lib/snapshot-build-rows.d.ts +60 -0
  274. package/dist/src/lib/snapshot-build-rows.js +87 -0
  275. package/dist/src/lib/snapshot-build-rows.js.map +1 -0
  276. package/dist/src/lib/snapshot-build.d.ts +50 -0
  277. package/dist/src/lib/snapshot-build.js +111 -0
  278. package/dist/src/lib/snapshot-build.js.map +1 -0
  279. package/dist/src/lib/snapshot-manifest-layout.d.ts +61 -0
  280. package/dist/src/lib/snapshot-manifest-layout.js +70 -0
  281. package/dist/src/lib/snapshot-manifest-layout.js.map +1 -0
  282. package/dist/src/lib/snapshots.d.ts +8 -9
  283. package/dist/src/lib/snapshots.js +20 -83
  284. package/dist/src/lib/snapshots.js.map +1 -1
  285. package/dist/src/lib/step-run-table.d.ts +43 -0
  286. package/dist/src/lib/step-run-table.js +129 -0
  287. package/dist/src/lib/step-run-table.js.map +1 -0
  288. package/dist/src/lib/storage-pending-retry.d.ts +26 -0
  289. package/dist/src/lib/storage-pending-retry.js +42 -0
  290. package/dist/src/lib/storage-pending-retry.js.map +1 -0
  291. package/dist/src/lib/swift-codegen/agentGenerator.d.ts +42 -0
  292. package/dist/src/lib/swift-codegen/agentGenerator.js +118 -0
  293. package/dist/src/lib/swift-codegen/agentGenerator.js.map +1 -0
  294. package/dist/src/lib/swift-codegen/banners.d.ts +24 -0
  295. package/dist/src/lib/swift-codegen/banners.js +25 -0
  296. package/dist/src/lib/swift-codegen/banners.js.map +1 -0
  297. package/dist/src/lib/swift-codegen/dbGenerator.js +19 -7
  298. package/dist/src/lib/swift-codegen/dbGenerator.js.map +1 -1
  299. package/dist/src/lib/swift-codegen/functionGenerator.d.ts +139 -0
  300. package/dist/src/lib/swift-codegen/functionGenerator.js +462 -0
  301. package/dist/src/lib/swift-codegen/functionGenerator.js.map +1 -0
  302. package/dist/src/lib/swift-codegen/generator.d.ts +7 -1
  303. package/dist/src/lib/swift-codegen/generator.js +28 -11
  304. package/dist/src/lib/swift-codegen/generator.js.map +1 -1
  305. package/dist/src/lib/swift-codegen/schemaToSwift.d.ts +15 -0
  306. package/dist/src/lib/swift-codegen/schemaToSwift.js +21 -4
  307. package/dist/src/lib/swift-codegen/schemaToSwift.js.map +1 -1
  308. package/dist/src/lib/sync-paths.d.ts +72 -55
  309. package/dist/src/lib/sync-paths.js +97 -100
  310. package/dist/src/lib/sync-paths.js.map +1 -1
  311. package/dist/src/lib/sync-resource-types.d.ts +23 -4
  312. package/dist/src/lib/sync-resource-types.js +106 -8
  313. package/dist/src/lib/sync-resource-types.js.map +1 -1
  314. package/dist/src/lib/sync-selectors.d.ts +45 -2
  315. package/dist/src/lib/sync-selectors.js +66 -5
  316. package/dist/src/lib/sync-selectors.js.map +1 -1
  317. package/dist/src/lib/template.d.ts +2 -2
  318. package/dist/src/lib/template.js +2 -2
  319. package/dist/src/lib/test-case-file-names.d.ts +40 -0
  320. package/dist/src/lib/test-case-file-names.js +91 -0
  321. package/dist/src/lib/test-case-file-names.js.map +1 -0
  322. package/dist/src/lib/test-case-keys.d.ts +1 -1
  323. package/dist/src/lib/test-case-keys.js +1 -1
  324. package/dist/src/lib/test-case-variables.d.ts +14 -0
  325. package/dist/src/lib/test-case-variables.js +42 -0
  326. package/dist/src/lib/test-case-variables.js.map +1 -1
  327. package/dist/src/lib/toml-database-config.js +19 -2
  328. package/dist/src/lib/toml-database-config.js.map +1 -1
  329. package/dist/src/lib/web-url.d.ts +40 -0
  330. package/dist/src/lib/web-url.js +76 -0
  331. package/dist/src/lib/web-url.js.map +1 -0
  332. package/dist/src/lib/webhook-deliver.d.ts +209 -0
  333. package/dist/src/lib/webhook-deliver.js +519 -0
  334. package/dist/src/lib/webhook-deliver.js.map +1 -0
  335. package/dist/src/lib/workflow-codegen/generator.d.ts +1 -1
  336. package/dist/src/lib/workflow-codegen/generator.js +1 -1
  337. package/dist/src/lib/workflow-toml-validator.d.ts +17 -8
  338. package/dist/src/lib/workflow-toml-validator.js +25 -12
  339. package/dist/src/lib/workflow-toml-validator.js.map +1 -1
  340. package/dist/src/lib/workflow-usage.d.ts +196 -0
  341. package/dist/src/lib/workflow-usage.js +310 -0
  342. package/dist/src/lib/workflow-usage.js.map +1 -0
  343. package/dist/src/types/index.d.ts +12 -2
  344. package/package.json +5 -4
@@ -0,0 +1,341 @@
1
+ /**
2
+ * Building a server function's bundle, in the CLI (#3179, project
3
+ * `server-functions`).
4
+ *
5
+ * The intent decides that the build happens here and never on the server:
6
+ * `config push` runs esbuild over the authored `entry`, inlines the npm
7
+ * dependencies, and ships the built bundle next to the authored source bytes
8
+ * in one envelope. The server verifies the hash and stores the object; it does
9
+ * not compile anything.
10
+ *
11
+ * ── The two import rules ─────────────────────────────────────────────────
12
+ *
13
+ * They look contradictory and are not (F-005):
14
+ *
15
+ * - A **filesystem import** — relative or absolute — must stay inside the
16
+ * config tree. `entry`, every import it reaches, and every symlink they
17
+ * traverse are realpath-resolved and checked against the tree root, so a
18
+ * push can never read a file off a developer's disk that the tree does not
19
+ * contain.
20
+ * - A **bare package specifier** is exempt. It resolves through Node into an
21
+ * ancestor `node_modules`, which is outside every config tree by
22
+ * construction; esbuild inlines it into the bundle, and it is never
23
+ * captured as an authored source (so `config pull` never writes
24
+ * `node_modules` content back).
25
+ *
26
+ * The exemption follows the specifier, not the path a file happens to sit at.
27
+ * A resolver plugin records the files a BARE specifier reached (and the files
28
+ * those reach in turn), so `import "../../node_modules/private/index.js"` — a
29
+ * relative filesystem import that merely lands in a `node_modules` directory —
30
+ * is still an escape and still refused. Deciding by path would have let that
31
+ * one specifier read any file on the disk and upload it.
32
+ *
33
+ * `primitive-functions` is the one bare specifier left EXTERNAL: the loader
34
+ * (#3180) supplies it at invoke time, so baking a copy into every bundle would
35
+ * pin the SDK version to whenever the function was last pushed.
36
+ *
37
+ * ── The retired specifier ────────────────────────────────────────────────
38
+ *
39
+ * That module was called `primitive-sdk` until #3209. This file is the one
40
+ * place in the repo that still writes the old name on purpose: without a
41
+ * detector, an author who copied an older example gets esbuild's generic
42
+ * `Could not resolve "primitive-sdk"`, which reads as a missing dependency
43
+ * rather than a rename. `RETIRED_SDK_MODULE` below is that detector, and
44
+ * `cli/tests/unit/retired-sdk-name-guard-3209.test.ts` allowlists exactly this
45
+ * site while proving the name appears nowhere else.
46
+ *
47
+ * The refusal is made TWICE, because one mechanism cannot see both halves:
48
+ *
49
+ * - the resolver plugin catches a runtime import, which is the one that
50
+ * would otherwise reach the loader and fail there;
51
+ * - a scan of the authored source catches the TYPE-ONLY spellings —
52
+ * `import type … from`, `export type … from`, and a plain named import
53
+ * used only in type position. TypeScript erases all three, and esbuild
54
+ * erases them before any resolver callback runs, so the plugin never sees
55
+ * a specifier to compare. Those imports build and push silently, leaving
56
+ * the stored source teaching an import that no longer exists.
57
+ *
58
+ * The scan is anchored at the start of a line so that prose about the retired
59
+ * name — a `//` comment, a `*` doc-comment line, a string holding an example —
60
+ * does not refuse a push. Missing an import someone hid mid-line is the safe
61
+ * direction to be wrong in; refusing a valid push is not.
62
+ *
63
+ * ── The canonical envelope encoding ──────────────────────────────────────
64
+ *
65
+ * `canonicalFunctionEnvelopeBytes` reproduces `canonicalEnvelopeBytes` in
66
+ * `src/services/function-bundle-storage.ts` byte for byte. The server hashes
67
+ * the envelope to decide whether a push is a no-op; the CLI hashes it to decide
68
+ * whether to make the call at all, and the two answers have to agree or a push
69
+ * the CLI called unchanged lands as a new version (or worse, the reverse).
70
+ * `cli/tests/unit/function-bundle-3179.test.ts` pins them against each other.
71
+ */
72
+ import * as esbuild from "esbuild";
73
+ import { createHash } from "crypto";
74
+ import { existsSync, readFileSync, realpathSync } from "fs";
75
+ import { isAbsolute, relative, resolve, sep } from "path";
76
+ /** The module the loader supplies; never bundled. */
77
+ export const PRIMITIVE_FUNCTIONS_MODULE = "primitive-functions";
78
+ /** What that module was called before #3209. Refused at push, by name. */
79
+ export const RETIRED_SDK_MODULE = "primitive-sdk";
80
+ /** The refusal both detectors report, so an author reads one sentence. */
81
+ const retiredModuleRefusal = () => `the '${RETIRED_SDK_MODULE}' module was renamed: import from ` +
82
+ `'${PRIMITIVE_FUNCTIONS_MODULE}' instead`;
83
+ /**
84
+ * Import and export forms naming the retired module, in the type-only
85
+ * spellings esbuild erases before the resolver plugin can see them (see the
86
+ * module note). Anchored at the start of a line, and the specifier must be the
87
+ * WHOLE quoted string, so `primitive-sdk-utils` and `./primitive-sdk.js` are
88
+ * untouched — the same exact match the plugin makes.
89
+ */
90
+ const RETIRED_IMPORT_FORMS = [
91
+ // `import type { X } from "…"`, `export type { X } from "…"`, `export * from
92
+ // "…"`, and every value spelling in between, on one line.
93
+ new RegExp(`^[ \\t]*(?:import|export)[ \\t\\w*{},$]*[ \\t]from[ \\t]*(['"])${RETIRED_SDK_MODULE}\\1`, "m"),
94
+ // The tail of a multi-line named list: `} from "…"`.
95
+ new RegExp(`^[ \\t]*\\}[ \\t]*from[ \\t]*(['"])${RETIRED_SDK_MODULE}\\1`, "m"),
96
+ // A bare side-effect import. The plugin catches this one too; it costs
97
+ // nothing to be sure the scan agrees with it.
98
+ new RegExp(`^[ \\t]*import[ \\t]*(['"])${RETIRED_SDK_MODULE}\\1`, "m"),
99
+ ];
100
+ /** Whether an authored source imports the retired module in any spelling. */
101
+ export function importsRetiredModule(source) {
102
+ return RETIRED_IMPORT_FORMS.some((pattern) => pattern.test(source));
103
+ }
104
+ /** Matches the server's `FUNCTION_ENVELOPE_SCHEMA_VERSION`. */
105
+ /**
106
+ * 2 since #3187: the envelope carries the collected query MANIFEST.
107
+ *
108
+ * Bumped rather than added quietly, because the encoding the hash is taken
109
+ * over changed: the manifest is part of config-version identity (D3187-SO-005)
110
+ * precisely so a manifest change makes a new version and a collector fix can
111
+ * reach a tree that was pushed before it.
112
+ */
113
+ export const FUNCTION_ENVELOPE_SCHEMA_VERSION = 2;
114
+ /** A push that cannot proceed: a missing entry, a build error, or an escape. */
115
+ export class FunctionBuildError extends Error {
116
+ constructor(message) {
117
+ super(message);
118
+ this.name = "FunctionBuildError";
119
+ }
120
+ }
121
+ /**
122
+ * The canonical encoding both sides hash. Fixed key order, sources sorted by
123
+ * path — see the module note; this must stay identical to the server's.
124
+ */
125
+ export function canonicalFunctionEnvelopeBytes(envelope) {
126
+ const canonical = {
127
+ schemaVersion: envelope.schemaVersion,
128
+ entry: envelope.entry,
129
+ toml: envelope.toml,
130
+ sources: [...envelope.sources]
131
+ .map((s) => ({ path: s.path, content: s.content }))
132
+ .sort((a, b) => (a.path < b.path ? -1 : a.path > b.path ? 1 : 0)),
133
+ bundle: envelope.bundle,
134
+ // #3187 — inside the hash, so a manifest change is a new version.
135
+ // `null` rather than absent when there is none, so the encoding of a
136
+ // manifest-less push is stable rather than depending on a missing key.
137
+ manifest: envelope.manifest ?? null,
138
+ // #3455 — the twin of the server's rule: the key is emitted ONLY when
139
+ // there is a schema, so a tree with no `models/models.toml` builds the
140
+ // same bytes it built before this change and its no-op detection is
141
+ // intact. `undefined` would be dropped by `JSON.stringify` anyway; the
142
+ // spread says the rule rather than relying on that.
143
+ ...(typeof envelope.documentSchema === "string" && envelope.documentSchema
144
+ ? { documentSchema: envelope.documentSchema }
145
+ : {}),
146
+ };
147
+ return new TextEncoder().encode(JSON.stringify(canonical));
148
+ }
149
+ export function functionEnvelopeHash(envelope) {
150
+ return createHash("sha256")
151
+ .update(Buffer.from(canonicalFunctionEnvelopeBytes(envelope)))
152
+ .digest("hex");
153
+ }
154
+ /** POSIX spelling, so a Windows push stores the same paths a macOS one does. */
155
+ const toPosix = (value) => value.split(sep).join("/");
156
+ /** Whether a tree-relative path names a `node_modules` file. */
157
+ export function isDependencyPath(path) {
158
+ return path.split("/").includes("node_modules");
159
+ }
160
+ /**
161
+ * `null` when `candidate` is inside `root`, else the tree-relative-ish spelling
162
+ * to name in the refusal. Lexical only — the caller realpaths first.
163
+ */
164
+ function outsideRoot(root, candidate) {
165
+ const rel = relative(root, candidate);
166
+ if (rel === "" || (!rel.startsWith("..") && !isAbsolute(rel)))
167
+ return null;
168
+ return toPosix(rel);
169
+ }
170
+ function escapeRefusal(what, path) {
171
+ return new FunctionBuildError(`${what} '${path}' resolves outside the config tree root. ` +
172
+ "Filesystem imports must stay inside the config tree; npm packages are " +
173
+ "imported by name and inlined into the bundle.");
174
+ }
175
+ /**
176
+ * Build one function's bundle and collect its authored sources.
177
+ *
178
+ * Throws `FunctionBuildError` — never a raw esbuild error — so `config push`
179
+ * has one thing to report and nothing is pushed for that function.
180
+ */
181
+ export async function buildFunctionBundle(options) {
182
+ const { configDir, entry, functionKey } = options;
183
+ const treeRoot = realpathSync(resolve(configDir));
184
+ // 1. The entry, lexically. An escaping entry is refused as an escape even
185
+ // when the file it names does not exist — "no such file" would be a
186
+ // misleading answer to `entry = "../../etc/passwd"`.
187
+ const entryAbs = resolve(treeRoot, entry);
188
+ const entryEscape = outsideRoot(treeRoot, entryAbs);
189
+ if (entryEscape !== null)
190
+ throw escapeRefusal("entry", toPosix(entry));
191
+ if (!existsSync(entryAbs)) {
192
+ throw new FunctionBuildError(`function '${functionKey}': entry file '${toPosix(entry)}' does not exist`);
193
+ }
194
+ // 2. …and after symlinks.
195
+ const entryReal = realpathSync(entryAbs);
196
+ if (outsideRoot(treeRoot, entryReal) !== null) {
197
+ throw escapeRefusal("entry", toPosix(entry));
198
+ }
199
+ const entryRelative = toPosix(relative(treeRoot, entryReal));
200
+ // Which files a BARE specifier reached. Membership — not the presence of a
201
+ // `node_modules` segment in the path — is what exempts a file from the tree
202
+ // boundary, so a relative or absolute import can never buy the exemption by
203
+ // pointing at a `node_modules` directory (see the module note).
204
+ const dependencyFiles = new Set();
205
+ const rememberDependency = (path) => {
206
+ if (!path)
207
+ return;
208
+ dependencyFiles.add(path);
209
+ try {
210
+ dependencyFiles.add(realpathSync(path));
211
+ }
212
+ catch {
213
+ /* a virtual or already-resolved path; the raw spelling is enough */
214
+ }
215
+ };
216
+ const isDependencyFile = (path) => {
217
+ if (dependencyFiles.has(path))
218
+ return true;
219
+ try {
220
+ return dependencyFiles.has(realpathSync(path));
221
+ }
222
+ catch {
223
+ return false;
224
+ }
225
+ };
226
+ const importBoundaryPlugin = {
227
+ name: "primitive-function-import-boundary",
228
+ setup(build) {
229
+ build.onResolve({ filter: /.*/ }, async (args) => {
230
+ // The nested `build.resolve` below re-enters this callback; the marker
231
+ // is what stops it recursing forever.
232
+ if (args.pluginData?.primitiveBoundaryResolved)
233
+ return null;
234
+ if (args.kind === "entry-point")
235
+ return null;
236
+ // The retired specifier, refused before esbuild can report it as a
237
+ // missing package (#3209). An EXACT match only: `primitive-sdk-utils`
238
+ // is a different package and `./primitive-sdk.ts` is a tree-local file,
239
+ // and both still resolve normally.
240
+ if (args.path === RETIRED_SDK_MODULE) {
241
+ return { errors: [{ text: retiredModuleRefusal() }] };
242
+ }
243
+ const bare = !args.path.startsWith(".") && !isAbsolute(args.path);
244
+ // A dependency's own relative imports are dependency files too — the
245
+ // exemption is inherited down the package's internal graph.
246
+ const fromDependency = !!args.importer && isDependencyFile(args.importer);
247
+ if (!bare && !fromDependency)
248
+ return null;
249
+ const resolved = await build.resolve(args.path, {
250
+ importer: args.importer,
251
+ namespace: args.namespace,
252
+ resolveDir: args.resolveDir,
253
+ kind: args.kind,
254
+ pluginData: { primitiveBoundaryResolved: true },
255
+ });
256
+ // Let esbuild resolve (and report) it the way it would have; nothing
257
+ // was recorded, so an unresolvable import stays esbuild's error.
258
+ if (resolved.errors.length > 0)
259
+ return null;
260
+ if (!resolved.external && resolved.path) {
261
+ rememberDependency(resolved.path);
262
+ }
263
+ return resolved;
264
+ });
265
+ },
266
+ };
267
+ let result;
268
+ try {
269
+ result = await esbuild.build({
270
+ entryPoints: [entryRelative],
271
+ absWorkingDir: treeRoot,
272
+ bundle: true,
273
+ write: false,
274
+ metafile: true,
275
+ format: "esm",
276
+ platform: "neutral",
277
+ target: "es2022",
278
+ // The loader supplies it; see the module note.
279
+ external: [PRIMITIVE_FUNCTIONS_MODULE],
280
+ plugins: [importBoundaryPlugin],
281
+ logLevel: "silent",
282
+ });
283
+ }
284
+ catch (error) {
285
+ const messages = Array.isArray(error?.errors)
286
+ ? error.errors.map((e) => {
287
+ const where = e?.location?.file
288
+ ? toPosix(String(e.location.file))
289
+ : toPosix(entry);
290
+ const line = e?.location?.line ? `:${e.location.line}` : "";
291
+ return ` ${where}${line}: ${e?.text ?? "build error"}`;
292
+ })
293
+ : [` ${toPosix(entry)}: ${error?.message ?? String(error)}`];
294
+ throw new FunctionBuildError(`function '${functionKey}' failed to build:\n${messages.join("\n")}`);
295
+ }
296
+ const output = result.outputFiles?.[0];
297
+ if (!output) {
298
+ throw new FunctionBuildError(`function '${functionKey}': the build produced no output for '${toPosix(entry)}'`);
299
+ }
300
+ const bundle = Buffer.from(output.contents);
301
+ // 3. Every file the build actually read, from the metafile — the honest list,
302
+ // rather than a re-parse of the imports. A file a BARE specifier reached is
303
+ // an inlined dependency and is dropped; every other input is a filesystem
304
+ // import, and one outside the tree is an escape esbuild followed that the
305
+ // push refuses.
306
+ const sources = [];
307
+ for (const input of Object.keys(result.metafile?.inputs ?? {})) {
308
+ const path = toPosix(input);
309
+ const absolute = resolve(treeRoot, input);
310
+ if (isDependencyFile(absolute))
311
+ continue;
312
+ if (path.startsWith("..") || isAbsolute(input)) {
313
+ throw escapeRefusal("import", path);
314
+ }
315
+ if (outsideRoot(treeRoot, realpathSync(absolute)) !== null) {
316
+ throw escapeRefusal("import", path);
317
+ }
318
+ // In-tree `node_modules` reached by a filesystem import: inside the
319
+ // boundary, so it builds — but `config pull` refuses to write a stored
320
+ // `node_modules` path, so capturing it would promise a round trip that
321
+ // cannot be kept.
322
+ if (isDependencyPath(path))
323
+ continue;
324
+ const content = readFileSync(absolute);
325
+ // The type-only half of the retired-specifier refusal (see the module
326
+ // note): esbuild erased these imports before the plugin could see them,
327
+ // so the build succeeded and the source would have been stored as pushed.
328
+ if (importsRetiredModule(content.toString("utf-8"))) {
329
+ throw new FunctionBuildError(`function '${functionKey}' failed to build:\n ${path}: ${retiredModuleRefusal()}`);
330
+ }
331
+ sources.push({ path, content });
332
+ }
333
+ sources.sort((a, b) => (a.path < b.path ? -1 : a.path > b.path ? 1 : 0));
334
+ return {
335
+ entry: entryRelative,
336
+ bundle,
337
+ contentHash: createHash("sha256").update(bundle).digest("hex"),
338
+ sources,
339
+ };
340
+ }
341
+ //# sourceMappingURL=function-bundle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"function-bundle.js","sourceRoot":"","sources":["../../../src/lib/function-bundle.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,123 @@
1
+ /**
2
+ * Collecting a function's query manifest at push time (#3187, project
3
+ * `server-functions` phase 5).
4
+ *
5
+ * ── Why the tree has to RUN ──────────────────────────────────────────────
6
+ *
7
+ * `defineQuery(name, { models, params, cache, run })` is a registration
8
+ * helper, and registrations are ordinary code: a name can be computed, a
9
+ * models list can come from a constant another file exports, a whole set can
10
+ * be registered in a loop. Static extraction would see none of that. So the
11
+ * manifest is collected by BUILDING the tree a second time with
12
+ * `primitive-functions` aliased to a recording stub and executing the result.
13
+ *
14
+ * ── Why it runs somewhere else ───────────────────────────────────────────
15
+ *
16
+ * D3187-SO-006. A function bundle inlines its tree-local and npm imports, so
17
+ * "execute the bundle" means "run arbitrary module scope" — with, if it ran
18
+ * inside the CLI, the developer's environment, credentials, filesystem and
19
+ * network. That is a large step up from what `config push` did before, which
20
+ * was to type-erase and bundle the same code without running it.
21
+ *
22
+ * So collection runs in a spawned child `node` with:
23
+ *
24
+ * - a SCRUBBED environment: an explicit minimal pass-through, so a token in
25
+ * the developer's shell is not readable by a project's module scope;
26
+ * - the config tree as the working directory;
27
+ * - a hard timeout, killed with `SIGKILL`, so a loop in a tree is a named
28
+ * refusal rather than a hung push;
29
+ * - its result read back over a structured pipe (a sentinel-framed line on
30
+ * stdout), so a tree that prints is not mistaken for a tree that reported.
31
+ *
32
+ * What remains is the trust a developer already extends to their own tree by
33
+ * running its build: this is npm-postinstall-equivalent, and the docs say so.
34
+ * Full network denial was considered and not taken (Node offers no reliable
35
+ * in-process cutoff), and so was static extraction (it cannot see computed
36
+ * registrations).
37
+ *
38
+ * ── What the manifest is, and is not ─────────────────────────────────────
39
+ *
40
+ * Documentation. Since #3279 function code acts as the system, so the
41
+ * manifest authorizes nothing anywhere: its one job is telling an operator
42
+ * what a version registered and what it TOUCHES — the models its code names
43
+ * and the families it reaches — through `primitive functions get`. That
44
+ * second half (schema version 2) comes from a STATIC SCAN of the built
45
+ * bundle: the direct records API names a model in a literal request argument
46
+ * with neither a registration nor `.model()` (D3279-006), so the run above
47
+ * cannot see it and the text can. A name the scan cannot resolve — a computed
48
+ * `modelName`, a `.model(variable)` — is marked `dynamicModels` rather than
49
+ * dropped, which is the difference between "names none" and "names these,
50
+ * and possibly more".
51
+ */
52
+ /** The manifest encoding, versioned with the envelope that carries it. */
53
+ export declare const FUNCTION_MANIFEST_SCHEMA_VERSION = 2;
54
+ /** How long a tree's module scope may run before collection gives up. */
55
+ export declare const COLLECT_TIMEOUT_MS = 20000;
56
+ /** A push that cannot proceed because its manifest could not be collected. */
57
+ export declare class FunctionCollectError extends Error {
58
+ constructor(message: string);
59
+ }
60
+ export interface CollectedQuery {
61
+ name: string;
62
+ /** `query` or `mutation` — which helper registered it. */
63
+ kind: "query" | "mutation";
64
+ /** The models the author declared it touches. */
65
+ models: string[];
66
+ /** Declared parameters, by name. `$caller` params are marked here. */
67
+ params: Record<string, {
68
+ type?: string;
69
+ caller?: boolean;
70
+ default?: unknown;
71
+ }>;
72
+ /** The declared cache policy, or null when caching is off. */
73
+ cache: {
74
+ ttlMs: number;
75
+ } | null;
76
+ /** True when every declared parameter binding is `$caller`-scoped. */
77
+ callerScoped: boolean;
78
+ }
79
+ export interface FunctionManifest {
80
+ schemaVersion: number;
81
+ queries: CollectedQuery[];
82
+ /** Every model the bundle names, deduplicated and sorted (#3279). */
83
+ models: string[];
84
+ /** Every `ctx.api.<family>` and ctx-helper family the bundle reaches. */
85
+ families: string[];
86
+ /** A model name the scan could not resolve; "and possibly more". */
87
+ dynamicModels: boolean;
88
+ }
89
+ export declare function scanBundleForManifest(bundle: string): {
90
+ models: string[];
91
+ families: string[];
92
+ dynamicModels: boolean;
93
+ };
94
+ /**
95
+ * The recording stub the collect build substitutes for
96
+ * `primitive-functions`.
97
+ *
98
+ * It records what was registered and does nothing else: `defineFunction` and
99
+ * every other export are inert, so a module that calls one at import time
100
+ * neither fails nor has an effect.
101
+ */
102
+ export declare const COLLECT_STUB_SOURCE = "\nconst registry = (globalThis.__PRIMITIVE_COLLECT_REGISTRY__ ||= []);\n\n// The default-coercion rule the SDK applies at registration (#3281,\n// D3281-SO-005), spelled here too so a default the declared type cannot\n// coerce is refused at PUSH \u2014 this stub is what push runs \u2014 rather than at\n// the first invocation. The vendored grammar (`coerceParamDefault` in\n// generated-config-surfaces.ts) is the same rule and re-checks the manifest.\nconst SCALAR_TYPES = [\"string\", \"number\", \"boolean\", \"any\"];\nfunction coerceScalar(type, value) {\n if (type === \"number\") {\n const n = typeof value === \"number\" ? value : Number(value);\n if (typeof value === \"boolean\" || value === null || value === \"\" || !Number.isFinite(n)) {\n return { ok: false, reason: \"must be a number\" };\n }\n return { ok: true, value: n };\n }\n if (type === \"boolean\") {\n if (typeof value === \"boolean\") return { ok: true, value };\n if (value === \"true\") return { ok: true, value: true };\n if (value === \"false\") return { ok: true, value: false };\n return { ok: false, reason: \"must be a boolean\" };\n }\n if (type === \"string\") {\n if (typeof value !== \"string\") return { ok: false, reason: \"must be a string\" };\n return { ok: true, value };\n }\n return { ok: true, value };\n}\nfunction coerceDefault(spec, value) {\n if (spec.type === \"array\") {\n if (!Array.isArray(value)) return { ok: false, reason: \"must be an array\" };\n const itemType = spec.items && spec.items.type ? String(spec.items.type) : \"any\";\n const out = [];\n for (const element of value) {\n const coerced = coerceScalar(itemType, element);\n if (!coerced.ok) return { ok: false, reason: \"every element \" + coerced.reason };\n out.push(coerced.value);\n }\n return { ok: true, value: out };\n }\n return coerceScalar(spec.type === undefined ? \"any\" : String(spec.type), value);\n}\n\nfunction record(kind, name, config) {\n const c = config || {};\n const params = {};\n for (const [key, value] of Object.entries(c.params || {})) {\n const spec = value && typeof value === \"object\" ? value : { type: String(value) };\n const entry = {};\n const fail = (message) => {\n throw new Error(\"'\" + name + \"': parameter '\" + key + \"' \" + message);\n };\n if (spec.type !== undefined) entry.type = String(spec.type);\n if (entry.type === \"array\") {\n if (spec.items !== undefined && spec.items !== null) {\n const itemType =\n spec.items && typeof spec.items === \"object\" ? String(spec.items.type ?? \"\") : \"\";\n if (!SCALAR_TYPES.includes(itemType)) {\n fail(\"declares an `items` type outside \" + SCALAR_TYPES.join(\", \") + \".\");\n }\n entry.items = { type: itemType };\n }\n if (spec.caller === true) fail(\"is an array bound to $caller; `caller` is a scalar binding.\");\n }\n if (spec.default !== undefined) {\n const coerced = coerceDefault(entry, spec.default);\n if (!coerced.ok) fail(\"has a default that \" + coerced.reason + \".\");\n entry.default = coerced.value;\n }\n if (spec.caller === true || spec === \"$caller\" || spec.type === \"$caller\") {\n entry.caller = true;\n }\n params[String(key)] = entry;\n }\n const declaredCaller = Object.values(params).some((p) => p.caller === true);\n registry.push({\n kind,\n name: String(name),\n models: Array.isArray(c.models) ? c.models.map(String) : [],\n params,\n cache:\n c.cache && typeof c.cache === \"object\" && Number(c.cache.ttlMs) > 0\n ? { ttlMs: Number(c.cache.ttlMs) }\n : null,\n callerScoped: declaredCaller,\n });\n return async () => {\n throw new Error(\n \"'\" + name + \"' was called during manifest collection; a registration's \" +\n \"`run` only executes inside a real invocation.\"\n );\n };\n}\n\n// The PUBLIC surface, all of it. An ESM import of a name a module does not\n// export is a build error, so a stub missing one export refuses a tree the\n// sandbox would have run \u2014 collection is mandatory, so that is a valid\n// function that cannot be pushed at all (CR3187-007). The constants carry the\n// runtime's own values so a registration computed from one collects the same\n// way it will run.\nexport const SDK_STUB_VERSION = \"collect\";\nexport const MAX_QUERY_CACHE_TTL_MS = 60000;\nexport const PMAP_DEFAULT_CONCURRENCY = 8;\nexport function defineQuery(name, config) { return record(\"query\", name, config); }\nexport function defineMutation(name, config) { return record(\"mutation\", name, config); }\nexport function defineFunction(keyOrHandler, maybeHandler) {\n // The KEYED form (#3281) returns a wrapper CARRYING its key, exactly as the\n // baked SDK's does. That is what push reads: the child resolves the callable\n // the bootstrap would select and compares THAT key to the file's\n // (D3281-SO-006). The registry entry is the child's report of what the\n // module scope did; it is not what the check consults, because a keyed\n // handler an entry merely imports for composition registers here too.\n if (typeof keyOrHandler === \"string\" || maybeHandler !== undefined) {\n registry.push({ kind: \"function\", name: String(keyOrHandler) });\n const wrapped = function (...args) {\n return maybeHandler(...args);\n };\n wrapped.functionKey = String(keyOrHandler);\n return wrapped;\n }\n return keyOrHandler;\n}\nexport function pMap(items, mapper) { return Promise.all((items || []).map(mapper)); }\nexport function ulid() { return \"00000000000000000000000000\"; }\nexport const stepPolicy = new Proxy({}, { get: () => ({}) });\n// #3482 \u2014 the runtime surface, and `assertRuntime` is INERT here on purpose.\n// Collection has no runtime: this child process exists to learn what a tree\n// registers, and there is nothing for an assertion to be about. A stub that\n// threw would refuse exactly the functions the assertion exists for \u2014 and the\n// placement the guide teaches is module scope, which collection runs.\nexport function assertRuntime() {}\nexport class FunctionRuntimeError extends Error {\n constructor(message, runtime, required) {\n super(message);\n this.name = \"FUNCTION_RUNTIME_REFUSED\";\n this.runtime = runtime;\n this.required = required;\n }\n}\nexport default {\n SDK_STUB_VERSION,\n defineFunction,\n defineQuery,\n defineMutation,\n pMap,\n ulid,\n assertRuntime,\n FunctionRuntimeError,\n};\n";
103
+ /**
104
+ * Collect one function's manifest.
105
+ *
106
+ * Throws `FunctionCollectError` for every failure — a build error, a module
107
+ * that throws at import, a loop that outlives the bound, or output that is not
108
+ * the framed result — because a push whose manifest could not be collected is
109
+ * refused rather than pushed without one (D3187-SO-005: the manifest is part
110
+ * of the envelope, so "later" would mean a different version).
111
+ */
112
+ export declare function collectFunctionManifest(options: {
113
+ configDir: string;
114
+ entry: string;
115
+ functionKey: string;
116
+ timeoutMs?: number;
117
+ /**
118
+ * The BUILT bundle's source, for the static scan (#3279). The collect
119
+ * bundle below aliases the SDK to a stub and is not what the platform
120
+ * runs; the real bundle is, and its literals are what the scan reads.
121
+ */
122
+ bundle?: string;
123
+ }): Promise<FunctionManifest>;