@mettlecast/domain-cli 0.2.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 (301) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/README.md +133 -0
  3. package/dist/builder/build-registry.d.ts +20 -0
  4. package/dist/builder/build-registry.js +178 -0
  5. package/dist/builder/build-types.d.ts +10 -0
  6. package/dist/builder/build-types.js +32 -0
  7. package/dist/builder/load-domain-module-config.d.ts +12 -0
  8. package/dist/builder/load-domain-module-config.js +34 -0
  9. package/dist/builder/load-module.d.ts +26 -0
  10. package/dist/builder/load-module.js +114 -0
  11. package/dist/builder/zod-to-json.d.ts +10 -0
  12. package/dist/builder/zod-to-json.js +15 -0
  13. package/dist/cli.d.ts +2 -0
  14. package/dist/cli.js +338 -0
  15. package/dist/commands/add-api.d.ts +32 -0
  16. package/dist/commands/add-api.js +106 -0
  17. package/dist/commands/add-component.d.ts +15 -0
  18. package/dist/commands/add-component.js +78 -0
  19. package/dist/commands/add-domain.d.ts +21 -0
  20. package/dist/commands/add-domain.js +71 -0
  21. package/dist/commands/add-flow.d.ts +14 -0
  22. package/dist/commands/add-flow.js +108 -0
  23. package/dist/commands/add-hook.d.ts +15 -0
  24. package/dist/commands/add-hook.js +65 -0
  25. package/dist/commands/add-migration.d.ts +26 -0
  26. package/dist/commands/add-migration.js +93 -0
  27. package/dist/commands/add-module.d.ts +7 -0
  28. package/dist/commands/add-module.js +261 -0
  29. package/dist/commands/add-page.d.ts +13 -0
  30. package/dist/commands/add-page.js +170 -0
  31. package/dist/commands/add-seed-page.d.ts +5 -0
  32. package/dist/commands/add-seed-page.js +251 -0
  33. package/dist/commands/add-subscriber.d.ts +30 -0
  34. package/dist/commands/add-subscriber.js +87 -0
  35. package/dist/commands/add-test.d.ts +22 -0
  36. package/dist/commands/add-test.js +285 -0
  37. package/dist/commands/audit.d.ts +39 -0
  38. package/dist/commands/audit.js +171 -0
  39. package/dist/commands/build-catalog.d.ts +68 -0
  40. package/dist/commands/build-catalog.js +105 -0
  41. package/dist/commands/build-flows.d.ts +26 -0
  42. package/dist/commands/build-flows.js +174 -0
  43. package/dist/commands/build.d.ts +17 -0
  44. package/dist/commands/build.js +39 -0
  45. package/dist/commands/check-hashes.d.ts +38 -0
  46. package/dist/commands/check-hashes.js +97 -0
  47. package/dist/commands/create-project.d.ts +5 -0
  48. package/dist/commands/create-project.js +272 -0
  49. package/dist/commands/dev.d.ts +15 -0
  50. package/dist/commands/dev.js +27 -0
  51. package/dist/commands/doctor.d.ts +48 -0
  52. package/dist/commands/doctor.js +1301 -0
  53. package/dist/commands/explain.d.ts +34 -0
  54. package/dist/commands/explain.js +167 -0
  55. package/dist/commands/power-tune.d.ts +1 -0
  56. package/dist/commands/power-tune.js +87 -0
  57. package/dist/commands/reseed-page.d.ts +6 -0
  58. package/dist/commands/reseed-page.js +297 -0
  59. package/dist/commands/show-dns.d.ts +15 -0
  60. package/dist/commands/show-dns.js +101 -0
  61. package/dist/commands/show.d.ts +46 -0
  62. package/dist/commands/show.js +135 -0
  63. package/dist/commands/test.d.ts +18 -0
  64. package/dist/commands/test.js +56 -0
  65. package/dist/commands/upgrade-backend.d.ts +9 -0
  66. package/dist/commands/upgrade-backend.js +46 -0
  67. package/dist/commands/upgrade-event.d.ts +22 -0
  68. package/dist/commands/upgrade-event.js +111 -0
  69. package/dist/commands/upgrade-frontend.d.ts +5 -0
  70. package/dist/commands/upgrade-frontend.js +99 -0
  71. package/dist/commands/upgrade.d.ts +7 -0
  72. package/dist/commands/upgrade.js +495 -0
  73. package/dist/commands/validate.d.ts +30 -0
  74. package/dist/commands/validate.js +148 -0
  75. package/dist/runtime-stubs/hydrate-local-ctx.d.ts +49 -0
  76. package/dist/runtime-stubs/hydrate-local-ctx.js +45 -0
  77. package/dist/runtime-stubs/load-secrets.d.ts +11 -0
  78. package/dist/runtime-stubs/load-secrets.js +37 -0
  79. package/dist/server/api-server.d.ts +21 -0
  80. package/dist/server/api-server.js +14 -0
  81. package/dist/server/mount-routes.d.ts +19 -0
  82. package/dist/server/mount-routes.js +42 -0
  83. package/dist/templates/api-skeleton.d.ts +18 -0
  84. package/dist/templates/api-skeleton.js +69 -0
  85. package/dist/templates/claude-md.d.ts +4 -0
  86. package/dist/templates/claude-md.js +7 -0
  87. package/dist/templates/dashboard-pages/index.d.ts +101 -0
  88. package/dist/templates/dashboard-pages/index.js +22 -0
  89. package/dist/templates/domain-config.d.ts +10 -0
  90. package/dist/templates/domain-config.js +19 -0
  91. package/dist/templates/events-skeleton.d.ts +9 -0
  92. package/dist/templates/events-skeleton.js +23 -0
  93. package/dist/templates/patterns/api/create-with-event.d.ts +5 -0
  94. package/dist/templates/patterns/api/create-with-event.js +69 -0
  95. package/dist/templates/patterns/api/idempotent-mutation.d.ts +5 -0
  96. package/dist/templates/patterns/api/idempotent-mutation.js +99 -0
  97. package/dist/templates/patterns/api/paginated-list.d.ts +5 -0
  98. package/dist/templates/patterns/api/paginated-list.js +71 -0
  99. package/dist/templates/patterns/api/simple-crud.d.ts +6 -0
  100. package/dist/templates/patterns/api/simple-crud.js +95 -0
  101. package/dist/templates/patterns/api/system-admin.d.ts +5 -0
  102. package/dist/templates/patterns/api/system-admin.js +98 -0
  103. package/dist/templates/patterns/api/webhook-receiver-style.d.ts +5 -0
  104. package/dist/templates/patterns/api/webhook-receiver-style.js +125 -0
  105. package/dist/templates/patterns/component/index.d.ts +25 -0
  106. package/dist/templates/patterns/component/index.js +814 -0
  107. package/dist/templates/patterns/flow/autonomous-remediation.d.ts +5 -0
  108. package/dist/templates/patterns/flow/autonomous-remediation.js +98 -0
  109. package/dist/templates/patterns/flow/fan-out-reaction.d.ts +5 -0
  110. package/dist/templates/patterns/flow/fan-out-reaction.js +53 -0
  111. package/dist/templates/patterns/flow/human-in-loop.d.ts +5 -0
  112. package/dist/templates/patterns/flow/human-in-loop.js +90 -0
  113. package/dist/templates/patterns/flow/multi-step-orchestration.d.ts +5 -0
  114. package/dist/templates/patterns/flow/multi-step-orchestration.js +67 -0
  115. package/dist/templates/patterns/hook/index.d.ts +7 -0
  116. package/dist/templates/patterns/hook/index.js +378 -0
  117. package/dist/templates/patterns/migration/column-add.d.ts +5 -0
  118. package/dist/templates/patterns/migration/column-add.js +52 -0
  119. package/dist/templates/patterns/migration/event-store.d.ts +6 -0
  120. package/dist/templates/patterns/migration/event-store.js +97 -0
  121. package/dist/templates/patterns/migration/index.d.ts +5 -0
  122. package/dist/templates/patterns/migration/index.js +52 -0
  123. package/dist/templates/patterns/migration/rls-policy.d.ts +5 -0
  124. package/dist/templates/patterns/migration/rls-policy.js +78 -0
  125. package/dist/templates/patterns/migration/tenant-scoped-table.d.ts +6 -0
  126. package/dist/templates/patterns/migration/tenant-scoped-table.js +81 -0
  127. package/dist/templates/patterns/page/dashboard.d.ts +4 -0
  128. package/dist/templates/patterns/page/dashboard.js +164 -0
  129. package/dist/templates/patterns/page/detail.d.ts +4 -0
  130. package/dist/templates/patterns/page/detail.js +162 -0
  131. package/dist/templates/patterns/page/form.d.ts +4 -0
  132. package/dist/templates/patterns/page/form.js +192 -0
  133. package/dist/templates/patterns/page/index.d.ts +8 -0
  134. package/dist/templates/patterns/page/index.js +14 -0
  135. package/dist/templates/patterns/page/list.d.ts +4 -0
  136. package/dist/templates/patterns/page/list.js +138 -0
  137. package/dist/templates/patterns/page/settings.d.ts +4 -0
  138. package/dist/templates/patterns/page/settings.js +318 -0
  139. package/dist/templates/patterns/page/wizard.d.ts +4 -0
  140. package/dist/templates/patterns/page/wizard.js +293 -0
  141. package/dist/templates/patterns/subscriber/audit-relay.d.ts +5 -0
  142. package/dist/templates/patterns/subscriber/audit-relay.js +51 -0
  143. package/dist/templates/patterns/subscriber/cascade-deletion.d.ts +5 -0
  144. package/dist/templates/patterns/subscriber/cascade-deletion.js +60 -0
  145. package/dist/templates/patterns/subscriber/single-step-projection.d.ts +5 -0
  146. package/dist/templates/patterns/subscriber/single-step-projection.js +36 -0
  147. package/dist/templates/readme.d.ts +4 -0
  148. package/dist/templates/readme.js +7 -0
  149. package/dist/templates/subscriber-skeleton.d.ts +11 -0
  150. package/dist/templates/subscriber-skeleton.js +23 -0
  151. package/dist/utils/checksum.d.ts +18 -0
  152. package/dist/utils/checksum.js +39 -0
  153. package/dist/utils/file-helpers.d.ts +35 -0
  154. package/dist/utils/file-helpers.js +59 -0
  155. package/dist/utils/header-inject.d.ts +15 -0
  156. package/dist/utils/header-inject.js +93 -0
  157. package/dist/utils/install-file.d.ts +17 -0
  158. package/dist/utils/install-file.js +78 -0
  159. package/dist/utils/logger.d.ts +12 -0
  160. package/dist/utils/logger.js +24 -0
  161. package/dist/utils/manifest.d.ts +28 -0
  162. package/dist/utils/manifest.js +93 -0
  163. package/dist/utils/s3-fetch.d.ts +25 -0
  164. package/dist/utils/s3-fetch.js +52 -0
  165. package/dist/utils/scaffold-config.d.ts +95 -0
  166. package/dist/utils/scaffold-config.js +53 -0
  167. package/dist/utils/token-substitution.d.ts +35 -0
  168. package/dist/utils/token-substitution.js +52 -0
  169. package/dist/utils/zod-extractor.d.ts +10 -0
  170. package/dist/utils/zod-extractor.js +28 -0
  171. package/package.json +43 -0
  172. package/src/__tests__/build-registry.test.ts +115 -0
  173. package/src/__tests__/build-types.test.ts +100 -0
  174. package/src/__tests__/builder/walkDomainDir.test.ts +140 -0
  175. package/src/__tests__/commands/add-domain.test.ts +174 -0
  176. package/src/__tests__/commands/add-flow.test.ts +69 -0
  177. package/src/__tests__/commands/add-module.test.ts +207 -0
  178. package/src/__tests__/commands/build-flows.test.ts +154 -0
  179. package/src/__tests__/commands/check-hashes.test.ts +142 -0
  180. package/src/__tests__/commands/create-project.test.ts +712 -0
  181. package/src/__tests__/commands/upgrade.test.ts +762 -0
  182. package/src/__tests__/doctor.test.ts +291 -0
  183. package/src/__tests__/hydrate-local-ctx.test.ts +71 -0
  184. package/src/__tests__/load-domain-module-config.test.ts +10 -0
  185. package/src/__tests__/mount-routes.test.ts +100 -0
  186. package/src/__tests__/scaffold-src/part-a-layout.test.ts +46 -0
  187. package/src/__tests__/scripts/package-scaffold.test.ts +45 -0
  188. package/src/__tests__/utils/checksum.test.ts +90 -0
  189. package/src/__tests__/utils/header-inject.test.ts +89 -0
  190. package/src/__tests__/utils/install-file.test.ts +207 -0
  191. package/src/__tests__/utils/manifest.test.ts +229 -0
  192. package/src/__tests__/utils/token-substitution.test.ts +134 -0
  193. package/src/__tests__/validate.test.ts +18 -0
  194. package/src/builder/build-registry.ts +237 -0
  195. package/src/builder/build-types.ts +36 -0
  196. package/src/builder/load-domain-module-config.ts +43 -0
  197. package/src/builder/load-module.ts +133 -0
  198. package/src/builder/zod-to-json.ts +16 -0
  199. package/src/cli.ts +387 -0
  200. package/src/commands/add-api.ts +145 -0
  201. package/src/commands/add-component.ts +116 -0
  202. package/src/commands/add-domain.ts +100 -0
  203. package/src/commands/add-flow.ts +136 -0
  204. package/src/commands/add-hook.ts +100 -0
  205. package/src/commands/add-migration.ts +129 -0
  206. package/src/commands/add-module.ts +347 -0
  207. package/src/commands/add-page.ts +242 -0
  208. package/src/commands/add-seed-page.ts +338 -0
  209. package/src/commands/add-subscriber.ts +123 -0
  210. package/src/commands/add-test.ts +328 -0
  211. package/src/commands/audit.ts +217 -0
  212. package/src/commands/build-catalog.ts +181 -0
  213. package/src/commands/build-flows.ts +198 -0
  214. package/src/commands/build.ts +59 -0
  215. package/src/commands/check-hashes.ts +150 -0
  216. package/src/commands/create-project.ts +367 -0
  217. package/src/commands/dev.ts +47 -0
  218. package/src/commands/doctor.ts +1362 -0
  219. package/src/commands/explain.ts +209 -0
  220. package/src/commands/power-tune.ts +112 -0
  221. package/src/commands/reseed-page.ts +410 -0
  222. package/src/commands/show-dns.ts +139 -0
  223. package/src/commands/show.ts +179 -0
  224. package/src/commands/test.ts +91 -0
  225. package/src/commands/upgrade-backend.ts +72 -0
  226. package/src/commands/upgrade-event.ts +175 -0
  227. package/src/commands/upgrade-frontend.ts +135 -0
  228. package/src/commands/upgrade.ts +668 -0
  229. package/src/commands/validate.ts +208 -0
  230. package/src/runtime-stubs/hydrate-local-ctx.ts +102 -0
  231. package/src/runtime-stubs/load-secrets.ts +40 -0
  232. package/src/server/api-server.ts +34 -0
  233. package/src/server/mount-routes.ts +68 -0
  234. package/src/templates/api-skeleton.ts +72 -0
  235. package/src/templates/claude-md.ts +7 -0
  236. package/src/templates/dashboard-pages/account/api-keys.tsx +107 -0
  237. package/src/templates/dashboard-pages/account/audit-log.tsx +60 -0
  238. package/src/templates/dashboard-pages/account/index.ts +5 -0
  239. package/src/templates/dashboard-pages/account/members.tsx +107 -0
  240. package/src/templates/dashboard-pages/account/profile.tsx +53 -0
  241. package/src/templates/dashboard-pages/account/workspace-settings.tsx +64 -0
  242. package/src/templates/dashboard-pages/auth/accept-invitation.tsx +62 -0
  243. package/src/templates/dashboard-pages/auth/choose-org.tsx +66 -0
  244. package/src/templates/dashboard-pages/auth/forgot-password.tsx +69 -0
  245. package/src/templates/dashboard-pages/auth/index.ts +10 -0
  246. package/src/templates/dashboard-pages/auth/login.tsx +75 -0
  247. package/src/templates/dashboard-pages/auth/mfa-setup.tsx +56 -0
  248. package/src/templates/dashboard-pages/auth/mfa-verify.tsx +49 -0
  249. package/src/templates/dashboard-pages/auth/reset-password.tsx +64 -0
  250. package/src/templates/dashboard-pages/auth/sign-out.tsx +20 -0
  251. package/src/templates/dashboard-pages/auth/signup.tsx +71 -0
  252. package/src/templates/dashboard-pages/auth/verify-email.tsx +53 -0
  253. package/src/templates/dashboard-pages/index.ts +22 -0
  254. package/src/templates/dashboard-pages/shell/dashboard-home.tsx +41 -0
  255. package/src/templates/dashboard-pages/shell/forbidden.tsx +46 -0
  256. package/src/templates/dashboard-pages/shell/index.ts +5 -0
  257. package/src/templates/dashboard-pages/shell/maintenance.tsx +27 -0
  258. package/src/templates/dashboard-pages/shell/not-found.tsx +34 -0
  259. package/src/templates/dashboard-pages/shell/server-error.tsx +44 -0
  260. package/src/templates/domain-config.ts +20 -0
  261. package/src/templates/events-skeleton.ts +24 -0
  262. package/src/templates/patterns/api/create-with-event.ts +72 -0
  263. package/src/templates/patterns/api/idempotent-mutation.ts +102 -0
  264. package/src/templates/patterns/api/paginated-list.ts +74 -0
  265. package/src/templates/patterns/api/simple-crud.ts +100 -0
  266. package/src/templates/patterns/api/system-admin.ts +101 -0
  267. package/src/templates/patterns/api/webhook-receiver-style.ts +128 -0
  268. package/src/templates/patterns/component/index.ts +833 -0
  269. package/src/templates/patterns/flow/autonomous-remediation.ts +101 -0
  270. package/src/templates/patterns/flow/fan-out-reaction.ts +56 -0
  271. package/src/templates/patterns/flow/human-in-loop.ts +93 -0
  272. package/src/templates/patterns/flow/multi-step-orchestration.ts +70 -0
  273. package/src/templates/patterns/hook/index.ts +382 -0
  274. package/src/templates/patterns/migration/column-add.ts +54 -0
  275. package/src/templates/patterns/migration/event-store.ts +99 -0
  276. package/src/templates/patterns/migration/index.ts +54 -0
  277. package/src/templates/patterns/migration/rls-policy.ts +80 -0
  278. package/src/templates/patterns/migration/tenant-scoped-table.ts +83 -0
  279. package/src/templates/patterns/page/dashboard.ts +164 -0
  280. package/src/templates/patterns/page/detail.ts +162 -0
  281. package/src/templates/patterns/page/form.ts +192 -0
  282. package/src/templates/patterns/page/index.ts +17 -0
  283. package/src/templates/patterns/page/list.ts +138 -0
  284. package/src/templates/patterns/page/settings.ts +318 -0
  285. package/src/templates/patterns/page/wizard.ts +293 -0
  286. package/src/templates/patterns/subscriber/audit-relay.ts +54 -0
  287. package/src/templates/patterns/subscriber/cascade-deletion.ts +63 -0
  288. package/src/templates/patterns/subscriber/single-step-projection.ts +39 -0
  289. package/src/templates/readme.ts +7 -0
  290. package/src/templates/subscriber-skeleton.ts +28 -0
  291. package/src/utils/checksum.ts +43 -0
  292. package/src/utils/file-helpers.ts +91 -0
  293. package/src/utils/header-inject.ts +126 -0
  294. package/src/utils/install-file.ts +99 -0
  295. package/src/utils/logger.ts +26 -0
  296. package/src/utils/manifest.ts +137 -0
  297. package/src/utils/s3-fetch.ts +91 -0
  298. package/src/utils/scaffold-config.ts +172 -0
  299. package/src/utils/token-substitution.ts +80 -0
  300. package/src/utils/zod-extractor.ts +31 -0
  301. package/tsconfig.json +13 -0
@@ -0,0 +1,91 @@
1
+ import { GetObjectCommand, S3Client } from '@aws-sdk/client-s3';
2
+ import { createHash } from 'crypto';
3
+ import { Readable } from 'stream';
4
+
5
+ export interface ModulesJson {
6
+ scaffoldVersion: string;
7
+ releasedAt: string;
8
+ modules: S3ModuleEntry[];
9
+ compatibility: {
10
+ cliMinVersion: string;
11
+ nodeMinVersion: string;
12
+ };
13
+ }
14
+
15
+ export interface S3ModuleEntry {
16
+ id: string;
17
+ version: string;
18
+ description: string;
19
+ dependencies: string[];
20
+ tarball: string;
21
+ sha256: string;
22
+ }
23
+
24
+ export interface VersionsJson {
25
+ latest: string;
26
+ versions: string[];
27
+ }
28
+
29
+ export async function fetchVersionsJson(bucket: string): Promise<VersionsJson> {
30
+ const client = new S3Client({});
31
+ const cmd = new GetObjectCommand({ Bucket: bucket, Key: 'versions.json' });
32
+ const res = await client.send(cmd);
33
+ const body = await streamToBuffer(res.Body as Readable);
34
+ return JSON.parse(body.toString('utf-8')) as VersionsJson;
35
+ }
36
+
37
+ export async function fetchModulesJson(bucket: string, version: string): Promise<ModulesJson> {
38
+ const client = new S3Client({});
39
+ const cmd = new GetObjectCommand({
40
+ Bucket: bucket,
41
+ Key: `versions/${version}/modules.json`,
42
+ });
43
+ const res = await client.send(cmd);
44
+ const body = await streamToBuffer(res.Body as Readable);
45
+ return JSON.parse(body.toString('utf-8')) as ModulesJson;
46
+ }
47
+
48
+ export async function fetchModuleTarball(
49
+ bucket: string,
50
+ version: string,
51
+ tarball: string,
52
+ expectedSha256: string
53
+ ): Promise<Buffer> {
54
+ const client = new S3Client({});
55
+ const key = `versions/${version}/${tarball}`;
56
+ const cmd = new GetObjectCommand({ Bucket: bucket, Key: key });
57
+ const res = await client.send(cmd);
58
+ const buf = await streamToBuffer(res.Body as Readable);
59
+ const actual = createHash('sha256').update(buf).digest('hex');
60
+ if (actual !== expectedSha256) {
61
+ throw new Error(
62
+ `Checksum mismatch for ${tarball}: expected ${expectedSha256}, got ${actual}`
63
+ );
64
+ }
65
+ return buf;
66
+ }
67
+
68
+ export async function fetchScaffoldFile(
69
+ bucket: string,
70
+ version: string,
71
+ path: string
72
+ ): Promise<string | null> {
73
+ const client = new S3Client({});
74
+ const cmd = new GetObjectCommand({ Bucket: bucket, Key: `versions/${version}/${path}` });
75
+ try {
76
+ const res = await client.send(cmd);
77
+ const body = await streamToBuffer(res.Body as Readable);
78
+ return body.toString('utf-8');
79
+ } catch (err: unknown) {
80
+ if ((err as { name?: string }).name === 'NoSuchKey') return null;
81
+ throw err;
82
+ }
83
+ }
84
+
85
+ async function streamToBuffer(stream: Readable): Promise<Buffer> {
86
+ const chunks: Buffer[] = [];
87
+ for await (const chunk of stream) {
88
+ chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk as ArrayBuffer));
89
+ }
90
+ return Buffer.concat(chunks);
91
+ }
@@ -0,0 +1,172 @@
1
+ import { readFile, writeFile } from 'fs/promises';
2
+ import path from 'path';
3
+
4
+ export type ModuleId =
5
+ | 'core'
6
+ | 'backend-lambda'
7
+ | 'db-aurora'
8
+ | 'auth-cognito'
9
+ | 'frontend'
10
+ | 'flows'
11
+ | 'data-management';
12
+
13
+ export type LogRetentionDays = 30 | 90 | 365 | 2557;
14
+
15
+ export interface SecurityOptions {
16
+ /** Enable CMK (KMS customer-managed keys) for DynamoDB, S3, SQS. ~$10–20/month */
17
+ cmk: boolean;
18
+ /** Enable GuardDuty threat detection with S3 protection. ~$15–25/month */
19
+ guardDuty: boolean;
20
+ /** Enable WAF WebACL on all domain API Gateways. ~$25–60/month */
21
+ waf: boolean;
22
+ /** Enable VPC interface endpoints for SM, SQS, EventBridge, Lambda. ~$85–100/month */
23
+ vpcInterfaceEndpoints: boolean;
24
+ /** Enable CloudWatch alarms and DLQ depth alarms per domain. ~$10–15/month */
25
+ cloudWatchAlarms: boolean;
26
+ /** Enable Cognito advanced security (adaptive auth + compromised-credential detection). Phase B. */
27
+ cognitoAdvancedSecurity?: boolean;
28
+ /** Cognito MFA enforcement level. Phase B. */
29
+ cognitoMfaEnforcement?: 'off' | 'optional' | 'required';
30
+ /** Secrets Manager auto-rotation cadence in days. 0 = disabled. Phase B. */
31
+ secretsRotationDays?: 0 | 30 | 90 | 365;
32
+ /** API Gateway minimum TLS version. Phase B. */
33
+ tlsMinimumVersion?: '1.2' | '1.3';
34
+ }
35
+
36
+ /** Cost / performance tunables — Phase B. Schema only in Phase A. */
37
+ export interface CostOptions {
38
+ auroraMinAcuNonProd?: 0 | 0.5 | 1;
39
+ auroraPerformanceInsights?: boolean;
40
+ apiGatewayAccessLogSamplingRate?: 0 | 0.1 | 1.0;
41
+ lambdaLogLevelDefault?: 'INFO' | 'WARN' | 'ERROR';
42
+ xRaySamplingRate?: number;
43
+ reservedConcurrencyPerDomain?: Record<string, number>;
44
+ }
45
+
46
+ /** Lifecycle tunables — Phase B. Schema only in Phase A. */
47
+ export interface LifecycleOptions {
48
+ dlqRetentionDays?: 7 | 14;
49
+ auroraBackupRetentionDays?: 7 | 14 | 35;
50
+ auditLogArchiveToS3?: boolean;
51
+ }
52
+
53
+ /** Per-environment URL configuration. */
54
+ export interface EnvironmentConfig {
55
+ /**
56
+ * Bare domain for the dashboard in this environment (no scheme, no path, no port).
57
+ * Example: "app.acme.com". When set, an ACM cert is provisioned and CloudFront is
58
+ * configured with this domain name. DNS records are surfaced in the Setup tab.
59
+ */
60
+ dashboardUrl?: string;
61
+ }
62
+
63
+ /** Optional per-environment URL overrides. */
64
+ export interface EnvironmentsConfig {
65
+ dev?: EnvironmentConfig;
66
+ staging?: EnvironmentConfig;
67
+ prod?: EnvironmentConfig;
68
+ }
69
+
70
+ export interface ScaffoldConfig {
71
+ $schema?: string;
72
+ /** Scaffold version this project was created with / last upgraded to */
73
+ scaffoldVersion: string;
74
+ /** Modules installed in this project */
75
+ enabledModules: ModuleId[];
76
+ /** Project identity — used for token substitution and resource naming */
77
+ projectName: string;
78
+ awsRegion: string;
79
+ awsAccountId: string;
80
+ /** Admin email collected at scaffold time (Cognito seed user). Present only when auth-cognito module is enabled. */
81
+ adminEmail?: string;
82
+ /** Domain IDs added via `tib add-domain` — NOT scaffold-owned, user-managed */
83
+ domainIds: string[];
84
+ /** Flow IDs added via `tib add-flow` — user-managed */
85
+ flowIds: string[];
86
+ /** S3 bucket used for scaffold fetches (defaults to public TIB bucket) */
87
+ scaffoldBucket: string;
88
+ /** Security feature opt-ins. All default false. */
89
+ securityOptions?: SecurityOptions;
90
+ /** ISO timestamp when scaffold was first deployed per environment. CMK and VPC endpoints are locked after first deploy. */
91
+ firstDeployedAt?: { dev?: string; prod?: string };
92
+ /** CloudWatch log retention in days. Default: 30. */
93
+ logRetentionDays?: LogRetentionDays;
94
+ /** Cost / performance tunables. Phase B — schema present, CDK not yet wired. */
95
+ costOptions?: CostOptions;
96
+ /** Lifecycle tunables. Phase B — schema present, CDK not yet wired. */
97
+ lifecycleOptions?: LifecycleOptions;
98
+ /** Per-environment URL configuration for custom domains. */
99
+ environments?: EnvironmentsConfig;
100
+ /** When true, CORS responses include Allow-Credentials: true (requires non-wildcard origins). */
101
+ allowCredentials?: boolean;
102
+ }
103
+
104
+ const DEFAULT_SCAFFOLD_CONFIG: Omit<ScaffoldConfig, 'domainIds' | 'flowIds'> = {
105
+ scaffoldVersion: '0.0.0',
106
+ enabledModules: ['core', 'backend-lambda'],
107
+ projectName: 'unknown',
108
+ awsRegion: 'eu-north-1',
109
+ awsAccountId: '',
110
+ scaffoldBucket: 'mc-scaffold',
111
+ securityOptions: {
112
+ cmk: false,
113
+ guardDuty: false,
114
+ waf: false,
115
+ vpcInterfaceEndpoints: false,
116
+ cloudWatchAlarms: false,
117
+ },
118
+ firstDeployedAt: {},
119
+ logRetentionDays: 30,
120
+ };
121
+
122
+ const CONFIG_PATH = '.mc/scaffold-config.json';
123
+
124
+ export async function readScaffoldConfig(projectRoot: string): Promise<ScaffoldConfig> {
125
+ const configPath = path.join(projectRoot, CONFIG_PATH);
126
+ const content = await readFile(configPath, 'utf-8');
127
+ const raw = JSON.parse(content) as Partial<ScaffoldConfig>;
128
+
129
+ // Backward compatibility: old files may only have domainIds/flowIds
130
+ if (!raw.scaffoldVersion) {
131
+ // eslint-disable-next-line no-console
132
+ console.warn(
133
+ '[tib] scaffold-config.json is missing scaffoldVersion — project was created before S3 scaffold migration. Run `tib upgrade` to backfill.'
134
+ );
135
+ }
136
+
137
+ return {
138
+ ...DEFAULT_SCAFFOLD_CONFIG,
139
+ domainIds: [],
140
+ flowIds: [],
141
+ ...raw,
142
+ } as ScaffoldConfig;
143
+ }
144
+
145
+ export async function writeScaffoldConfig(
146
+ projectRoot: string,
147
+ config: ScaffoldConfig
148
+ ): Promise<void> {
149
+ const configPath = path.join(projectRoot, CONFIG_PATH);
150
+ await writeFile(configPath, JSON.stringify(config, null, 2) + '\n', 'utf-8');
151
+ }
152
+
153
+ export function updateScaffoldConfig(
154
+ config: ScaffoldConfig,
155
+ updates: Partial<ScaffoldConfig>
156
+ ): ScaffoldConfig {
157
+ return { ...config, ...updates };
158
+ }
159
+
160
+ /**
161
+ * Add a domain ID to the scaffold config file on disk.
162
+ */
163
+ export async function addDomainToScaffoldConfig(
164
+ domainId: string,
165
+ projectRoot: string
166
+ ): Promise<void> {
167
+ const config = await readScaffoldConfig(projectRoot);
168
+ if (!config.domainIds.includes(domainId)) {
169
+ config.domainIds.push(domainId);
170
+ await writeScaffoldConfig(projectRoot, config);
171
+ }
172
+ }
@@ -0,0 +1,80 @@
1
+ export interface TokenContext {
2
+ PROJECT_NAME: string;
3
+ PROJECT_NAME_PASCAL: string;
4
+ PROJECT_NAME_UPPER: string;
5
+ AWS_REGION: string;
6
+ AWS_ACCOUNT_ID: string;
7
+ ADMIN_EMAIL: string;
8
+ SCAFFOLD_VERSION: string;
9
+ SCAFFOLD_DATE: string;
10
+ TIB_CLI_VERSION: string;
11
+ }
12
+
13
+ export interface ScaffoldConfigForTokens {
14
+ projectName: string;
15
+ awsRegion: string;
16
+ awsAccountId: string;
17
+ adminEmail?: string;
18
+ }
19
+
20
+ /**
21
+ * Replace all {{TOKEN}} placeholders in a template string with values from ctx.
22
+ * Throws if an unknown token is encountered.
23
+ */
24
+ export function applyTokens(template: string, ctx: TokenContext): string {
25
+ return template.replace(/\{\{([A-Z_]+)\}\}/g, (match, key: string) => {
26
+ const value = (ctx as unknown as Record<string, string>)[key];
27
+ if (value === undefined) {
28
+ throw new Error(`Unknown scaffold token: {{${key}}}`);
29
+ }
30
+ return value;
31
+ });
32
+ }
33
+
34
+ /**
35
+ * Build a TokenContext from a scaffold config and resolved version.
36
+ */
37
+ export function buildTokenContext(
38
+ config: ScaffoldConfigForTokens,
39
+ scaffoldVersion: string,
40
+ cliVersion: string
41
+ ): TokenContext {
42
+ const name = config.projectName;
43
+ return {
44
+ PROJECT_NAME: name,
45
+ PROJECT_NAME_PASCAL: toPascalCase(name),
46
+ PROJECT_NAME_UPPER: toUpperSnakeCase(name),
47
+ AWS_REGION: config.awsRegion,
48
+ AWS_ACCOUNT_ID: config.awsAccountId,
49
+ ADMIN_EMAIL: config.adminEmail ?? '',
50
+ SCAFFOLD_VERSION: scaffoldVersion,
51
+ SCAFFOLD_DATE: new Date().toISOString().split('T')[0],
52
+ TIB_CLI_VERSION: cliVersion,
53
+ };
54
+ }
55
+
56
+ function toPascalCase(kebab: string): string {
57
+ return kebab
58
+ .split('-')
59
+ .map((part) => part.charAt(0).toUpperCase() + part.slice(1))
60
+ .join('');
61
+ }
62
+
63
+ function toUpperSnakeCase(kebab: string): string {
64
+ return kebab.replace(/-/g, '_').toUpperCase();
65
+ }
66
+
67
+ /**
68
+ * Returns true if the given file extension indicates the file should receive token substitution.
69
+ * Only .tpl files are substituted.
70
+ */
71
+ export function isTemplateFile(filename: string): boolean {
72
+ return filename.endsWith('.tpl');
73
+ }
74
+
75
+ /**
76
+ * Strip the .tpl extension from a filename to get the install path.
77
+ */
78
+ export function stripTplExtension(filename: string): string {
79
+ return filename.endsWith('.tpl') ? filename.slice(0, -4) : filename;
80
+ }
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Utilities for extracting Zod schemas to JSON Schema format.
3
+ * Uses zod-to-json-schema to convert live Zod objects to JSON-serializable schema.
4
+ */
5
+
6
+ import { zodToJsonSchema } from 'zod-to-json-schema';
7
+
8
+ /**
9
+ * Extract a Zod schema to its JSON Schema representation.
10
+ * @param schema - A Zod schema object (e.g., z.object({...})).
11
+ * @returns JSON Schema object or null if extraction fails.
12
+ */
13
+ export function extractZodSchema(schema: unknown): Record<string, unknown> | null {
14
+ if (!schema || typeof schema !== 'object') {
15
+ return null;
16
+ }
17
+
18
+ try {
19
+ // Check if this looks like a Zod schema by inspecting for the parse method
20
+ if (typeof (schema as { parse?: unknown }).parse === 'function') {
21
+ // Use type assertion to bypass TypeScript compatibility issues with zod versions
22
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
23
+ const jsonSchema = zodToJsonSchema(schema as any);
24
+ return jsonSchema as Record<string, unknown>;
25
+ }
26
+ } catch {
27
+ // Silently return null if extraction fails
28
+ }
29
+
30
+ return null;
31
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,13 @@
1
+ {
2
+ "extends": "../../tsconfig.base.json",
3
+ "compilerOptions": {
4
+ "outDir": "dist",
5
+ "rootDir": "src",
6
+ "declaration": true,
7
+ "noEmit": false,
8
+ "module": "ESNext",
9
+ "moduleResolution": "bundler"
10
+ },
11
+ "include": ["src/**/*"],
12
+ "exclude": ["src/**/__tests__/**", "src/templates/**", "node_modules", "dist"]
13
+ }