@mondaydotcomorg/z2h-cli 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (157) hide show
  1. package/README.md +16 -0
  2. package/bin/z2h-cli.js +2 -0
  3. package/dist/commands/build.d.ts +5 -0
  4. package/dist/commands/build.d.ts.map +1 -0
  5. package/dist/commands/build.js +37 -0
  6. package/dist/commands/clean.d.ts +5 -0
  7. package/dist/commands/clean.d.ts.map +1 -0
  8. package/dist/commands/clean.js +24 -0
  9. package/dist/commands/deploy.d.ts +6 -0
  10. package/dist/commands/deploy.d.ts.map +1 -0
  11. package/dist/commands/deploy.js +92 -0
  12. package/dist/commands/dev.d.ts +5 -0
  13. package/dist/commands/dev.d.ts.map +1 -0
  14. package/dist/commands/dev.js +58 -0
  15. package/dist/constants.d.ts +25 -0
  16. package/dist/constants.d.ts.map +1 -0
  17. package/dist/constants.js +67 -0
  18. package/dist/esm/commands/build.d.ts +5 -0
  19. package/dist/esm/commands/build.d.ts.map +1 -0
  20. package/dist/esm/commands/build.mjs +35 -0
  21. package/dist/esm/commands/clean.d.ts +5 -0
  22. package/dist/esm/commands/clean.d.ts.map +1 -0
  23. package/dist/esm/commands/clean.mjs +22 -0
  24. package/dist/esm/commands/deploy.d.ts +6 -0
  25. package/dist/esm/commands/deploy.d.ts.map +1 -0
  26. package/dist/esm/commands/deploy.mjs +86 -0
  27. package/dist/esm/commands/dev.d.ts +5 -0
  28. package/dist/esm/commands/dev.d.ts.map +1 -0
  29. package/dist/esm/commands/dev.mjs +56 -0
  30. package/dist/esm/constants.d.ts +25 -0
  31. package/dist/esm/constants.d.ts.map +1 -0
  32. package/dist/esm/constants.mjs +57 -0
  33. package/dist/esm/index.d.ts +2 -0
  34. package/dist/esm/index.d.ts.map +1 -0
  35. package/dist/esm/index.mjs +86 -0
  36. package/dist/esm/shadow/consumer-pkg.d.ts +24 -0
  37. package/dist/esm/shadow/consumer-pkg.d.ts.map +1 -0
  38. package/dist/esm/shadow/consumer-pkg.mjs +81 -0
  39. package/dist/esm/shadow/gitignore.d.ts +7 -0
  40. package/dist/esm/shadow/gitignore.d.ts.map +1 -0
  41. package/dist/esm/shadow/gitignore.mjs +29 -0
  42. package/dist/esm/shadow/merge-package-json.d.ts +16 -0
  43. package/dist/esm/shadow/merge-package-json.d.ts.map +1 -0
  44. package/dist/esm/shadow/merge-package-json.mjs +58 -0
  45. package/dist/esm/shadow/metadata.d.ts +4 -0
  46. package/dist/esm/shadow/metadata.d.ts.map +1 -0
  47. package/dist/esm/shadow/metadata.mjs +18 -0
  48. package/dist/esm/shadow/paths.d.ts +3 -0
  49. package/dist/esm/shadow/paths.d.ts.map +1 -0
  50. package/dist/esm/shadow/paths.mjs +25 -0
  51. package/dist/esm/shadow/port.d.ts +7 -0
  52. package/dist/esm/shadow/port.d.ts.map +1 -0
  53. package/dist/esm/shadow/port.mjs +34 -0
  54. package/dist/esm/shadow/prepare.d.ts +3 -0
  55. package/dist/esm/shadow/prepare.d.ts.map +1 -0
  56. package/dist/esm/shadow/prepare.mjs +60 -0
  57. package/dist/esm/shadow/scaffold.d.ts +7 -0
  58. package/dist/esm/shadow/scaffold.d.ts.map +1 -0
  59. package/dist/esm/shadow/scaffold.mjs +112 -0
  60. package/dist/esm/shadow/sync.d.ts +9 -0
  61. package/dist/esm/shadow/sync.d.ts.map +1 -0
  62. package/dist/esm/shadow/sync.mjs +29 -0
  63. package/dist/esm/shadow/yarnrc.d.ts +10 -0
  64. package/dist/esm/shadow/yarnrc.d.ts.map +1 -0
  65. package/dist/esm/shadow/yarnrc.mjs +27 -0
  66. package/dist/esm/types.d.ts +53 -0
  67. package/dist/esm/types.d.ts.map +1 -0
  68. package/dist/esm/types.mjs +1 -0
  69. package/dist/esm/util/app-name.d.ts +12 -0
  70. package/dist/esm/util/app-name.d.ts.map +1 -0
  71. package/dist/esm/util/app-name.mjs +17 -0
  72. package/dist/esm/util/logger.d.ts +22 -0
  73. package/dist/esm/util/logger.d.ts.map +1 -0
  74. package/dist/esm/util/logger.mjs +59 -0
  75. package/dist/esm/util/manifest.d.ts +31 -0
  76. package/dist/esm/util/manifest.d.ts.map +1 -0
  77. package/dist/esm/util/manifest.mjs +31 -0
  78. package/dist/esm/util/s3/client.d.ts +11 -0
  79. package/dist/esm/util/s3/client.d.ts.map +1 -0
  80. package/dist/esm/util/s3/client.mjs +38 -0
  81. package/dist/esm/util/s3/upload.d.ts +2 -0
  82. package/dist/esm/util/s3/upload.d.ts.map +1 -0
  83. package/dist/esm/util/s3/upload.mjs +32 -0
  84. package/dist/index.d.ts +2 -0
  85. package/dist/index.d.ts.map +1 -0
  86. package/dist/index.js +86 -0
  87. package/dist/shadow/consumer-pkg.d.ts +24 -0
  88. package/dist/shadow/consumer-pkg.d.ts.map +1 -0
  89. package/dist/shadow/consumer-pkg.js +84 -0
  90. package/dist/shadow/gitignore.d.ts +7 -0
  91. package/dist/shadow/gitignore.d.ts.map +1 -0
  92. package/dist/shadow/gitignore.js +35 -0
  93. package/dist/shadow/merge-package-json.d.ts +16 -0
  94. package/dist/shadow/merge-package-json.d.ts.map +1 -0
  95. package/dist/shadow/merge-package-json.js +66 -0
  96. package/dist/shadow/metadata.d.ts +4 -0
  97. package/dist/shadow/metadata.d.ts.map +1 -0
  98. package/dist/shadow/metadata.js +21 -0
  99. package/dist/shadow/paths.d.ts +3 -0
  100. package/dist/shadow/paths.d.ts.map +1 -0
  101. package/dist/shadow/paths.js +31 -0
  102. package/dist/shadow/port.d.ts +7 -0
  103. package/dist/shadow/port.d.ts.map +1 -0
  104. package/dist/shadow/port.js +41 -0
  105. package/dist/shadow/prepare.d.ts +3 -0
  106. package/dist/shadow/prepare.d.ts.map +1 -0
  107. package/dist/shadow/prepare.js +62 -0
  108. package/dist/shadow/scaffold.d.ts +7 -0
  109. package/dist/shadow/scaffold.d.ts.map +1 -0
  110. package/dist/shadow/scaffold.js +118 -0
  111. package/dist/shadow/sync.d.ts +9 -0
  112. package/dist/shadow/sync.d.ts.map +1 -0
  113. package/dist/shadow/sync.js +31 -0
  114. package/dist/shadow/yarnrc.d.ts +10 -0
  115. package/dist/shadow/yarnrc.d.ts.map +1 -0
  116. package/dist/shadow/yarnrc.js +33 -0
  117. package/dist/types.d.ts +53 -0
  118. package/dist/types.d.ts.map +1 -0
  119. package/dist/types.js +1 -0
  120. package/dist/util/app-name.d.ts +12 -0
  121. package/dist/util/app-name.d.ts.map +1 -0
  122. package/dist/util/app-name.js +20 -0
  123. package/dist/util/logger.d.ts +22 -0
  124. package/dist/util/logger.d.ts.map +1 -0
  125. package/dist/util/logger.js +71 -0
  126. package/dist/util/manifest.d.ts +31 -0
  127. package/dist/util/manifest.d.ts.map +1 -0
  128. package/dist/util/manifest.js +36 -0
  129. package/dist/util/s3/client.d.ts +11 -0
  130. package/dist/util/s3/client.d.ts.map +1 -0
  131. package/dist/util/s3/client.js +48 -0
  132. package/dist/util/s3/upload.d.ts +2 -0
  133. package/dist/util/s3/upload.d.ts.map +1 -0
  134. package/dist/util/s3/upload.js +39 -0
  135. package/package.json +56 -0
  136. package/src/commands/build.ts +42 -0
  137. package/src/commands/clean.ts +26 -0
  138. package/src/commands/deploy.ts +114 -0
  139. package/src/commands/dev.ts +64 -0
  140. package/src/constants.ts +63 -0
  141. package/src/index.ts +90 -0
  142. package/src/shadow/consumer-pkg.ts +100 -0
  143. package/src/shadow/gitignore.ts +30 -0
  144. package/src/shadow/merge-package-json.ts +62 -0
  145. package/src/shadow/metadata.ts +17 -0
  146. package/src/shadow/paths.ts +24 -0
  147. package/src/shadow/port.ts +34 -0
  148. package/src/shadow/prepare.ts +68 -0
  149. package/src/shadow/scaffold.ts +120 -0
  150. package/src/shadow/sync.ts +30 -0
  151. package/src/shadow/yarnrc.ts +29 -0
  152. package/src/types.ts +60 -0
  153. package/src/util/app-name.ts +16 -0
  154. package/src/util/logger.ts +64 -0
  155. package/src/util/manifest.ts +65 -0
  156. package/src/util/s3/client.ts +40 -0
  157. package/src/util/s3/upload.ts +41 -0
package/README.md ADDED
@@ -0,0 +1,16 @@
1
+ # z2h-cli
2
+
3
+ CLI for the Zero-to-Hero microfrontend workflow. Handles local dev and deployment to S3.
4
+
5
+ ## Commands
6
+
7
+ ```bash
8
+ z2h dev # start a local Trident dev server; open at /bigbrain-vibe/<app>?zth_local=<port>
9
+ z2h deploy # build and upload to S3, bump the manifest version
10
+ z2h build # build only (no upload)
11
+ z2h clean # remove the .zth shadow directory
12
+ ```
13
+
14
+ ## Deploy
15
+
16
+ Requires standard AWS credentials in the environment. The CLI writes directly to S3 (`BUCKET_WRITE_URL`) and reads the shared manifest through the CDN (`BUCKET_READ_DNS_URL`). See `src/util/s3/client.ts` for the bucket and domain values.
package/bin/z2h-cli.js ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ require('../dist/index.js');
@@ -0,0 +1,5 @@
1
+ export interface BuildOptions {
2
+ json?: boolean;
3
+ }
4
+ export declare function buildCommand(opts: BuildOptions): Promise<void>;
5
+ //# sourceMappingURL=build.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/commands/build.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,wBAAsB,YAAY,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAgCpE"}
@@ -0,0 +1,37 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+
3
+ const fsExtra = require('fs-extra');
4
+ const execa = require('execa');
5
+ const util_logger = require('../util/logger.js');
6
+ const shadow_prepare = require('../shadow/prepare.js');
7
+
8
+ async function buildCommand(opts) {
9
+ if (opts.json) {
10
+ util_logger.setOutputMode('json');
11
+ }
12
+ const ctx = await shadow_prepare.prepareShadow();
13
+ // Typecheck against the shadow's tsconfig (the consumer dir has none).
14
+ // Errors fail the build before we waste time on the Trident pipeline.
15
+ // preferLocal=true makes execa prepend the consumer's node_modules/.bin
16
+ // to PATH, so `tsc` resolves to the version hoisted from .zth's
17
+ // trident-toolkit dep — no npx overhead, no extra template deps.
18
+ util_logger.info(`type-checking "${ctx.appName}"`);
19
+ await execa.execa('tsc', ['--noEmit', '-p', ctx.paths.shadowTsconfig], {
20
+ cwd: ctx.paths.consumerDir,
21
+ preferLocal: true,
22
+ stdio: 'inherit',
23
+ });
24
+ util_logger.info(`building "${ctx.appName}" via trident`);
25
+ await execa.execa('yarn', ['build'], { cwd: ctx.paths.shadowDir, stdio: 'inherit' });
26
+ if (!(await fsExtra.pathExists(ctx.paths.shadowBuild))) {
27
+ throw new Error(`Expected build output at ${ctx.paths.shadowBuild} — not found.`);
28
+ }
29
+ util_logger.output(`[z2h-cli] build complete — artifacts at ${ctx.paths.shadowBuild}`, {
30
+ ok: true,
31
+ appName: ctx.appName,
32
+ port: ctx.port,
33
+ buildDir: ctx.paths.shadowBuild,
34
+ });
35
+ }
36
+
37
+ exports.buildCommand = buildCommand;
@@ -0,0 +1,5 @@
1
+ export interface CleanOptions {
2
+ json?: boolean;
3
+ }
4
+ export declare function cleanCommand(opts: CleanOptions): Promise<void>;
5
+ //# sourceMappingURL=clean.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clean.d.ts","sourceRoot":"","sources":["../../src/commands/clean.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,wBAAsB,YAAY,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAiBpE"}
@@ -0,0 +1,24 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+
3
+ const fsExtra = require('fs-extra');
4
+ const util_logger = require('../util/logger.js');
5
+ const shadow_paths = require('../shadow/paths.js');
6
+
7
+ async function cleanCommand(opts) {
8
+ if (opts.json) {
9
+ util_logger.setOutputMode('json');
10
+ }
11
+ const paths = shadow_paths.resolveConsumerPaths(process.cwd());
12
+ const existed = await fsExtra.pathExists(paths.shadowDir);
13
+ if (existed) {
14
+ util_logger.info(`removing ${paths.shadowDir}`);
15
+ await fsExtra.remove(paths.shadowDir);
16
+ }
17
+ util_logger.output(existed ? `[z2h-cli] cleaned shadow at ${paths.shadowDir}` : '[z2h-cli] nothing to clean', {
18
+ ok: true,
19
+ shadowDir: paths.shadowDir,
20
+ removed: existed,
21
+ });
22
+ }
23
+
24
+ exports.cleanCommand = cleanCommand;
@@ -0,0 +1,6 @@
1
+ export interface DeployOptions {
2
+ dryRun?: boolean;
3
+ json?: boolean;
4
+ }
5
+ export declare function deployCommand(opts: DeployOptions): Promise<void>;
6
+ //# sourceMappingURL=deploy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deploy.d.ts","sourceRoot":"","sources":["../../src/commands/deploy.ts"],"names":[],"mappings":"AAoBA,MAAM,WAAW,aAAa;IAC5B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAaD,wBAAsB,aAAa,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CA6EtE"}
@@ -0,0 +1,92 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+
3
+ const path = require('node:path');
4
+ const fsExtra = require('fs-extra');
5
+ require('execa');
6
+ const util_logger = require('../util/logger.js');
7
+ const shadow_paths = require('../shadow/paths.js');
8
+ const util_manifest = require('../util/manifest.js');
9
+ const util_s3_upload = require('../util/s3/upload.js');
10
+ const util_s3_client = require('../util/s3/client.js');
11
+ const util_appName = require('../util/app-name.js');
12
+ const commands_build = require('./build.js');
13
+
14
+ const _interopDefault = e => e && e.__esModule ? e : { default: e };
15
+
16
+ const path__default = /*#__PURE__*/_interopDefault(path);
17
+
18
+ const APONO_BUNDLE = '<APONO_BUNDLE_NAME>'; // TODO: replace with actual bundle name once infra setup is complete
19
+ async function requestAponoAccess() {
20
+ {
21
+ util_logger.warn(`skipping Apono request — APONO_BUNDLE is still a placeholder ("${APONO_BUNDLE}"). Set it in deploy.ts before relying on auto-grant.`);
22
+ return;
23
+ }
24
+ }
25
+ async function deployCommand(opts) {
26
+ if (opts.json) {
27
+ util_logger.setOutputMode('json');
28
+ }
29
+ util_logger.info('checking S3 bucket');
30
+ await util_s3_client.assertBucketExists();
31
+ util_logger.info('building');
32
+ await commands_build.buildCommand({ json: opts.json });
33
+ const paths = shadow_paths.resolveConsumerPaths(process.cwd());
34
+ const consumerPkg = (await fsExtra.readJson(paths.consumerPkg));
35
+ if (!consumerPkg.name) {
36
+ throw new Error('Consumer package.json must have a "name" field');
37
+ }
38
+ const appName = util_appName.mfAppName(consumerPkg.name);
39
+ if (!(await fsExtra.pathExists(paths.shadowBuild))) {
40
+ throw new Error(`No build output at ${paths.shadowBuild} after build step.`);
41
+ }
42
+ // Trident emits the canonical per-MF manifest at build/asset-manifest.json.
43
+ const assetManifestPath = path__default.default.join(paths.shadowBuild, 'asset-manifest.json');
44
+ if (!(await fsExtra.pathExists(assetManifestPath))) {
45
+ throw new Error(`Missing asset-manifest.json at ${assetManifestPath}.`);
46
+ }
47
+ const assetManifest = (await fsExtra.readJson(assetManifestPath));
48
+ util_logger.info('reading current Z2H manifest');
49
+ const manifest = await util_manifest.readManifest();
50
+ const version = util_manifest.nextVersion(manifest, appName);
51
+ const keyPrefix = `${appName}/${version}`;
52
+ const url = `${util_s3_client.BUCKET_READ_DNS_URL}/${keyPrefix}`;
53
+ if (opts.dryRun) {
54
+ util_logger.output(`[z2h-cli] dry-run: would upload to s3://${util_s3_client.BUCKET_WRITE_NAME}/${keyPrefix}/ as v${version}`, {
55
+ ok: true,
56
+ dryRun: true,
57
+ appName,
58
+ version,
59
+ bucket: util_s3_client.BUCKET_WRITE_NAME,
60
+ keyPrefix,
61
+ url,
62
+ entry: { ...assetManifest, version, url },
63
+ });
64
+ return;
65
+ }
66
+ await requestAponoAccess();
67
+ util_logger.info(`uploading build → s3://${util_s3_client.BUCKET_WRITE_NAME}/${keyPrefix}/`);
68
+ await util_s3_upload.uploadDir(paths.shadowBuild, keyPrefix);
69
+ const entry = {
70
+ ...assetManifest,
71
+ version,
72
+ url,
73
+ };
74
+ util_logger.info(`updating manifest entry "${appName}" → v${version}`);
75
+ await util_manifest.writeManifest(util_manifest.upsertEntry(manifest, appName, entry));
76
+ // The host MF parses the app name from the URL and prepends `mf-` itself
77
+ // before looking it up in the manifest. So the user-facing URL must use
78
+ // the consumer's de-scoped package name (no `mf-` prefix, no `@scope/`).
79
+ const liveUrl = `https://bigbrain.me/bigbrain-vibe/${util_appName.cleanAppName(consumerPkg.name)}`;
80
+ util_logger.output(`[z2h-cli] deployed ✅\n app: ${appName}\n version: ${version}\n open: ${liveUrl}`, {
81
+ ok: true,
82
+ appName,
83
+ version,
84
+ bucket: util_s3_client.BUCKET_WRITE_NAME,
85
+ keyPrefix,
86
+ url,
87
+ liveUrl,
88
+ entry,
89
+ });
90
+ }
91
+
92
+ exports.deployCommand = deployCommand;
@@ -0,0 +1,5 @@
1
+ export interface DevOptions {
2
+ json?: boolean;
3
+ }
4
+ export declare function devCommand(opts: DevOptions): Promise<void>;
5
+ //# sourceMappingURL=dev.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../src/commands/dev.ts"],"names":[],"mappings":"AASA,MAAM,WAAW,UAAU;IACzB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAID,wBAAsB,UAAU,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAgDhE"}
@@ -0,0 +1,58 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+
3
+ const fsExtra = require('fs-extra');
4
+ const chokidar = require('chokidar');
5
+ const execa = require('execa');
6
+ const util_logger = require('../util/logger.js');
7
+ const shadow_prepare = require('../shadow/prepare.js');
8
+ const shadow_consumerPkg = require('../shadow/consumer-pkg.js');
9
+ const shadow_sync = require('../shadow/sync.js');
10
+
11
+ const TRIDENT_READY_PATTERN = /Server started at/i;
12
+ async function devCommand(opts) {
13
+ if (opts.json) {
14
+ util_logger.setOutputMode('json');
15
+ }
16
+ const ctx = await shadow_prepare.prepareShadow();
17
+ const { port } = ctx;
18
+ const url = `https://bigbrain.me/bigbrain-vibe/${ctx.appName}?zth_local=${port}`;
19
+ util_logger.info('starting z2h app');
20
+ // stdout is piped so we can detect trident's ready banner before printing
21
+ // our own ready line. stdin/stderr stay inherited so colored errors and
22
+ // interactive prompts still flow naturally.
23
+ const server = execa.execa('yarn', ['start'], {
24
+ cwd: ctx.paths.shadowDir,
25
+ stdio: ['inherit', 'pipe', 'inherit'],
26
+ });
27
+ let readyPrinted = false;
28
+ server.stdout?.on('data', (chunk) => {
29
+ process.stdout.write(chunk);
30
+ if (!readyPrinted && TRIDENT_READY_PATTERN.test(chunk.toString())) {
31
+ readyPrinted = true;
32
+ util_logger.output(`\n[z2h-cli] ready — open:\n ${url}\n`, {
33
+ ok: true,
34
+ appName: ctx.appName,
35
+ port,
36
+ url,
37
+ });
38
+ }
39
+ });
40
+ // Only watch consumer package.json. Source changes flow through Vite's
41
+ // native import graph — the wrapper imports consumer src via relative
42
+ // path, so Vite's HMR picks up edits without any rsync.
43
+ const pkgWatcher = chokidar.watch(ctx.paths.consumerPkg, { ignoreInitial: true });
44
+ pkgWatcher.on('change', async () => {
45
+ util_logger.warn('consumer package.json changed — re-checking deps');
46
+ try {
47
+ const raw = (await fsExtra.readJson(ctx.paths.consumerPkg));
48
+ const { pkg } = await shadow_consumerPkg.ensureConsumerPkg(ctx.paths.consumerPkg, raw);
49
+ await shadow_sync.syncShadow(ctx.paths, pkg);
50
+ }
51
+ catch (err) {
52
+ util_logger.errorLog(`re-prepare failed: ${err.message}`);
53
+ }
54
+ });
55
+ await server;
56
+ }
57
+
58
+ exports.devCommand = devCommand;
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Cross-file constants. Narrowly-used literals (templates, prefixes used in
3
+ * one place) stay local to their file to keep this index small.
4
+ */
5
+ export declare const SHADOW_DIR_NAME = ".zth";
6
+ /**
7
+ * Protected runtime deps that MUST resolve to a single instance across the
8
+ * wrapper (.zth) and the consumer's src. Declared as peerDependencies in
9
+ * the shadow pkg so yarn hoists them from the workspace root — which is
10
+ * why we enforce their presence in the consumer's own package.json.
11
+ */
12
+ export declare const PROTECTED_DEPS: Record<string, string>;
13
+ /**
14
+ * Protected dev deps. Same idempotent treatment as PROTECTED_DEPS but live
15
+ * in the consumer's `devDependencies`. These give the LLM-authored consumer
16
+ * code access to monday.com platform types out of the box.
17
+ */
18
+ export declare const PROTECTED_DEV_DEPS: Record<string, string>;
19
+ export declare const WORKSPACE_DEV_DEPS: Record<string, string>;
20
+ export declare const SHADOW_SCRIPTS: Record<string, string>;
21
+ export declare const MIN_PORT = 13000;
22
+ export declare const MAX_PORT = 19999;
23
+ export declare const GITIGNORE_ENTRIES: string[];
24
+ export declare const YARNRC_LINES: string[];
25
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,eAAO,MAAM,eAAe,SAAS,CAAC;AAGtC;;;;;GAKG;AACH,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAMjD,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAGrD,CAAC;AAIF,eAAO,MAAM,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAKrD,CAAC;AAEF,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAGjD,CAAC;AAMF,eAAO,MAAM,QAAQ,QAAQ,CAAC;AAC9B,eAAO,MAAM,QAAQ,QAAQ,CAAC;AAG9B,eAAO,MAAM,iBAAiB,UAAY,CAAC;AAG3C,eAAO,MAAM,YAAY,UAIxB,CAAC"}
@@ -0,0 +1,67 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+
3
+ /**
4
+ * Cross-file constants. Narrowly-used literals (templates, prefixes used in
5
+ * one place) stay local to their file to keep this index small.
6
+ */
7
+ // ─────────── Shadow dir layout ───────────
8
+ const SHADOW_DIR_NAME = '.zth';
9
+ // ─────────── Consumer pkg enforcement ──────
10
+ /**
11
+ * Protected runtime deps that MUST resolve to a single instance across the
12
+ * wrapper (.zth) and the consumer's src. Declared as peerDependencies in
13
+ * the shadow pkg so yarn hoists them from the workspace root — which is
14
+ * why we enforce their presence in the consumer's own package.json.
15
+ */
16
+ const PROTECTED_DEPS = {
17
+ react: '^18.2.0',
18
+ 'react-dom': '^18.2.0',
19
+ 'react-error-boundary': '^3.1.3',
20
+ '@mondaydotcomorg/trident-runtime': '^1.24.1',
21
+ '@vibe/core': '^4.0.1',
22
+ };
23
+ /**
24
+ * Protected dev deps. Same idempotent treatment as PROTECTED_DEPS but live
25
+ * in the consumer's `devDependencies`. These give the LLM-authored consumer
26
+ * code access to monday.com platform types out of the box.
27
+ */
28
+ const PROTECTED_DEV_DEPS = {
29
+ '@mondaydotcomorg/mf-api-types': '^0.1.1',
30
+ '@mondaydotcomorg/bigbrain-types': '^0.3.3',
31
+ };
32
+ // ─────────── Shadow pkg template ───────────
33
+ // TODO — Add trident mf-types / bigbrain-types opt-in.
34
+ const WORKSPACE_DEV_DEPS = {
35
+ '@mondaydotcomorg/trident-toolkit': '^2.9.25',
36
+ '@types/react': '^18.0.14',
37
+ '@types/react-dom': '^18.0.5',
38
+ typescript: '^5.7.2',
39
+ };
40
+ const SHADOW_SCRIPTS = {
41
+ start: 'trident start',
42
+ build: 'trident build',
43
+ };
44
+ // ─────────── Auto-allocated dev port range ────
45
+ // High enough to dodge common dev defaults (3000 Next, 5173 Vite, 8080).
46
+ // Collisions within the 7k-port pool are rare for POC; if trident can't
47
+ // bind, the user sees a clear bind error from the dev server and re-runs.
48
+ const MIN_PORT = 13000;
49
+ const MAX_PORT = 19999;
50
+ // ─────────── Gitignore entries auto-appended to the consumer's file ────
51
+ const GITIGNORE_ENTRIES = ['.zth/'];
52
+ // ─────────── .yarnrc.yml written to new consumer apps ────
53
+ const YARNRC_LINES = [
54
+ 'nodeLinker: node-modules',
55
+ "npmAuthToken: '${NPM_TOKEN}'",
56
+ "npmRegistryServer: 'https://registry.npmjs.org/'",
57
+ ];
58
+
59
+ exports.GITIGNORE_ENTRIES = GITIGNORE_ENTRIES;
60
+ exports.MAX_PORT = MAX_PORT;
61
+ exports.MIN_PORT = MIN_PORT;
62
+ exports.PROTECTED_DEPS = PROTECTED_DEPS;
63
+ exports.PROTECTED_DEV_DEPS = PROTECTED_DEV_DEPS;
64
+ exports.SHADOW_DIR_NAME = SHADOW_DIR_NAME;
65
+ exports.SHADOW_SCRIPTS = SHADOW_SCRIPTS;
66
+ exports.WORKSPACE_DEV_DEPS = WORKSPACE_DEV_DEPS;
67
+ exports.YARNRC_LINES = YARNRC_LINES;
@@ -0,0 +1,5 @@
1
+ export interface BuildOptions {
2
+ json?: boolean;
3
+ }
4
+ export declare function buildCommand(opts: BuildOptions): Promise<void>;
5
+ //# sourceMappingURL=build.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../../src/commands/build.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,wBAAsB,YAAY,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAgCpE"}
@@ -0,0 +1,35 @@
1
+ import { pathExists } from 'fs-extra';
2
+ import { execa } from 'execa';
3
+ import { setOutputMode, info, output } from '../util/logger.mjs';
4
+ import { prepareShadow } from '../shadow/prepare.mjs';
5
+
6
+ async function buildCommand(opts) {
7
+ if (opts.json) {
8
+ setOutputMode('json');
9
+ }
10
+ const ctx = await prepareShadow();
11
+ // Typecheck against the shadow's tsconfig (the consumer dir has none).
12
+ // Errors fail the build before we waste time on the Trident pipeline.
13
+ // preferLocal=true makes execa prepend the consumer's node_modules/.bin
14
+ // to PATH, so `tsc` resolves to the version hoisted from .zth's
15
+ // trident-toolkit dep — no npx overhead, no extra template deps.
16
+ info(`type-checking "${ctx.appName}"`);
17
+ await execa('tsc', ['--noEmit', '-p', ctx.paths.shadowTsconfig], {
18
+ cwd: ctx.paths.consumerDir,
19
+ preferLocal: true,
20
+ stdio: 'inherit',
21
+ });
22
+ info(`building "${ctx.appName}" via trident`);
23
+ await execa('yarn', ['build'], { cwd: ctx.paths.shadowDir, stdio: 'inherit' });
24
+ if (!(await pathExists(ctx.paths.shadowBuild))) {
25
+ throw new Error(`Expected build output at ${ctx.paths.shadowBuild} — not found.`);
26
+ }
27
+ output(`[z2h-cli] build complete — artifacts at ${ctx.paths.shadowBuild}`, {
28
+ ok: true,
29
+ appName: ctx.appName,
30
+ port: ctx.port,
31
+ buildDir: ctx.paths.shadowBuild,
32
+ });
33
+ }
34
+
35
+ export { buildCommand };
@@ -0,0 +1,5 @@
1
+ export interface CleanOptions {
2
+ json?: boolean;
3
+ }
4
+ export declare function cleanCommand(opts: CleanOptions): Promise<void>;
5
+ //# sourceMappingURL=clean.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clean.d.ts","sourceRoot":"","sources":["../../../src/commands/clean.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,wBAAsB,YAAY,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAiBpE"}
@@ -0,0 +1,22 @@
1
+ import { pathExists, remove } from 'fs-extra';
2
+ import { setOutputMode, info, output } from '../util/logger.mjs';
3
+ import { resolveConsumerPaths } from '../shadow/paths.mjs';
4
+
5
+ async function cleanCommand(opts) {
6
+ if (opts.json) {
7
+ setOutputMode('json');
8
+ }
9
+ const paths = resolveConsumerPaths(process.cwd());
10
+ const existed = await pathExists(paths.shadowDir);
11
+ if (existed) {
12
+ info(`removing ${paths.shadowDir}`);
13
+ await remove(paths.shadowDir);
14
+ }
15
+ output(existed ? `[z2h-cli] cleaned shadow at ${paths.shadowDir}` : '[z2h-cli] nothing to clean', {
16
+ ok: true,
17
+ shadowDir: paths.shadowDir,
18
+ removed: existed,
19
+ });
20
+ }
21
+
22
+ export { cleanCommand };
@@ -0,0 +1,6 @@
1
+ export interface DeployOptions {
2
+ dryRun?: boolean;
3
+ json?: boolean;
4
+ }
5
+ export declare function deployCommand(opts: DeployOptions): Promise<void>;
6
+ //# sourceMappingURL=deploy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deploy.d.ts","sourceRoot":"","sources":["../../../src/commands/deploy.ts"],"names":[],"mappings":"AAoBA,MAAM,WAAW,aAAa;IAC5B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAaD,wBAAsB,aAAa,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CA6EtE"}
@@ -0,0 +1,86 @@
1
+ import path from 'node:path';
2
+ import { readJson, pathExists } from 'fs-extra';
3
+ import 'execa';
4
+ import { setOutputMode, info, output, warn } from '../util/logger.mjs';
5
+ import { resolveConsumerPaths } from '../shadow/paths.mjs';
6
+ import { readManifest, nextVersion, writeManifest, upsertEntry } from '../util/manifest.mjs';
7
+ import { uploadDir } from '../util/s3/upload.mjs';
8
+ import { assertBucketExists, BUCKET_WRITE_NAME, BUCKET_READ_DNS_URL } from '../util/s3/client.mjs';
9
+ import { mfAppName, cleanAppName } from '../util/app-name.mjs';
10
+ import { buildCommand } from './build.mjs';
11
+
12
+ const APONO_BUNDLE = '<APONO_BUNDLE_NAME>'; // TODO: replace with actual bundle name once infra setup is complete
13
+ async function requestAponoAccess() {
14
+ {
15
+ warn(`skipping Apono request — APONO_BUNDLE is still a placeholder ("${APONO_BUNDLE}"). Set it in deploy.ts before relying on auto-grant.`);
16
+ return;
17
+ }
18
+ }
19
+ async function deployCommand(opts) {
20
+ if (opts.json) {
21
+ setOutputMode('json');
22
+ }
23
+ info('checking S3 bucket');
24
+ await assertBucketExists();
25
+ info('building');
26
+ await buildCommand({ json: opts.json });
27
+ const paths = resolveConsumerPaths(process.cwd());
28
+ const consumerPkg = (await readJson(paths.consumerPkg));
29
+ if (!consumerPkg.name) {
30
+ throw new Error('Consumer package.json must have a "name" field');
31
+ }
32
+ const appName = mfAppName(consumerPkg.name);
33
+ if (!(await pathExists(paths.shadowBuild))) {
34
+ throw new Error(`No build output at ${paths.shadowBuild} after build step.`);
35
+ }
36
+ // Trident emits the canonical per-MF manifest at build/asset-manifest.json.
37
+ const assetManifestPath = path.join(paths.shadowBuild, 'asset-manifest.json');
38
+ if (!(await pathExists(assetManifestPath))) {
39
+ throw new Error(`Missing asset-manifest.json at ${assetManifestPath}.`);
40
+ }
41
+ const assetManifest = (await readJson(assetManifestPath));
42
+ info('reading current Z2H manifest');
43
+ const manifest = await readManifest();
44
+ const version = nextVersion(manifest, appName);
45
+ const keyPrefix = `${appName}/${version}`;
46
+ const url = `${BUCKET_READ_DNS_URL}/${keyPrefix}`;
47
+ if (opts.dryRun) {
48
+ output(`[z2h-cli] dry-run: would upload to s3://${BUCKET_WRITE_NAME}/${keyPrefix}/ as v${version}`, {
49
+ ok: true,
50
+ dryRun: true,
51
+ appName,
52
+ version,
53
+ bucket: BUCKET_WRITE_NAME,
54
+ keyPrefix,
55
+ url,
56
+ entry: { ...assetManifest, version, url },
57
+ });
58
+ return;
59
+ }
60
+ await requestAponoAccess();
61
+ info(`uploading build → s3://${BUCKET_WRITE_NAME}/${keyPrefix}/`);
62
+ await uploadDir(paths.shadowBuild, keyPrefix);
63
+ const entry = {
64
+ ...assetManifest,
65
+ version,
66
+ url,
67
+ };
68
+ info(`updating manifest entry "${appName}" → v${version}`);
69
+ await writeManifest(upsertEntry(manifest, appName, entry));
70
+ // The host MF parses the app name from the URL and prepends `mf-` itself
71
+ // before looking it up in the manifest. So the user-facing URL must use
72
+ // the consumer's de-scoped package name (no `mf-` prefix, no `@scope/`).
73
+ const liveUrl = `https://bigbrain.me/bigbrain-vibe/${cleanAppName(consumerPkg.name)}`;
74
+ output(`[z2h-cli] deployed ✅\n app: ${appName}\n version: ${version}\n open: ${liveUrl}`, {
75
+ ok: true,
76
+ appName,
77
+ version,
78
+ bucket: BUCKET_WRITE_NAME,
79
+ keyPrefix,
80
+ url,
81
+ liveUrl,
82
+ entry,
83
+ });
84
+ }
85
+
86
+ export { deployCommand };
@@ -0,0 +1,5 @@
1
+ export interface DevOptions {
2
+ json?: boolean;
3
+ }
4
+ export declare function devCommand(opts: DevOptions): Promise<void>;
5
+ //# sourceMappingURL=dev.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../../src/commands/dev.ts"],"names":[],"mappings":"AASA,MAAM,WAAW,UAAU;IACzB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAID,wBAAsB,UAAU,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAgDhE"}
@@ -0,0 +1,56 @@
1
+ import { readJson } from 'fs-extra';
2
+ import { watch } from 'chokidar';
3
+ import { execa } from 'execa';
4
+ import { setOutputMode, info, output, warn, errorLog } from '../util/logger.mjs';
5
+ import { prepareShadow } from '../shadow/prepare.mjs';
6
+ import { ensureConsumerPkg } from '../shadow/consumer-pkg.mjs';
7
+ import { syncShadow } from '../shadow/sync.mjs';
8
+
9
+ const TRIDENT_READY_PATTERN = /Server started at/i;
10
+ async function devCommand(opts) {
11
+ if (opts.json) {
12
+ setOutputMode('json');
13
+ }
14
+ const ctx = await prepareShadow();
15
+ const { port } = ctx;
16
+ const url = `https://bigbrain.me/bigbrain-vibe/${ctx.appName}?zth_local=${port}`;
17
+ info('starting z2h app');
18
+ // stdout is piped so we can detect trident's ready banner before printing
19
+ // our own ready line. stdin/stderr stay inherited so colored errors and
20
+ // interactive prompts still flow naturally.
21
+ const server = execa('yarn', ['start'], {
22
+ cwd: ctx.paths.shadowDir,
23
+ stdio: ['inherit', 'pipe', 'inherit'],
24
+ });
25
+ let readyPrinted = false;
26
+ server.stdout?.on('data', (chunk) => {
27
+ process.stdout.write(chunk);
28
+ if (!readyPrinted && TRIDENT_READY_PATTERN.test(chunk.toString())) {
29
+ readyPrinted = true;
30
+ output(`\n[z2h-cli] ready — open:\n ${url}\n`, {
31
+ ok: true,
32
+ appName: ctx.appName,
33
+ port,
34
+ url,
35
+ });
36
+ }
37
+ });
38
+ // Only watch consumer package.json. Source changes flow through Vite's
39
+ // native import graph — the wrapper imports consumer src via relative
40
+ // path, so Vite's HMR picks up edits without any rsync.
41
+ const pkgWatcher = watch(ctx.paths.consumerPkg, { ignoreInitial: true });
42
+ pkgWatcher.on('change', async () => {
43
+ warn('consumer package.json changed — re-checking deps');
44
+ try {
45
+ const raw = (await readJson(ctx.paths.consumerPkg));
46
+ const { pkg } = await ensureConsumerPkg(ctx.paths.consumerPkg, raw);
47
+ await syncShadow(ctx.paths, pkg);
48
+ }
49
+ catch (err) {
50
+ errorLog(`re-prepare failed: ${err.message}`);
51
+ }
52
+ });
53
+ await server;
54
+ }
55
+
56
+ export { devCommand };
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Cross-file constants. Narrowly-used literals (templates, prefixes used in
3
+ * one place) stay local to their file to keep this index small.
4
+ */
5
+ export declare const SHADOW_DIR_NAME = ".zth";
6
+ /**
7
+ * Protected runtime deps that MUST resolve to a single instance across the
8
+ * wrapper (.zth) and the consumer's src. Declared as peerDependencies in
9
+ * the shadow pkg so yarn hoists them from the workspace root — which is
10
+ * why we enforce their presence in the consumer's own package.json.
11
+ */
12
+ export declare const PROTECTED_DEPS: Record<string, string>;
13
+ /**
14
+ * Protected dev deps. Same idempotent treatment as PROTECTED_DEPS but live
15
+ * in the consumer's `devDependencies`. These give the LLM-authored consumer
16
+ * code access to monday.com platform types out of the box.
17
+ */
18
+ export declare const PROTECTED_DEV_DEPS: Record<string, string>;
19
+ export declare const WORKSPACE_DEV_DEPS: Record<string, string>;
20
+ export declare const SHADOW_SCRIPTS: Record<string, string>;
21
+ export declare const MIN_PORT = 13000;
22
+ export declare const MAX_PORT = 19999;
23
+ export declare const GITIGNORE_ENTRIES: string[];
24
+ export declare const YARNRC_LINES: string[];
25
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,eAAO,MAAM,eAAe,SAAS,CAAC;AAGtC;;;;;GAKG;AACH,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAMjD,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAGrD,CAAC;AAIF,eAAO,MAAM,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAKrD,CAAC;AAEF,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAGjD,CAAC;AAMF,eAAO,MAAM,QAAQ,QAAQ,CAAC;AAC9B,eAAO,MAAM,QAAQ,QAAQ,CAAC;AAG9B,eAAO,MAAM,iBAAiB,UAAY,CAAC;AAG3C,eAAO,MAAM,YAAY,UAIxB,CAAC"}