@mondaydotcomorg/z2h-cli 0.7.2 → 0.9.1

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 (90) hide show
  1. package/dist/commands/build.d.ts +1 -1
  2. package/dist/commands/build.d.ts.map +1 -1
  3. package/dist/commands/build.js +4 -3
  4. package/dist/commands/clean.d.ts +1 -1
  5. package/dist/commands/clean.d.ts.map +1 -1
  6. package/dist/commands/clean.js +5 -4
  7. package/dist/commands/create-workspace.d.ts +1 -1
  8. package/dist/commands/create-workspace.d.ts.map +1 -1
  9. package/dist/commands/create-workspace.js +14 -14
  10. package/dist/commands/create.d.ts +1 -1
  11. package/dist/commands/create.d.ts.map +1 -1
  12. package/dist/commands/create.js +27 -13
  13. package/dist/commands/deploy.d.ts +1 -1
  14. package/dist/commands/deploy.d.ts.map +1 -1
  15. package/dist/commands/deploy.js +45 -11
  16. package/dist/commands/dev.d.ts +1 -1
  17. package/dist/commands/dev.d.ts.map +1 -1
  18. package/dist/commands/dev.js +10 -6
  19. package/dist/commands/migrate.d.ts +1 -1
  20. package/dist/commands/migrate.d.ts.map +1 -1
  21. package/dist/commands/migrate.js +1 -1
  22. package/dist/esm/commands/build.d.ts +1 -1
  23. package/dist/esm/commands/build.d.ts.map +1 -1
  24. package/dist/esm/commands/build.mjs +2 -1
  25. package/dist/esm/commands/clean.d.ts +1 -1
  26. package/dist/esm/commands/clean.d.ts.map +1 -1
  27. package/dist/esm/commands/clean.mjs +2 -1
  28. package/dist/esm/commands/create-workspace.d.ts +1 -1
  29. package/dist/esm/commands/create-workspace.d.ts.map +1 -1
  30. package/dist/esm/commands/create-workspace.mjs +1 -1
  31. package/dist/esm/commands/create.d.ts +1 -1
  32. package/dist/esm/commands/create.d.ts.map +1 -1
  33. package/dist/esm/commands/create.mjs +16 -2
  34. package/dist/esm/commands/deploy.d.ts +1 -1
  35. package/dist/esm/commands/deploy.d.ts.map +1 -1
  36. package/dist/esm/commands/deploy.mjs +42 -8
  37. package/dist/esm/commands/dev.d.ts +1 -1
  38. package/dist/esm/commands/dev.d.ts.map +1 -1
  39. package/dist/esm/commands/dev.mjs +5 -1
  40. package/dist/esm/commands/migrate.d.ts +1 -1
  41. package/dist/esm/commands/migrate.d.ts.map +1 -1
  42. package/dist/esm/commands/migrate.mjs +1 -1
  43. package/dist/esm/index.mjs +4 -1
  44. package/dist/esm/migrations/auto-migrate.mjs +1 -1
  45. package/dist/esm/templates/app/claude-settings.mjs +1 -1
  46. package/dist/esm/util/git/__tests__/repo.test.d.ts +2 -0
  47. package/dist/esm/util/git/__tests__/repo.test.d.ts.map +1 -0
  48. package/dist/esm/util/git/repo.d.ts +12 -0
  49. package/dist/esm/util/git/repo.d.ts.map +1 -0
  50. package/dist/esm/util/git/repo.mjs +105 -0
  51. package/dist/esm/util/manifest.d.ts +1 -0
  52. package/dist/esm/util/manifest.d.ts.map +1 -1
  53. package/dist/index.js +4 -1
  54. package/dist/migrations/auto-migrate.js +11 -11
  55. package/dist/shadow/consumer-pkg.js +2 -2
  56. package/dist/shadow/gitignore.js +4 -4
  57. package/dist/shadow/merge-package-json.js +2 -2
  58. package/dist/shadow/metadata.js +4 -4
  59. package/dist/shadow/prepare.js +5 -5
  60. package/dist/shadow/scaffold.js +8 -8
  61. package/dist/shadow/sync.js +3 -3
  62. package/dist/templates/app/claude-settings.js +1 -1
  63. package/dist/util/auth/auth-store.js +4 -4
  64. package/dist/util/auth/write-auth.js +3 -3
  65. package/dist/util/git/__tests__/repo.test.d.ts +2 -0
  66. package/dist/util/git/__tests__/repo.test.d.ts.map +1 -0
  67. package/dist/util/git/repo.d.ts +12 -0
  68. package/dist/util/git/repo.d.ts.map +1 -0
  69. package/dist/util/git/repo.js +120 -0
  70. package/dist/util/manifest.d.ts +1 -0
  71. package/dist/util/manifest.d.ts.map +1 -1
  72. package/dist/util/s3/upload.js +2 -2
  73. package/dist/util/workspace.js +3 -3
  74. package/package.json +1 -1
  75. package/src/commands/__tests__/create-workspace.test.ts +4 -4
  76. package/src/commands/__tests__/create.test.ts +12 -5
  77. package/src/commands/build.ts +2 -1
  78. package/src/commands/clean.ts +2 -1
  79. package/src/commands/create-workspace.ts +1 -1
  80. package/src/commands/create.ts +15 -2
  81. package/src/commands/deploy.ts +43 -8
  82. package/src/commands/dev.ts +5 -1
  83. package/src/commands/migrate.ts +1 -1
  84. package/src/index.ts +4 -1
  85. package/src/migrations/auto-migrate.ts +3 -3
  86. package/src/templates/app/CLAUDE.md +3 -1
  87. package/src/templates/app/claude-settings.json +1 -1
  88. package/src/util/git/__tests__/repo.test.ts +208 -0
  89. package/src/util/git/repo.ts +112 -0
  90. package/src/util/manifest.ts +1 -0
@@ -1,17 +1,18 @@
1
1
  import path from 'node:path';
2
2
  import os from 'node:os';
3
3
  import { readJson, pathExists } from 'fs-extra';
4
- import { setOutputMode, info, output } from '../util/logger.mjs';
4
+ import { setOutputMode, info, output, warn } from '../util/logger.mjs';
5
5
  import { resolveConsumerPaths } from '../shadow/paths.mjs';
6
6
  import { readManifest, nextVersion, writeManifest, upsertEntry } from '../util/manifest.mjs';
7
7
  import { uploadDir } from '../util/s3/upload.mjs';
8
- import { BUCKET_WRITE_NAME, BUCKET_READ_DNS_URL } from '../constants.mjs';
8
+ import { BUCKET_WRITE_NAME, brokerBaseUrl, BUCKET_READ_DNS_URL } from '../constants.mjs';
9
9
  import { setupS3Client } from '../util/s3/client.mjs';
10
10
  import { readZthAuth } from '../util/auth/auth-store.mjs';
11
11
  import { mfAppName, cleanAppName } from '../util/app-name.mjs';
12
12
  import { buildCommand } from './build.mjs';
13
13
 
14
- async function deployCommand(opts) {
14
+ // Should be run from the consumer app directory — uses process.cwd() to locate it.
15
+ async function deployCommand(opts = {}) {
15
16
  if (opts.json) {
16
17
  setOutputMode('json');
17
18
  }
@@ -23,7 +24,7 @@ async function deployCommand(opts) {
23
24
  const appName = mfAppName(consumerPkg.name);
24
25
  // Validate the user's deploy token is on disk before doing any expensive
25
26
  // work. Throws Z2hAuthMissingError with a remediation hint if not.
26
- await readZthAuth();
27
+ const { token } = await readZthAuth();
27
28
  setupS3Client({ appName });
28
29
  info('reading current Z2H manifest');
29
30
  const manifest = await readManifest();
@@ -61,10 +62,18 @@ async function deployCommand(opts) {
61
62
  });
62
63
  return;
63
64
  }
64
- info(`uploading build → s3://${BUCKET_WRITE_NAME}/${keyPrefix}/`);
65
- await uploadDir(paths.shadowBuild, keyPrefix);
66
- info(`updating manifest entry "${appName}" → v${version}`);
67
- await writeManifest(upsertEntry(manifest, appName, entry));
65
+ try {
66
+ // Lock is acquired here — uploadDir triggers the STS credential provider on first S3 call
67
+ info(`uploading build → s3://${BUCKET_WRITE_NAME}/${keyPrefix}/`);
68
+ await uploadDir(paths.shadowBuild, keyPrefix);
69
+ info(`updating manifest entry "${appName}" → v${version}`);
70
+ await writeManifest(upsertEntry(manifest, appName, entry));
71
+ info(`registering app "${appName}" → v${version}`);
72
+ await registerApp(appName, token, version, entry);
73
+ }
74
+ finally {
75
+ await releaseLockBestEffort(appName, token);
76
+ }
68
77
  // The host MF parses the app name from the URL and prepends `mf-` itself
69
78
  // before looking it up in the manifest. So the user-facing URL must use
70
79
  // the consumer's de-scoped package name (no `mf-` prefix, no `@scope/`).
@@ -80,5 +89,30 @@ async function deployCommand(opts) {
80
89
  entry,
81
90
  });
82
91
  }
92
+ async function registerApp(appName, token, version, entry) {
93
+ const res = await fetch(`${brokerBaseUrl()}/z2h-cli/apps/register`, {
94
+ method: 'POST',
95
+ headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' },
96
+ body: JSON.stringify({ appName, version, entry }),
97
+ });
98
+ if (!res.ok) {
99
+ const text = await res.text();
100
+ throw new Error(`App registration failed (${res.status}): ${text.slice(0, 1024)}`);
101
+ }
102
+ }
103
+ // best-effort — the 5-min TTL backstop handles failures
104
+ async function releaseLockBestEffort(appName, token) {
105
+ try {
106
+ await fetch(`${brokerBaseUrl()}/z2h-cli/lock/release`, {
107
+ method: 'POST',
108
+ headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' },
109
+ body: JSON.stringify({ appName }),
110
+ });
111
+ info(`lock released for ${appName}`);
112
+ }
113
+ catch {
114
+ warn(`failed to release lock for ${appName}`);
115
+ }
116
+ }
83
117
 
84
118
  export { deployCommand };
@@ -1,5 +1,5 @@
1
1
  export interface DevOptions {
2
2
  json?: boolean;
3
3
  }
4
- export declare function devCommand(opts: DevOptions): Promise<void>;
4
+ export declare function devCommand(opts?: DevOptions): Promise<void>;
5
5
  //# sourceMappingURL=dev.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../../src/commands/dev.ts"],"names":[],"mappings":"AAWA,MAAM,WAAW,UAAU;IACzB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAID,wBAAsB,UAAU,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAuEhE"}
1
+ {"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../../src/commands/dev.ts"],"names":[],"mappings":"AAWA,MAAM,WAAW,UAAU;IACzB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAKD,wBAAsB,UAAU,CAAC,IAAI,GAAE,UAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CA0ErE"}
@@ -9,7 +9,8 @@ import { ensureConsumerPkg } from '../shadow/consumer-pkg.mjs';
9
9
  import { syncShadow } from '../shadow/sync.mjs';
10
10
 
11
11
  const TRIDENT_READY_PATTERN = /Server started at/i;
12
- async function devCommand(opts) {
12
+ // Should be run from the consumer app directory — uses process.cwd() to locate it.
13
+ async function devCommand(opts = {}) {
13
14
  if (opts.json) {
14
15
  setOutputMode('json');
15
16
  }
@@ -23,6 +24,9 @@ async function devCommand(opts) {
23
24
  const server = execa('yarn', ['start'], {
24
25
  cwd: ctx.paths.shadowDir,
25
26
  stdio: ['inherit', 'pipe', 'inherit'],
27
+ // Trident requires NPM_TOKEN to be set or it refuses to start; 'FAKE_TOKEN' satisfies the check without real credentials.
28
+ // we always pass a fake token for same behavior for all users (no matter if they have a token or not)
29
+ env: { ...process.env, NPM_TOKEN: 'FAKE_TOKEN' },
26
30
  });
27
31
  const pidFile = path.join(ctx.paths.shadowDir, 'dev.pid');
28
32
  if (server.pid) {
@@ -2,5 +2,5 @@ export interface MigrateOptions {
2
2
  dryRun?: boolean;
3
3
  json?: boolean;
4
4
  }
5
- export declare function migrateCommand(cliVersion: string, opts: MigrateOptions): Promise<void>;
5
+ export declare function migrateCommand(cliVersion: string, opts?: MigrateOptions): Promise<void>;
6
6
  //# sourceMappingURL=migrate.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"migrate.d.ts","sourceRoot":"","sources":["../../../src/commands/migrate.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,cAAc;IAC7B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,wBAAsB,cAAc,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAM5F"}
1
+ {"version":3,"file":"migrate.d.ts","sourceRoot":"","sources":["../../../src/commands/migrate.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,cAAc;IAC7B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,wBAAsB,cAAc,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,GAAE,cAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CAMjG"}
@@ -1,7 +1,7 @@
1
1
  import { setOutputMode } from '../util/logger.mjs';
2
2
  import { autoMigrate } from '../migrations/auto-migrate.mjs';
3
3
 
4
- async function migrateCommand(cliVersion, opts) {
4
+ async function migrateCommand(cliVersion, opts = {}) {
5
5
  if (opts.json) {
6
6
  setOutputMode('json');
7
7
  }
@@ -19,7 +19,10 @@ const { version } = createRequire(import.meta.url)('../package.json');
19
19
  const UPDATE_SCRIPT = path.join(os.homedir(), 'Development', 'bigbrain-z2h', 'z2h', 'setup', 'update.sh');
20
20
  function selfUpdate() {
21
21
  try {
22
- execa('bash', [UPDATE_SCRIPT], { detached: true, stdio: 'ignore' }).unref();
22
+ execa('bash', [UPDATE_SCRIPT], {
23
+ detached: true,
24
+ stdio: 'ignore',
25
+ }).unref();
23
26
  }
24
27
  catch (err) {
25
28
  errorLog(`Z2H auto-update failed to start: ${err.message}`);
@@ -1,5 +1,5 @@
1
- import path from 'node:path';
2
1
  import { createRequire } from 'node:module';
2
+ import path from 'node:path';
3
3
  import { fileURLToPath } from 'node:url';
4
4
  import { pathExists, readJson, writeJson, writeFile } from 'fs-extra';
5
5
  import { execa } from 'execa';
@@ -9,7 +9,7 @@ var hooks = {
9
9
  hooks: [
10
10
  {
11
11
  type: "command",
12
- command: "if [ -f .zth/dev.pid ]; then kill $(cat .zth/dev.pid) 2>/dev/null; rm .zth/dev.pid; fi"
12
+ command: "if [ -f .zth/dev.pid ]; then PGID=$(ps -o pgid= -p $(cat .zth/dev.pid) 2>/dev/null | tr -d ' '); [ -n \"$PGID\" ] && kill -- -$PGID 2>/dev/null; rm -f .zth/dev.pid; fi"
13
13
  }
14
14
  ]
15
15
  }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=repo.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repo.test.d.ts","sourceRoot":"","sources":["../../../../../src/util/git/__tests__/repo.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,12 @@
1
+ export declare class GitConflictError extends Error {
2
+ constructor(message: string);
3
+ }
4
+ export declare function defaultS3Remote(app: string): string;
5
+ export declare function initAndPush(dir: string, remote: string): Promise<void>;
6
+ export declare function cloneRepo(remote: string, dir: string): Promise<void>;
7
+ export declare function safeBackupIfDirty(dir: string): Promise<void>;
8
+ export declare function pullAndResolve(dir: string): Promise<void>;
9
+ export declare function remoteHead(dir: string): Promise<string>;
10
+ export declare function localHead(dir: string): Promise<string>;
11
+ export declare function commitDetailedAndPush(dir: string, version: number): Promise<void>;
12
+ //# sourceMappingURL=repo.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repo.d.ts","sourceRoot":"","sources":["../../../../src/util/git/repo.ts"],"names":[],"mappings":"AAKA,qBAAa,gBAAiB,SAAQ,KAAK;gBAC7B,OAAO,EAAE,MAAM;CAI5B;AAID,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED,wBAAsB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAO5E;AAED,wBAAsB,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE1E;AAED,wBAAsB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAclE;AAED,wBAAsB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAS/D;AAED,wBAAsB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAO7D;AAED,wBAAsB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAG5D;AAED,wBAAsB,qBAAqB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CASvF"}
@@ -0,0 +1,105 @@
1
+ import path from 'node:path';
2
+ import fs from 'fs-extra';
3
+ import { execa } from 'execa';
4
+ import { BUCKET_WRITE_NAME } from '../../constants.mjs';
5
+
6
+ class GitConflictError extends Error {
7
+ constructor(message) {
8
+ super(message);
9
+ this.name = 'GitConflictError';
10
+ }
11
+ }
12
+ const REQUIRED_GITIGNORE_ENTRIES = ['node_modules/', '.zth/', 'build/'];
13
+ function defaultS3Remote(app) {
14
+ return `s3://${BUCKET_WRITE_NAME}/${app}/git`;
15
+ }
16
+ async function initAndPush(dir, remote) {
17
+ await ensureGitignore(dir);
18
+ await execa('git', ['init', '-b', 'master'], { cwd: dir });
19
+ await execa('git', ['add', '.'], { cwd: dir });
20
+ await execa('git', ['commit', '-m', 'Initial commit'], { cwd: dir });
21
+ await execa('git', ['remote', 'add', 'origin', remote], { cwd: dir });
22
+ await execa('git', ['push', '-u', 'origin', 'master'], { cwd: dir });
23
+ }
24
+ async function cloneRepo(remote, dir) {
25
+ await execa('git', ['clone', remote, dir]);
26
+ }
27
+ async function safeBackupIfDirty(dir) {
28
+ let status;
29
+ try {
30
+ ({ stdout: status } = await execa('git', ['status', '--porcelain'], { cwd: dir }));
31
+ }
32
+ catch {
33
+ return;
34
+ }
35
+ if (!status.trim()) {
36
+ return;
37
+ }
38
+ const sha = await localHead(dir).catch(() => 'unknown');
39
+ const appName = path.basename(dir);
40
+ const backupDir = path.join(path.dirname(dir), `${appName}.backup-${sha}`);
41
+ await fs.copy(dir, backupDir, { overwrite: false });
42
+ }
43
+ async function pullAndResolve(dir) {
44
+ try {
45
+ await execa('git', ['pull', '--ff-only'], { cwd: dir });
46
+ }
47
+ catch {
48
+ // TODO(Phase 7): safeBackupIfDirty(dir) → resolveDivergence(dir) instead of throwing
49
+ throw new GitConflictError('This app changed while you were working — please re-open it to get the latest version.');
50
+ }
51
+ }
52
+ async function remoteHead(dir) {
53
+ const { stdout } = await execa('git', ['ls-remote', 'origin', 'refs/heads/master'], { cwd: dir });
54
+ const sha = stdout.split('\t')[0]?.trim();
55
+ if (!sha) {
56
+ throw new Error('could not read remote head — is the remote reachable?');
57
+ }
58
+ return sha;
59
+ }
60
+ async function localHead(dir) {
61
+ const { stdout } = await execa('git', ['rev-parse', 'HEAD'], { cwd: dir });
62
+ return stdout.trim();
63
+ }
64
+ async function commitDetailedAndPush(dir, version) {
65
+ const message = await buildCommitMessage(dir, version);
66
+ await execa('git', ['add', '.'], { cwd: dir });
67
+ await execa('git', ['commit', '-m', message], { cwd: dir });
68
+ try {
69
+ await execa('git', ['push'], { cwd: dir });
70
+ }
71
+ catch {
72
+ throw new GitConflictError('push rejected — remote has new commits');
73
+ }
74
+ }
75
+ async function buildCommitMessage(dir, version) {
76
+ // TODO(Phase 7): replace with LLM-generated summary using git diff + commit messages
77
+ const { stdout } = await execa('git', ['status', '--short'], { cwd: dir });
78
+ const files = stdout
79
+ .split('\n')
80
+ .map(line => line.slice(3).trim())
81
+ .filter(Boolean);
82
+ const fileList = files.length
83
+ ? files.slice(0, 5).join(', ') + (files.length > 5 ? ` (+${files.length - 5} more)` : '')
84
+ : 'no changes';
85
+ return `v${version}: deploy — ${fileList}`;
86
+ }
87
+ async function ensureGitignore(dir) {
88
+ const gitignorePath = path.join(dir, '.gitignore');
89
+ let content = '';
90
+ try {
91
+ content = await fs.readFile(gitignorePath, 'utf8');
92
+ }
93
+ catch {
94
+ // file doesn't exist yet
95
+ }
96
+ const lines = content.split('\n').map(l => l.trim());
97
+ const missing = REQUIRED_GITIGNORE_ENTRIES.filter(entry => !lines.includes(entry));
98
+ if (missing.length === 0) {
99
+ return;
100
+ }
101
+ const separator = content && !content.endsWith('\n') ? '\n' : '';
102
+ await fs.outputFile(gitignorePath, content + separator + missing.join('\n') + '\n');
103
+ }
104
+
105
+ export { GitConflictError, cloneRepo, commitDetailedAndPush, defaultS3Remote, initAndPush, localHead, pullAndResolve, remoteHead, safeBackupIfDirty };
@@ -18,6 +18,7 @@ export interface AssetManifestFile {
18
18
  nonExternalsEntrypoints?: string[];
19
19
  scriptType?: 'module' | 'classic';
20
20
  mfs?: string[];
21
+ gitRemote: string;
21
22
  }
22
23
  export interface ManifestEntry extends AssetManifestFile {
23
24
  version: number;
@@ -1 +1 @@
1
- {"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../../src/util/manifest.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,SAAS;IACxB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACtC;AAED;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IAChC,UAAU,EAAE,OAAO,CAAC;IACpB,oBAAoB,EAAE,OAAO,CAAC;IAC9B,MAAM,EAAE,SAAS,EAAE,CAAC;IACpB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,uBAAuB,CAAC,EAAE,MAAM,EAAE,CAAC;IACnC,UAAU,CAAC,EAAE,QAAQ,GAAG,SAAS,CAAC;IAClC,GAAG,CAAC,EAAE,MAAM,EAAE,CAAC;CAChB;AAED,MAAM,WAAW,aAAc,SAAQ,iBAAiB;IACtD,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;AAErD,wBAAsB,YAAY,IAAI,OAAO,CAAC,QAAQ,CAAC,CAQtD;AAED,wBAAgB,WAAW,CAAC,QAAQ,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,UAI1D;AAED,wBAAgB,WAAW,CAAC,QAAQ,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,GAAG,QAAQ,CAE3F;AAED,wBAAsB,aAAa,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAWrE"}
1
+ {"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../../src/util/manifest.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,SAAS;IACxB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACtC;AAED;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IAChC,UAAU,EAAE,OAAO,CAAC;IACpB,oBAAoB,EAAE,OAAO,CAAC;IAC9B,MAAM,EAAE,SAAS,EAAE,CAAC;IACpB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,uBAAuB,CAAC,EAAE,MAAM,EAAE,CAAC;IACnC,UAAU,CAAC,EAAE,QAAQ,GAAG,SAAS,CAAC;IAClC,GAAG,CAAC,EAAE,MAAM,EAAE,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,aAAc,SAAQ,iBAAiB;IACtD,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;AAErD,wBAAsB,YAAY,IAAI,OAAO,CAAC,QAAQ,CAAC,CAQtD;AAED,wBAAgB,WAAW,CAAC,QAAQ,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,UAI1D;AAED,wBAAgB,WAAW,CAAC,QAAQ,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,GAAG,QAAQ,CAE3F;AAED,wBAAsB,aAAa,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAWrE"}
package/dist/index.js CHANGED
@@ -25,7 +25,10 @@ const { version } = node_module.createRequire((typeof document === 'undefined' ?
25
25
  const UPDATE_SCRIPT = path__default.default.join(os__default.default.homedir(), 'Development', 'bigbrain-z2h', 'z2h', 'setup', 'update.sh');
26
26
  function selfUpdate() {
27
27
  try {
28
- execa.execa('bash', [UPDATE_SCRIPT], { detached: true, stdio: 'ignore' }).unref();
28
+ execa.execa('bash', [UPDATE_SCRIPT], {
29
+ detached: true,
30
+ stdio: 'ignore',
31
+ }).unref();
29
32
  }
30
33
  catch (err) {
31
34
  util_logger.errorLog(`Z2H auto-update failed to start: ${err.message}`);
@@ -1,9 +1,9 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
 
3
- const path = require('node:path');
4
3
  const node_module = require('node:module');
4
+ const path = require('node:path');
5
5
  const node_url = require('node:url');
6
- const fsExtra = require('fs-extra');
6
+ const fs = require('fs-extra');
7
7
  const execa = require('execa');
8
8
  const semver = require('semver');
9
9
  const util_logger = require('../util/logger.js');
@@ -20,11 +20,11 @@ const NX_JSON_CONTENT = '{\n "extends": "@mondaydotcomorg/trident-monorepo/pres
20
20
  // ─── Helpers ───
21
21
  async function readState(workspaceHome) {
22
22
  const statePath = path__default.default.join(workspaceHome, STATE_FILE);
23
- if (!(await fsExtra.pathExists(statePath))) {
23
+ if (!(await fs.pathExists(statePath))) {
24
24
  return null;
25
25
  }
26
26
  try {
27
- return (await fsExtra.readJson(statePath));
27
+ return (await fs.readJson(statePath));
28
28
  }
29
29
  catch {
30
30
  return null;
@@ -32,7 +32,7 @@ async function readState(workspaceHome) {
32
32
  }
33
33
  async function writeState(workspaceHome, state) {
34
34
  const statePath = path__default.default.join(workspaceHome, STATE_FILE);
35
- await fsExtra.writeJson(statePath, state, { spaces: 2 });
35
+ await fs.writeJson(statePath, state, { spaces: 2 });
36
36
  }
37
37
  async function yarnInstall(workspaceHome, context) {
38
38
  util_logger.info(`${context} — running yarn install...`);
@@ -69,11 +69,11 @@ function isNxAvailable(workspaceHome) {
69
69
  async function ensureWorkspaceNx(workspaceHome) {
70
70
  const nxJsonPath = path__default.default.join(workspaceHome, 'nx.json');
71
71
  const pkgPath = path__default.default.join(workspaceHome, 'package.json');
72
- if (!(await fsExtra.pathExists(nxJsonPath))) {
73
- await fsExtra.writeFile(nxJsonPath, NX_JSON_CONTENT);
72
+ if (!(await fs.pathExists(nxJsonPath))) {
73
+ await fs.writeFile(nxJsonPath, NX_JSON_CONTENT);
74
74
  util_logger.info('added nx.json to workspace');
75
75
  }
76
- const pkg = (await fsExtra.readJson(pkgPath));
76
+ const pkg = (await fs.readJson(pkgPath));
77
77
  if (!pkg.devDependencies?.['@mondaydotcomorg/trident-monorepo']) {
78
78
  pkg.devDependencies = pkg.devDependencies ?? {};
79
79
  pkg.devDependencies['@mondaydotcomorg/trident-monorepo'] = await getLatestTrientMonorepoVersion();
@@ -82,7 +82,7 @@ async function ensureWorkspaceNx(workspaceHome) {
82
82
  pkg.scripts = pkg.scripts ?? {};
83
83
  pkg.scripts.nx = 'nx';
84
84
  }
85
- await fsExtra.writeJson(pkgPath, pkg, { spaces: 2 });
85
+ await fs.writeJson(pkgPath, pkg, { spaces: 2 });
86
86
  // Only install if NX isn't already importable from the workspace
87
87
  if (!isNxAvailable(workspaceHome)) {
88
88
  const ok = await yarnInstall(workspaceHome, 'NX not found, installing');
@@ -110,11 +110,11 @@ async function autoMigrate(cliVersion, dryRun = false) {
110
110
  // migrations.json is at the package root — two dirs up from dist/migrations/
111
111
  const thisDir = path__default.default.dirname(node_url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('migrations/auto-migrate.js', document.baseURI).href))));
112
112
  const migrationsJsonPath = path__default.default.resolve(thisDir, '..', '..', 'migrations.json');
113
- if (!(await fsExtra.pathExists(migrationsJsonPath))) {
113
+ if (!(await fs.pathExists(migrationsJsonPath))) {
114
114
  util_logger.warn('migrations.json not found — skipping migrations');
115
115
  return;
116
116
  }
117
- const migrationsJson = (await fsExtra.readJson(migrationsJsonPath));
117
+ const migrationsJson = (await fs.readJson(migrationsJsonPath));
118
118
  // Filter to pending migrations (version > lastVersion AND <= cliVersion).
119
119
  // CONVENTION: a migration's `version` field must equal the CLI release it
120
120
  // ships with (not the feature branch version). This ensures the `gt` check
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
 
3
- const fsExtra = require('fs-extra');
3
+ const fs = require('fs-extra');
4
4
 
5
5
  /**
6
6
  * The consumer pkg is a thin manifest. Z2H apps live inside a yarn
@@ -15,7 +15,7 @@ async function ensureConsumerPkg(pkgPath, pkg) {
15
15
  return { changed: false, pkg };
16
16
  }
17
17
  const next = { ...pkg, private: true };
18
- await fsExtra.writeJson(pkgPath, next, { spaces: 2 });
18
+ await fs.writeJson(pkgPath, next, { spaces: 2 });
19
19
  return { changed: true, pkg: next };
20
20
  }
21
21
 
@@ -1,7 +1,7 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
 
3
3
  const path = require('node:path');
4
- const fsExtra = require('fs-extra');
4
+ const fs = require('fs-extra');
5
5
  const constants = require('../constants.js');
6
6
 
7
7
  const _interopDefault = e => e && e.__esModule ? e : { default: e };
@@ -16,8 +16,8 @@ const path__default = /*#__PURE__*/_interopDefault(path);
16
16
  async function ensureGitignore(consumerDir) {
17
17
  const gitignorePath = path__default.default.join(consumerDir, '.gitignore');
18
18
  let body = '';
19
- if (await fsExtra.pathExists(gitignorePath)) {
20
- body = await fsExtra.readFile(gitignorePath, 'utf8');
19
+ if (await fs.pathExists(gitignorePath)) {
20
+ body = await fs.readFile(gitignorePath, 'utf8');
21
21
  }
22
22
  const existing = new Set(body
23
23
  .split('\n')
@@ -29,7 +29,7 @@ async function ensureGitignore(consumerDir) {
29
29
  }
30
30
  const prefix = body.length && !body.endsWith('\n') ? '\n' : '';
31
31
  const block = `${prefix}\n# z2h-cli\n${missing.join('\n')}\n`;
32
- await fsExtra.writeFile(gitignorePath, body + block);
32
+ await fs.writeFile(gitignorePath, body + block);
33
33
  }
34
34
 
35
35
  exports.ensureGitignore = ensureGitignore;
@@ -1,7 +1,7 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
 
3
3
  const crypto = require('node:crypto');
4
- const fsExtra = require('fs-extra');
4
+ const fs = require('fs-extra');
5
5
  const constants = require('../constants.js');
6
6
  const util_appName = require('../util/app-name.js');
7
7
 
@@ -59,7 +59,7 @@ function hashConsumerDeps(consumer) {
59
59
  .digest('hex');
60
60
  }
61
61
  async function writeShadowPkg(shadowPkgPath, shadow) {
62
- await fsExtra.writeJson(shadowPkgPath, shadow, { spaces: 2 });
62
+ await fs.writeJson(shadowPkgPath, shadow, { spaces: 2 });
63
63
  }
64
64
 
65
65
  exports.buildShadowPkg = buildShadowPkg;
@@ -1,20 +1,20 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
 
3
- const fsExtra = require('fs-extra');
3
+ const fs = require('fs-extra');
4
4
 
5
5
  async function readMetadata(paths) {
6
- if (!(await fsExtra.pathExists(paths.shadowMetadata))) {
6
+ if (!(await fs.pathExists(paths.shadowMetadata))) {
7
7
  return null;
8
8
  }
9
9
  try {
10
- return (await fsExtra.readJson(paths.shadowMetadata));
10
+ return (await fs.readJson(paths.shadowMetadata));
11
11
  }
12
12
  catch {
13
13
  return null;
14
14
  }
15
15
  }
16
16
  async function writeMetadata(paths, meta) {
17
- await fsExtra.writeJson(paths.shadowMetadata, meta, { spaces: 2 });
17
+ await fs.writeJson(paths.shadowMetadata, meta, { spaces: 2 });
18
18
  }
19
19
 
20
20
  exports.readMetadata = readMetadata;
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
 
3
- const fsExtra = require('fs-extra');
3
+ const fs = require('fs-extra');
4
4
  const util_logger = require('../util/logger.js');
5
5
  const util_appName = require('../util/app-name.js');
6
6
  const shadow_paths = require('./paths.js');
@@ -13,13 +13,13 @@ const shadow_sync = require('./sync.js');
13
13
 
14
14
  async function prepareShadow() {
15
15
  const paths = shadow_paths.resolveConsumerPaths(process.cwd());
16
- if (!(await fsExtra.pathExists(paths.consumerPkg))) {
16
+ if (!(await fs.pathExists(paths.consumerPkg))) {
17
17
  throw new Error(`No package.json found in ${paths.consumerDir}`);
18
18
  }
19
- if (!(await fsExtra.pathExists(paths.consumerSrcEntry))) {
19
+ if (!(await fs.pathExists(paths.consumerSrcEntry))) {
20
20
  throw new Error(`Consumer must have src/index.tsx (in ${paths.consumerDir})`);
21
21
  }
22
- const rawConsumerPkg = (await fsExtra.readJson(paths.consumerPkg));
22
+ const rawConsumerPkg = (await fs.readJson(paths.consumerPkg));
23
23
  if (!rawConsumerPkg.name) {
24
24
  throw new Error('Consumer package.json must have a "name" field');
25
25
  }
@@ -29,7 +29,7 @@ async function prepareShadow() {
29
29
  util_logger.info(`ensured consumer pkg shape at ${paths.consumerPkg}`);
30
30
  }
31
31
  await shadow_gitignore.ensureGitignore(paths.consumerDir);
32
- await fsExtra.ensureDir(paths.shadowDir);
32
+ await fs.ensureDir(paths.shadowDir);
33
33
  const metadata = await resolvePortAndMetadata(paths, appName);
34
34
  const port = metadata.port;
35
35
  util_logger.info(`preparing shadow at ${paths.shadowDir} (port ${port})`);
@@ -1,7 +1,7 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
 
3
3
  const path = require('node:path');
4
- const fsExtra = require('fs-extra');
4
+ const fs = require('fs-extra');
5
5
 
6
6
  const _interopDefault = e => e && e.__esModule ? e : { default: e };
7
7
 
@@ -110,14 +110,14 @@ const TSCONFIG_TEMPLATE = {
110
110
  * shadow dir is a deterministic function of the CLI version — no drift.
111
111
  */
112
112
  async function scaffoldShadow(paths, appName, port) {
113
- await fsExtra.ensureDir(paths.shadowSrc);
114
- await fsExtra.writeFile(paths.shadowWrapper, WRAPPER_TEMPLATE);
115
- await fsExtra.writeFile(paths.shadowTridentrc, tridentrcTemplate(appName, port));
116
- await fsExtra.writeFile(paths.shadowNvmrc, `${process.version}\n`);
117
- await fsExtra.writeFile(paths.shadowDts, dtsFileTemplate());
118
- await fsExtra.writeJson(paths.shadowTsconfig, TSCONFIG_TEMPLATE, { spaces: 2 });
113
+ await fs.ensureDir(paths.shadowSrc);
114
+ await fs.writeFile(paths.shadowWrapper, WRAPPER_TEMPLATE);
115
+ await fs.writeFile(paths.shadowTridentrc, tridentrcTemplate(appName, port));
116
+ await fs.writeFile(paths.shadowNvmrc, `${process.version}\n`);
117
+ await fs.writeFile(paths.shadowDts, dtsFileTemplate());
118
+ await fs.writeJson(paths.shadowTsconfig, TSCONFIG_TEMPLATE, { spaces: 2 });
119
119
  // Drop a stub README so contributors who open .zth/ know what they're looking at.
120
- await fsExtra.writeFile(path__default.default.join(paths.shadowDir, 'README.md'), '# .zth/\nGenerated by z2h-cli. Do not edit — run `z2h-cli build` or `z2h-cli dev` to refresh.\n');
120
+ await fs.writeFile(path__default.default.join(paths.shadowDir, 'README.md'), '# .zth/\nGenerated by z2h-cli. Do not edit — run `z2h-cli build` or `z2h-cli dev` to refresh.\n');
121
121
  }
122
122
 
123
123
  exports.scaffoldShadow = scaffoldShadow;
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
 
3
- const fsExtra = require('fs-extra');
3
+ const fs = require('fs-extra');
4
4
  const util_logger = require('../util/logger.js');
5
5
  const util_npm_install = require('../util/npm/install.js');
6
6
  const shadow_mergePackageJson = require('./merge-package-json.js');
@@ -15,14 +15,14 @@ async function syncShadow(paths, consumerPkg) {
15
15
  const shadow = shadow_mergePackageJson.buildShadowPkg(consumerPkg);
16
16
  await shadow_mergePackageJson.writeShadowPkg(paths.shadowPkg, shadow);
17
17
  const newHash = shadow_mergePackageJson.hashConsumerDeps(consumerPkg);
18
- const oldHash = (await fsExtra.pathExists(paths.shadowDepsHash)) ? await fsExtra.readFile(paths.shadowDepsHash, 'utf8') : null;
18
+ const oldHash = (await fs.pathExists(paths.shadowDepsHash)) ? await fs.readFile(paths.shadowDepsHash, 'utf8') : null;
19
19
  if (oldHash !== newHash) {
20
20
  util_logger.info(oldHash ? 'consumer deps changed — yarn install' : 'first run — yarn install');
21
21
  // Yarn 4 is cache-first and non-interactive by default in non-TTY
22
22
  // contexts, so plain `yarn install` is all we need. runYarnInstall injects
23
23
  // the npm-broker token, preflights auth, and re-auths on a broker 401.
24
24
  await util_npm_install.runYarnInstall({ cwd: paths.consumerDir });
25
- await fsExtra.writeFile(paths.shadowDepsHash, newHash);
25
+ await fs.writeFile(paths.shadowDepsHash, newHash);
26
26
  }
27
27
  }
28
28
 
@@ -11,7 +11,7 @@ var hooks = {
11
11
  hooks: [
12
12
  {
13
13
  type: "command",
14
- command: "if [ -f .zth/dev.pid ]; then kill $(cat .zth/dev.pid) 2>/dev/null; rm .zth/dev.pid; fi"
14
+ command: "if [ -f .zth/dev.pid ]; then PGID=$(ps -o pgid= -p $(cat .zth/dev.pid) 2>/dev/null | tr -d ' '); [ -n \"$PGID\" ] && kill -- -$PGID 2>/dev/null; rm -f .zth/dev.pid; fi"
15
15
  }
16
16
  ]
17
17
  }
@@ -2,7 +2,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
 
3
3
  const path = require('node:path');
4
4
  const os = require('node:os');
5
- const fsExtra = require('fs-extra');
5
+ const fs = require('fs-extra');
6
6
 
7
7
  const _interopDefault = e => e && e.__esModule ? e : { default: e };
8
8
 
@@ -23,10 +23,10 @@ class Z2hAuthMissingError extends Error {
23
23
  }
24
24
  }
25
25
  async function readZthAuth() {
26
- if (!(await fsExtra.pathExists(Z2H_AUTH_FILE))) {
26
+ if (!(await fs.pathExists(Z2H_AUTH_FILE))) {
27
27
  throw new Z2hAuthMissingError(Z2H_AUTH_FILE);
28
28
  }
29
- const parsed = (await fsExtra.readJson(Z2H_AUTH_FILE));
29
+ const parsed = (await fs.readJson(Z2H_AUTH_FILE));
30
30
  if (!parsed.token) {
31
31
  throw new Error(`${Z2H_AUTH_FILE} is missing a "token" string field.`);
32
32
  }
@@ -43,7 +43,7 @@ async function readZthAuth() {
43
43
  */
44
44
  function tryReadAuthTokenSync() {
45
45
  try {
46
- const parsed = fsExtra.readJsonSync(Z2H_AUTH_FILE);
46
+ const parsed = fs.readJsonSync(Z2H_AUTH_FILE);
47
47
  return parsed?.token ?? null;
48
48
  }
49
49
  catch {