@starci/hfs 4.0.8 → 4.0.10

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 (703) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/LICENSE +21 -0
  3. package/README.md +81 -39
  4. package/emit/contracts.mjs +56 -9
  5. package/emit/db-types.mjs +169 -0
  6. package/emit/events.mjs +41 -0
  7. package/emit/operations-worker.mjs +1 -1
  8. package/emit/operations.mjs +2 -2
  9. package/emit/schema-worker.mjs +1 -1
  10. package/lint/bound-sys.cjs +50 -0
  11. package/lint/run.mjs +131 -24
  12. package/package.json +16 -10
  13. package/report/sonar.mjs +8 -8
  14. package/runtime/engine/admission.mjs +308 -0
  15. package/runtime/engine/canonical-json.mjs +10 -0
  16. package/runtime/engine/config.mjs +486 -0
  17. package/runtime/engine/db/blob.mjs +315 -0
  18. package/runtime/engine/db/ledger-paths.mjs +83 -0
  19. package/runtime/engine/db/ledger.mjs +1118 -0
  20. package/runtime/engine/db/machine-connection.mjs +135 -0
  21. package/runtime/engine/db/machine-schema.mjs +84 -0
  22. package/runtime/engine/db/machine.mjs +1367 -0
  23. package/runtime/engine/db/migrations/machine/0001-init.sql +924 -0
  24. package/runtime/engine/db/migrations/runtime/0001-init.sql +1108 -0
  25. package/runtime/engine/db/provider-reservations.mjs +101 -0
  26. package/runtime/engine/digest.mjs +16 -0
  27. package/runtime/engine/invalid-config.mjs +15 -0
  28. package/runtime/engine/orca-config.mjs +27 -0
  29. package/runtime/engine/refuse.mjs +11 -0
  30. package/runtime/engine/secrets.mjs +130 -0
  31. package/runtime/knowledge/hfs/canon-pins.yaml +162 -31
  32. package/runtime/knowledge/hfs/peer-integrations.yaml +2 -2
  33. package/runtime/knowledge/hfs/rules.yaml +2059 -0
  34. package/runtime/knowledge/hfs/slots.yaml +912 -120
  35. package/runtime/knowledge/patterns/be/api.yaml +369 -0
  36. package/runtime/knowledge/patterns/be/cli.yaml +297 -0
  37. package/runtime/knowledge/patterns/be/domain.yaml +113 -0
  38. package/runtime/knowledge/patterns/be/event-bus.yaml +285 -0
  39. package/runtime/knowledge/patterns/be/jobs.yaml +261 -0
  40. package/runtime/knowledge/patterns/be/projections.yaml +178 -0
  41. package/runtime/knowledge/patterns/be/queues.yaml +236 -0
  42. package/runtime/knowledge/patterns/be/reactors.yaml +140 -0
  43. package/runtime/knowledge/patterns/be/realtime.yaml +222 -0
  44. package/runtime/knowledge/patterns/be/saga.yaml +248 -0
  45. package/runtime/knowledge/patterns/be/webhooks.yaml +221 -0
  46. package/runtime/knowledge/patterns/fe/folder.yaml +131 -25
  47. package/runtime/knowledge/sonar-gate.yaml +52 -18
  48. package/runtime/modules/kernel/failure-codes.yaml +611 -51
  49. package/runtime/modules/models/registry.yaml +553 -0
  50. package/runtime/modules/models/runtimes.yaml +695 -0
  51. package/runtime/modules/ops/_labels.yaml +53 -0
  52. package/runtime/scripts/api/fs/forbidden-root.mjs +51 -0
  53. package/runtime/scripts/api/fs/is-link-like.mjs +25 -0
  54. package/runtime/scripts/api/fs/lib.mjs +16 -2
  55. package/runtime/scripts/api/fs/safe-remove.mjs +12 -132
  56. package/runtime/scripts/api/git/config-get.mjs +10 -0
  57. package/runtime/scripts/api/git/diff.mjs +5 -0
  58. package/runtime/scripts/api/git/lib.mjs +18 -26
  59. package/runtime/scripts/api/git/log.mjs +5 -0
  60. package/runtime/scripts/api/git/ls-files.mjs +6 -0
  61. package/runtime/scripts/api/git/ls-tree.mjs +5 -0
  62. package/runtime/scripts/api/git/merge-base.mjs +9 -0
  63. package/runtime/scripts/api/git/remote.mjs +5 -0
  64. package/runtime/scripts/api/git/rev-parse-query.mjs +5 -0
  65. package/runtime/scripts/api/git/show.mjs +6 -0
  66. package/runtime/scripts/api/node/lib.mjs +14 -0
  67. package/runtime/scripts/api/node/spawn-node.mjs +6 -0
  68. package/runtime/scripts/api/process/lib.mjs +111 -0
  69. package/runtime/scripts/api/process/owned-process.mjs +78 -0
  70. package/runtime/scripts/api/process/resolve-real-tool.mjs +46 -0
  71. package/runtime/scripts/api/process/run-program.mjs +7 -0
  72. package/runtime/scripts/api/process/stop-owned-process.mjs +9 -0
  73. package/runtime/scripts/api/sops/decrypt.mjs +9 -12
  74. package/runtime/scripts/api/sops/lib.mjs +255 -0
  75. package/runtime/scripts/api/sops/seal.mjs +22 -0
  76. package/runtime/scripts/connectors/lib.mjs +488 -0
  77. package/runtime/scripts/hfs/architecture/ast-walks.mjs +220 -0
  78. package/runtime/scripts/hfs/architecture/backend.mjs +16 -23
  79. package/runtime/scripts/hfs/architecture/background-unowned.mjs +16 -34
  80. package/runtime/scripts/hfs/architecture/client-reaches-server.mjs +3 -1
  81. package/runtime/scripts/hfs/architecture/clones.mjs +4 -4
  82. package/runtime/scripts/hfs/architecture/config.mjs +9 -6
  83. package/runtime/scripts/hfs/architecture/connection-map.mjs +20 -8
  84. package/runtime/scripts/hfs/architecture/context-coupling.mjs +88 -0
  85. package/runtime/scripts/hfs/architecture/context-map.mjs +237 -0
  86. package/runtime/scripts/hfs/architecture/context-owner.mjs +82 -0
  87. package/runtime/scripts/hfs/architecture/context-platform-tables.mjs +47 -0
  88. package/runtime/scripts/hfs/architecture/context-transaction.mjs +60 -0
  89. package/runtime/scripts/hfs/architecture/contract-fixture-guard.mjs +4 -10
  90. package/runtime/scripts/hfs/architecture/contracts.mjs +33 -162
  91. package/runtime/scripts/hfs/architecture/dead-exports.mjs +58 -29
  92. package/runtime/scripts/hfs/architecture/doc-language.mjs +1 -1
  93. package/runtime/scripts/hfs/architecture/entrypoint.mjs +2 -1
  94. package/runtime/scripts/hfs/architecture/fe-slot-allows.mjs +2 -2
  95. package/runtime/scripts/hfs/architecture/feature-shape.mjs +5 -2
  96. package/runtime/scripts/hfs/architecture/framework-pinned.mjs +1 -1
  97. package/runtime/scripts/hfs/architecture/frontend.mjs +17 -43
  98. package/runtime/scripts/hfs/architecture/hfs.mjs +24 -39
  99. package/runtime/scripts/hfs/architecture/i18n-keys.mjs +1 -1
  100. package/runtime/scripts/hfs/architecture/index.mjs +17 -4
  101. package/runtime/scripts/hfs/architecture/machine-ast.mjs +44 -11
  102. package/runtime/scripts/hfs/architecture/managed-scripts.mjs +27 -0
  103. package/runtime/scripts/hfs/architecture/module-per-transport.mjs +30 -6
  104. package/runtime/scripts/hfs/architecture/next-data.mjs +22 -63
  105. package/runtime/scripts/hfs/architecture/owners.mjs +35 -15
  106. package/runtime/scripts/hfs/architecture/register-once.mjs +2 -1
  107. package/runtime/scripts/hfs/architecture/registration.mjs +23 -81
  108. package/runtime/scripts/hfs/architecture/required-files.mjs +20 -12
  109. package/runtime/scripts/hfs/architecture/schema-owner.mjs +17 -114
  110. package/runtime/scripts/hfs/architecture/server-action.mjs +24 -0
  111. package/runtime/scripts/hfs/architecture/side-boundary.mjs +16 -0
  112. package/runtime/scripts/hfs/architecture/source-names.mjs +27 -147
  113. package/runtime/scripts/hfs/architecture/sql-owner.mjs +59 -18
  114. package/runtime/scripts/hfs/architecture/sql-returning.mjs +64 -0
  115. package/runtime/scripts/hfs/architecture/supabase-ast.mjs +111 -0
  116. package/runtime/scripts/hfs/architecture/supabase-be.mjs +131 -0
  117. package/runtime/scripts/hfs/architecture/supabase-tables.mjs +42 -0
  118. package/runtime/scripts/hfs/architecture/supabase.mjs +434 -0
  119. package/runtime/scripts/hfs/architecture/surface.mjs +9 -3
  120. package/runtime/scripts/hfs/architecture/test-world-files.mjs +9 -19
  121. package/runtime/scripts/hfs/architecture/tiers.mjs +47 -5
  122. package/runtime/scripts/hfs/architecture/transport-owner.mjs +3 -3
  123. package/runtime/scripts/hfs/architecture/typescript.mjs +12 -26
  124. package/runtime/scripts/hfs/architecture.mjs +4 -4
  125. package/runtime/scripts/hfs/check.mjs +75 -72
  126. package/runtime/scripts/hfs/coverage-scope.mjs +162 -0
  127. package/runtime/scripts/hfs/declaration-shape.mjs +62 -0
  128. package/runtime/scripts/hfs/declaration-slots.mjs +75 -0
  129. package/runtime/scripts/hfs/edition-slots.mjs +66 -0
  130. package/runtime/scripts/hfs/manifest-shape.mjs +109 -32
  131. package/runtime/scripts/hfs/param-names.mjs +18 -0
  132. package/runtime/scripts/hfs/path-findings.mjs +1 -1
  133. package/runtime/scripts/hfs/repo-identity.mjs +9 -6
  134. package/runtime/scripts/hfs/rule-params-shape.mjs +50 -0
  135. package/runtime/scripts/hfs/rules/app-root.mjs +51 -0
  136. package/runtime/scripts/hfs/rules/cli.mjs +37 -0
  137. package/runtime/scripts/hfs/rules/contract-compat.mjs +71 -0
  138. package/runtime/scripts/hfs/rules/contract.mjs +10 -9
  139. package/runtime/scripts/hfs/rules/database-config.mjs +102 -0
  140. package/runtime/scripts/hfs/rules/database-constants.mjs +13 -0
  141. package/runtime/scripts/hfs/rules/database-migrations.mjs +111 -0
  142. package/runtime/scripts/hfs/rules/database-plpgsql.mjs +233 -0
  143. package/runtime/scripts/hfs/rules/database-sql.mjs +336 -0
  144. package/runtime/scripts/hfs/rules/database.mjs +68 -0
  145. package/runtime/scripts/hfs/rules/deps.mjs +1 -1
  146. package/runtime/scripts/hfs/rules/docker.mjs +259 -0
  147. package/runtime/scripts/hfs/rules/edition.mjs +111 -0
  148. package/runtime/scripts/hfs/rules/event-bus.mjs +153 -0
  149. package/runtime/scripts/hfs/rules/fe-contract-documents.mjs +1 -1
  150. package/runtime/scripts/hfs/rules/fe-no-tests.mjs +6 -5
  151. package/runtime/scripts/hfs/rules/frontend-tree.mjs +9 -9
  152. package/runtime/scripts/hfs/rules/integration-specs.mjs +3 -6
  153. package/runtime/scripts/hfs/rules/kinds.mjs +84 -0
  154. package/runtime/scripts/hfs/rules/lint-suppression.mjs +1 -1
  155. package/runtime/scripts/hfs/rules/monorepo.mjs +179 -0
  156. package/runtime/scripts/hfs/rules/peer-integrations.mjs +3 -3
  157. package/runtime/scripts/hfs/rules/pipeline.mjs +11 -21
  158. package/runtime/scripts/hfs/rules/proof-commands.mjs +2 -2
  159. package/runtime/scripts/hfs/rules/read.mjs +1 -1
  160. package/runtime/scripts/hfs/rules/repo-local-checks.mjs +2 -2
  161. package/runtime/scripts/hfs/rules/saga.mjs +170 -0
  162. package/runtime/scripts/hfs/rules/secrets.mjs +3 -3
  163. package/runtime/scripts/hfs/rules/services.mjs +220 -0
  164. package/runtime/scripts/hfs/rules/spec-placement.mjs +1 -1
  165. package/runtime/scripts/hfs/rules/stacks.mjs +3 -3
  166. package/runtime/scripts/hfs/rules/supabase-secrets.mjs +89 -0
  167. package/runtime/scripts/hfs/rules/test-topology.mjs +2 -2
  168. package/runtime/scripts/hfs/secret.mjs +209 -0
  169. package/runtime/scripts/hfs/slots.mjs +78 -108
  170. package/runtime/scripts/hfs/sql/pg-parse.mjs +46 -0
  171. package/runtime/scripts/hfs/test-world-slot.mjs +6 -0
  172. package/runtime/scripts/hfs/tree.mjs +5 -4
  173. package/runtime/scripts/hfs/typescript-programs.mjs +0 -5
  174. package/runtime/scripts/hfs/view.mjs +3 -2
  175. package/runtime/scripts/lib/clip.mjs +19 -0
  176. package/runtime/scripts/lib/display-names.mjs +259 -0
  177. package/runtime/scripts/lib/dockerfile.mjs +124 -0
  178. package/runtime/scripts/lib/env.mjs +10 -0
  179. package/runtime/scripts/lib/event-contract.mjs +103 -0
  180. package/runtime/scripts/lib/example-refs.mjs +158 -0
  181. package/runtime/scripts/lib/fs-kind.mjs +14 -4
  182. package/runtime/scripts/lib/git.mjs +36 -0
  183. package/runtime/scripts/lib/graphql-contract.mjs +1 -1
  184. package/runtime/scripts/lib/i18n.mjs +86 -0
  185. package/runtime/scripts/lib/json-schema.mjs +52 -0
  186. package/runtime/scripts/lib/json.mjs +13 -3
  187. package/runtime/scripts/lib/language.mjs +24 -5
  188. package/runtime/scripts/lib/list.mjs +20 -0
  189. package/runtime/scripts/lib/mutation-fence.mjs +15 -0
  190. package/runtime/scripts/lib/package-at.mjs +37 -0
  191. package/runtime/scripts/lib/path-key.mjs +57 -2
  192. package/runtime/scripts/lib/process-identity.mjs +6 -0
  193. package/runtime/scripts/lib/read-text.mjs +34 -0
  194. package/runtime/scripts/lib/read-yaml.mjs +18 -0
  195. package/runtime/scripts/lib/redact.mjs +161 -0
  196. package/runtime/scripts/lib/regex.mjs +4 -0
  197. package/runtime/scripts/lib/same-text.mjs +5 -0
  198. package/runtime/scripts/lib/secret-patterns.mjs +4 -3
  199. package/runtime/scripts/lib/sleep-sync.mjs +2 -1
  200. package/runtime/scripts/lib/sleep.mjs +7 -0
  201. package/runtime/scripts/lib/sops-envelope.mjs +112 -0
  202. package/runtime/scripts/lib/source-phrases.mjs +34 -0
  203. package/runtime/scripts/lib/sqlite.mjs +21 -0
  204. package/runtime/scripts/lib/stack-services.mjs +7 -31
  205. package/runtime/scripts/lib/ts-ast.mjs +35 -0
  206. package/runtime/scripts/lib/walk.mjs +4 -3
  207. package/scaffold/add-app.mjs +174 -0
  208. package/scaffold/add-cli-lite.mjs +257 -0
  209. package/scaffold/add-inbox-lite.mjs +314 -0
  210. package/scaffold/add-table.mjs +344 -0
  211. package/scaffold/add.mjs +299 -0
  212. package/scaffold/app.mjs +358 -69
  213. package/scaffold/edition-gate.mjs +25 -0
  214. package/scaffold/image.mjs +19 -0
  215. package/scaffold/lite-exports.mjs +186 -0
  216. package/scaffold/service.mjs +32 -26
  217. package/scaffold/supabase-ports.mjs +26 -0
  218. package/src/main.mjs +327 -0
  219. package/sync/cli.mjs +6 -9
  220. package/sync/format.mjs +1 -1
  221. package/sync/hygiene.mjs +10 -10
  222. package/sync/index.mjs +167 -104
  223. package/sync/managed.mjs +19 -11
  224. package/sync/sonar-key.mjs +5 -0
  225. package/templates/app/ci-workflows/github/workflows/ci.yml +14 -14
  226. package/templates/app/ci-workflows/github/workflows/images.yml +37 -0
  227. package/templates/app/ci-workflows/sonar-steps.yml +9 -0
  228. package/templates/app/ci-workflows-lite/github/workflows/ci.yml +66 -0
  229. package/templates/app/ci-workflows-lite/github/workflows/db-deploy.yml +31 -0
  230. package/templates/app/ci-workflows-lite/github/workflows/images.yml +37 -0
  231. package/templates/app/codegen-lite/scripts/codegen.mjs +32 -0
  232. package/templates/app/docker-ignore/dockerignore +50 -0
  233. package/templates/app/gitignore-lite +35 -0
  234. package/templates/app/hooks/husky/pre-commit +3 -8
  235. package/templates/app/hooks/husky/pre-push +45 -6
  236. package/templates/app/package-scripts/core.json +8 -0
  237. package/templates/app/package-scripts/package.json +3 -10
  238. package/templates/app/package-scripts-lite/package.json +15 -0
  239. package/templates/app/quality-config/codecov.yml +15 -3
  240. package/templates/app/quality-config/sonar-base.properties +4 -0
  241. package/templates/app/quality-config/sonar-project.properties +1 -4
  242. package/templates/app/quality-config-lite/sonar-project.properties +5 -0
  243. package/templates/app/skeleton/.starcistacks/dev/seeds/primary-notes.sql +5 -0
  244. package/templates/app/skeleton/.starciwork/features/system-health/index.yaml +4 -0
  245. package/templates/app/skeleton/.starciwork/{features/index.yaml → index.yaml} +2 -2
  246. package/templates/app/skeleton/README.md +7 -5
  247. package/templates/app/skeleton-lite/.sops.yaml +3 -0
  248. package/templates/app/skeleton-lite/.starcistacks/dev/environment.json +5 -0
  249. package/templates/app/skeleton-lite/.starcistacks/dev/secrets/.gitkeep +1 -0
  250. package/templates/app/skeleton-lite/.starciwork/shell/index.yaml +55 -0
  251. package/templates/app/skeleton-lite/README.md +40 -0
  252. package/templates/app/skeleton-lite/supabase/config.toml +41 -0
  253. package/templates/app/skeleton-lite/supabase/migrations/__timestamp___baseline.sql +56 -0
  254. package/templates/app/skeleton-lite/supabase/seed.sql +0 -0
  255. package/templates/app/task-graph/turbo.json +23 -0
  256. package/templates/app/tool-config-lite/prettierignore +2 -0
  257. package/templates/app/tool-config-lite/prettierrc +1 -0
  258. package/templates/app/upgrade-full/.starcistacks/application-stacks.yaml +38 -0
  259. package/templates/app/upgrade-full/.starcistacks/dev/README.md +10 -0
  260. package/templates/app/upgrade-full/.starcistacks/dev/infra/compose/api.yaml +13 -0
  261. package/templates/app/upgrade-full/.starcistacks/dev/infra/compose/compose.yaml +3 -0
  262. package/templates/app/upgrade-full/.starcistacks/dev/infra/compose/postgres.yaml +12 -0
  263. package/templates/app/upgrade-full/.starcistacks/dev/infra/metadata.json +7 -0
  264. package/templates/be/common/main-listen.ts.partial +14 -0
  265. package/templates/be/common/sql-ident.ts.partial +7 -0
  266. package/templates/be/common/sql-tag.ts.partial +5 -0
  267. package/templates/be/image/api/Dockerfile +38 -0
  268. package/templates/be/image/cli/Dockerfile +38 -0
  269. package/templates/be/image/worker/Dockerfile +36 -0
  270. package/templates/be/inbox/database-client.ts.tpl +50 -0
  271. package/templates/be/inbox/index.ts.tpl +2 -0
  272. package/templates/be/inbox/migration.sql.tpl +29 -0
  273. package/templates/be/inbox/module-definition.ts.tpl +6 -0
  274. package/templates/be/inbox/module.ts.tpl +14 -0
  275. package/templates/be/inbox/options.ts.tpl +2 -0
  276. package/templates/be/inbox/service.ts.tpl +33 -0
  277. package/templates/be/inbox/sql.ts.tpl +16 -0
  278. package/templates/be/inbox/webhook-door.ts.tpl +36 -0
  279. package/templates/be/patterns/api/application.command.http.ts.tpl +10 -0
  280. package/templates/be/patterns/api/application.command.ts.tpl +10 -0
  281. package/templates/be/patterns/api/application.contracts.ts.tpl +11 -0
  282. package/templates/be/patterns/api/application.handler.http.ts.tpl +22 -0
  283. package/templates/be/patterns/api/application.handler.ts.tpl +22 -0
  284. package/templates/be/patterns/api/feature.index.http.ts.tpl +1 -0
  285. package/templates/be/patterns/api/feature.index.ts.tpl +1 -0
  286. package/templates/be/patterns/api/feature.module.ts.tpl +6 -0
  287. package/templates/be/patterns/api/graphql.input.ts.tpl +13 -0
  288. package/templates/be/patterns/api/graphql.mapper.ts.tpl +9 -0
  289. package/templates/be/patterns/api/graphql.module.ts.tpl +7 -0
  290. package/templates/be/patterns/api/graphql.resolver.ts.tpl +27 -0
  291. package/templates/be/patterns/api/graphql.type.ts.tpl +9 -0
  292. package/templates/be/patterns/api/http.controller.ts.tpl +27 -0
  293. package/templates/be/patterns/api/http.mapper.ts.tpl +9 -0
  294. package/templates/be/patterns/api/http.module.ts.tpl +7 -0
  295. package/templates/be/patterns/api/http.request.ts.tpl +10 -0
  296. package/templates/be/patterns/api/http.response.ts.tpl +5 -0
  297. package/templates/be/patterns/cli/group.cli.spec.ts.tpl +15 -0
  298. package/templates/be/patterns/cli/group.cli.ts.tpl +11 -0
  299. package/templates/be/patterns/cli/group.module.ts.tpl +7 -0
  300. package/templates/be/patterns/cli/sub.run.cli.spec.ts.tpl +17 -0
  301. package/templates/be/patterns/cli/sub.run.cli.ts.tpl +15 -0
  302. package/templates/be/patterns/event-bus/platform/errors/event-bus.error.ts.tpl +22 -0
  303. package/templates/be/patterns/event-bus/platform/event-bus.config.ts.tpl +19 -0
  304. package/templates/be/patterns/event-bus/platform/event-bus.contracts.ts.tpl +58 -0
  305. package/templates/be/patterns/event-bus/platform/event-bus.decorators.ts.tpl +46 -0
  306. package/templates/be/patterns/event-bus/platform/event-bus.log-events.ts.tpl +12 -0
  307. package/templates/be/patterns/event-bus/platform/event-bus.module-definition.ts.tpl +10 -0
  308. package/templates/be/patterns/event-bus/platform/event-bus.module.ts.tpl +52 -0
  309. package/templates/be/patterns/event-bus/platform/event-bus.options.ts.tpl +19 -0
  310. package/templates/be/patterns/event-bus/platform/event-bus.port.ts.tpl +28 -0
  311. package/templates/be/patterns/event-bus/platform/event-bus.service.spec.ts.tpl +165 -0
  312. package/templates/be/patterns/event-bus/platform/event-bus.service.ts.tpl +93 -0
  313. package/templates/be/patterns/event-bus/platform/event-envelope.policy.spec.ts.tpl +90 -0
  314. package/templates/be/patterns/event-bus/platform/event-envelope.policy.ts.tpl +58 -0
  315. package/templates/be/patterns/event-bus/platform/event-relay.service.spec.ts.tpl +136 -0
  316. package/templates/be/patterns/event-bus/platform/event-relay.service.ts.tpl +56 -0
  317. package/templates/be/patterns/event-bus/platform/event-runner.service.spec.ts.tpl +272 -0
  318. package/templates/be/patterns/event-bus/platform/event-runner.service.ts.tpl +128 -0
  319. package/templates/be/patterns/event-bus/platform/event-transport.port.ts.tpl +180 -0
  320. package/templates/be/patterns/event-bus/platform/event.policy.spec.ts.tpl +67 -0
  321. package/templates/be/patterns/event-bus/platform/event.policy.ts.tpl +38 -0
  322. package/templates/be/patterns/event-bus/platform/index.ts.tpl +11 -0
  323. package/templates/be/patterns/event-bus/platform/kafka-event-transport.client.spec.ts.tpl +348 -0
  324. package/templates/be/patterns/event-bus/platform/kafka-event-transport.client.ts.tpl +241 -0
  325. package/templates/be/patterns/event-bus/platform/messages/event-bus.messages.ts.tpl +15 -0
  326. package/templates/be/patterns/event-bus/platform/persistence/connection.ts.tpl +8 -0
  327. package/templates/be/patterns/event-bus/platform/persistence/entities/event-outbox.entity.ts.tpl +37 -0
  328. package/templates/be/patterns/event-bus/platform/persistence/event-bus.rows.ts.tpl +11 -0
  329. package/templates/be/patterns/event-bus/platform/persistence/event-bus.sql.ts.tpl +12 -0
  330. package/templates/be/patterns/event-bus/platform/persistence/migrations/1789800009000-create-event-outbox.ts.tpl +26 -0
  331. package/templates/be/patterns/jobs/job.index.ts.tpl +1 -0
  332. package/templates/be/patterns/jobs/job.module.ts.tpl +6 -0
  333. package/templates/be/patterns/jobs/job.processor.ts.tpl +20 -0
  334. package/templates/be/patterns/jobs/job.queue.module.ts.tpl +20 -0
  335. package/templates/be/patterns/jobs/job.step.ts.tpl +19 -0
  336. package/templates/be/patterns/jobs/platform/fenced.processor.spec.ts.tpl +31 -0
  337. package/templates/be/patterns/jobs/platform/fenced.processor.ts.tpl +13 -0
  338. package/templates/be/patterns/jobs/platform/job-claim.service.spec.ts.tpl +150 -0
  339. package/templates/be/patterns/jobs/platform/job-claim.service.ts.tpl +100 -0
  340. package/templates/be/patterns/jobs/platform/job-runner.service.spec.ts.tpl +138 -0
  341. package/templates/be/patterns/jobs/platform/job-runner.service.ts.tpl +69 -0
  342. package/templates/be/patterns/jobs/platform/jobs.config.ts.tpl +11 -0
  343. package/templates/be/patterns/jobs/platform/jobs.contracts.ts.tpl +62 -0
  344. package/templates/be/patterns/jobs/platform/jobs.decorators.ts.tpl +31 -0
  345. package/templates/be/patterns/jobs/platform/jobs.error.ts.tpl +22 -0
  346. package/templates/be/patterns/jobs/platform/jobs.index.ts.tpl +11 -0
  347. package/templates/be/patterns/jobs/platform/jobs.log-events.ts.tpl +9 -0
  348. package/templates/be/patterns/jobs/platform/jobs.messages.ts.tpl +15 -0
  349. package/templates/be/patterns/jobs/platform/jobs.module-definition.ts.tpl +10 -0
  350. package/templates/be/patterns/jobs/platform/jobs.module.ts.tpl +32 -0
  351. package/templates/be/patterns/jobs/platform/jobs.options.ts.tpl +11 -0
  352. package/templates/be/patterns/jobs/platform/jobs.port.ts.tpl +36 -0
  353. package/templates/be/patterns/jobs/platform/persistence.connection.ts.tpl +8 -0
  354. package/templates/be/patterns/jobs/platform/persistence.job.entity.ts.tpl +53 -0
  355. package/templates/be/patterns/jobs/platform/persistence.jobs.rows.ts.tpl +13 -0
  356. package/templates/be/patterns/jobs/platform/persistence.jobs.sql.ts.tpl +33 -0
  357. package/templates/be/patterns/jobs/platform/persistence.migration.ts.tpl +29 -0
  358. package/templates/be/patterns/outbox/platform/index.ts.tpl +2 -0
  359. package/templates/be/patterns/outbox/platform/outbox-relay.policy.spec.ts.tpl +96 -0
  360. package/templates/be/patterns/outbox/platform/outbox-relay.policy.ts.tpl +78 -0
  361. package/templates/be/patterns/outbox/platform/outbox.log-events.ts.tpl +5 -0
  362. package/templates/be/patterns/projections/migration.ts.tpl +18 -0
  363. package/templates/be/patterns/projections/persistence.connection.ts.tpl +8 -0
  364. package/templates/be/patterns/projections/projection.entity.ts.tpl +9 -0
  365. package/templates/be/patterns/projections/projection.index.ts.tpl +3 -0
  366. package/templates/be/patterns/projections/projection.module-definition.ts.tpl +7 -0
  367. package/templates/be/patterns/projections/projection.module.ts.tpl +18 -0
  368. package/templates/be/patterns/projections/projection.options.ts.tpl +2 -0
  369. package/templates/be/patterns/projections/projection.projection.spec.ts.tpl +55 -0
  370. package/templates/be/patterns/projections/projection.projection.ts.tpl +21 -0
  371. package/templates/be/patterns/queues/platform/bullmq-queue-transport.client.spec.ts.tpl +142 -0
  372. package/templates/be/patterns/queues/platform/bullmq-queue-transport.client.ts.tpl +81 -0
  373. package/templates/be/patterns/queues/platform/persistence.connection.ts.tpl +8 -0
  374. package/templates/be/patterns/queues/platform/persistence.migration.ts.tpl +25 -0
  375. package/templates/be/patterns/queues/platform/persistence.queue-outbox.entity.ts.tpl +25 -0
  376. package/templates/be/patterns/queues/platform/persistence.queue.rows.ts.tpl +9 -0
  377. package/templates/be/patterns/queues/platform/persistence.queue.sql.ts.tpl +12 -0
  378. package/templates/be/patterns/queues/platform/queue-outbox.service.spec.ts.tpl +48 -0
  379. package/templates/be/patterns/queues/platform/queue-outbox.service.ts.tpl +17 -0
  380. package/templates/be/patterns/queues/platform/queue-relay.service.spec.ts.tpl +128 -0
  381. package/templates/be/patterns/queues/platform/queue-relay.service.ts.tpl +48 -0
  382. package/templates/be/patterns/queues/platform/queue-transport.port.ts.tpl +115 -0
  383. package/templates/be/patterns/queues/platform/queue-worker.service.spec.ts.tpl +91 -0
  384. package/templates/be/patterns/queues/platform/queue-worker.service.ts.tpl +45 -0
  385. package/templates/be/patterns/queues/platform/queue.config.ts.tpl +15 -0
  386. package/templates/be/patterns/queues/platform/queue.contracts.ts.tpl +31 -0
  387. package/templates/be/patterns/queues/platform/queue.decorators.ts.tpl +45 -0
  388. package/templates/be/patterns/queues/platform/queue.index.ts.tpl +7 -0
  389. package/templates/be/patterns/queues/platform/queue.log-events.ts.tpl +5 -0
  390. package/templates/be/patterns/queues/platform/queue.module-definition.ts.tpl +10 -0
  391. package/templates/be/patterns/queues/platform/queue.module.ts.tpl +62 -0
  392. package/templates/be/patterns/queues/platform/queue.options.ts.tpl +22 -0
  393. package/templates/be/patterns/queues/platform/queue.policy.spec.ts.tpl +19 -0
  394. package/templates/be/patterns/queues/platform/queue.policy.ts.tpl +11 -0
  395. package/templates/be/patterns/queues/platform/queue.port.ts.tpl +14 -0
  396. package/templates/be/patterns/queues/queue.index.ts.tpl +3 -0
  397. package/templates/be/patterns/queues/queue.module.ts.tpl +6 -0
  398. package/templates/be/patterns/queues/queue.queue.ts.tpl +23 -0
  399. package/templates/be/patterns/reactors/application.command.ts.tpl +10 -0
  400. package/templates/be/patterns/reactors/application.contracts.ts.tpl +12 -0
  401. package/templates/be/patterns/reactors/application.handler.ts.tpl +22 -0
  402. package/templates/be/patterns/reactors/consumer.ts.tpl +19 -0
  403. package/templates/be/patterns/reactors/message.module.ts.tpl +20 -0
  404. package/templates/be/patterns/reactors/reactor.index.ts.tpl +1 -0
  405. package/templates/be/patterns/reactors/reactor.module.ts.tpl +6 -0
  406. package/templates/be/patterns/realtime/channel.graphql.module.ts.tpl +6 -0
  407. package/templates/be/patterns/realtime/channel.index.ts.tpl +1 -0
  408. package/templates/be/patterns/realtime/channel.input.ts.tpl +12 -0
  409. package/templates/be/patterns/realtime/channel.subscription.spec.ts.tpl +51 -0
  410. package/templates/be/patterns/realtime/channel.subscription.ts.tpl +32 -0
  411. package/templates/be/patterns/realtime/channel.type.ts.tpl +9 -0
  412. package/templates/be/patterns/saga/saga.compensate.command.ts.tpl +11 -0
  413. package/templates/be/patterns/saga/saga.compensate.contracts.ts.tpl +7 -0
  414. package/templates/be/patterns/saga/saga.compensate.handler.ts.tpl +22 -0
  415. package/templates/be/patterns/saga/saga.compensation.ts.tpl +21 -0
  416. package/templates/be/patterns/saga/saga.complete.command.ts.tpl +11 -0
  417. package/templates/be/patterns/saga/saga.complete.contracts.ts.tpl +7 -0
  418. package/templates/be/patterns/saga/saga.complete.handler.ts.tpl +22 -0
  419. package/templates/be/patterns/saga/saga.done.consumer.ts.tpl +21 -0
  420. package/templates/be/patterns/saga/saga.failed.consumer.ts.tpl +21 -0
  421. package/templates/be/patterns/saga/saga.index.ts.tpl +1 -0
  422. package/templates/be/patterns/saga/saga.message.module.ts.tpl +23 -0
  423. package/templates/be/patterns/saga/saga.module.ts.tpl +20 -0
  424. package/templates/be/patterns/saga/saga.service.spec.ts.tpl +70 -0
  425. package/templates/be/patterns/saga/saga.service.ts.tpl +44 -0
  426. package/templates/be/patterns/saga/saga.state.ts.tpl +14 -0
  427. package/templates/be/patterns/saga/saga.step.ts.tpl +11 -0
  428. package/templates/be/patterns/saga/saga.undo.command.ts.tpl +10 -0
  429. package/templates/be/patterns/saga/saga.undo.contracts.ts.tpl +5 -0
  430. package/templates/be/patterns/saga/saga.undo.handler.ts.tpl +21 -0
  431. package/templates/be/patterns/webhooks/webhook.door.spec.ts.tpl +72 -0
  432. package/templates/be/patterns/webhooks/webhook.door.ts.tpl +36 -0
  433. package/templates/be/patterns/webhooks/webhook.http.module.ts.tpl +6 -0
  434. package/templates/be/patterns/webhooks/webhook.index.ts.tpl +1 -0
  435. package/templates/be/patterns/webhooks/webhook.request.ts.tpl +9 -0
  436. package/templates/be/skeleton/apps/__app__/src/__app__.options.ts +3 -0
  437. package/templates/be/skeleton/apps/__app__/src/app.module.ts +15 -2
  438. package/templates/be/skeleton/apps/__app__/src/main.ts +7 -15
  439. package/templates/be/skeleton/apps/cli/src/app.module.ts +30 -0
  440. package/templates/be/skeleton/apps/cli/src/cli.options.ts +22 -0
  441. package/templates/be/skeleton/apps/cli/src/main.ts +24 -0
  442. package/templates/be/skeleton/src/features/cli/cli.module.ts +7 -0
  443. package/templates/be/skeleton/src/features/cli/index.ts +1 -0
  444. package/templates/be/skeleton/src/features/cli/migrate/migrate.cli.spec.ts +17 -0
  445. package/templates/be/skeleton/src/features/cli/migrate/migrate.cli.ts +15 -0
  446. package/templates/be/skeleton/src/features/cli/migrate/migrate.module.ts +7 -0
  447. package/templates/be/skeleton/src/features/cli/migrate/subs/run.cli.spec.ts +17 -0
  448. package/templates/be/skeleton/src/features/cli/migrate/subs/run.cli.ts +18 -0
  449. package/templates/be/skeleton/src/features/cli/seed/seed.cli.spec.ts +17 -0
  450. package/templates/be/skeleton/src/features/cli/seed/seed.cli.ts +15 -0
  451. package/templates/be/skeleton/src/features/cli/seed/seed.module.ts +7 -0
  452. package/templates/be/skeleton/src/features/cli/seed/subs/run.cli.spec.ts +33 -0
  453. package/templates/be/skeleton/src/features/cli/seed/subs/run.cli.ts +34 -0
  454. package/templates/be/skeleton/src/modules/domain/identity/admission.policy.spec.ts +13 -0
  455. package/templates/be/skeleton/src/modules/domain/identity/auth.guard.spec.ts +40 -0
  456. package/templates/be/skeleton/src/modules/domain/identity/messages/identity.messages.ts +1 -1
  457. package/templates/be/skeleton/src/modules/domain/note/errors/note.error.ts +16 -0
  458. package/templates/be/skeleton/src/modules/domain/note/index.ts +3 -0
  459. package/templates/be/skeleton/src/modules/domain/note/note.contracts.ts +19 -0
  460. package/templates/be/skeleton/src/modules/domain/note/note.decorators.ts +9 -0
  461. package/templates/be/skeleton/src/modules/domain/note/note.module-definition.ts +7 -0
  462. package/templates/be/skeleton/src/modules/domain/note/note.module.ts +19 -0
  463. package/templates/be/skeleton/src/modules/domain/note/note.options.ts +2 -0
  464. package/templates/be/skeleton/src/modules/domain/note/note.service.spec.ts +76 -0
  465. package/templates/be/skeleton/src/modules/domain/note/note.service.ts +37 -0
  466. package/templates/be/skeleton/src/modules/domain/note/persistence/connection.ts +8 -0
  467. package/templates/be/skeleton/src/modules/domain/note/persistence/entities/note.entity.ts +17 -0
  468. package/templates/be/skeleton/src/modules/domain/note/persistence/migrations/1790000000000-init-note.ts +22 -0
  469. package/templates/be/skeleton/src/modules/domain/note/persistence/note.rows.ts +17 -0
  470. package/templates/be/skeleton/src/modules/domain/note/persistence/note.sql.ts +4 -0
  471. package/templates/be/skeleton/src/modules/platform/config/env-source.config.ts +20 -0
  472. package/templates/be/skeleton/src/modules/platform/config/index.ts +1 -1
  473. package/templates/be/skeleton/src/modules/platform/cqrs/cqrs.contracts.ts +18 -0
  474. package/templates/be/skeleton/src/modules/platform/database/connection-source.client.spec.ts +41 -0
  475. package/templates/be/skeleton/src/modules/platform/database/connection-source.client.ts +17 -0
  476. package/templates/be/skeleton/src/modules/platform/database/database.module-definition.ts +13 -0
  477. package/templates/be/skeleton/src/modules/platform/database/database.module.ts +77 -0
  478. package/templates/be/skeleton/src/modules/platform/database/database.options.ts +30 -0
  479. package/templates/be/skeleton/src/modules/platform/database/database.port.ts +65 -0
  480. package/templates/be/skeleton/src/modules/platform/database/database.sql.ts +47 -0
  481. package/templates/be/skeleton/src/modules/platform/database/errors/database.error.ts +16 -0
  482. package/templates/be/skeleton/src/modules/platform/database/index.ts +9 -0
  483. package/templates/be/skeleton/src/modules/platform/database/migrate-connections.client.ts +30 -0
  484. package/templates/be/skeleton/src/modules/platform/database/migration-runner.service.spec.ts +84 -0
  485. package/templates/be/skeleton/src/modules/platform/database/migration-runner.service.ts +23 -0
  486. package/templates/be/skeleton/src/modules/platform/database/primary.config.ts +9 -0
  487. package/templates/be/skeleton/src/modules/platform/database/primary.connection.ts +2 -0
  488. package/templates/be/skeleton/src/modules/platform/database/primary.decorators.ts +10 -0
  489. package/templates/be/skeleton/src/modules/platform/database/seed-connections.client.spec.ts +108 -0
  490. package/templates/be/skeleton/src/modules/platform/database/seed-connections.client.ts +75 -0
  491. package/templates/be/skeleton/src/modules/platform/database/seed-runner.service.spec.ts +88 -0
  492. package/templates/be/skeleton/src/modules/platform/database/seed-runner.service.ts +29 -0
  493. package/templates/be/skeleton/src/modules/platform/errors/errors.filter.spec.ts +48 -0
  494. package/templates/be/skeleton/src/modules/platform/errors/messages/errors.messages.ts +1 -1
  495. package/templates/be/skeleton/src/modules/platform/http-security/errors/http-security.error.ts +12 -0
  496. package/templates/be/skeleton/src/modules/platform/http-security/execution-request.mapper.spec.ts +16 -0
  497. package/templates/be/skeleton/src/modules/platform/http-security/http-security.config.ts +8 -1
  498. package/templates/be/skeleton/src/modules/platform/http-security/http-security.decorators.ts +8 -0
  499. package/templates/be/skeleton/src/modules/platform/http-security/http-security.module.ts +14 -1
  500. package/templates/be/skeleton/src/modules/platform/http-security/http-security.options.ts +12 -0
  501. package/templates/be/skeleton/src/modules/platform/http-security/messages/http-security.messages.ts +10 -2
  502. package/templates/be/skeleton/src/modules/platform/http-security/origin.guard.spec.ts +63 -0
  503. package/templates/be/skeleton/src/modules/platform/http-security/rate-limit.guard.spec.ts +108 -0
  504. package/templates/be/skeleton/src/modules/platform/http-security/request-validation.service.spec.ts +39 -0
  505. package/templates/be/skeleton/src/modules/platform/http-security/request-validation.service.ts +25 -0
  506. package/templates/be/skeleton/src/modules/platform/http-security/webhook-signature.service.spec.ts +172 -0
  507. package/templates/be/skeleton/src/modules/platform/http-security/webhook-signature.service.ts +66 -0
  508. package/templates/be/skeleton/src/modules/platform/logging/logging.log-events.ts +3 -1
  509. package/templates/be/skeleton/src/modules/platform/primitives/outcome.mapper.spec.ts +52 -0
  510. package/templates/be/skeleton-lite/apps/api/Dockerfile +37 -0
  511. package/templates/be/skeleton-lite/apps/api/src/api.options.ts +16 -0
  512. package/templates/be/skeleton-lite/apps/api/src/app.module.ts +81 -0
  513. package/templates/be/skeleton-lite/apps/api/src/main.ts +34 -0
  514. package/templates/be/skeleton-lite/src/modules/domain/identity/admission.policy.ts +14 -0
  515. package/templates/be/skeleton-lite/src/modules/domain/identity/auth.guard.ts +50 -0
  516. package/templates/be/skeleton-lite/src/modules/domain/identity/identity.contracts.ts +26 -0
  517. package/templates/be/skeleton-lite/src/modules/domain/identity/identity.decorators.ts +19 -0
  518. package/templates/be/skeleton-lite/src/modules/domain/identity/identity.module.ts +26 -0
  519. package/templates/be/skeleton-lite/src/modules/domain/identity/identity.options.ts +7 -0
  520. package/templates/be/skeleton-lite/src/modules/domain/identity/index.ts +6 -0
  521. package/templates/be/skeleton-lite/src/modules/integrations/supabase/errors/supabase.error.ts +19 -0
  522. package/templates/be/skeleton-lite/src/modules/integrations/supabase/index.ts +10 -0
  523. package/templates/be/skeleton-lite/src/modules/integrations/supabase/supabase.client.ts +24 -0
  524. package/templates/be/skeleton-lite/src/modules/integrations/supabase/supabase.config.ts +8 -0
  525. package/templates/be/skeleton-lite/src/modules/integrations/supabase/supabase.decorators.ts +17 -0
  526. package/templates/be/skeleton-lite/src/modules/integrations/supabase/supabase.jwks.ts +32 -0
  527. package/templates/be/skeleton-lite/src/modules/integrations/supabase/supabase.options.ts +24 -0
  528. package/templates/be/skeleton-lite/src/modules/platform/cqrs/index.ts +4 -0
  529. package/templates/be/skeleton-lite/src/modules/platform/database/database.module.ts +54 -0
  530. package/templates/be/skeleton-lite/src/modules/platform/database/database.options.ts +23 -0
  531. package/templates/be/skeleton-lite/src/modules/platform/database/database.port.ts +10 -0
  532. package/templates/be/skeleton-lite/src/modules/platform/database/database.sql.ts +49 -0
  533. package/templates/be/skeleton-lite/src/modules/platform/database/index.ts +4 -0
  534. package/templates/be/skeleton-lite/src/modules/platform/database/migration-runner.service.ts +21 -0
  535. package/templates/be/skeleton-lite/src/modules/platform/database/primary.config.ts +11 -0
  536. package/templates/be/skeleton-lite/src/modules/platform/database/seed-runner.service.ts +28 -0
  537. package/templates/be/skeleton-lite/src/modules/platform/http-security/http-security.module.ts +25 -0
  538. package/templates/be/skeleton-lite/src/modules/platform/http-security/index.ts +9 -0
  539. package/templates/be/skeleton-lite/src/modules/platform/i18n/index.ts +4 -0
  540. package/templates/be/skeleton-lite/src/modules/platform/logging/index.ts +5 -0
  541. package/templates/be/table/error.ts.tpl +16 -0
  542. package/templates/be/table/index.ts.tpl +2 -0
  543. package/templates/be/table/migration.sql.tpl +51 -0
  544. package/templates/be/table/module-definition.ts.tpl +7 -0
  545. package/templates/be/table/module.ts.tpl +14 -0
  546. package/templates/be/table/options.ts.tpl +2 -0
  547. package/templates/be/table/rows.ts.tpl +4 -0
  548. package/templates/be/table/service.ts.tpl +23 -0
  549. package/templates/be/table/sql.ts.tpl +4 -0
  550. package/templates/be/tool-config/jest.config.js +3 -1
  551. package/templates/be/upgrade-full/apps/cli/src/app.module.ts +14 -0
  552. package/templates/be/upgrade-full/apps/cli/src/main.ts +26 -0
  553. package/templates/be/upgrade-full/src/features/cli/cli.module.ts +6 -0
  554. package/templates/be/upgrade-full/src/features/cli/migrate/subs/run.cli.ts +23 -0
  555. package/templates/common/gitignore.base +1 -2
  556. package/templates/fe/app/package.json.tpl +1 -0
  557. package/templates/fe/app/tsconfig.json +12 -0
  558. package/templates/fe/common/app-layout.tsx.partial +8 -0
  559. package/templates/fe/common/site-shell.tsx.partial +9 -0
  560. package/templates/fe/image/next/Dockerfile +42 -0
  561. package/templates/fe/skeleton/apps/app/next.config.ts +23 -0
  562. package/templates/fe/skeleton/apps/app/postcss.config.mjs +7 -0
  563. package/templates/fe/skeleton/apps/{__app__ → app}/src/app/[locale]/error.tsx +2 -2
  564. package/templates/fe/skeleton/apps/app/src/app/[locale]/layout.tsx +22 -0
  565. package/templates/fe/skeleton/apps/{__app__ → app}/src/app/[locale]/loading.tsx +2 -2
  566. package/templates/fe/skeleton/apps/{__app__ → app}/src/app/[locale]/not-found.tsx +2 -2
  567. package/templates/fe/skeleton/apps/app/src/app/[locale]/page.tsx +9 -0
  568. package/templates/fe/skeleton/apps/{__app__ → app}/src/app/global-error.tsx +2 -2
  569. package/templates/fe/skeleton/apps/app/src/app/globals.css +10 -0
  570. package/templates/fe/skeleton/apps/app/src/features/layouts/AppLayout/index.tsx +18 -0
  571. package/templates/fe/skeleton/apps/app/src/features/pages/AppErrorPage/component.tsx +19 -0
  572. package/templates/fe/skeleton/apps/app/src/features/pages/AppErrorPage/index.tsx +11 -0
  573. package/templates/fe/skeleton/apps/app/src/features/pages/AppGlobalErrorPage/index.tsx +16 -0
  574. package/templates/fe/skeleton/apps/app/src/features/pages/AppHomePage/component.tsx +10 -0
  575. package/templates/fe/skeleton/apps/app/src/features/pages/AppHomePage/index.tsx +15 -0
  576. package/templates/fe/skeleton/apps/app/src/features/pages/AppLoadingPage/index.tsx +8 -0
  577. package/templates/fe/skeleton/apps/app/src/features/pages/AppNotFoundPage/index.tsx +9 -0
  578. package/templates/fe/skeleton/apps/app/src/modules/i18n/index.ts +4 -0
  579. package/templates/fe/skeleton/apps/app/src/modules/i18n/messages/vi.json +28 -0
  580. package/templates/fe/skeleton/apps/app/src/modules/i18n/request.ts +4 -0
  581. package/templates/fe/skeleton/apps/app/src/modules/routes/index.ts +4 -0
  582. package/templates/fe/skeleton/apps/app/src/proxy.ts +1 -0
  583. package/templates/fe/skeleton/apps/{__app__ → landing}/next.config.ts +4 -2
  584. package/templates/fe/skeleton/apps/landing/postcss.config.mjs +7 -0
  585. package/templates/fe/skeleton/apps/landing/src/app/[locale]/error.tsx +10 -0
  586. package/templates/fe/skeleton/apps/landing/src/app/[locale]/layout.tsx +22 -0
  587. package/templates/fe/skeleton/apps/landing/src/app/[locale]/loading.tsx +6 -0
  588. package/templates/fe/skeleton/apps/landing/src/app/[locale]/not-found.tsx +6 -0
  589. package/templates/fe/skeleton/apps/landing/src/app/[locale]/page.tsx +9 -0
  590. package/templates/fe/skeleton/apps/landing/src/app/global-error.tsx +10 -0
  591. package/templates/fe/skeleton/apps/landing/src/app/globals.css +10 -0
  592. package/templates/fe/skeleton/apps/landing/src/features/layouts/LandingLayout/index.tsx +24 -0
  593. package/templates/fe/skeleton/apps/landing/src/features/pages/LandingErrorPage/component.tsx +18 -0
  594. package/templates/fe/skeleton/apps/landing/src/features/pages/LandingErrorPage/index.tsx +11 -0
  595. package/templates/fe/skeleton/apps/landing/src/features/pages/LandingGlobalErrorPage/index.tsx +16 -0
  596. package/templates/fe/skeleton/apps/landing/src/features/pages/LandingLoadingPage/index.tsx +8 -0
  597. package/templates/fe/skeleton/apps/landing/src/features/pages/LandingNotFoundPage/index.tsx +9 -0
  598. package/templates/fe/skeleton/apps/landing/src/features/pages/LandingPage/component.tsx +24 -0
  599. package/templates/fe/skeleton/apps/landing/src/features/pages/LandingPage/index.tsx +16 -0
  600. package/templates/fe/skeleton/apps/landing/src/modules/config/index.ts +12 -0
  601. package/templates/fe/skeleton/apps/landing/src/modules/i18n/index.ts +7 -0
  602. package/templates/fe/skeleton/apps/landing/src/modules/i18n/messages/vi.json +31 -0
  603. package/templates/fe/skeleton/apps/landing/src/modules/i18n/request.ts +4 -0
  604. package/templates/fe/skeleton/apps/landing/src/modules/routes/index.ts +4 -0
  605. package/templates/fe/skeleton/apps/landing/src/proxy.ts +1 -0
  606. package/templates/fe/skeleton/packages/__project__-i18n/src/index.ts +49 -0
  607. package/templates/fe/skeleton/packages/__project__-i18n/src/proxy.ts +24 -0
  608. package/templates/fe/skeleton/packages/__project__-i18n/src/routing.ts +20 -0
  609. package/templates/fe/skeleton/packages/__project__-ui/src/branches/Providers/index.tsx +23 -0
  610. package/templates/fe/skeleton/packages/__project__-ui/src/composites/ErrorNotice/index.tsx +14 -0
  611. package/templates/fe/skeleton/packages/__project__-ui/src/composites/GlobalErrorNotice/index.tsx +25 -0
  612. package/templates/fe/skeleton/packages/__project__-ui/src/composites/LoadingNotice/index.tsx +9 -0
  613. package/templates/fe/skeleton/packages/__project__-ui/src/composites/LocaleShell/index.tsx +21 -0
  614. package/templates/fe/skeleton/packages/__project__-ui/src/composites/NotFoundNotice/index.tsx +19 -0
  615. package/templates/fe/skeleton/packages/__project__-ui/src/composites/SiteShell/classNames.ts +4 -0
  616. package/templates/fe/skeleton/packages/__project__-ui/src/composites/SiteShell/index.tsx +19 -0
  617. package/templates/fe/skeleton/packages/__project__-ui/src/index.ts +6 -0
  618. package/templates/fe/skeleton-lite/apps/web/next.config.ts +22 -0
  619. package/templates/fe/skeleton-lite/apps/web/src/app/[locale]/error.tsx +10 -0
  620. package/templates/fe/skeleton-lite/apps/web/src/app/[locale]/layout.tsx +37 -0
  621. package/templates/fe/skeleton-lite/apps/web/src/app/[locale]/loading.tsx +6 -0
  622. package/templates/fe/skeleton-lite/apps/web/src/app/[locale]/not-found.tsx +6 -0
  623. package/templates/fe/skeleton-lite/apps/web/src/app/[locale]/page.tsx +9 -0
  624. package/templates/fe/skeleton-lite/apps/web/src/app/[locale]/providers.tsx +26 -0
  625. package/templates/fe/skeleton-lite/apps/web/src/app/auth/callback/route.ts +24 -0
  626. package/templates/fe/skeleton-lite/apps/web/src/app/global-error.tsx +10 -0
  627. package/templates/fe/{skeleton/apps/__app__ → skeleton-lite/apps/web}/src/app/globals.css +1 -1
  628. package/templates/fe/skeleton-lite/apps/web/src/app/health/live/route.ts +5 -0
  629. package/templates/fe/skeleton-lite/apps/web/src/components/blocks/SignInForm/component.tsx +29 -0
  630. package/templates/fe/skeleton-lite/apps/web/src/components/blocks/SignInForm/index.tsx +41 -0
  631. package/templates/fe/skeleton-lite/apps/web/src/components/blocks/SignOutButton/component.tsx +17 -0
  632. package/templates/fe/skeleton-lite/apps/web/src/components/blocks/SignOutButton/index.tsx +38 -0
  633. package/templates/fe/skeleton-lite/apps/web/src/components/composites/ErrorNotice/index.tsx +13 -0
  634. package/templates/fe/skeleton-lite/apps/web/src/components/composites/GlobalErrorNotice/index.tsx +24 -0
  635. package/templates/fe/skeleton-lite/apps/web/src/components/composites/LoadingNotice/index.tsx +7 -0
  636. package/templates/fe/skeleton-lite/apps/web/src/components/composites/NotFoundNotice/index.tsx +18 -0
  637. package/templates/fe/skeleton-lite/apps/web/src/components/composites/SiteShell/classNames.ts +4 -0
  638. package/templates/fe/skeleton-lite/apps/web/src/components/composites/SiteShell/index.tsx +13 -0
  639. package/templates/fe/skeleton-lite/apps/web/src/features/layouts/AppLayout/index.tsx +31 -0
  640. package/templates/fe/skeleton-lite/apps/web/src/features/pages/AppErrorPage/component.tsx +12 -0
  641. package/templates/fe/skeleton-lite/apps/web/src/features/pages/AppErrorPage/index.tsx +10 -0
  642. package/templates/fe/skeleton-lite/apps/web/src/features/pages/AppGlobalErrorPage/index.tsx +15 -0
  643. package/templates/fe/skeleton-lite/apps/web/src/features/pages/AppHomePage/component.tsx +14 -0
  644. package/templates/fe/skeleton-lite/apps/web/src/features/pages/AppHomePage/index.tsx +30 -0
  645. package/templates/fe/skeleton-lite/apps/web/src/features/pages/AppLoadingPage/index.tsx +8 -0
  646. package/templates/fe/skeleton-lite/apps/web/src/features/pages/AppNotFoundPage/index.tsx +9 -0
  647. package/templates/fe/skeleton-lite/apps/web/src/modules/brand/brand.css +20 -0
  648. package/templates/fe/skeleton-lite/apps/web/src/modules/brand/index.ts +2 -0
  649. package/templates/fe/skeleton-lite/apps/web/src/modules/config/index.ts +20 -0
  650. package/templates/fe/skeleton-lite/apps/web/src/modules/db/auth/read-session.ts +25 -0
  651. package/templates/fe/skeleton-lite/apps/web/src/modules/db/auth/write-sign-in.ts +25 -0
  652. package/templates/fe/skeleton-lite/apps/web/src/modules/db/auth/write-sign-out.ts +17 -0
  653. package/templates/fe/skeleton-lite/apps/web/src/modules/db/browser.ts +14 -0
  654. package/templates/fe/skeleton-lite/apps/web/src/modules/db/index.ts +3 -0
  655. package/templates/fe/skeleton-lite/apps/web/src/modules/db/outcome.ts +59 -0
  656. package/templates/fe/skeleton-lite/apps/web/src/modules/db/principal.ts +29 -0
  657. package/templates/fe/skeleton-lite/apps/web/src/modules/db/server.ts +70 -0
  658. package/templates/fe/skeleton-lite/apps/web/src/modules/db/validation/validation.mapper.ts +50 -0
  659. package/templates/fe/skeleton-lite/apps/web/src/modules/i18n/index.ts +8 -0
  660. package/templates/fe/skeleton-lite/apps/web/src/modules/i18n/messages/vi.json +48 -0
  661. package/templates/fe/skeleton-lite/apps/web/src/modules/i18n/request.ts +16 -0
  662. package/templates/fe/skeleton-lite/apps/web/src/modules/i18n/routing.ts +14 -0
  663. package/templates/fe/skeleton-lite/apps/web/src/modules/routes/index.ts +7 -0
  664. package/templates/fe/skeleton-lite/apps/web/src/modules/routes/safe-next-path.ts +26 -0
  665. package/templates/fe/skeleton-lite/apps/web/src/proxy.ts +43 -0
  666. package/templates/fe/table/read.ts.tpl +16 -0
  667. package/templates/fe/table/write.ts.tpl +16 -0
  668. package/upgrade/check.mjs +137 -0
  669. package/upgrade/index.mjs +524 -0
  670. package/bin/hfs.mjs +0 -233
  671. package/runtime/scripts/api/fs/rmdir-link.mjs +0 -12
  672. package/runtime/scripts/lib/test-secrets.mjs +0 -116
  673. package/templates/fe/skeleton/apps/__app__/src/app/[locale]/layout.tsx +0 -20
  674. package/templates/fe/skeleton/apps/__app__/src/app/[locale]/page.tsx +0 -9
  675. package/templates/fe/skeleton/apps/__app__/src/components/composites/FailureScreen/index.tsx +0 -28
  676. package/templates/fe/skeleton/apps/__app__/src/features/layouts/LocaleShell/index.tsx +0 -35
  677. package/templates/fe/skeleton/apps/__app__/src/features/pages/ErrorPage/component.tsx +0 -19
  678. package/templates/fe/skeleton/apps/__app__/src/features/pages/ErrorPage/index.tsx +0 -11
  679. package/templates/fe/skeleton/apps/__app__/src/features/pages/GlobalErrorPage/component.tsx +0 -24
  680. package/templates/fe/skeleton/apps/__app__/src/features/pages/GlobalErrorPage/index.tsx +0 -14
  681. package/templates/fe/skeleton/apps/__app__/src/features/pages/HomePage/component.tsx +0 -21
  682. package/templates/fe/skeleton/apps/__app__/src/features/pages/HomePage/index.tsx +0 -15
  683. package/templates/fe/skeleton/apps/__app__/src/features/pages/LoadingPage/component.tsx +0 -23
  684. package/templates/fe/skeleton/apps/__app__/src/features/pages/LoadingPage/index.tsx +0 -8
  685. package/templates/fe/skeleton/apps/__app__/src/features/pages/NotFoundPage/component.tsx +0 -28
  686. package/templates/fe/skeleton/apps/__app__/src/features/pages/NotFoundPage/index.tsx +0 -8
  687. package/templates/fe/skeleton/apps/__app__/src/modules/i18n/config.ts +0 -8
  688. package/templates/fe/skeleton/apps/__app__/src/modules/i18n/index.ts +0 -2
  689. package/templates/fe/skeleton/apps/__app__/src/modules/i18n/messages/vi.json +0 -25
  690. package/templates/fe/skeleton/apps/__app__/src/modules/i18n/request.ts +0 -19
  691. package/templates/fe/skeleton/apps/__app__/src/modules/i18n/routing.ts +0 -9
  692. package/templates/fe/skeleton/apps/__app__/src/modules/routes/index.ts +0 -4
  693. package/templates/fe/skeleton/apps/__app__/src/proxy.ts +0 -10
  694. /package/templates/be/skeleton/src/features/{system-health → api/system-health}/application/check-liveness.contracts.ts +0 -0
  695. /package/templates/be/skeleton/src/features/{system-health → api/system-health}/application/check-liveness.handler.ts +0 -0
  696. /package/templates/be/skeleton/src/features/{system-health → api/system-health}/application/check-liveness.query.ts +0 -0
  697. /package/templates/be/skeleton/src/features/{system-health → api/system-health}/index.ts +0 -0
  698. /package/templates/be/skeleton/src/features/{system-health → api/system-health}/system-health.module.ts +0 -0
  699. /package/templates/be/skeleton/src/features/{system-health → api/system-health}/transport/http/live.controller.ts +0 -0
  700. /package/templates/be/skeleton/src/features/{system-health → api/system-health}/transport/http/system-health-http.module.ts +0 -0
  701. /package/templates/fe/skeleton/apps/{__app__ → app}/src/app/health/live/route.ts +0 -0
  702. /package/templates/fe/skeleton/apps/{__app__ → app}/src/modules/config/index.ts +0 -0
  703. /package/templates/fe/{skeleton/apps/__app__ → skeleton-lite/apps/web}/postcss.config.mjs +0 -0
package/bin/hfs.mjs DELETED
@@ -1,233 +0,0 @@
1
- #!/usr/bin/env node
2
- // hfs - the HFS command line of a StarCi app: one repository, `<app>/`, with one package.json, lockfile and node_modules at its root
3
- // and two sides, be/ and fe/, declared by the one hfs.json of kind app. Every verb runs at the app root.
4
- // hfs check [--repo <dir>] [--json] [--fast] [--base <ref>]
5
- // every tracked path has a slot; required files exist; nothing forbidden or
6
- // tracked-that-must-be-ignored; pins match; every managed file equals its render
7
- // (sync/managed.mjs, the .gitignore block and sonar-project.properties included); no empty or ghost
8
- // directory, no untracked entry outside an ignored slot; plaintext secrets, the .starcistacks shape, CI
9
- // and pre-push canon steps, dependency version skew, the contract snapshot and the test, wire and i18n
10
- // trees; prettier over every tracked file through the repository's own install (sync/format.mjs; not under
11
- // --fast, and a repository without prettier is a refusal); soft-size backlog (report only); then the whole
12
- // architecture machine (tiers, owners, clones, dead exports, module registration, the
13
- // front-end and back-end source rules), each violation a finding with its why.
14
- // --fast: only what changed since the merge-base with origin/main (else main; --base
15
- // overrides it); the machine
16
- // runs on those owners without clones and dead exports. No merge-base is a refusal
17
- // (exit 2), never a silent full pass. Exit 1 on any error-level finding. The root checks run once and
18
- // the side checks and the machine once per side, the side folder as their root; every path is app-relative.
19
- // hfs lint [--repo <dir>] [--changed <file>...] [--fix] [--format text|json] [--sonar <file>]
20
- // the ONE lint entry (npm run lint): ESLint per side with that side's canon config (per-file rules and
21
- // the project-graph rules), this check's findings, and stylelint over the fe side, as one starci/lint@1
22
- // report; --sonar writes the one Sonar import file. Exit 0 clean, 1 findings, 2 a tool could not run (lint/run.mjs).
23
- // hfs scaffold app <name> [--into <dir>] a new app <dir>/<name>/: the root (hfs.json, package.json, managed files, .starciwork) and the
24
- // be/ and fe/ skeletons (scaffold/app.mjs). Refuses an existing directory.
25
- // hfs explain <path> [--repo <dir>] [--json] which slot owns the path, its tier, allowed imports, required tests.
26
- // hfs emit-contracts [--repo <dir>] write be/contracts/<app>/schema.graphql of every api app that serves GraphQL (emit/contracts.mjs):
27
- // printSchema(lexicographicSortSchema) of the resolvers the app root composes; no env, no database, no network.
28
- // hfs sync (--check | --write) [--root <dir>] the managed files of the root (scripts, husky, CI, .gitignore block, sonar, prettier) and
29
- // of each side (tsconfig, eslint, jest, stylelint); sync/cli.mjs
30
- // hfs work-hygiene the pre-commit guard: staged .starciwork and .starcistacks paths, and the secrets guard over every staged file (read from the index); sync/cli.mjs
31
- // hfs new service <dir> <name> [--inject <Decorator>=<module>:<Type> | <Class>=<module>]... [--repo <dir>]
32
- // a back-end `<name>.service.ts` and its `<name>.service.spec.ts` skeleton (scaffold/service.mjs; <dir> is
33
- // relative to be/): the spec is built
34
- // with Test.createTestingModule, one provider per constructor dependency (kit doubles from @starci/jest-preset),
35
- // one placeholder it per public method. Never overwrites a file.
36
- // hfs new spec <file>.service.ts [--repo <dir>] the spec skeleton of an existing service, read from its constructor with the repository's TypeScript
37
- // Every finding names a why code and carries its Vietnamese text. check, lint and explain read the app, never write to it. Exit codes:
38
- // 0 clean, 1 error findings, 2 a refusal or bad usage.
39
- import path from 'node:path';
40
- import { fileURLToPath } from 'node:url';
41
- import { isMain } from '../runtime/scripts/lib/is-main.mjs';
42
- import { checkRepository, explainPath, trackedFiles } from '../runtime/scripts/hfs/check.mjs';
43
- import { HfsSlotsError, loadSlotManifest, readRepoDeclaration } from '../runtime/scripts/hfs/slots.mjs';
44
- import { formatFindings } from '../sync/format.mjs';
45
- import { main as syncMain } from '../sync/cli.mjs';
46
- import { SyncError, loadPresets } from '../sync/index.mjs';
47
- import { managedFindings } from '../sync/managed.mjs';
48
- import { emitContracts } from '../emit/contracts.mjs';
49
- import { ScaffoldError, newService, newSpec } from '../scaffold/service.mjs';
50
- import { scaffoldApp } from '../scaffold/app.mjs';
51
- import { contractEmitFindings } from '../runtime/scripts/hfs/rules/contract.mjs';
52
- import { lintRepository, parseLintArgs, printLintText } from '../lint/run.mjs';
53
- import { writeReport } from '../report/sonar.mjs';
54
-
55
- const USAGE = `hfs check [--repo <dir>] [--json] [--fast] [--base <ref>]
56
- hfs lint [--repo <dir>] [--changed <file>...] [--fix] [--format text|json] [--sonar <file>]
57
- hfs scaffold app <name> [--into <dir>]
58
- hfs emit-contracts [--repo <dir>]
59
- hfs explain <path> [--repo <dir>] [--json]
60
- hfs sync (--check | --write) [--root <dir>]
61
- hfs work-hygiene
62
- hfs new service <dir> <name> [--inject <Decorator>=<module>:<Type> | <Class>=<module>]... [--repo <dir>]
63
- hfs new spec <file>.service.ts [--repo <dir>]
64
- `;
65
- const PER_CODE_LIMIT = 25;
66
- const VALUE_FLAGS = new Set(['--repo', '--base', '--inject', '--into']);
67
- /** Flags that may repeat: their values are collected in order. */
68
- const LIST_FLAGS = new Set(['--inject']);
69
- const BOOL_FLAGS = new Set(['--json', '--fast']);
70
-
71
- function parse(argv) {
72
- const opts = { positional: [] };
73
- for (let i = 0; i < argv.length; i += 1) {
74
- const arg = argv[i];
75
- if (VALUE_FLAGS.has(arg)) {
76
- if (argv[i + 1] === undefined) throw new Error(`${arg} needs a value`);
77
- opts[arg.slice(2)] = LIST_FLAGS.has(arg) ? [...(opts[arg.slice(2)] ?? []), argv[i + 1]] : argv[i + 1];
78
- i += 1;
79
- }
80
- else if (BOOL_FLAGS.has(arg)) opts[arg.slice(2)] = true;
81
- else if (arg.startsWith('--')) throw new Error(`unknown flag ${arg}`);
82
- else opts.positional.push(arg);
83
- }
84
- return opts;
85
- }
86
-
87
- function printCheck(result, out) {
88
- const { counts } = result;
89
- out(`hfs check${result.fast ? ' --fast' : ''} ${result.repoRoot} (profile ${result.profile ?? 'unknown'}, manifest ${result.manifest}, ${result.tracked} tracked paths)\n`);
90
- if (result.fast) out(` ${result.fast.changed} path${result.fast.changed === 1 ? '' : 's'} changed since ${result.fast.base.slice(0, 12)}\n`);
91
- out(` architecture machine: ${result.machine.status === 'ran' ? `ran over ${result.machine.files} source files${result.machine.paths ? ` (owners ${result.machine.paths.join(', ')})` : ''}` : `skipped, ${result.machine.reason}`}\n`);
92
- if (result.contracts) out(` contract snapshots: ${result.contracts.status === 'checked' ? `emitted and compared, ${result.contracts.apps.map((a) => `${a.app}/${a.artifact} ${a.status}`).join(', ') || 'no api app'}` : `skipped, ${result.contracts.reason}`}
93
- `);
94
- const byCode = new Map();
95
- for (const f of result.findings) byCode.set(f.code, [...(byCode.get(f.code) ?? []), f]);
96
- for (const [code, list] of byCode) {
97
- const first = list[0];
98
- out(`\n[${first.level.toUpperCase()}] ${code} x${list.length}: ${first.titleVi}\n ${first.whyVi}\n -> ${first.nextStepVi}\n`);
99
- for (const f of list.slice(0, PER_CODE_LIMIT)) out(` - ${f.message}\n`);
100
- if (list.length > PER_CODE_LIMIT) out(` ... and ${list.length - PER_CODE_LIMIT} more (use --json for all)\n`);
101
- }
102
- out(`\n${counts.error} error finding${counts.error === 1 ? '' : 's'}, ${counts.info} report-only\n`);
103
- }
104
-
105
- function printExplain(e, out) {
106
- out(`${e.path}\n`);
107
- if (e.status === 'no-slot') {
108
- out(` no slot owns this path (${e.code}): ${e.titleVi}\n ${e.whyVi}\n`);
109
- if (e.nearest) out(` nearest slot ${e.nearest.slot}, pattern ${e.nearest.pattern}; matched ${e.nearest.matchedPrefix || '.'}, then expected ${e.nearest.expectedNext ?? 'nothing'}\n`);
110
- return;
111
- }
112
- if (e.status === 'ambiguous') { out(` owned equally by ${e.candidates.join(', ')} (${e.code}): ${e.titleVi}\n`); return; }
113
- out(` slot ${e.slot} (${e.pattern})\n presence ${e.presence}, ${e.tracking}\n tier ${e.tier}${e.owner ? ` owner ${e.owner.root} (${e.owner.slot})` : ''}\n`);
114
- out(` imports ${e.allowedImports ? `may import ${e.allowedImports.join(', ')}; ${e.importRule}` : (e.importRule ?? 'not applicable')}\n`);
115
- out(` tests ${e.tests}: ${e.testsMeaning}\n`);
116
- if (e.requiredFiles.length) out(` requires ${e.requiredFiles.join(', ')}\n`);
117
- if (e.goesTo) out(` belongs at ${e.goesTo}\n`);
118
- if (e.rules) out(` rules ${e.rules.join(', ')}\n`);
119
- if (e.code) out(` ${e.code}: ${e.titleVi}\n ${e.whyVi}\n`);
120
- }
121
-
122
- /**
123
- * The app pass: slots, managed files, formatter, contract snapshots and the architecture machine's check surface, root and sides.
124
- * `only` limits the formatter to those (app-relative) files.
125
- */
126
- async function runCheck({ repoRoot, fast = false, base, only, presets, prettier }) {
127
- const tracked = trackedFiles(repoRoot);
128
- // Managed files of the root and both sides, the .gitignore block and sonar against their render (R04, R05, R11, ...), and prettier
129
- // through the app's own install (R19, never under --fast).
130
- const extraFindings = [...await managedFindings({ repoRoot, tracked, presets }), ...(fast ? [] : await formatFindings({ repoRoot, files: only ?? tracked, prettier }))];
131
- // R23 against the be side itself (full pass only): the committed snapshots equal what `emit-contracts` writes now.
132
- let contracts = null;
133
- let be = null;
134
- try { be = readRepoDeclaration(loadSlotManifest(), repoRoot).sides?.be ?? null; } catch { /* checkRepository reports the unreadable declaration */ }
135
- if (be) {
136
- if (fast) contracts = { status: 'skipped', reason: '--fast does not emit the apps' };
137
- else {
138
- const files = tracked.filter((file) => file.startsWith('be/')).map((file) => file.slice('be/'.length));
139
- const emitted = contractEmitFindings({ repoRoot: path.join(repoRoot, 'be'), files, repo: be, emit: emitContracts });
140
- extraFindings.push(...emitted.findings.map((finding) => ({ ...finding, side: 'be', path: `be/${finding.path}` })));
141
- contracts = { status: 'checked', apps: emitted.apps };
142
- }
143
- }
144
- const result = checkRepository({ repoRoot, fast, base, extraFindings });
145
- if (contracts) result.contracts = contracts;
146
- return result;
147
- }
148
-
149
- /** `hfs lint`: ESLint per side, the app checks and stylelint over the fe side as one report; see lint/run.mjs. */
150
- async function lintMain(argv, { stdout, presets, prettier }) {
151
- const opts = parseLintArgs(argv);
152
- const repoRoot = path.resolve(opts.repo ?? process.cwd());
153
- const { report, sonar, exit } = await lintRepository({
154
- repoRoot, opts, trackedFiles,
155
- hfsCheck: (root) => runCheck({ repoRoot: root, only: opts.changed ?? undefined, presets, prettier }),
156
- });
157
- if (opts.sonar !== undefined) writeReport(path.resolve(opts.sonar), sonar);
158
- if (opts.format === 'json') stdout(`${JSON.stringify(report, null, 2)}
159
- `); else printLintText(report, stdout);
160
- return exit;
161
- }
162
-
163
- /**
164
- * The jest preset a new app renders its Sonar exclusions from: the one installed beside this @starci/hfs (`npx -p @starci/hfs -p
165
- * @starci/jest-preset hfs scaffold app <name>`, or an install that holds both). None is a refusal, never a render without it.
166
- */
167
- async function scaffoldPresets() {
168
- try { return await loadPresets(path.dirname(fileURLToPath(import.meta.url))); } catch (error) {
169
- throw new SyncError('HFS_SYNC_PRESET_MISSING', `${error.message.replace(/^[A-Z_]+: /, '')}; run hfs scaffold with @starci/jest-preset installed beside @starci/hfs (npx -p @starci/hfs -p @starci/jest-preset hfs scaffold app <name>)`);
170
- }
171
- }
172
-
173
- /** `presets` and `prettier` are test seams: the Sonar exclusions sync would load from the repository's installed preset, and the repository's own prettier. */
174
- export async function main(argv, { stdout = (s) => process.stdout.write(s), stderr = (s) => process.stderr.write(s), presets, prettier } = {}) {
175
- const [verb, ...rest] = argv;
176
- if (!['check', 'lint', 'scaffold', 'explain', 'sync', 'work-hygiene', 'emit-contracts', 'new'].includes(verb)) { stderr(USAGE); return 2; }
177
- try {
178
- if (verb === 'sync' || verb === 'work-hygiene') return await syncMain(argv);
179
- if (verb === 'lint') return await lintMain(rest, { stdout, presets, prettier });
180
- const opts = parse(rest);
181
- const repoRoot = path.resolve(opts.repo ?? process.cwd());
182
- if (verb === 'check') {
183
- if (opts.positional.length) throw new Error('hfs check takes no path');
184
- if (opts.base !== undefined && opts.fast !== true) throw new Error('--base names the ref --fast compares with; it needs --fast');
185
- const result = await runCheck({ repoRoot, fast: opts.fast === true, base: opts.base, presets, prettier });
186
- if (opts.json) stdout(`${JSON.stringify(result, null, 2)}\n`); else printCheck(result, stdout);
187
- return result.ok ? 0 : 1;
188
- }
189
- if (verb === 'emit-contracts') {
190
- if (opts.positional.length) throw new Error('hfs emit-contracts takes no path');
191
- const be = readRepoDeclaration(loadSlotManifest(), repoRoot).sides?.be;
192
- if (!be) throw new Error('hfs emit-contracts runs at the app root (the folder of hfs.json)');
193
- const { written, skipped, standIns } = emitContracts({ repoRoot: path.join(repoRoot, 'be'), declaration: be });
194
- for (const file of written) stdout(`wrote be/${file}
195
- `);
196
- stdout(`hfs emit-contracts: ${written.length} written${skipped.length ? `, ${skipped.join(', ')} serve no GraphQL` : ''}
197
- `);
198
- for (const [app, lines] of Object.entries(standIns)) {
199
- stdout(`${app}: ${lines.length} dependenc${lines.length === 1 ? 'y' : 'ies'} of the resolvers could not load here and stood in (no GraphQL type is affected):\n`);
200
- for (const line of lines) stdout(` ${line}\n`);
201
- }
202
- return 0;
203
- }
204
- if (verb === 'new') {
205
- const [kind, ...args] = opts.positional;
206
- let written;
207
- if (kind === 'service' && args.length === 2) written = newService({ repoRoot, dir: args[0], name: args[1], inject: opts.inject ?? [] });
208
- else if (kind === 'spec' && args.length === 1 && opts.inject === undefined) written = newSpec({ repoRoot, file: args[0] });
209
- else throw new Error('hfs new takes `service <dir> <name> [--inject ...]` or `spec <file>.service.ts`');
210
- for (const file of written) stdout(`created ${file}
211
- `);
212
- return 0;
213
- }
214
- if (verb === 'scaffold') {
215
- const [kind, name, ...extra] = opts.positional;
216
- if (kind !== 'app' || !name || extra.length || opts.repo !== undefined) throw new Error('hfs scaffold takes `app <name> [--into <dir>]`');
217
- const { root: created, files } = scaffoldApp({ name, into: path.resolve(opts.into ?? process.cwd()), presets: presets ?? await scaffoldPresets() });
218
- stdout(`hfs scaffold app: created ${created} (${files.length} files); next: npm ci, then npm run lint\n`);
219
- return 0;
220
- }
221
- if (opts.positional.length !== 1) throw new Error('hfs explain takes exactly one path');
222
- const explained = explainPath({ repoRoot, input: opts.positional[0] });
223
- if (opts.json) stdout(`${JSON.stringify(explained, null, 2)}\n`); else printExplain(explained, stdout);
224
- return explained.status === 'no-slot' || explained.status === 'ambiguous' ? 1 : 0;
225
- } catch (error) {
226
- stderr(error instanceof HfsSlotsError || error instanceof SyncError ? `${error.message}\n` : error instanceof ScaffoldError ? `${error.code}: ${error.message}\n` : `hfs: ${error.message}\n${USAGE}`);
227
- return 2;
228
- }
229
- }
230
-
231
- // Run when this file is the entry point, compared by real path: through a node_modules junction or an npx shim argv[1] is
232
- // the junction path while import.meta.url is the resolved one, and a plain comparison silently skipped main (hfs printed nothing).
233
- if (isMain(import.meta.url)) process.exitCode = await main(process.argv.slice(2));
@@ -1,12 +0,0 @@
1
- // rmdir-link.mjs — the link-safe removal primitive: `cmd /d /c rmdir <link>` (no /s) removes a Windows junction or
2
- // directory symlink as a link and never touches its target. scripts/api/fs/safe-remove.mjs removeLink is its one caller and
3
- // checks afterwards that the link is gone (unlinkOnly); this file only issues the call.
4
-
5
- import { spawnSync } from 'node:child_process';
6
-
7
- /** Issue `cmd /d /c rmdir <p>` on Windows; elsewhere nothing (a POSIX link is unlinked by the caller). {status, error}. */
8
- export function rmdirLink(p, { platform = process.platform } = {}) {
9
- if (platform !== 'win32') return { status: null, error: null };
10
- const r = spawnSync('cmd', ['/d', '/c', 'rmdir', p], { windowsHide: true, encoding: 'utf8' });
11
- return { status: r.status, error: r.error?.message ?? null };
12
- }
@@ -1,116 +0,0 @@
1
- #!/usr/bin/env node
2
- // test-secrets.mjs — test credentials follow the product repository's own `.starcistacks` convention (owner ruling
3
- // push-scan-test-secrets-encrypted, 2026-09-28: they work exactly like the stack custody and a plaintext password is never pushed).
4
- // There is no store of the runtime's own: a test credential lives at `<repo>/.starcistacks/<stack>/secrets/test/<name>`,
5
- // its plaintext git-ignored by the repo's `.starcistacks/**` rules and only the sops-encrypted twin `<name>.enc`
6
- // committed. It is written with the repository's existing command (`node scripts/stack-secret.mjs set
7
- // <stack>/secrets/test/<name>`, npm run secret:set), which encrypts against the recipients `.sops.yaml` names and
8
- // removes the plaintext; this module only READS: the local plaintext when present, else the `.enc` decrypted by sops
9
- // with the shared age identity (SOPS_AGE_KEY_FILE, default ~/.starci/master.identity) into memory.
10
- // A credential that need not be stable across runs (a disposable account registered per run) is generated per run
11
- // and stored nowhere. A value is never logged.
12
- //
13
- // node scripts/lib/test-secrets.mjs get <name> --repo <path> [--stack dev] [--reveal] prints nothing unless --reveal
14
- //
15
- // In a script: import { testSecret } from '<runtime>/scripts/lib/test-secrets.mjs';
16
- // const password = testSecret('login-capture-password', { repo });
17
- // The push secret scan (scripts/supervisor/push-mains.mjs) passes a `.enc` only when isSopsEnvelope holds.
18
- import fs from 'node:fs';
19
- import path from 'node:path';
20
- import { sopsDecrypt } from '../api/sops/decrypt.mjs';
21
- import { fileURLToPath } from 'node:url';
22
- import { parseYaml } from '../../engine/yaml.mjs';
23
-
24
- const NAME = /^[a-z0-9][a-z0-9._-]{0,63}$/;
25
- const STACK = /^[a-z0-9][a-z0-9-]{0,31}$/;
26
- /** One sops-encrypted leaf: `ENC[AES256_GCM,data:...,iv:...,tag:...,type:...]` (data may be empty). */
27
- const SOPS_VALUE = /^ENC\[AES256_GCM,data:[A-Za-z0-9+/=]*,iv:[A-Za-z0-9+/=]+,tag:[A-Za-z0-9+/=]+,type:[a-z]+\]$/;
28
-
29
- /** Where test credential `name` of `stack` lives in `repo`: {plain, enc, rel}. `rel` is the path the repo's
30
- * `stack-secret.mjs set` takes. */
31
- export function testSecretPaths(name, { repo, stack = 'dev' } = {}) {
32
- if (!NAME.test(String(name ?? ''))) throw new Error(`test secret name must match ${NAME} (got ${JSON.stringify(name)})`);
33
- if (!STACK.test(String(stack ?? ''))) throw new Error(`stack must match ${STACK} (got ${JSON.stringify(stack)})`);
34
- if (!repo) throw new Error('test secret needs {repo}: the product repository whose .starcistacks holds it');
35
- const rel = `${stack}/secrets/test/${name}`;
36
- const plain = path.join(path.resolve(String(repo)), '.starcistacks', stack, 'secrets', 'test', name);
37
- return { plain, enc: `${plain}.enc`, rel };
38
- }
39
-
40
- /** The command that stores a test credential, in the product repository's own tooling. */
41
- export const setCommand = (name = '<name>', stack = 'dev') => `node scripts/stack-secret.mjs set ${stack}/secrets/test/${name}`;
42
-
43
- /** sops' format for a plaintext path, as the repository's stack-secret.mjs formatFor decides it. */
44
- export const sopsFormatFor = (file) => (file.endsWith('.env') ? 'dotenv' : /\.json$/.test(file) ? 'json' : /\.(ya?ml|kubeconfig)$/.test(file) ? 'yaml' : 'binary');
45
-
46
- /** The sops binary: PATH, then winget's Links and Packages (spawn without a shell ignores PATHEXT). */
47
- export function resolveSops(env = process.env) {
48
- const win = process.platform === 'win32';
49
- const names = win ? ['sops.exe', 'sops'] : ['sops'];
50
- const dirs = String(env.PATH ?? '').split(win ? ';' : ':').filter(Boolean);
51
- if (win && env.LOCALAPPDATA) {
52
- const winget = path.join(env.LOCALAPPDATA, 'Microsoft', 'WinGet');
53
- dirs.push(path.join(winget, 'Links'));
54
- const packages = path.join(winget, 'Packages');
55
- try { for (const e of fs.readdirSync(packages)) if (/sops/i.test(e)) dirs.push(path.join(packages, e)); } catch { /* none */ }
56
- }
57
- for (const dir of dirs) for (const n of names) { const f = path.join(dir, n); try { if (fs.statSync(f).isFile()) return f; } catch { /* next */ } }
58
- return null;
59
- }
60
-
61
- /** Read test credential `name`: the local plaintext when present, else its committed `.enc` through sops. */
62
- export function testSecret(name, { repo, stack = 'dev', env = process.env, sops = null } = {}) {
63
- const { plain, enc, rel } = testSecretPaths(name, { repo, stack });
64
- if (fs.existsSync(plain)) return fs.readFileSync(plain, 'utf8').replace(/\r?\n$/, '');
65
- if (!fs.existsSync(enc)) throw new Error(`test secret ${name} is not in .starcistacks/${rel}.enc; store it with \`${setCommand(name, stack)}\` in ${repo}`);
66
- const bin = sops ?? resolveSops(env);
67
- if (!bin) throw new Error('sops is not installed (Windows: winget install Mozilla.SOPS)');
68
- const format = sopsFormatFor(plain);
69
- const r = sopsDecrypt(bin, ['--decrypt', '--input-type', format, '--output-type', format, enc], { cwd: path.resolve(String(repo)), env, maxBuffer: 1024 * 1024 });
70
- if (r.status !== 0) throw new Error(`test secret ${name}: sops could not decrypt .starcistacks/${rel}.enc (${String(r.stderr ?? r.error?.message ?? '').trim().split(/\r?\n/).pop()})`);
71
- return String(r.stdout).replace(/\r?\n$/, '');
72
- }
73
-
74
- /** Every leaf outside the `sops` block is an ENC[...] value (or null); the block itself carries a mac. */
75
- const allEncrypted = (node) => {
76
- if (node === null) return true;
77
- if (Array.isArray(node)) return node.every(allEncrypted);
78
- if (typeof node === 'object') return Object.values(node).every(allEncrypted);
79
- return typeof node === 'string' && SOPS_VALUE.test(node);
80
- };
81
- const sopsTree = (doc) => !!doc && typeof doc === 'object' && !Array.isArray(doc) && !!doc.sops && typeof doc.sops === 'object'
82
- && typeof doc.sops.mac === 'string' && SOPS_VALUE.test(doc.sops.mac)
83
- && Object.keys(doc).length > 1 && Object.entries(doc).every(([k, v]) => k === 'sops' || allEncrypted(v));
84
-
85
- /**
86
- * True only for a sops-encrypted file with no plaintext value: binary/json form ({"data": ENC[...], "sops": {...}}),
87
- * yaml form (every value ENC[...] plus the sops block) or dotenv form (KEY=ENC[...] lines plus sops_* metadata).
88
- * The sops metadata must carry its mac. A key kept plaintext through `unencrypted_suffix` does not pass.
89
- */
90
- export function isSopsEnvelope(text) {
91
- const src = String(text ?? '').replace(/^/, '');
92
- if (!src.trim()) return false;
93
- try { return sopsTree(JSON.parse(src)); } catch { /* not JSON */ }
94
- const lines = src.split(/\r?\n/).filter((l) => l.trim() && !/^\s*#/.test(l));
95
- if (lines.length && lines.every((l) => /^[A-Za-z_][A-Za-z0-9_]*=/.test(l))) {
96
- const pairs = lines.map((l) => [l.slice(0, l.indexOf('=')), l.slice(l.indexOf('=') + 1)]);
97
- const meta = pairs.filter(([k]) => k.startsWith('sops_'));
98
- const vals = pairs.filter(([k]) => !k.startsWith('sops_'));
99
- return vals.length > 0 && vals.every(([, v]) => SOPS_VALUE.test(v)) && meta.some(([k, v]) => k === 'sops_mac' && SOPS_VALUE.test(v));
100
- }
101
- try { return sopsTree(parseYaml(src)); } catch { return false; }
102
- }
103
-
104
- if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
105
- const [cmd, name, ...rest] = process.argv.slice(2);
106
- const opt = (f) => { const i = rest.indexOf(f); return i >= 0 ? rest[i + 1] : undefined; };
107
- try {
108
- if (cmd === 'get') {
109
- const value = testSecret(name, { repo: opt('--repo'), stack: opt('--stack') ?? 'dev' });
110
- if (rest.includes('--reveal')) process.stdout.write(`${value}\n`);
111
- } else {
112
- console.error(`usage: test-secrets.mjs get <name> --repo <path> [--stack dev] [--reveal]\nstore one with the product repo's own command: ${setCommand()}`);
113
- process.exitCode = 2;
114
- }
115
- } catch (error) { console.error(String(error?.message ?? error)); process.exitCode = 1; }
116
- }
@@ -1,20 +0,0 @@
1
- import type { Metadata } from "next"
2
- import type { ReactNode } from "react"
3
- import { LocaleShell, localeMetadata } from "@/features/layouts/LocaleShell"
4
- import "../globals.css"
5
-
6
- type LayoutProps = {
7
- readonly children: ReactNode
8
- readonly params: Promise<{ readonly locale: string }>
9
- }
10
-
11
- /** The localized document title of this route segment. */
12
- export const generateMetadata = async (props: LayoutProps): Promise<Metadata> =>
13
- localeMetadata((await props.params).locale)
14
-
15
- /** The locale segment's layout slot: it mounts the locale shell around the segment. */
16
- const Layout = async (props: LayoutProps) => (
17
- <LocaleShell lang={(await props.params).locale}>{props.children}</LocaleShell>
18
- )
19
-
20
- export default Layout
@@ -1,9 +0,0 @@
1
- import { HomePage, homeMetadata } from "@/features/pages/HomePage"
2
-
3
- /** The document title of this page, from the catalog of the requested locale. */
4
- export const generateMetadata = homeMetadata
5
-
6
- /** The locale root's page slot: it mounts the home page and nothing else. */
7
- const Page = () => <HomePage />
8
-
9
- export default Page
@@ -1,28 +0,0 @@
1
- import { Button, GrammarRoot, Heading, PageContainer, WorkspaceShell } from "@starci/grammar/common"
2
-
3
- /** Props for {@link FailureScreen}. */
4
- type FailureScreenProps = {
5
- /** What failed, said to the reader. */
6
- readonly title: string
7
- /** The label of the one recovery action. */
8
- readonly retryLabel: string
9
- /** Runs the recovery: the boundary re-renders what failed. */
10
- readonly onRetry: () => void
11
- }
12
-
13
- /** A whole-screen failure with its one recovery action: the drawing both error boundaries share. */
14
- export const FailureScreen = (props: FailureScreenProps) => (
15
- <GrammarRoot>
16
- <WorkspaceShell
17
- primaryLabel={props.title}
18
- primary={
19
- <PageContainer measure="reading">
20
- <Heading level={1}>{props.title}</Heading>
21
- <Button variant="danger" onPress={props.onRetry}>
22
- {props.retryLabel}
23
- </Button>
24
- </PageContainer>
25
- }
26
- />
27
- </GrammarRoot>
28
- )
@@ -1,35 +0,0 @@
1
- import type { Metadata } from "next"
2
- import { notFound } from "next/navigation"
3
- import { hasLocale, NextIntlClientProvider } from "next-intl"
4
- import { getMessages, getTranslations, setRequestLocale } from "next-intl/server"
5
- import type { ReactNode } from "react"
6
- import { siteUrl } from "@/modules/config"
7
- import { routing } from "@/modules/i18n"
8
-
9
- type LocaleShellProps = {
10
- readonly lang: string
11
- readonly children: ReactNode
12
- }
13
-
14
- /** The document title and the absolute base of every metadata URL, for the language in the address. */
15
- export const localeMetadata = async (lang: string): Promise<Metadata> => {
16
- if (!hasLocale(routing.locales, lang)) notFound()
17
- const t = await getTranslations({ locale: lang, namespace: "app" })
18
- return { title: t("title"), metadataBase: new URL(siteUrl()) }
19
- }
20
-
21
- /** The document of one route language: `<html lang>` from the address and the catalog handed to client components. */
22
- export const LocaleShell = async (props: LocaleShellProps) => {
23
- if (!hasLocale(routing.locales, props.lang)) notFound()
24
- setRequestLocale(props.lang)
25
- const messages = await getMessages()
26
- return (
27
- <html lang={props.lang}>
28
- <body className="min-h-dvh">
29
- <NextIntlClientProvider locale={props.lang} messages={messages}>
30
- {props.children}
31
- </NextIntlClientProvider>
32
- </body>
33
- </html>
34
- )
35
- }
@@ -1,19 +0,0 @@
1
- import { FailureScreen } from "@/components/composites/FailureScreen"
2
-
3
- /** Props for {@link ErrorPageBase}. */
4
- export type ErrorPageBaseProps = {
5
- /** The words the failure shows. */
6
- readonly props: {
7
- readonly title: string
8
- readonly retryLabel: string
9
- }
10
- /** What the surface reports upward. */
11
- readonly on: {
12
- readonly retry: () => void
13
- }
14
- }
15
-
16
- /** Draw the failure of the locale segment with its one recovery action. */
17
- export const ErrorPageBase = (props: ErrorPageBaseProps) => (
18
- <FailureScreen title={props.props.title} retryLabel={props.props.retryLabel} onRetry={props.on.retry} />
19
- )
@@ -1,11 +0,0 @@
1
- import { useTranslations } from "next-intl"
2
- import { ErrorPageBase } from "./component"
3
-
4
- /** The public props of the locale error page: the boundary hands it the retry. */
5
- type ErrorPageProps = { readonly onRetry: () => void }
6
-
7
- /** A render failure of the locale segment shows this instead of a blank page; retry re-renders the segment. */
8
- export const ErrorPage = (props: ErrorPageProps) => {
9
- const t = useTranslations("errors.page")
10
- return <ErrorPageBase props={{ title: t("title"), retryLabel: t("retry") }} on={{ retry: props.onRetry }} />
11
- }
@@ -1,24 +0,0 @@
1
- import { FailureScreen } from "@/components/composites/FailureScreen"
2
-
3
- /** Props for {@link GlobalErrorPageBase}. */
4
- export type GlobalErrorPageBaseProps = {
5
- /** The language of the document and the words the failure shows. */
6
- readonly props: {
7
- readonly lang: string
8
- readonly title: string
9
- readonly retryLabel: string
10
- }
11
- /** What the surface reports upward. */
12
- readonly on: {
13
- readonly retry: () => void
14
- }
15
- }
16
-
17
- /** Draw the whole document, because this boundary replaces the root layout that would have drawn it. */
18
- export const GlobalErrorPageBase = (props: GlobalErrorPageBaseProps) => (
19
- <html lang={props.props.lang}>
20
- <body>
21
- <FailureScreen title={props.props.title} retryLabel={props.props.retryLabel} onRetry={props.on.retry} />
22
- </body>
23
- </html>
24
- )
@@ -1,14 +0,0 @@
1
- import { DEFAULT_LOCALE } from "@/modules/i18n"
2
- import messages from "@/modules/i18n/messages/vi.json"
3
- import { GlobalErrorPageBase } from "./component"
4
-
5
- /** The public props of the last-resort error page: the boundary hands it the retry. */
6
- type GlobalErrorPageProps = { readonly onRetry: () => void }
7
-
8
- /** The last-resort boundary above the locale layout: it has no provider, so it reads the default catalog directly. */
9
- export const GlobalErrorPage = (props: GlobalErrorPageProps) => (
10
- <GlobalErrorPageBase
11
- props={{ lang: DEFAULT_LOCALE, title: messages.errors.global.title, retryLabel: messages.errors.global.retry }}
12
- on={{ retry: props.onRetry }}
13
- />
14
- )
@@ -1,21 +0,0 @@
1
- import { GrammarRoot, Heading, PageContainer, WorkspaceShell } from "@starci/grammar/common"
2
-
3
- /** Props for {@link HomePageBase}. */
4
- export type HomePageBaseProps = {
5
- /** The words the page shows. */
6
- readonly props: { readonly title: string }
7
- }
8
-
9
- /** Draw the front door of the app. */
10
- export const HomePageBase = (props: HomePageBaseProps) => (
11
- <GrammarRoot>
12
- <WorkspaceShell
13
- primaryLabel={props.props.title}
14
- primary={
15
- <PageContainer measure="reading">
16
- <Heading level={1}>{props.props.title}</Heading>
17
- </PageContainer>
18
- }
19
- />
20
- </GrammarRoot>
21
- )
@@ -1,15 +0,0 @@
1
- import type { Metadata } from "next"
2
- import { getTranslations } from "next-intl/server"
3
- import { HomePageBase } from "./component"
4
-
5
- /** The document title of the home page, from the catalog of the requested locale. */
6
- export const homeMetadata = async (): Promise<Metadata> => {
7
- const t = await getTranslations("home")
8
- return { title: t("title") }
9
- }
10
-
11
- /** The first page of the app: a server component, so no catalog is shipped for it. */
12
- export const HomePage = async () => {
13
- const t = await getTranslations("home")
14
- return <HomePageBase props={{ title: t("title") }} />
15
- }
@@ -1,23 +0,0 @@
1
- import { GrammarRoot, PageContainer, Text, WorkspaceShell } from "@starci/grammar/common"
2
-
3
- /** Props for {@link LoadingPageBase}. */
4
- export type LoadingPageBaseProps = {
5
- /** The words the wait announces. */
6
- readonly props: { readonly message: string }
7
- }
8
-
9
- /** Draw the wait as one politely announced line. */
10
- export const LoadingPageBase = (props: LoadingPageBaseProps) => (
11
- <GrammarRoot>
12
- <WorkspaceShell
13
- primaryLabel={props.props.message}
14
- primary={
15
- <PageContainer measure="reading">
16
- <Text live="polite" tone="muted">
17
- {props.props.message}
18
- </Text>
19
- </PageContainer>
20
- }
21
- />
22
- </GrammarRoot>
23
- )
@@ -1,8 +0,0 @@
1
- import { getTranslations } from "next-intl/server"
2
- import { LoadingPageBase } from "./component"
3
-
4
- /** Shown while a route of the locale segment resolves. */
5
- export const LoadingPage = async () => {
6
- const t = await getTranslations("loading")
7
- return <LoadingPageBase props={{ message: t("message") }} />
8
- }
@@ -1,28 +0,0 @@
1
- import { GrammarRoot, Heading, PageContainer, TextAction, WorkspaceShell } from "@starci/grammar/common"
2
- import { ROUTES } from "@/modules/routes"
3
-
4
- /** Props for {@link NotFoundPageBase}. */
5
- export type NotFoundPageBaseProps = {
6
- /** The words the page shows. */
7
- readonly props: {
8
- readonly title: string
9
- readonly homeLabel: string
10
- }
11
- }
12
-
13
- /** Draw the missing-page message and the way back to the front door. */
14
- export const NotFoundPageBase = (props: NotFoundPageBaseProps) => (
15
- <GrammarRoot>
16
- <WorkspaceShell
17
- primaryLabel={props.props.title}
18
- primary={
19
- <PageContainer measure="reading">
20
- <Heading level={1}>{props.props.title}</Heading>
21
- <TextAction appearance="inline" href={ROUTES.home}>
22
- {props.props.homeLabel}
23
- </TextAction>
24
- </PageContainer>
25
- }
26
- />
27
- </GrammarRoot>
28
- )