@cosmicdrift/kumiko-framework 0.1.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 (388) hide show
  1. package/README.md +159 -0
  2. package/package.json +91 -0
  3. package/src/__tests__/anonymous-access.integration.ts +325 -0
  4. package/src/__tests__/error-contract.integration.ts +435 -0
  5. package/src/__tests__/field-access.integration.ts +269 -0
  6. package/src/__tests__/full-stack.integration.ts +914 -0
  7. package/src/__tests__/ownership.integration.ts +449 -0
  8. package/src/__tests__/reference-data.integration.ts +198 -0
  9. package/src/__tests__/transition-guard.integration.ts +340 -0
  10. package/src/api/__tests__/api.test.ts +337 -0
  11. package/src/api/__tests__/auth-middleware-transport.test.ts +80 -0
  12. package/src/api/__tests__/auth-routes-cookie.test.ts +179 -0
  13. package/src/api/__tests__/batch.integration.ts +404 -0
  14. package/src/api/__tests__/body-limit.test.ts +88 -0
  15. package/src/api/__tests__/csrf-middleware.test.ts +97 -0
  16. package/src/api/__tests__/dispatcher-live.integration.ts +216 -0
  17. package/src/api/__tests__/metrics-endpoint.test.ts +126 -0
  18. package/src/api/__tests__/nested-write.integration.ts +213 -0
  19. package/src/api/__tests__/readiness.test.ts +76 -0
  20. package/src/api/__tests__/request-id-middleware.test.ts +72 -0
  21. package/src/api/__tests__/sse-broker.test.ts +58 -0
  22. package/src/api/__tests__/sse-route.test.ts +112 -0
  23. package/src/api/anonymous-cookie.ts +60 -0
  24. package/src/api/api-constants.ts +64 -0
  25. package/src/api/auth-middleware.ts +418 -0
  26. package/src/api/auth-routes.ts +982 -0
  27. package/src/api/csrf-middleware.ts +77 -0
  28. package/src/api/index.ts +31 -0
  29. package/src/api/jwt.ts +66 -0
  30. package/src/api/observability-middleware.ts +89 -0
  31. package/src/api/readiness.ts +132 -0
  32. package/src/api/request-context.ts +49 -0
  33. package/src/api/request-id-middleware.ts +50 -0
  34. package/src/api/route-registrars.ts +195 -0
  35. package/src/api/routes.ts +135 -0
  36. package/src/api/server.ts +640 -0
  37. package/src/api/sse-broker.ts +71 -0
  38. package/src/api/sse-route.ts +62 -0
  39. package/src/api/tokens.ts +16 -0
  40. package/src/db/__tests__/apply-entity-event-tenant.integration.ts +159 -0
  41. package/src/db/__tests__/compound-types.test.ts +114 -0
  42. package/src/db/__tests__/connection-options.test.ts +68 -0
  43. package/src/db/__tests__/cursor.test.ts +41 -0
  44. package/src/db/__tests__/db-helpers.test.ts +369 -0
  45. package/src/db/__tests__/dialect-instant.test.ts +50 -0
  46. package/src/db/__tests__/drizzle-helpers.integration.ts +186 -0
  47. package/src/db/__tests__/drizzle-table-types.test.ts +162 -0
  48. package/src/db/__tests__/encryption.test.ts +39 -0
  49. package/src/db/__tests__/event-store-executor-list.integration.ts +313 -0
  50. package/src/db/__tests__/event-store-executor.integration.ts +235 -0
  51. package/src/db/__tests__/implicit-projection-equivalence.integration.ts +304 -0
  52. package/src/db/__tests__/located-timestamp.test.ts +184 -0
  53. package/src/db/__tests__/money.test.ts +199 -0
  54. package/src/db/__tests__/multi-row-insert.integration.ts +76 -0
  55. package/src/db/__tests__/parse-auto-verb.test.ts +70 -0
  56. package/src/db/__tests__/required-not-null-migration-safety.integration.ts +105 -0
  57. package/src/db/__tests__/row-helpers.test.ts +59 -0
  58. package/src/db/__tests__/schema-migration.integration.ts +273 -0
  59. package/src/db/__tests__/table-builder-indexes.test.ts +153 -0
  60. package/src/db/__tests__/table-builder-required.test.ts +216 -0
  61. package/src/db/__tests__/tenant-db.integration.ts +606 -0
  62. package/src/db/__tests__/unique-violation-mapping.integration.ts +166 -0
  63. package/src/db/apply-entity-event.ts +188 -0
  64. package/src/db/assert-exists-in.ts +59 -0
  65. package/src/db/compound-types.ts +47 -0
  66. package/src/db/connection.ts +104 -0
  67. package/src/db/cursor.ts +83 -0
  68. package/src/db/dialect.ts +109 -0
  69. package/src/db/eagerload.ts +174 -0
  70. package/src/db/encryption.ts +39 -0
  71. package/src/db/event-store-executor.ts +906 -0
  72. package/src/db/index.ts +55 -0
  73. package/src/db/located-timestamp.ts +114 -0
  74. package/src/db/money.ts +120 -0
  75. package/src/db/pg-error.ts +46 -0
  76. package/src/db/reference-data.ts +77 -0
  77. package/src/db/row-helpers.ts +53 -0
  78. package/src/db/schema-inspection.ts +25 -0
  79. package/src/db/table-builder.ts +475 -0
  80. package/src/db/tenant-db.ts +434 -0
  81. package/src/engine/__tests__/auth-claims-registrar.test.ts +74 -0
  82. package/src/engine/__tests__/boot-validator-located-timestamps.test.ts +108 -0
  83. package/src/engine/__tests__/boot-validator.test.ts +1865 -0
  84. package/src/engine/__tests__/build-app-schema.test.ts +154 -0
  85. package/src/engine/__tests__/claim-keys.test.ts +274 -0
  86. package/src/engine/__tests__/config-helpers.test.ts +236 -0
  87. package/src/engine/__tests__/effective-features.test.ts +86 -0
  88. package/src/engine/__tests__/engine.test.ts +1461 -0
  89. package/src/engine/__tests__/entity-handlers.test.ts +274 -0
  90. package/src/engine/__tests__/event-helpers.test.ts +68 -0
  91. package/src/engine/__tests__/extends-registrar.test.ts +159 -0
  92. package/src/engine/__tests__/factories-long-text.test.ts +84 -0
  93. package/src/engine/__tests__/factories-time.test.ts +158 -0
  94. package/src/engine/__tests__/field-predicates.test.ts +48 -0
  95. package/src/engine/__tests__/hook-phases.test.ts +132 -0
  96. package/src/engine/__tests__/identifiers.test.ts +35 -0
  97. package/src/engine/__tests__/lifecycle-hooks.test.ts +237 -0
  98. package/src/engine/__tests__/nav.test.ts +267 -0
  99. package/src/engine/__tests__/ownership.test.ts +421 -0
  100. package/src/engine/__tests__/parse-ref-target.test.ts +43 -0
  101. package/src/engine/__tests__/projection-helpers.test.ts +62 -0
  102. package/src/engine/__tests__/projection.test.ts +191 -0
  103. package/src/engine/__tests__/qualified-name.test.ts +264 -0
  104. package/src/engine/__tests__/resolve-config-or-param.test.ts +315 -0
  105. package/src/engine/__tests__/run-in.test.ts +38 -0
  106. package/src/engine/__tests__/schema-builder.test.ts +380 -0
  107. package/src/engine/__tests__/screen.test.ts +408 -0
  108. package/src/engine/__tests__/state-machine.test.ts +148 -0
  109. package/src/engine/__tests__/system-user.test.ts +57 -0
  110. package/src/engine/__tests__/validation-hooks.test.ts +71 -0
  111. package/src/engine/access.ts +23 -0
  112. package/src/engine/boot-validator.ts +1528 -0
  113. package/src/engine/build-app-schema.ts +125 -0
  114. package/src/engine/config-helpers.ts +115 -0
  115. package/src/engine/constants.ts +85 -0
  116. package/src/engine/create-app.ts +98 -0
  117. package/src/engine/define-feature.ts +702 -0
  118. package/src/engine/define-handler.ts +78 -0
  119. package/src/engine/define-roles.ts +19 -0
  120. package/src/engine/effective-features.ts +87 -0
  121. package/src/engine/entity-handlers.ts +364 -0
  122. package/src/engine/event-helpers.ts +73 -0
  123. package/src/engine/factories.ts +328 -0
  124. package/src/engine/feature-ast/__tests__/canonical-form.test.ts +416 -0
  125. package/src/engine/feature-ast/__tests__/parse-happy-path.test.ts +197 -0
  126. package/src/engine/feature-ast/__tests__/parse-real-features.test.ts +128 -0
  127. package/src/engine/feature-ast/__tests__/parse.test.ts +888 -0
  128. package/src/engine/feature-ast/__tests__/patch.test.ts +360 -0
  129. package/src/engine/feature-ast/__tests__/patcher.test.ts +469 -0
  130. package/src/engine/feature-ast/__tests__/render-roundtrip.test.ts +287 -0
  131. package/src/engine/feature-ast/extractors.ts +2562 -0
  132. package/src/engine/feature-ast/index.ts +105 -0
  133. package/src/engine/feature-ast/parse.ts +369 -0
  134. package/src/engine/feature-ast/patch.ts +525 -0
  135. package/src/engine/feature-ast/patcher.ts +518 -0
  136. package/src/engine/feature-ast/patterns.ts +434 -0
  137. package/src/engine/feature-ast/render.ts +602 -0
  138. package/src/engine/feature-ast/source-location.ts +45 -0
  139. package/src/engine/field-access.ts +120 -0
  140. package/src/engine/index.ts +254 -0
  141. package/src/engine/ownership.ts +337 -0
  142. package/src/engine/parse-ref-target.ts +22 -0
  143. package/src/engine/pattern-library/__tests__/library.test.ts +351 -0
  144. package/src/engine/pattern-library/index.ts +24 -0
  145. package/src/engine/pattern-library/library.ts +1117 -0
  146. package/src/engine/pattern-library/types.ts +255 -0
  147. package/src/engine/projection-helpers.ts +85 -0
  148. package/src/engine/qualified-name.ts +122 -0
  149. package/src/engine/read-claim.ts +31 -0
  150. package/src/engine/registry.ts +1325 -0
  151. package/src/engine/resolve-config-or-param.ts +153 -0
  152. package/src/engine/run-in.ts +29 -0
  153. package/src/engine/schema-builder.ts +175 -0
  154. package/src/engine/screen-filter-ops.ts +51 -0
  155. package/src/engine/state-machine.ts +70 -0
  156. package/src/engine/system-user.ts +32 -0
  157. package/src/engine/types/config.ts +306 -0
  158. package/src/engine/types/event-type-map.ts +37 -0
  159. package/src/engine/types/feature.ts +574 -0
  160. package/src/engine/types/fields.ts +422 -0
  161. package/src/engine/types/handlers.ts +742 -0
  162. package/src/engine/types/hooks.ts +142 -0
  163. package/src/engine/types/http-route.ts +54 -0
  164. package/src/engine/types/identifiers.ts +47 -0
  165. package/src/engine/types/index.ts +208 -0
  166. package/src/engine/types/nav.ts +46 -0
  167. package/src/engine/types/projection.ts +132 -0
  168. package/src/engine/types/relations.ts +51 -0
  169. package/src/engine/types/screen.ts +452 -0
  170. package/src/engine/types/workspace.ts +42 -0
  171. package/src/engine/validation.ts +33 -0
  172. package/src/entrypoint/__tests__/entrypoint-job-wiring.integration.ts +173 -0
  173. package/src/entrypoint/__tests__/split-deploy.integration.ts +297 -0
  174. package/src/entrypoint/index.ts +442 -0
  175. package/src/errors/__tests__/classes.test.ts +371 -0
  176. package/src/errors/__tests__/write-failures.test.ts +109 -0
  177. package/src/errors/classes.ts +249 -0
  178. package/src/errors/i18n/de.yaml +83 -0
  179. package/src/errors/i18n/en.yaml +80 -0
  180. package/src/errors/index.ts +41 -0
  181. package/src/errors/kumiko-error.ts +67 -0
  182. package/src/errors/reasons.ts +36 -0
  183. package/src/errors/serialize.ts +136 -0
  184. package/src/errors/transition-details.ts +30 -0
  185. package/src/errors/write-error-info.ts +123 -0
  186. package/src/errors/zod-bridge.ts +49 -0
  187. package/src/event-store/__tests__/admin-api.integration.ts +361 -0
  188. package/src/event-store/__tests__/event-store.integration.ts +584 -0
  189. package/src/event-store/__tests__/get-stream-version-perf.integration.ts +83 -0
  190. package/src/event-store/__tests__/perf.integration.ts +255 -0
  191. package/src/event-store/__tests__/snapshot.integration.ts +267 -0
  192. package/src/event-store/__tests__/upcaster-dead-letter.integration.ts +204 -0
  193. package/src/event-store/__tests__/upcaster.integration.ts +460 -0
  194. package/src/event-store/admin-api.ts +257 -0
  195. package/src/event-store/archive.ts +106 -0
  196. package/src/event-store/errors.ts +35 -0
  197. package/src/event-store/event-store.ts +405 -0
  198. package/src/event-store/events-schema.ts +90 -0
  199. package/src/event-store/index.ts +50 -0
  200. package/src/event-store/snapshot.ts +210 -0
  201. package/src/event-store/upcaster-dead-letter.ts +119 -0
  202. package/src/event-store/upcaster.ts +147 -0
  203. package/src/files/__tests__/content-disposition.test.ts +123 -0
  204. package/src/files/__tests__/file-field-column.integration.ts +103 -0
  205. package/src/files/__tests__/file-field-pipeline.integration.ts +211 -0
  206. package/src/files/__tests__/file-handle.test.ts +122 -0
  207. package/src/files/__tests__/files.integration.ts +830 -0
  208. package/src/files/__tests__/storage-tracking.integration.ts +153 -0
  209. package/src/files/content-disposition.ts +55 -0
  210. package/src/files/file-handle.ts +63 -0
  211. package/src/files/file-ref-table.ts +22 -0
  212. package/src/files/file-routes.ts +353 -0
  213. package/src/files/in-memory-provider.ts +62 -0
  214. package/src/files/index.ts +29 -0
  215. package/src/files/local-provider.ts +35 -0
  216. package/src/files/storage-tracking.ts +60 -0
  217. package/src/files/types.ts +118 -0
  218. package/src/i18n/__tests__/i18n.test.ts +72 -0
  219. package/src/i18n/index.ts +29 -0
  220. package/src/jobs/__tests__/job-event-trigger.integration.ts +172 -0
  221. package/src/jobs/__tests__/job-multi-trigger.integration.ts +144 -0
  222. package/src/jobs/__tests__/jobs.integration.ts +566 -0
  223. package/src/jobs/index.ts +2 -0
  224. package/src/jobs/job-runner.ts +574 -0
  225. package/src/lifecycle/__tests__/create-test-lifecycle.ts +19 -0
  226. package/src/lifecycle/__tests__/lifecycle-server.integration.ts +108 -0
  227. package/src/lifecycle/__tests__/lifecycle.test.ts +212 -0
  228. package/src/lifecycle/__tests__/signal-handlers.test.ts +106 -0
  229. package/src/lifecycle/index.ts +13 -0
  230. package/src/lifecycle/lifecycle.ts +160 -0
  231. package/src/lifecycle/signal-handlers.ts +62 -0
  232. package/src/logging/__tests__/pino-trace-bridge.test.ts +50 -0
  233. package/src/logging/index.ts +3 -0
  234. package/src/logging/pino-logger.ts +64 -0
  235. package/src/logging/types.ts +7 -0
  236. package/src/migrations/__tests__/compare-snapshots.test.ts +150 -0
  237. package/src/migrations/__tests__/detect-drift.integration.ts +320 -0
  238. package/src/migrations/__tests__/detect-projections-to-rebuild.integration.ts +134 -0
  239. package/src/migrations/__tests__/rebuild-marker.test.ts +79 -0
  240. package/src/migrations/index.ts +28 -0
  241. package/src/migrations/projection-detection.ts +149 -0
  242. package/src/migrations/rebuild-marker.ts +64 -0
  243. package/src/migrations/schema-drift.ts +395 -0
  244. package/src/observability/__tests__/console-provider.test.ts +67 -0
  245. package/src/observability/__tests__/metric-validator.test.ts +87 -0
  246. package/src/observability/__tests__/noop-provider.test.ts +82 -0
  247. package/src/observability/__tests__/observability.integration.ts +559 -0
  248. package/src/observability/__tests__/prometheus-meter.test.ts +144 -0
  249. package/src/observability/__tests__/recording-meter.test.ts +101 -0
  250. package/src/observability/__tests__/recording-tracer.test.ts +110 -0
  251. package/src/observability/__tests__/sensitive-filter.test.ts +98 -0
  252. package/src/observability/console-provider.ts +130 -0
  253. package/src/observability/context.ts +26 -0
  254. package/src/observability/fallback.ts +34 -0
  255. package/src/observability/ids.ts +25 -0
  256. package/src/observability/index.ts +79 -0
  257. package/src/observability/metric-validator.ts +86 -0
  258. package/src/observability/metrics-handle.ts +56 -0
  259. package/src/observability/noop-provider.ts +146 -0
  260. package/src/observability/prometheus-meter.ts +284 -0
  261. package/src/observability/recording-meter.ts +156 -0
  262. package/src/observability/recording-tracer.ts +198 -0
  263. package/src/observability/redis-wrapper.ts +132 -0
  264. package/src/observability/sensitive-filter.ts +108 -0
  265. package/src/observability/standard-metrics.ts +213 -0
  266. package/src/observability/types/index.ts +29 -0
  267. package/src/observability/types/metric.ts +56 -0
  268. package/src/observability/types/provider.ts +32 -0
  269. package/src/observability/types/span.ts +64 -0
  270. package/src/pipeline/__tests__/archive-stream.integration.ts +220 -0
  271. package/src/pipeline/__tests__/auth-claims-resolver.test.ts +279 -0
  272. package/src/pipeline/__tests__/cascade-handler.integration.ts +419 -0
  273. package/src/pipeline/__tests__/cascade-handler.test.ts +52 -0
  274. package/src/pipeline/__tests__/causation-chain.integration.ts +206 -0
  275. package/src/pipeline/__tests__/ctx-bridge.integration.ts +234 -0
  276. package/src/pipeline/__tests__/dispatcher.test.ts +379 -0
  277. package/src/pipeline/__tests__/distributed-lock.integration.ts +67 -0
  278. package/src/pipeline/__tests__/domain-events-projections.integration.ts +323 -0
  279. package/src/pipeline/__tests__/event-dedup.integration.ts +153 -0
  280. package/src/pipeline/__tests__/event-define-event-strict.integration.ts +202 -0
  281. package/src/pipeline/__tests__/event-dispatcher-lifecycle.integration.ts +220 -0
  282. package/src/pipeline/__tests__/event-dispatcher-multi-instance.integration.ts +423 -0
  283. package/src/pipeline/__tests__/event-dispatcher-pg-listen.integration.ts +123 -0
  284. package/src/pipeline/__tests__/event-dispatcher-recovery.integration.ts +202 -0
  285. package/src/pipeline/__tests__/event-dispatcher-second-audit.integration.ts +290 -0
  286. package/src/pipeline/__tests__/event-dispatcher-strict.test.ts +65 -0
  287. package/src/pipeline/__tests__/event-dispatcher.integration.ts +287 -0
  288. package/src/pipeline/__tests__/event-retention.integration.ts +239 -0
  289. package/src/pipeline/__tests__/fetch-for-writing.integration.ts +281 -0
  290. package/src/pipeline/__tests__/lifecycle-pipeline.test.ts +430 -0
  291. package/src/pipeline/__tests__/load-aggregate-query.integration.ts +266 -0
  292. package/src/pipeline/__tests__/msp-error-mode.integration.ts +149 -0
  293. package/src/pipeline/__tests__/msp-multi-hop.integration.ts +228 -0
  294. package/src/pipeline/__tests__/msp-rebuild.integration.ts +368 -0
  295. package/src/pipeline/__tests__/multi-stream-projection.integration.ts +341 -0
  296. package/src/pipeline/__tests__/perf-rebuild.integration.ts +147 -0
  297. package/src/pipeline/__tests__/projection-rebuild.integration.ts +551 -0
  298. package/src/pipeline/__tests__/query-projection.integration.ts +201 -0
  299. package/src/pipeline/__tests__/redis-pipeline.integration.ts +306 -0
  300. package/src/pipeline/append-event-core.ts +117 -0
  301. package/src/pipeline/auth-claims-resolver.ts +103 -0
  302. package/src/pipeline/cascade-handler.ts +113 -0
  303. package/src/pipeline/dispatcher.ts +1585 -0
  304. package/src/pipeline/distributed-lock.ts +37 -0
  305. package/src/pipeline/entity-cache.ts +113 -0
  306. package/src/pipeline/event-consumer-state.ts +108 -0
  307. package/src/pipeline/event-dedup.ts +23 -0
  308. package/src/pipeline/event-dispatcher.ts +1016 -0
  309. package/src/pipeline/event-retention.ts +154 -0
  310. package/src/pipeline/idempotency.ts +76 -0
  311. package/src/pipeline/index.ts +66 -0
  312. package/src/pipeline/lifecycle-pipeline.ts +409 -0
  313. package/src/pipeline/msp-rebuild.ts +242 -0
  314. package/src/pipeline/multi-stream-apply-context.ts +115 -0
  315. package/src/pipeline/projection-rebuild.ts +334 -0
  316. package/src/pipeline/projection-state.ts +72 -0
  317. package/src/pipeline/projections-runner.ts +56 -0
  318. package/src/pipeline/redis-keys.ts +11 -0
  319. package/src/pipeline/system-hooks.ts +190 -0
  320. package/src/random/__tests__/generate.test.ts +149 -0
  321. package/src/random/generate.ts +141 -0
  322. package/src/random/index.ts +8 -0
  323. package/src/random/words.ts +392 -0
  324. package/src/rate-limit/__tests__/dispatcher-l3.integration.ts +111 -0
  325. package/src/rate-limit/__tests__/middleware.integration.ts +189 -0
  326. package/src/rate-limit/__tests__/resolver.integration.ts +189 -0
  327. package/src/rate-limit/bucket.ts +36 -0
  328. package/src/rate-limit/index.ts +14 -0
  329. package/src/rate-limit/middleware.ts +152 -0
  330. package/src/rate-limit/resolver.ts +267 -0
  331. package/src/redis/__tests__/redis-options.test.ts +54 -0
  332. package/src/redis/index.ts +74 -0
  333. package/src/search/__tests__/meilisearch-adapter.integration.ts +236 -0
  334. package/src/search/__tests__/search-adapter.test.ts +256 -0
  335. package/src/search/in-memory-adapter.ts +123 -0
  336. package/src/search/index.ts +12 -0
  337. package/src/search/meilisearch-adapter.ts +106 -0
  338. package/src/search/types.ts +39 -0
  339. package/src/secrets/__tests__/dek-cache.test.ts +213 -0
  340. package/src/secrets/__tests__/env-master-key-provider.test.ts +119 -0
  341. package/src/secrets/__tests__/envelope.test.ts +74 -0
  342. package/src/secrets/__tests__/leak-guard.test.ts +92 -0
  343. package/src/secrets/__tests__/rotation.test.ts +149 -0
  344. package/src/secrets/dek-cache.ts +116 -0
  345. package/src/secrets/env-master-key-provider.ts +162 -0
  346. package/src/secrets/envelope.ts +55 -0
  347. package/src/secrets/index.ts +19 -0
  348. package/src/secrets/leak-guard.ts +87 -0
  349. package/src/secrets/rotation.ts +34 -0
  350. package/src/secrets/types.ts +107 -0
  351. package/src/stack/db.ts +104 -0
  352. package/src/stack/event-collector.ts +23 -0
  353. package/src/stack/index.ts +32 -0
  354. package/src/stack/redis.ts +44 -0
  355. package/src/stack/request-helper.ts +168 -0
  356. package/src/stack/table-helpers.ts +104 -0
  357. package/src/stack/test-stack.ts +357 -0
  358. package/src/stack/test-users.ts +37 -0
  359. package/src/testing/__tests__/e2e-generator.test.ts +230 -0
  360. package/src/testing/__tests__/ensure-entity-table.integration.ts +54 -0
  361. package/src/testing/access-assertions.ts +15 -0
  362. package/src/testing/assertions.ts +35 -0
  363. package/src/testing/e2e-generator.ts +465 -0
  364. package/src/testing/expect-error.ts +25 -0
  365. package/src/testing/handler-context.ts +125 -0
  366. package/src/testing/http-cookies.ts +52 -0
  367. package/src/testing/index.ts +41 -0
  368. package/src/testing/late-bound.ts +39 -0
  369. package/src/testing/mutable-master-key-provider.ts +31 -0
  370. package/src/testing/observability-recorder.ts +54 -0
  371. package/src/testing/shared-entities.ts +49 -0
  372. package/src/testing/utils.ts +1 -0
  373. package/src/testing/wait-for.ts +31 -0
  374. package/src/time/__tests__/polyfill.test.ts +73 -0
  375. package/src/time/__tests__/tz-context.test.ts +121 -0
  376. package/src/time/index.ts +21 -0
  377. package/src/time/polyfill.ts +70 -0
  378. package/src/time/tz-context.ts +107 -0
  379. package/src/ui-types/app-schema.ts +57 -0
  380. package/src/ui-types/index.ts +65 -0
  381. package/src/utils/__tests__/assert.test.ts +17 -0
  382. package/src/utils/__tests__/env-parse.test.ts +54 -0
  383. package/src/utils/assert.ts +18 -0
  384. package/src/utils/env-parse.ts +16 -0
  385. package/src/utils/ids.ts +16 -0
  386. package/src/utils/index.ts +5 -0
  387. package/src/utils/safe-json.ts +30 -0
  388. package/src/utils/serialization.ts +7 -0
@@ -0,0 +1,105 @@
1
+ // Public API of the feature-ast module. Consumers (Designer, AI patcher,
2
+ // CLI) import exclusively from here.
3
+
4
+ // Forwarded barrel — keeps the pattern-library reachable through
5
+ // @cosmicdrift/kumiko-framework/engine without forcing a separate sub-path import.
6
+ export type {
7
+ FormFieldLabel,
8
+ FormFieldSpec,
9
+ FormInputType,
10
+ PatternCategory,
11
+ PatternFormSchema,
12
+ } from "../pattern-library";
13
+ export { getPatternSchema, groupByCategory, PATTERN_LIBRARY } from "../pattern-library";
14
+ export type { ParseError, ParseResult } from "./parse";
15
+ export { parseFeatureFile, parseSourceFile } from "./parse";
16
+ export type { PatternChange, PatternId } from "./patch";
17
+ export {
18
+ addPattern,
19
+ applyChanges,
20
+ removePattern,
21
+ replacePattern,
22
+ SINGLETON_KINDS,
23
+ } from "./patch";
24
+ export type {
25
+ AddAuthClaimsArgs,
26
+ AddClaimKeyArgs,
27
+ AddConfigArgs,
28
+ AddDefineEventArgs,
29
+ AddEntityArgs,
30
+ AddEntityHookArgs,
31
+ AddEventMigrationArgs,
32
+ AddHookArgs,
33
+ AddHttpRouteArgs,
34
+ AddJobArgs,
35
+ AddMetricArgs,
36
+ AddMultiStreamProjectionArgs,
37
+ AddNavArgs,
38
+ AddNotificationArgs,
39
+ AddOptionalRequiresArgs,
40
+ AddProjectionArgs,
41
+ AddQueryHandlerArgs,
42
+ AddReadsConfigArgs,
43
+ AddReferenceDataArgs,
44
+ AddRelationArgs,
45
+ AddRequiresArgs,
46
+ AddScreenArgs,
47
+ AddSecretArgs,
48
+ AddToggleableArgs,
49
+ AddTranslationsArgs,
50
+ AddUseExtensionArgs,
51
+ AddWorkspaceArgs,
52
+ AddWriteHandlerArgs,
53
+ FeaturePatcher,
54
+ } from "./patcher";
55
+ export { createFeaturePatcher } from "./patcher";
56
+ export type {
57
+ AuthClaimsPattern,
58
+ ClaimKeyPattern,
59
+ ConfigPattern,
60
+ DefineEventPattern,
61
+ Editability,
62
+ EntityHookPattern,
63
+ // Static patterns
64
+ EntityPattern,
65
+ EventMigrationPattern,
66
+ ExtendsRegistrarPattern,
67
+ FeaturePattern,
68
+ FeaturePatternKind,
69
+ HookPattern,
70
+ HttpRoutePattern,
71
+ JobPattern,
72
+ MetricPattern,
73
+ MultiStreamProjectionPattern,
74
+ NavPattern,
75
+ NotificationPattern,
76
+ OptionalRequiresPattern,
77
+ ProjectionPattern,
78
+ QueryHandlerPattern,
79
+ ReadsConfigPattern,
80
+ ReferenceDataPattern,
81
+ RelationPattern,
82
+ RequiresPattern,
83
+ // Mixed patterns
84
+ ScreenPattern,
85
+ SecretPattern,
86
+ SystemScopePattern,
87
+ ToggleablePattern,
88
+ TranslationsPattern,
89
+ // Catch-all
90
+ UnknownPattern,
91
+ UseExtensionPattern,
92
+ WorkspacePattern,
93
+ WriteHandlerPattern,
94
+ } from "./patterns";
95
+ export { getEditability } from "./patterns";
96
+ export type { RenderFeatureFileInput } from "./render";
97
+ export {
98
+ FEATURE_FILE_VERSION,
99
+ renderFeatureFile,
100
+ renderPattern,
101
+ renderValue,
102
+ VERSION_HEADER,
103
+ } from "./render";
104
+ export type { SourceLocation, SourcePosition } from "./source-location";
105
+ export { sourceLocationFromNode } from "./source-location";
@@ -0,0 +1,369 @@
1
+ // parseFeatureFile — entry-point for AST pattern detection. Reads a
2
+ // `defineFeature.ts` file, walks the `setup(r => { ... })` callback,
3
+ // and emits one FeaturePattern per recognised `r.*` call.
4
+ //
5
+ // **Pipeline position:**
6
+ //
7
+ // ┌──────────────────┐ parseFeatureFile ┌─────────────────────┐
8
+ // │ feature-file.ts │ ──────────────────────► │ ParseResult │
9
+ // │ (defineFeature │ │ - featureName │
10
+ // │ with r.* calls) │ │ - patterns: FP[] │
11
+ // └──────────────────┘ │ - errors: PE[] │
12
+ // └─────────────────────┘
13
+ //
14
+ // **What is NOT extracted:**
15
+ // - Imports, helper functions, local consts between the `r.*` calls.
16
+ // Those stay in the file buffer and survive every patch unchanged.
17
+ // - Top-level code outside `defineFeature(...)`. Designer/AI treat
18
+ // such files as "not a feature file".
19
+ //
20
+ // **Skeleton status (C1.3):** interface fixed, extractors are TODO.
21
+ // Per-pattern extractors fill in iteratively (C1.5) — each round adds
22
+ // one extractor + a focused test.
23
+
24
+ import type { ArrowFunction, CallExpression, ParameterDeclaration, SourceFile } from "ts-morph";
25
+ import { Project, SyntaxKind } from "ts-morph";
26
+
27
+ import {
28
+ type ExtractOutput,
29
+ extractAuthClaims,
30
+ extractClaimKey,
31
+ extractConfig,
32
+ extractDefineEvent,
33
+ extractEntity,
34
+ extractEntityHook,
35
+ extractEventMigration,
36
+ extractExtendsRegistrar,
37
+ extractHook,
38
+ extractHttpRoute,
39
+ extractJob,
40
+ extractMetric,
41
+ extractMultiStreamProjection,
42
+ extractNav,
43
+ extractNotification,
44
+ extractOptionalRequires,
45
+ extractProjection,
46
+ extractQueryHandler,
47
+ extractReadsConfig,
48
+ extractReferenceData,
49
+ extractRelation,
50
+ extractRequires,
51
+ extractScreen,
52
+ extractSecret,
53
+ extractSystemScope,
54
+ extractToggleable,
55
+ extractTranslations,
56
+ extractUseExtension,
57
+ extractWorkspace,
58
+ extractWriteHandler,
59
+ } from "./extractors";
60
+ import type { FeaturePattern, UnknownPattern } from "./patterns";
61
+ import { type SourceLocation, sourceLocationFromNode } from "./source-location";
62
+
63
+ // =============================================================================
64
+ // Public API
65
+ // =============================================================================
66
+
67
+ export type ParseError = {
68
+ // Which r.* call could not be parsed (only the method name —
69
+ // a call without a method name isn't an r.* call and never lands
70
+ // here).
71
+ readonly methodName: string;
72
+ // Where in the file. The Designer can highlight the spot
73
+ // ("call not understood here").
74
+ readonly source: SourceLocation;
75
+ // Free-form description (e.g. "argument 0 is not an object literal,
76
+ // cannot read EntityDefinition statically").
77
+ readonly reason: string;
78
+ };
79
+
80
+ export type ParseResult = {
81
+ // Extracted from `defineFeature("name", ...)`. Undefined when the
82
+ // file has no `defineFeature` call (then `patterns` is empty too).
83
+ readonly featureName: string | undefined;
84
+ // Recognised r.* calls in source order.
85
+ readonly patterns: readonly FeaturePattern[];
86
+ // Calls whose arguments we could not statically read. The method
87
+ // name is known; only the payload was unreachable. Designer renders
88
+ // them as "cannot edit", AI patcher leaves them alone. Distinct from
89
+ // UnknownPattern (where the method name itself is unknown).
90
+ readonly errors: readonly ParseError[];
91
+ };
92
+
93
+ /**
94
+ * Parse the given feature file and return all recognised r.* calls
95
+ * as a FeaturePattern list.
96
+ *
97
+ * Does NOT throw on TypeScript errors — the visitor works on the syntax
98
+ * tree, not on the type checker. Files with type errors can still be
99
+ * parsed structurally (Designer keeps showing them, AI can suggest fixes).
100
+ *
101
+ * Throws on filesystem / parse errors that ts-morph cannot recover from.
102
+ */
103
+ export function parseFeatureFile(filePath: string): ParseResult {
104
+ const project = new Project({
105
+ // Skip tsconfig file discovery: we only ever load this single file.
106
+ // Without these flags ts-morph would resolve the whole tsconfig
107
+ // tree, which is expensive on large repos and unnecessary for
108
+ // structural analysis.
109
+ skipAddingFilesFromTsConfig: true,
110
+ skipFileDependencyResolution: true,
111
+ });
112
+ const sourceFile = project.addSourceFileAtPath(filePath);
113
+ return parseSourceFile(sourceFile);
114
+ }
115
+
116
+ /**
117
+ * Same as parseFeatureFile, but for SourceFiles already loaded by the
118
+ * caller. Useful for tests + the Designer (which keeps its own Project
119
+ * instance and avoids re-IO per parse).
120
+ */
121
+ export function parseSourceFile(sourceFile: SourceFile): ParseResult {
122
+ const setupCall = findDefineFeatureCall(sourceFile);
123
+ if (!setupCall) {
124
+ return { featureName: undefined, patterns: [], errors: [] };
125
+ }
126
+
127
+ const featureName = extractFeatureName(setupCall);
128
+ const setupCallback = extractSetupCallback(setupCall);
129
+ if (!setupCallback) {
130
+ return { featureName, patterns: [], errors: [] };
131
+ }
132
+
133
+ const registrarParamName = extractRegistrarParamName(setupCallback);
134
+ if (!registrarParamName) {
135
+ return { featureName, patterns: [], errors: [] };
136
+ }
137
+
138
+ const patterns: FeaturePattern[] = [];
139
+ const errors: ParseError[] = [];
140
+
141
+ walkSetupCallback(setupCallback, registrarParamName, sourceFile, patterns, errors);
142
+
143
+ return { featureName, patterns, errors };
144
+ }
145
+
146
+ // =============================================================================
147
+ // Internal — locate defineFeature + setup callback
148
+ // =============================================================================
149
+
150
+ /**
151
+ * Find the `defineFeature(name, setup)` call in the source file.
152
+ * Convention: each feature file invokes `defineFeature` exactly once
153
+ * at top level. If multiple calls exist (unusual outside of test
154
+ * helpers) we take the first.
155
+ */
156
+ function findDefineFeatureCall(sourceFile: SourceFile): CallExpression | undefined {
157
+ for (const stmt of sourceFile.getDescendantsOfKind(SyntaxKind.CallExpression)) {
158
+ const expr = stmt.getExpression();
159
+ if (expr.getText() === "defineFeature") {
160
+ return stmt;
161
+ }
162
+ }
163
+ return undefined;
164
+ }
165
+
166
+ /**
167
+ * Read the feature name from the first argument of `defineFeature(...)`.
168
+ * Returns undefined when the argument is not a string literal (e.g.
169
+ * dynamic name from a const). Designer can still load the file but the
170
+ * AI generator will never produce such a setup.
171
+ */
172
+ function extractFeatureName(call: CallExpression): string | undefined {
173
+ const arg = call.getArguments()[0];
174
+ if (!arg) return undefined;
175
+ const literal = arg.asKind(SyntaxKind.StringLiteral);
176
+ if (!literal) return undefined;
177
+ return literal.getLiteralValue();
178
+ }
179
+
180
+ /**
181
+ * Read the `setup` callback (second argument) from `defineFeature(...)`.
182
+ * We only support the arrow-function form here — function expressions
183
+ * have not turned up in any sample so far. If a future feature needs
184
+ * them, this is the single hook to extend.
185
+ */
186
+ function extractSetupCallback(call: CallExpression): ArrowFunction | undefined {
187
+ const arg = call.getArguments()[1];
188
+ if (!arg) return undefined;
189
+ return arg.asKind(SyntaxKind.ArrowFunction);
190
+ }
191
+
192
+ /**
193
+ * Read the parameter name of the setup callback's first parameter.
194
+ * Idiomatic feature files call it `r`, but `(registrar) => { ... }` or
195
+ * `(reg) => { ... }` are equally legal — the visitor must follow the
196
+ * author's choice or it would silently miss every call.
197
+ *
198
+ * Returns undefined when the callback takes no parameter at all (a
199
+ * feature that does nothing — empty patterns list, no error).
200
+ */
201
+ function extractRegistrarParamName(setup: ArrowFunction): string | undefined {
202
+ const param: ParameterDeclaration | undefined = setup.getParameters()[0];
203
+ if (!param) return undefined;
204
+ return param.getName();
205
+ }
206
+
207
+ // =============================================================================
208
+ // Internal — walk + dispatch
209
+ // =============================================================================
210
+
211
+ /**
212
+ * Walk the body of the setup callback and route every `<param>.<method>(...)`
213
+ * call to the matching extractor. Helper functions / local variables /
214
+ * imports are ignored.
215
+ *
216
+ * We rely on `getDescendantsOfKind` rather than walking only direct
217
+ * children: the `r.*` API is always called on the registrar variable,
218
+ * which the closure rules keep scoped to the setup callback. Nested
219
+ * calls inside a writeHandler closure would not see `r` and therefore
220
+ * cannot pose as feature-level patterns — collisions are
221
+ * structurally impossible.
222
+ */
223
+ function walkSetupCallback(
224
+ setup: ArrowFunction,
225
+ registrarParamName: string,
226
+ sourceFile: SourceFile,
227
+ patterns: FeaturePattern[],
228
+ errors: ParseError[],
229
+ ): void {
230
+ const body = setup.getBody();
231
+ for (const call of body.getDescendantsOfKind(SyntaxKind.CallExpression)) {
232
+ const methodName = extractRegistrarMethodName(call, registrarParamName);
233
+ if (!methodName) continue; // Not a registrar call — ignore.
234
+ const result = dispatchExtractor(methodName, call, sourceFile);
235
+ if (result.kind === "pattern") {
236
+ patterns.push(result.pattern);
237
+ } else {
238
+ errors.push(result.error);
239
+ }
240
+ }
241
+ }
242
+
243
+ /**
244
+ * Returns the method name when the call has the form
245
+ * `<registrarParamName>.<method>(...)`, otherwise undefined.
246
+ *
247
+ * Reads the property-access expression on the call's left-hand side
248
+ * and matches the receiver against the captured parameter name. Any
249
+ * other shape (free function call, method call on something else)
250
+ * returns undefined and is skipped by the walker.
251
+ */
252
+ function extractRegistrarMethodName(
253
+ call: CallExpression,
254
+ registrarParamName: string,
255
+ ): string | undefined {
256
+ const expr = call.getExpression();
257
+ const propAccess = expr.asKind(SyntaxKind.PropertyAccessExpression);
258
+ if (!propAccess) return undefined;
259
+ const receiver = propAccess.getExpression();
260
+ if (receiver.getText() !== registrarParamName) return undefined;
261
+ return propAccess.getName();
262
+ }
263
+
264
+ // =============================================================================
265
+ // Internal — pattern extractors (skeleton, implementation in C1.5)
266
+ // =============================================================================
267
+
268
+ /**
269
+ * Route an `<r>.<method>(...)` call to its concrete extractor. New
270
+ * r.* APIs → new case + new extractor + new pattern type in patterns.ts.
271
+ * The discriminated union forces consumers (Designer, AI patcher) to
272
+ * commit to the new kind via compile errors.
273
+ *
274
+ * Skeleton: every recognised method currently returns an UnknownPattern
275
+ * with the right method name. C1.5 replaces the cases with concrete
276
+ * extractors one at a time.
277
+ */
278
+ function dispatchExtractor(
279
+ methodName: string,
280
+ call: CallExpression,
281
+ sourceFile: SourceFile,
282
+ ): ExtractOutput<FeaturePattern> {
283
+ switch (methodName) {
284
+ // Round 1 — simplest static patterns
285
+ case "requires":
286
+ return extractRequires(call, sourceFile);
287
+ case "optionalRequires":
288
+ return extractOptionalRequires(call, sourceFile);
289
+ case "readsConfig":
290
+ return extractReadsConfig(call, sourceFile);
291
+ case "systemScope":
292
+ return extractSystemScope(call, sourceFile);
293
+ case "toggleable":
294
+ return extractToggleable(call, sourceFile);
295
+ // Round 2 — object-literal-based static patterns
296
+ case "entity":
297
+ return extractEntity(call, sourceFile);
298
+ case "relation":
299
+ return extractRelation(call, sourceFile);
300
+ case "nav":
301
+ return extractNav(call, sourceFile);
302
+ case "workspace":
303
+ return extractWorkspace(call, sourceFile);
304
+ // Round 3 — complex static patterns
305
+ case "config":
306
+ return extractConfig(call, sourceFile);
307
+ case "translations":
308
+ return extractTranslations(call, sourceFile);
309
+ case "metric":
310
+ return extractMetric(call, sourceFile);
311
+ case "secret":
312
+ return extractSecret(call, sourceFile);
313
+ case "claimKey":
314
+ return extractClaimKey(call, sourceFile);
315
+ case "referenceData":
316
+ return extractReferenceData(call, sourceFile);
317
+ case "useExtension":
318
+ return extractUseExtension(call, sourceFile);
319
+ // Round 4 — mixed (header + body) patterns
320
+ case "hook":
321
+ return extractHook(call, sourceFile);
322
+ case "entityHook":
323
+ return extractEntityHook(call, sourceFile);
324
+ case "authClaims":
325
+ return extractAuthClaims(call, sourceFile);
326
+ case "writeHandler":
327
+ return extractWriteHandler(call, sourceFile);
328
+ case "queryHandler":
329
+ return extractQueryHandler(call, sourceFile);
330
+ case "job":
331
+ return extractJob(call, sourceFile);
332
+ case "httpRoute":
333
+ return extractHttpRoute(call, sourceFile);
334
+ case "defineEvent":
335
+ return extractDefineEvent(call, sourceFile);
336
+ case "eventMigration":
337
+ return extractEventMigration(call, sourceFile);
338
+ case "notification":
339
+ return extractNotification(call, sourceFile);
340
+ case "projection":
341
+ return extractProjection(call, sourceFile);
342
+ case "multiStreamProjection":
343
+ return extractMultiStreamProjection(call, sourceFile);
344
+ case "screen":
345
+ return extractScreen(call, sourceFile);
346
+ // Round 5 — opaque patterns
347
+ case "extendsRegistrar":
348
+ return extractExtendsRegistrar(call, sourceFile);
349
+ // Unknown method — UnknownPattern signal so Designer/AI surface it
350
+ // as "custom call" without losing the source location.
351
+ default:
352
+ return {
353
+ kind: "pattern",
354
+ pattern: makeUnknownPattern(methodName, call, sourceFile),
355
+ };
356
+ }
357
+ }
358
+
359
+ function makeUnknownPattern(
360
+ methodName: string,
361
+ call: CallExpression,
362
+ sourceFile: SourceFile,
363
+ ): UnknownPattern {
364
+ return {
365
+ kind: "unknown",
366
+ methodName,
367
+ source: sourceLocationFromNode(call, sourceFile),
368
+ };
369
+ }