@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.
- package/README.md +16 -0
- package/bin/z2h-cli.js +2 -0
- package/dist/commands/build.d.ts +5 -0
- package/dist/commands/build.d.ts.map +1 -0
- package/dist/commands/build.js +37 -0
- package/dist/commands/clean.d.ts +5 -0
- package/dist/commands/clean.d.ts.map +1 -0
- package/dist/commands/clean.js +24 -0
- package/dist/commands/deploy.d.ts +6 -0
- package/dist/commands/deploy.d.ts.map +1 -0
- package/dist/commands/deploy.js +92 -0
- package/dist/commands/dev.d.ts +5 -0
- package/dist/commands/dev.d.ts.map +1 -0
- package/dist/commands/dev.js +58 -0
- package/dist/constants.d.ts +25 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +67 -0
- package/dist/esm/commands/build.d.ts +5 -0
- package/dist/esm/commands/build.d.ts.map +1 -0
- package/dist/esm/commands/build.mjs +35 -0
- package/dist/esm/commands/clean.d.ts +5 -0
- package/dist/esm/commands/clean.d.ts.map +1 -0
- package/dist/esm/commands/clean.mjs +22 -0
- package/dist/esm/commands/deploy.d.ts +6 -0
- package/dist/esm/commands/deploy.d.ts.map +1 -0
- package/dist/esm/commands/deploy.mjs +86 -0
- package/dist/esm/commands/dev.d.ts +5 -0
- package/dist/esm/commands/dev.d.ts.map +1 -0
- package/dist/esm/commands/dev.mjs +56 -0
- package/dist/esm/constants.d.ts +25 -0
- package/dist/esm/constants.d.ts.map +1 -0
- package/dist/esm/constants.mjs +57 -0
- package/dist/esm/index.d.ts +2 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.mjs +86 -0
- package/dist/esm/shadow/consumer-pkg.d.ts +24 -0
- package/dist/esm/shadow/consumer-pkg.d.ts.map +1 -0
- package/dist/esm/shadow/consumer-pkg.mjs +81 -0
- package/dist/esm/shadow/gitignore.d.ts +7 -0
- package/dist/esm/shadow/gitignore.d.ts.map +1 -0
- package/dist/esm/shadow/gitignore.mjs +29 -0
- package/dist/esm/shadow/merge-package-json.d.ts +16 -0
- package/dist/esm/shadow/merge-package-json.d.ts.map +1 -0
- package/dist/esm/shadow/merge-package-json.mjs +58 -0
- package/dist/esm/shadow/metadata.d.ts +4 -0
- package/dist/esm/shadow/metadata.d.ts.map +1 -0
- package/dist/esm/shadow/metadata.mjs +18 -0
- package/dist/esm/shadow/paths.d.ts +3 -0
- package/dist/esm/shadow/paths.d.ts.map +1 -0
- package/dist/esm/shadow/paths.mjs +25 -0
- package/dist/esm/shadow/port.d.ts +7 -0
- package/dist/esm/shadow/port.d.ts.map +1 -0
- package/dist/esm/shadow/port.mjs +34 -0
- package/dist/esm/shadow/prepare.d.ts +3 -0
- package/dist/esm/shadow/prepare.d.ts.map +1 -0
- package/dist/esm/shadow/prepare.mjs +60 -0
- package/dist/esm/shadow/scaffold.d.ts +7 -0
- package/dist/esm/shadow/scaffold.d.ts.map +1 -0
- package/dist/esm/shadow/scaffold.mjs +112 -0
- package/dist/esm/shadow/sync.d.ts +9 -0
- package/dist/esm/shadow/sync.d.ts.map +1 -0
- package/dist/esm/shadow/sync.mjs +29 -0
- package/dist/esm/shadow/yarnrc.d.ts +10 -0
- package/dist/esm/shadow/yarnrc.d.ts.map +1 -0
- package/dist/esm/shadow/yarnrc.mjs +27 -0
- package/dist/esm/types.d.ts +53 -0
- package/dist/esm/types.d.ts.map +1 -0
- package/dist/esm/types.mjs +1 -0
- package/dist/esm/util/app-name.d.ts +12 -0
- package/dist/esm/util/app-name.d.ts.map +1 -0
- package/dist/esm/util/app-name.mjs +17 -0
- package/dist/esm/util/logger.d.ts +22 -0
- package/dist/esm/util/logger.d.ts.map +1 -0
- package/dist/esm/util/logger.mjs +59 -0
- package/dist/esm/util/manifest.d.ts +31 -0
- package/dist/esm/util/manifest.d.ts.map +1 -0
- package/dist/esm/util/manifest.mjs +31 -0
- package/dist/esm/util/s3/client.d.ts +11 -0
- package/dist/esm/util/s3/client.d.ts.map +1 -0
- package/dist/esm/util/s3/client.mjs +38 -0
- package/dist/esm/util/s3/upload.d.ts +2 -0
- package/dist/esm/util/s3/upload.d.ts.map +1 -0
- package/dist/esm/util/s3/upload.mjs +32 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +86 -0
- package/dist/shadow/consumer-pkg.d.ts +24 -0
- package/dist/shadow/consumer-pkg.d.ts.map +1 -0
- package/dist/shadow/consumer-pkg.js +84 -0
- package/dist/shadow/gitignore.d.ts +7 -0
- package/dist/shadow/gitignore.d.ts.map +1 -0
- package/dist/shadow/gitignore.js +35 -0
- package/dist/shadow/merge-package-json.d.ts +16 -0
- package/dist/shadow/merge-package-json.d.ts.map +1 -0
- package/dist/shadow/merge-package-json.js +66 -0
- package/dist/shadow/metadata.d.ts +4 -0
- package/dist/shadow/metadata.d.ts.map +1 -0
- package/dist/shadow/metadata.js +21 -0
- package/dist/shadow/paths.d.ts +3 -0
- package/dist/shadow/paths.d.ts.map +1 -0
- package/dist/shadow/paths.js +31 -0
- package/dist/shadow/port.d.ts +7 -0
- package/dist/shadow/port.d.ts.map +1 -0
- package/dist/shadow/port.js +41 -0
- package/dist/shadow/prepare.d.ts +3 -0
- package/dist/shadow/prepare.d.ts.map +1 -0
- package/dist/shadow/prepare.js +62 -0
- package/dist/shadow/scaffold.d.ts +7 -0
- package/dist/shadow/scaffold.d.ts.map +1 -0
- package/dist/shadow/scaffold.js +118 -0
- package/dist/shadow/sync.d.ts +9 -0
- package/dist/shadow/sync.d.ts.map +1 -0
- package/dist/shadow/sync.js +31 -0
- package/dist/shadow/yarnrc.d.ts +10 -0
- package/dist/shadow/yarnrc.d.ts.map +1 -0
- package/dist/shadow/yarnrc.js +33 -0
- package/dist/types.d.ts +53 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +1 -0
- package/dist/util/app-name.d.ts +12 -0
- package/dist/util/app-name.d.ts.map +1 -0
- package/dist/util/app-name.js +20 -0
- package/dist/util/logger.d.ts +22 -0
- package/dist/util/logger.d.ts.map +1 -0
- package/dist/util/logger.js +71 -0
- package/dist/util/manifest.d.ts +31 -0
- package/dist/util/manifest.d.ts.map +1 -0
- package/dist/util/manifest.js +36 -0
- package/dist/util/s3/client.d.ts +11 -0
- package/dist/util/s3/client.d.ts.map +1 -0
- package/dist/util/s3/client.js +48 -0
- package/dist/util/s3/upload.d.ts +2 -0
- package/dist/util/s3/upload.d.ts.map +1 -0
- package/dist/util/s3/upload.js +39 -0
- package/package.json +56 -0
- package/src/commands/build.ts +42 -0
- package/src/commands/clean.ts +26 -0
- package/src/commands/deploy.ts +114 -0
- package/src/commands/dev.ts +64 -0
- package/src/constants.ts +63 -0
- package/src/index.ts +90 -0
- package/src/shadow/consumer-pkg.ts +100 -0
- package/src/shadow/gitignore.ts +30 -0
- package/src/shadow/merge-package-json.ts +62 -0
- package/src/shadow/metadata.ts +17 -0
- package/src/shadow/paths.ts +24 -0
- package/src/shadow/port.ts +34 -0
- package/src/shadow/prepare.ts +68 -0
- package/src/shadow/scaffold.ts +120 -0
- package/src/shadow/sync.ts +30 -0
- package/src/shadow/yarnrc.ts +29 -0
- package/src/types.ts +60 -0
- package/src/util/app-name.ts +16 -0
- package/src/util/logger.ts +64 -0
- package/src/util/manifest.ts +65 -0
- package/src/util/s3/client.ts +40 -0
- package/src/util/s3/upload.ts +41 -0
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { ensureDir, writeFile, writeJson } from 'fs-extra';
|
|
3
|
+
|
|
4
|
+
const WRAPPER_TEMPLATE = `import '@vibe/core/tokens';
|
|
5
|
+
import ConsumerApp from '../../src/index';
|
|
6
|
+
import React from 'react';
|
|
7
|
+
import * as ReactDOM from 'react-dom/client';
|
|
8
|
+
import { ErrorBoundary } from 'react-error-boundary';
|
|
9
|
+
|
|
10
|
+
const roots = new Map<HTMLElement, ReactDOM.Root>();
|
|
11
|
+
|
|
12
|
+
export function init() {}
|
|
13
|
+
|
|
14
|
+
export function render(element: HTMLElement) {
|
|
15
|
+
const root = ReactDOM.createRoot(element);
|
|
16
|
+
root.render(
|
|
17
|
+
<ErrorBoundary fallback={<div style={{ padding: 16 }}>This app crashed.</div>}>
|
|
18
|
+
<ConsumerApp />
|
|
19
|
+
</ErrorBoundary>,
|
|
20
|
+
);
|
|
21
|
+
roots.set(element, root);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function unmount({ element }: { element: HTMLElement }) {
|
|
25
|
+
const root = roots.get(element);
|
|
26
|
+
if (root) {
|
|
27
|
+
root.unmount();
|
|
28
|
+
roots.delete(element);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
`;
|
|
32
|
+
const tridentrcTemplate = (appName, port) => `/** @type {import("@mondaydotcomorg/trident-user-config").MicroFrontendConfig} */
|
|
33
|
+
const config = {
|
|
34
|
+
appName: '${appName}',
|
|
35
|
+
port: ${port},
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
module.exports = config;
|
|
39
|
+
`;
|
|
40
|
+
const dtsFileTemplate = () => `
|
|
41
|
+
declare module '*.module.css' {
|
|
42
|
+
const classNames: {
|
|
43
|
+
[className: string]: string;
|
|
44
|
+
};
|
|
45
|
+
export = classNames;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
declare module '*.module.scss' {
|
|
49
|
+
const classNames: {
|
|
50
|
+
[className: string]: string;
|
|
51
|
+
};
|
|
52
|
+
export = classNames;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
declare module '*.jpg' {
|
|
56
|
+
const e: string;
|
|
57
|
+
export default e;
|
|
58
|
+
}
|
|
59
|
+
declare module '*.jpeg' {
|
|
60
|
+
const e: string;
|
|
61
|
+
export default e;
|
|
62
|
+
}
|
|
63
|
+
declare module '*.png' {
|
|
64
|
+
const e: string;
|
|
65
|
+
export default e;
|
|
66
|
+
}
|
|
67
|
+
declare module '*.riv' {
|
|
68
|
+
const e: string;
|
|
69
|
+
export default e;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
declare module '*.wasm' {
|
|
73
|
+
const e: string;
|
|
74
|
+
export default e;
|
|
75
|
+
}
|
|
76
|
+
`;
|
|
77
|
+
const TSCONFIG_TEMPLATE = {
|
|
78
|
+
compilerOptions: {
|
|
79
|
+
target: 'es5',
|
|
80
|
+
lib: ['dom', 'dom.iterable', 'esnext'],
|
|
81
|
+
allowJs: false,
|
|
82
|
+
skipLibCheck: true,
|
|
83
|
+
esModuleInterop: true,
|
|
84
|
+
allowSyntheticDefaultImports: true,
|
|
85
|
+
strict: false,
|
|
86
|
+
module: 'esnext',
|
|
87
|
+
moduleResolution: 'bundler',
|
|
88
|
+
resolveJsonModule: true,
|
|
89
|
+
noImplicitAny: false,
|
|
90
|
+
isolatedModules: true,
|
|
91
|
+
baseUrl: 'src',
|
|
92
|
+
noEmit: true,
|
|
93
|
+
jsx: 'react-jsx',
|
|
94
|
+
},
|
|
95
|
+
include: ['src', '../src'],
|
|
96
|
+
};
|
|
97
|
+
/**
|
|
98
|
+
* Write every generated file under .zth/. Overwrites on every run so the
|
|
99
|
+
* shadow dir is a deterministic function of the CLI version — no drift.
|
|
100
|
+
*/
|
|
101
|
+
async function scaffoldShadow(paths, appName, port) {
|
|
102
|
+
await ensureDir(paths.shadowSrc);
|
|
103
|
+
await writeFile(paths.shadowWrapper, WRAPPER_TEMPLATE);
|
|
104
|
+
await writeFile(paths.shadowTridentrc, tridentrcTemplate(appName, port));
|
|
105
|
+
await writeFile(paths.shadowNvmrc, `${process.version}\n`);
|
|
106
|
+
await writeFile(paths.shadowDts, dtsFileTemplate());
|
|
107
|
+
await writeJson(paths.shadowTsconfig, TSCONFIG_TEMPLATE, { spaces: 2 });
|
|
108
|
+
// Drop a stub README so contributors who open .zth/ know what they're looking at.
|
|
109
|
+
await writeFile(path.join(paths.shadowDir, 'README.md'), '# .zth/\nGenerated by z2h-cli. Do not edit — run `z2h-cli build` or `z2h-cli dev` to refresh.\n');
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export { scaffoldShadow };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ConsumerPaths, ConsumerPkg } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Regenerate the shadow package.json from the current CLI template and
|
|
4
|
+
* run `yarn install` at the consumer dir iff the consumer's declared deps
|
|
5
|
+
* have changed since the last install. Idempotent — safe to call on every
|
|
6
|
+
* build, dev start, or consumer package.json edit.
|
|
7
|
+
*/
|
|
8
|
+
export declare function syncShadow(paths: ConsumerPaths, consumerPkg: ConsumerPkg): Promise<void>;
|
|
9
|
+
//# sourceMappingURL=sync.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../../src/shadow/sync.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAE3D;;;;;GAKG;AACH,wBAAsB,UAAU,CAAC,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAiB9F"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { pathExists, readFile, writeFile } from 'fs-extra';
|
|
2
|
+
import { execa } from 'execa';
|
|
3
|
+
import { info } from '../util/logger.mjs';
|
|
4
|
+
import { buildShadowPkg, writeShadowPkg, hashConsumerDeps } from './merge-package-json.mjs';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Regenerate the shadow package.json from the current CLI template and
|
|
8
|
+
* run `yarn install` at the consumer dir iff the consumer's declared deps
|
|
9
|
+
* have changed since the last install. Idempotent — safe to call on every
|
|
10
|
+
* build, dev start, or consumer package.json edit.
|
|
11
|
+
*/
|
|
12
|
+
async function syncShadow(paths, consumerPkg) {
|
|
13
|
+
const shadow = buildShadowPkg(consumerPkg);
|
|
14
|
+
await writeShadowPkg(paths.shadowPkg, shadow);
|
|
15
|
+
const newHash = hashConsumerDeps(consumerPkg);
|
|
16
|
+
const oldHash = (await pathExists(paths.shadowDepsHash)) ? await readFile(paths.shadowDepsHash, 'utf8') : null;
|
|
17
|
+
if (oldHash !== newHash) {
|
|
18
|
+
info(oldHash ? 'consumer deps changed — yarn install' : 'first run — yarn install');
|
|
19
|
+
// Yarn 4 is cache-first and non-interactive by default
|
|
20
|
+
// in non-TTY contexts, so no flags are needed
|
|
21
|
+
await execa('yarn', ['install'], {
|
|
22
|
+
cwd: paths.consumerDir,
|
|
23
|
+
stdio: 'inherit',
|
|
24
|
+
});
|
|
25
|
+
await writeFile(paths.shadowDepsHash, newHash);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export { syncShadow };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ensure the consumer has a `.yarnrc.yml` that pins `nodeLinker: node-modules`.
|
|
3
|
+
*
|
|
4
|
+
* Yarn 4 defaults to PnP, which trident-toolkit's webpack pipeline doesn't
|
|
5
|
+
* support cleanly (webpack expects a flat node_modules). We force the
|
|
6
|
+
* classic linker so installs produce a real `node_modules/`. Idempotent —
|
|
7
|
+
* leaves any other settings the user added alone.
|
|
8
|
+
*/
|
|
9
|
+
export declare function ensureYarnRc(consumerDir: string): Promise<void>;
|
|
10
|
+
//# sourceMappingURL=yarnrc.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"yarnrc.d.ts","sourceRoot":"","sources":["../../../src/shadow/yarnrc.ts"],"names":[],"mappings":"AAIA;;;;;;;GAOG;AAEH,wBAAsB,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAerE"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { pathExists, writeFile, readFile } from 'fs-extra';
|
|
3
|
+
import { YARNRC_LINES } from '../constants.mjs';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Ensure the consumer has a `.yarnrc.yml` that pins `nodeLinker: node-modules`.
|
|
7
|
+
*
|
|
8
|
+
* Yarn 4 defaults to PnP, which trident-toolkit's webpack pipeline doesn't
|
|
9
|
+
* support cleanly (webpack expects a flat node_modules). We force the
|
|
10
|
+
* classic linker so installs produce a real `node_modules/`. Idempotent —
|
|
11
|
+
* leaves any other settings the user added alone.
|
|
12
|
+
*/
|
|
13
|
+
async function ensureYarnRc(consumerDir) {
|
|
14
|
+
const yarnrcPath = path.join(consumerDir, '.yarnrc.yml');
|
|
15
|
+
if (!(await pathExists(yarnrcPath))) {
|
|
16
|
+
await writeFile(yarnrcPath, YARNRC_LINES.join('\n\n') + '\n');
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
const body = await readFile(yarnrcPath, 'utf8');
|
|
20
|
+
if (/^\s*nodeLinker\s*:/m.test(body)) {
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
const prefix = body.length && !body.endsWith('\n') ? '\n' : '';
|
|
24
|
+
await writeFile(yarnrcPath, body + prefix + 'nodeLinker: node-modules\n');
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export { ensureYarnRc };
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared domain types for the Z2H CLI. Command-scoped option types live
|
|
3
|
+
* with their command; narrow single-use types stay local to their file.
|
|
4
|
+
*/
|
|
5
|
+
export interface ConsumerPkg {
|
|
6
|
+
name: string;
|
|
7
|
+
version?: string;
|
|
8
|
+
private?: boolean;
|
|
9
|
+
workspaces?: string[] | {
|
|
10
|
+
packages?: string[];
|
|
11
|
+
};
|
|
12
|
+
dependencies?: Record<string, string>;
|
|
13
|
+
devDependencies?: Record<string, string>;
|
|
14
|
+
peerDependencies?: Record<string, string>;
|
|
15
|
+
scripts?: Record<string, string>;
|
|
16
|
+
[k: string]: unknown;
|
|
17
|
+
}
|
|
18
|
+
export interface ShadowPkg {
|
|
19
|
+
name: string;
|
|
20
|
+
version: string;
|
|
21
|
+
private: true;
|
|
22
|
+
scripts: Record<string, string>;
|
|
23
|
+
peerDependencies: Record<string, string>;
|
|
24
|
+
devDependencies: Record<string, string>;
|
|
25
|
+
}
|
|
26
|
+
export interface ShadowMetadata {
|
|
27
|
+
createdAt: string;
|
|
28
|
+
appName: string;
|
|
29
|
+
port: number;
|
|
30
|
+
}
|
|
31
|
+
export interface ConsumerPaths {
|
|
32
|
+
consumerDir: string;
|
|
33
|
+
consumerPkg: string;
|
|
34
|
+
consumerSrc: string;
|
|
35
|
+
consumerSrcEntry: string;
|
|
36
|
+
shadowDir: string;
|
|
37
|
+
shadowPkg: string;
|
|
38
|
+
shadowSrc: string;
|
|
39
|
+
shadowWrapper: string;
|
|
40
|
+
shadowTridentrc: string;
|
|
41
|
+
shadowNvmrc: string;
|
|
42
|
+
shadowDts: string;
|
|
43
|
+
shadowTsconfig: string;
|
|
44
|
+
shadowBuild: string;
|
|
45
|
+
shadowDepsHash: string;
|
|
46
|
+
shadowMetadata: string;
|
|
47
|
+
}
|
|
48
|
+
export interface PreparedShadow {
|
|
49
|
+
appName: string;
|
|
50
|
+
port: number;
|
|
51
|
+
paths: ConsumerPaths;
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,EAAE,GAAG;QAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IAChD,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzC,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC1C,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;CACtB;AAGD,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,IAAI,CAAC;IACd,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzC,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACzC;AAGD,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;CACd;AAGD,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB,EAAE,MAAM,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;CACxB;AAGD,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,aAAa,CAAC;CACtB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Strip any npm scope (`@scope/`) from a package name.
|
|
3
|
+
* e.g. `@trident/customer-viewer` → `customer-viewer`, `foo` → `foo`.
|
|
4
|
+
*/
|
|
5
|
+
export declare function cleanAppName(name: string): string;
|
|
6
|
+
/**
|
|
7
|
+
* Canonical MF bundle name: the de-scoped app name with an `mf-` prefix.
|
|
8
|
+
* This matches the trident convention (shadow pkg is `@trident/mf-<app>`,
|
|
9
|
+
* emitted bundle is `MF-mf-<app>`).
|
|
10
|
+
*/
|
|
11
|
+
export declare function mfAppName(name: string): string;
|
|
12
|
+
//# sourceMappingURL=app-name.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app-name.d.ts","sourceRoot":"","sources":["../../../src/util/app-name.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE9C"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Strip any npm scope (`@scope/`) from a package name.
|
|
3
|
+
* e.g. `@trident/customer-viewer` → `customer-viewer`, `foo` → `foo`.
|
|
4
|
+
*/
|
|
5
|
+
function cleanAppName(name) {
|
|
6
|
+
return name.replace(/^@[^/]+\//, '');
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Canonical MF bundle name: the de-scoped app name with an `mf-` prefix.
|
|
10
|
+
* This matches the trident convention (shadow pkg is `@trident/mf-<app>`,
|
|
11
|
+
* emitted bundle is `MF-mf-<app>`).
|
|
12
|
+
*/
|
|
13
|
+
function mfAppName(name) {
|
|
14
|
+
return `mf-${cleanAppName(name)}`;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export { cleanAppName, mfAppName };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export type OutputMode = 'human' | 'json';
|
|
2
|
+
export declare function setOutputMode(next: OutputMode): void;
|
|
3
|
+
export declare function getOutputMode(): OutputMode;
|
|
4
|
+
/**
|
|
5
|
+
* Progress, info, and warnings go to stderr so stdout stays clean
|
|
6
|
+
* for machine-readable output. Always suppressed in JSON mode except
|
|
7
|
+
* when the consumer explicitly wants chatty progress (e.g. setup).
|
|
8
|
+
*/
|
|
9
|
+
export declare function info(msg: string): void;
|
|
10
|
+
export declare function warn(msg: string): void;
|
|
11
|
+
export declare function errorLog(msg: string): void;
|
|
12
|
+
/**
|
|
13
|
+
* Data output. In human mode writes `human` to stdout; in JSON mode writes
|
|
14
|
+
* JSON-stringified `data` to stdout. Exactly one line of stdout per call.
|
|
15
|
+
*/
|
|
16
|
+
export declare function output(human: string, data: unknown): void;
|
|
17
|
+
/**
|
|
18
|
+
* Emit a structured failure payload (JSON mode) or a red error line (human mode),
|
|
19
|
+
* then exit with the given code.
|
|
20
|
+
*/
|
|
21
|
+
export declare function fail(message: string, payload: Record<string, unknown>, exitCode?: number): never;
|
|
22
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../../src/util/logger.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,MAAM,CAAC;AAI1C,wBAAgB,aAAa,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,CAEpD;AAED,wBAAgB,aAAa,IAAI,UAAU,CAE1C;AAED;;;;GAIG;AACH,wBAAgB,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAItC;AAED,wBAAgB,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAItC;AAED,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAI1C;AAED;;;GAGG;AACH,wBAAgB,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,IAAI,CAMzD;AAED;;;GAGG;AACH,wBAAgB,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,QAAQ,SAAI,GAAG,KAAK,CAU3F"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import pc from 'picocolors';
|
|
2
|
+
|
|
3
|
+
let mode = 'human';
|
|
4
|
+
function setOutputMode(next) {
|
|
5
|
+
mode = next;
|
|
6
|
+
}
|
|
7
|
+
function getOutputMode() {
|
|
8
|
+
return mode;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Progress, info, and warnings go to stderr so stdout stays clean
|
|
12
|
+
* for machine-readable output. Always suppressed in JSON mode except
|
|
13
|
+
* when the consumer explicitly wants chatty progress (e.g. setup).
|
|
14
|
+
*/
|
|
15
|
+
function info(msg) {
|
|
16
|
+
if (mode === 'human') {
|
|
17
|
+
process.stderr.write(pc.cyan(`[z2h-cli] ${msg}\n`));
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
function warn(msg) {
|
|
21
|
+
if (mode === 'human') {
|
|
22
|
+
process.stderr.write(pc.yellow(`[z2h-cli] ${msg}\n`));
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
function errorLog(msg) {
|
|
26
|
+
if (mode === 'human') {
|
|
27
|
+
process.stderr.write(pc.red(`[z2h-cli] ${msg}\n`));
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Data output. In human mode writes `human` to stdout; in JSON mode writes
|
|
32
|
+
* JSON-stringified `data` to stdout. Exactly one line of stdout per call.
|
|
33
|
+
*/
|
|
34
|
+
function output(human, data) {
|
|
35
|
+
if (mode === 'json') {
|
|
36
|
+
process.stdout.write(`${JSON.stringify(data)}\n`);
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
process.stdout.write(`${human}\n`);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Emit a structured failure payload (JSON mode) or a red error line (human mode),
|
|
44
|
+
* then exit with the given code.
|
|
45
|
+
*/
|
|
46
|
+
function fail(message, payload, exitCode = 1) {
|
|
47
|
+
if (mode === 'json') {
|
|
48
|
+
process.stdout.write(`${JSON.stringify({ ok: false, error: message, ...payload })}\n`);
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
process.stderr.write(pc.red(`[z2h-cli] ${message}\n`));
|
|
52
|
+
if (typeof payload.suggestedCommand === 'string') {
|
|
53
|
+
process.stderr.write(pc.dim(` → ${payload.suggestedCommand}\n`));
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
process.exit(exitCode);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export { errorLog, fail, getOutputMode, info, output, setOutputMode, warn };
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export interface SharedDep {
|
|
2
|
+
name?: string;
|
|
3
|
+
globalName: string;
|
|
4
|
+
url?: string;
|
|
5
|
+
minVersion?: string;
|
|
6
|
+
dependencies: Record<string, number>;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Shape of the `asset-manifest.json` trident-toolkit emits alongside the
|
|
10
|
+
* bundle. We consume this file directly as the base for a Z2H registry
|
|
11
|
+
* entry — deploy.ts only overlays `version` and `url`.
|
|
12
|
+
*/
|
|
13
|
+
export interface AssetManifestFile {
|
|
14
|
+
sameAsHost: boolean;
|
|
15
|
+
skipTranslationFetch: boolean;
|
|
16
|
+
shared: SharedDep[];
|
|
17
|
+
entrypoints: string[];
|
|
18
|
+
nonExternalsEntrypoints?: string[];
|
|
19
|
+
scriptType?: 'module' | 'classic';
|
|
20
|
+
mfs?: string[];
|
|
21
|
+
}
|
|
22
|
+
export interface ManifestEntry extends AssetManifestFile {
|
|
23
|
+
version: number;
|
|
24
|
+
url: string;
|
|
25
|
+
}
|
|
26
|
+
export type Manifest = Record<string, ManifestEntry>;
|
|
27
|
+
export declare function readManifest(): Promise<Manifest>;
|
|
28
|
+
export declare function nextVersion(manifest: Manifest, app: string): number;
|
|
29
|
+
export declare function upsertEntry(manifest: Manifest, app: string, entry: ManifestEntry): Manifest;
|
|
30
|
+
export declare function writeManifest(manifest: Manifest): Promise<void>;
|
|
31
|
+
//# sourceMappingURL=manifest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../../src/util/manifest.ts"],"names":[],"mappings":"AAGA,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;CACb;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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { PutObjectCommand } from '@aws-sdk/client-s3';
|
|
2
|
+
import { MANIFEST_READ_URL, getS3Client, BUCKET_WRITE_NAME, MANIFEST_KEY } from './s3/client.mjs';
|
|
3
|
+
|
|
4
|
+
async function readManifest() {
|
|
5
|
+
// Read via the public CDN endpoint, no AWS auth required.
|
|
6
|
+
const res = await fetch(MANIFEST_READ_URL);
|
|
7
|
+
if (!res.ok) {
|
|
8
|
+
throw new Error(`failed to read manifest from ${MANIFEST_READ_URL}: HTTP ${res.status}`);
|
|
9
|
+
}
|
|
10
|
+
return (await res.json());
|
|
11
|
+
}
|
|
12
|
+
function nextVersion(manifest, app) {
|
|
13
|
+
const current = manifest[app]?.version;
|
|
14
|
+
const n = current ? Number(current) : 0;
|
|
15
|
+
return (Number.isNaN(n) ? 0 : n) + 1;
|
|
16
|
+
}
|
|
17
|
+
function upsertEntry(manifest, app, entry) {
|
|
18
|
+
return { ...manifest, [app]: entry };
|
|
19
|
+
}
|
|
20
|
+
async function writeManifest(manifest) {
|
|
21
|
+
const s3 = getS3Client();
|
|
22
|
+
await s3.send(new PutObjectCommand({
|
|
23
|
+
Bucket: BUCKET_WRITE_NAME,
|
|
24
|
+
Key: MANIFEST_KEY,
|
|
25
|
+
Body: JSON.stringify(manifest, null, 2),
|
|
26
|
+
ContentType: 'application/json',
|
|
27
|
+
CacheControl: 'no-cache',
|
|
28
|
+
}));
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export { nextVersion, readManifest, upsertEntry, writeManifest };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { S3Client } from '@aws-sdk/client-s3';
|
|
2
|
+
export declare const BUCKET_WRITE_NAME = "prod-use1-bigbrain-zth-mf-assets";
|
|
3
|
+
export declare const REGION = "us-east-1";
|
|
4
|
+
export declare const BUCKET_WRITE_URL = "https://prod-use1-bigbrain-zth-mf-assets.s3.us-east-1.amazonaws.com";
|
|
5
|
+
export declare const BUCKET_READ_DNS_NAME = "bigbrain-zth-mf-assets";
|
|
6
|
+
export declare const BUCKET_READ_DNS_URL = "https://bigbrain-zth-mf-assets.bigbrain.me";
|
|
7
|
+
export declare const MANIFEST_KEY = "mf-assets";
|
|
8
|
+
export declare const MANIFEST_READ_URL = "https://bigbrain-zth-mf-assets.bigbrain.me/mf-assets";
|
|
9
|
+
export declare function getS3Client(): S3Client;
|
|
10
|
+
export declare function assertBucketExists(): Promise<void>;
|
|
11
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../../src/util/s3/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,QAAQ,EAAsB,MAAM,oBAAoB,CAAC;AAErF,eAAO,MAAM,iBAAiB,qCAAqC,CAAC;AACpE,eAAO,MAAM,MAAM,cAAc,CAAC;AAClC,eAAO,MAAM,gBAAgB,wEAA4D,CAAC;AAE1F,eAAO,MAAM,oBAAoB,2BAA2B,CAAC;AAC7D,eAAO,MAAM,mBAAmB,+CAAgD,CAAC;AAKjF,eAAO,MAAM,YAAY,cAAc,CAAC;AACxC,eAAO,MAAM,iBAAiB,yDAA2C,CAAC;AAI1E,wBAAgB,WAAW,IAAI,QAAQ,CAKtC;AAED,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,IAAI,CAAC,CAexD"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { S3Client, HeadBucketCommand, S3ServiceException } from '@aws-sdk/client-s3';
|
|
2
|
+
|
|
3
|
+
const BUCKET_WRITE_NAME = 'prod-use1-bigbrain-zth-mf-assets';
|
|
4
|
+
const REGION = 'us-east-1';
|
|
5
|
+
const BUCKET_WRITE_URL = `https://${BUCKET_WRITE_NAME}.s3.${REGION}.amazonaws.com`;
|
|
6
|
+
const BUCKET_READ_DNS_NAME = 'bigbrain-zth-mf-assets';
|
|
7
|
+
const BUCKET_READ_DNS_URL = `https://${BUCKET_READ_DNS_NAME}.bigbrain.me`;
|
|
8
|
+
// No `.json` extension — TridentSkeleton's `mfUrl` API appends `/mf-assets`
|
|
9
|
+
// to the bucket base when fetching, so the manifest must live at this exact
|
|
10
|
+
// key. See microfrontends/mf-bigbrain-zth/.../ZeroToHeroHost.tsx.
|
|
11
|
+
const MANIFEST_KEY = 'mf-assets';
|
|
12
|
+
const MANIFEST_READ_URL = `${BUCKET_READ_DNS_URL}/${MANIFEST_KEY}`;
|
|
13
|
+
let client = null;
|
|
14
|
+
function getS3Client() {
|
|
15
|
+
if (!client) {
|
|
16
|
+
client = new S3Client({ region: REGION });
|
|
17
|
+
}
|
|
18
|
+
return client;
|
|
19
|
+
}
|
|
20
|
+
async function assertBucketExists() {
|
|
21
|
+
try {
|
|
22
|
+
await getS3Client().send(new HeadBucketCommand({ Bucket: BUCKET_WRITE_NAME }));
|
|
23
|
+
}
|
|
24
|
+
catch (err) {
|
|
25
|
+
if (err instanceof S3ServiceException) {
|
|
26
|
+
const status = err.$metadata.httpStatusCode;
|
|
27
|
+
if (status === 404 || err.name === 'NotFound' || err.name === 'NoSuchBucket') {
|
|
28
|
+
throw new Error(`S3 bucket "${BUCKET_WRITE_NAME}" does not exist (region: ${REGION}).`);
|
|
29
|
+
}
|
|
30
|
+
if (status === 403) {
|
|
31
|
+
throw new Error(`No access to S3 bucket "${BUCKET_WRITE_NAME}" (region: ${REGION}). Check AWS credentials.`);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
throw err;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export { BUCKET_READ_DNS_NAME, BUCKET_READ_DNS_URL, BUCKET_WRITE_NAME, BUCKET_WRITE_URL, MANIFEST_KEY, MANIFEST_READ_URL, REGION, assertBucketExists, getS3Client };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"upload.d.ts","sourceRoot":"","sources":["../../../../src/util/s3/upload.ts"],"names":[],"mappings":"AAcA,wBAAsB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CA0BtF"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { readFile } from 'fs-extra';
|
|
3
|
+
import { readdir } from 'node:fs/promises';
|
|
4
|
+
import { lookup } from 'mime-types';
|
|
5
|
+
import pMap from 'p-map';
|
|
6
|
+
import { PutObjectCommand } from '@aws-sdk/client-s3';
|
|
7
|
+
import { getS3Client, BUCKET_WRITE_NAME } from './client.mjs';
|
|
8
|
+
|
|
9
|
+
// Each deploy uploads to a version-prefixed path (<app>/<version>/...), so
|
|
10
|
+
// the URL itself is the cache key. Assets never need to be revalidated.
|
|
11
|
+
const FOREVER = 'public, immutable';
|
|
12
|
+
const UPLOAD_CONCURRENCY = 5;
|
|
13
|
+
async function uploadDir(localDir, keyPrefix) {
|
|
14
|
+
const entries = await readdir(localDir, { recursive: true, withFileTypes: true });
|
|
15
|
+
const files = entries.filter(e => e.isFile()).map(e => path.relative(localDir, path.join(e.parentPath, e.name)));
|
|
16
|
+
const s3 = getS3Client();
|
|
17
|
+
await pMap(files, async (rel) => {
|
|
18
|
+
const body = await readFile(path.join(localDir, rel));
|
|
19
|
+
const contentType = lookup(rel) || 'application/octet-stream';
|
|
20
|
+
const key = `${keyPrefix}/${rel.split(path.sep).join('/')}`;
|
|
21
|
+
await s3.send(new PutObjectCommand({
|
|
22
|
+
Bucket: BUCKET_WRITE_NAME,
|
|
23
|
+
Key: key,
|
|
24
|
+
Body: body,
|
|
25
|
+
ContentType: contentType,
|
|
26
|
+
CacheControl: FOREVER,
|
|
27
|
+
}));
|
|
28
|
+
}, { concurrency: UPLOAD_CONCURRENCY });
|
|
29
|
+
return files.map(f => f.split(path.sep).join('/'));
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export { uploadDir };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
const commander = require('commander');
|
|
2
|
+
const commands_dev = require('./commands/dev.js');
|
|
3
|
+
const commands_build = require('./commands/build.js');
|
|
4
|
+
const commands_clean = require('./commands/clean.js');
|
|
5
|
+
const commands_deploy = require('./commands/deploy.js');
|
|
6
|
+
const util_logger = require('./util/logger.js');
|
|
7
|
+
|
|
8
|
+
async function main() {
|
|
9
|
+
const program = new commander.Command();
|
|
10
|
+
program
|
|
11
|
+
.name('z2h-cli')
|
|
12
|
+
.description([
|
|
13
|
+
'Zero-to-Hero CLI — ship LLM-generated React apps as Trident MFs.',
|
|
14
|
+
'',
|
|
15
|
+
'Each consumer dir is self-contained: a shadow at <consumer>/.zth/',
|
|
16
|
+
'wraps the consumer source as a Trident MF. Run from inside any',
|
|
17
|
+
'consumer dir (the one with your src/index.tsx).',
|
|
18
|
+
'',
|
|
19
|
+
'Exit codes:',
|
|
20
|
+
' 0 success',
|
|
21
|
+
' 1 user-resolvable error (bad cwd, invalid package.json, lock held)',
|
|
22
|
+
' 2 system error (yarn install or trident build failed)',
|
|
23
|
+
].join('\n'))
|
|
24
|
+
.version('0.0.0');
|
|
25
|
+
program
|
|
26
|
+
.command('build')
|
|
27
|
+
.description('Build the consumer into its .zth/ shadow and copy artifacts to ./build/')
|
|
28
|
+
.option('--json', 'emit structured JSON on stdout')
|
|
29
|
+
.action(async (opts) => {
|
|
30
|
+
try {
|
|
31
|
+
await commands_build.buildCommand(opts);
|
|
32
|
+
}
|
|
33
|
+
catch (err) {
|
|
34
|
+
// fail() emits a structured JSON error on stdout in --json mode and
|
|
35
|
+
// a red line on stderr in human mode, then exits. errorLog alone is
|
|
36
|
+
// silent in JSON mode, which leaves machine consumers with no signal.
|
|
37
|
+
util_logger.fail(`build failed: ${err.message}`, { command: 'build' }, 2);
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
program
|
|
41
|
+
.command('dev')
|
|
42
|
+
.description('Start the Trident dev server against .zth/ with native Vite HMR')
|
|
43
|
+
.option('--json', 'emit structured JSON on stdout')
|
|
44
|
+
.action(async (opts) => {
|
|
45
|
+
try {
|
|
46
|
+
await commands_dev.devCommand(opts);
|
|
47
|
+
}
|
|
48
|
+
catch (err) {
|
|
49
|
+
util_logger.fail(`dev failed: ${err.message}`, { command: 'dev' }, 2);
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
program
|
|
53
|
+
.command('clean')
|
|
54
|
+
.description('Delete <consumer>/.zth/ and <consumer>/build/')
|
|
55
|
+
.option('--json', 'emit structured JSON on stdout')
|
|
56
|
+
.action(async (opts) => {
|
|
57
|
+
try {
|
|
58
|
+
await commands_clean.cleanCommand(opts);
|
|
59
|
+
}
|
|
60
|
+
catch (err) {
|
|
61
|
+
util_logger.fail(`clean failed: ${err.message}`, { command: 'clean' }, 2);
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
program
|
|
65
|
+
.command('deploy')
|
|
66
|
+
.description('Build, upload artifacts to S3, and update the Z2H manifest')
|
|
67
|
+
.option('--dry-run', 'print what would happen without uploading anything')
|
|
68
|
+
.option('--json', 'emit structured JSON on stdout')
|
|
69
|
+
.action(async (opts) => {
|
|
70
|
+
try {
|
|
71
|
+
await commands_deploy.deployCommand(opts);
|
|
72
|
+
}
|
|
73
|
+
catch (err) {
|
|
74
|
+
util_logger.fail(`deploy failed: ${err.message}`, { command: 'deploy' }, 2);
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
await program.parseAsync(process.argv);
|
|
78
|
+
}
|
|
79
|
+
void main()
|
|
80
|
+
.then(() => {
|
|
81
|
+
process.exit(0);
|
|
82
|
+
})
|
|
83
|
+
.catch((err) => {
|
|
84
|
+
util_logger.errorLog(`main failed: ${err.message}`);
|
|
85
|
+
process.exit(1);
|
|
86
|
+
});
|