@mondaydotcomorg/z2h-cli 0.25.9 → 0.26.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/dist/commands/backend.js +2 -2
- package/dist/commands/deploy.d.ts +1 -0
- package/dist/commands/deploy.d.ts.map +1 -1
- package/dist/commands/deploy.js +19 -3
- package/dist/commands/generate.d.ts +12 -0
- package/dist/commands/generate.d.ts.map +1 -0
- package/dist/commands/generate.js +190 -0
- package/dist/commands/templates.d.ts +7 -0
- package/dist/commands/templates.d.ts.map +1 -0
- package/dist/commands/templates.js +23 -0
- package/dist/esm/commands/deploy.d.ts +1 -0
- package/dist/esm/commands/deploy.d.ts.map +1 -1
- package/dist/esm/commands/deploy.mjs +19 -4
- package/dist/esm/commands/generate.d.ts +12 -0
- package/dist/esm/commands/generate.d.ts.map +1 -0
- package/dist/esm/commands/generate.mjs +182 -0
- package/dist/esm/commands/templates.d.ts +7 -0
- package/dist/esm/commands/templates.d.ts.map +1 -0
- package/dist/esm/commands/templates.mjs +21 -0
- package/dist/esm/index.mjs +16 -1
- package/dist/esm/util/dashboard-templates/load-catalog.d.ts +22 -0
- package/dist/esm/util/dashboard-templates/load-catalog.d.ts.map +1 -0
- package/dist/esm/util/dashboard-templates/load-catalog.mjs +55 -0
- package/dist/esm/util/dashboard-templates/patch-bundle.d.ts +12 -0
- package/dist/esm/util/dashboard-templates/patch-bundle.d.ts.map +1 -0
- package/dist/esm/util/dashboard-templates/patch-bundle.mjs +108 -0
- package/dist/index.js +16 -1
- package/dist/util/app-name.js +2 -2
- package/dist/util/dashboard-templates/load-catalog.d.ts +22 -0
- package/dist/util/dashboard-templates/load-catalog.d.ts.map +1 -0
- package/dist/util/dashboard-templates/load-catalog.js +64 -0
- package/dist/util/dashboard-templates/patch-bundle.d.ts +12 -0
- package/dist/util/dashboard-templates/patch-bundle.d.ts.map +1 -0
- package/dist/util/dashboard-templates/patch-bundle.js +116 -0
- package/package.json +4 -2
- package/src/commands/deploy.ts +24 -5
- package/src/commands/generate.ts +225 -0
- package/src/commands/templates.ts +20 -0
- package/src/index.ts +36 -1
- package/src/util/dashboard-templates/load-catalog.ts +80 -0
- package/src/util/dashboard-templates/patch-bundle.ts +127 -0
package/dist/esm/index.mjs
CHANGED
|
@@ -11,6 +11,8 @@ import { deleteCommand } from './commands/delete.mjs';
|
|
|
11
11
|
import { grantCommand, revokeCommand, transferOwnerCommand } from './commands/grant.mjs';
|
|
12
12
|
import { createWorkspaceCommand } from './commands/create-workspace.mjs';
|
|
13
13
|
import { createCommand } from './commands/create.mjs';
|
|
14
|
+
import { generateCommand } from './commands/generate.mjs';
|
|
15
|
+
import { templatesCommand } from './commands/templates.mjs';
|
|
14
16
|
import { generateZ2HTokenCommand } from './commands/generate-z2h-token.mjs';
|
|
15
17
|
import { migrateCommand } from './commands/migrate.mjs';
|
|
16
18
|
import { tagCommand } from './commands/tag.mjs';
|
|
@@ -90,6 +92,7 @@ async function main() {
|
|
|
90
92
|
.option('--remote <type>', 'First deploy only: source control remote to initialise — s3 (shared storage, recommended, auto-backed-up) or github (manage it yourself in your own repo). Error if the app already has a git remote.')
|
|
91
93
|
.option('--repo-url <url>', 'First deploy only: GitHub repo URL — required when --remote=github. Error if the app already has a git remote.')
|
|
92
94
|
.option('--description <text>', 'short (<=200 char) description of the app')
|
|
95
|
+
.option('--prebuilt-dir <path>', 'internal — used by `generate-app-template`: skip the build step and deploy this already-built directory as-is')
|
|
93
96
|
.action(runCommand({
|
|
94
97
|
// A preview is a real deploy for observability, tracked as its own event since
|
|
95
98
|
// the command name alone (`deploy`) can't distinguish it from a live deploy.
|
|
@@ -117,7 +120,7 @@ async function main() {
|
|
|
117
120
|
.action(runCommand({}, (opts) => generateZ2HTokenCommand(opts)));
|
|
118
121
|
program
|
|
119
122
|
.command('create <app-name>')
|
|
120
|
-
.description(`Scaffold a
|
|
123
|
+
.description(`Scaffold a blank Z2H consumer app inside ${getWorkspaceHome()}/ using a built-in template (default | html-embed). If a catalog template already fits what you're building, use \`generate-app-template\` instead.`)
|
|
121
124
|
.option('--template <name>', 'Template name (default | html-embed)')
|
|
122
125
|
.option('--html-file <path>', 'Path to an HTML file to embed (implies --template html-embed)')
|
|
123
126
|
.option('--remote <type>', 'Source control remote: s3 (shared storage, recommended, auto-backed-up) or github (manage it yourself in your own repo)')
|
|
@@ -129,6 +132,18 @@ async function main() {
|
|
|
129
132
|
remote: opts.remote ?? 'unknown',
|
|
130
133
|
}),
|
|
131
134
|
}, (appName, opts) => createCommand(appName, opts)));
|
|
135
|
+
program
|
|
136
|
+
.command('templates')
|
|
137
|
+
.description("List the BigBrain Studio (Z2H) template catalog — id, title, description, and each template's widget schema")
|
|
138
|
+
.action(runCommand({}, () => templatesCommand()));
|
|
139
|
+
program
|
|
140
|
+
.command('generate-app-template <app-name>')
|
|
141
|
+
.description(`Scaffold + preview a Z2H app/dashboard from a templates catalog entry inside ${getWorkspaceHome()}/ — copies a prebuilt template, patches in real widget data, and deploys a preview. No build, no yarn install, no live deploy — run \`z2h-cli deploy\` yourself from the app dir once you're happy with it.`)
|
|
142
|
+
.requiredOption('--template <id>', 'catalog template id — see `z2h-cli templates --json`')
|
|
143
|
+
.requiredOption('--input <json>', "JSON string — shape is template-defined, validated wholesale against the template's configSchema (see `z2h-cli templates --json`)")
|
|
144
|
+
.action(runCommand({
|
|
145
|
+
data: ([appName, opts]) => ({ app_name: appName, template: opts.template }),
|
|
146
|
+
}, (appName, opts) => generateCommand(appName, opts)));
|
|
132
147
|
program
|
|
133
148
|
.command('edit <app-name>')
|
|
134
149
|
.description(`Pull the latest version of an app into ${getWorkspaceHome()}/<app-name>, cloning it first if needed`)
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export type ValidateConfigResult = {
|
|
2
|
+
success: true;
|
|
3
|
+
data: unknown;
|
|
4
|
+
} | {
|
|
5
|
+
success: false;
|
|
6
|
+
error: string;
|
|
7
|
+
};
|
|
8
|
+
export interface DashboardTemplateEntry {
|
|
9
|
+
id: string;
|
|
10
|
+
title: string;
|
|
11
|
+
description: string;
|
|
12
|
+
/** Absolute path to this template's dir — source + its already-built .zth/build. */
|
|
13
|
+
templateDir: string;
|
|
14
|
+
/** JSON Schema for this template's whole `--input` config object — shape is template-defined. */
|
|
15
|
+
configSchema: Record<string, unknown>;
|
|
16
|
+
/** Validates --input against this template's actual zod schema — the JSON Schema above is
|
|
17
|
+
* display-only (catalog listing), this is what `generate` really validates against. */
|
|
18
|
+
validateConfig: (input: unknown) => ValidateConfigResult;
|
|
19
|
+
}
|
|
20
|
+
export declare function findTemplate(id: string): DashboardTemplateEntry;
|
|
21
|
+
export declare function loadDashboardTemplatesCatalog(): DashboardTemplateEntry[];
|
|
22
|
+
//# sourceMappingURL=load-catalog.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"load-catalog.d.ts","sourceRoot":"","sources":["../../../../src/util/dashboard-templates/load-catalog.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,oBAAoB,GAAG;IAAE,OAAO,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAE,GAAG;IAAE,OAAO,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAExG,MAAM,WAAW,sBAAsB;IACrC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,oFAAoF;IACpF,WAAW,EAAE,MAAM,CAAC;IACpB,iGAAiG;IACjG,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACtC;4FACwF;IACxF,cAAc,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,oBAAoB,CAAC;CAC1D;AA+BD,wBAAgB,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,sBAAsB,CAQ/D;AAED,wBAAgB,6BAA6B,IAAI,sBAAsB,EAAE,CAoBxE"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import { createRequire } from 'node:module';
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
|
|
6
|
+
// Each template defines its catalog metadata and its config shape once, in template.ts (compiled
|
|
7
|
+
// to dist/template.js by dashboard-templates' build script) — the JSON Schema used for catalog
|
|
8
|
+
// listing is derived from its zod configSchema here rather than hand-duplicated as a separate JSON
|
|
9
|
+
// literal, and --input validation goes through the same zod schema directly (see validateConfig),
|
|
10
|
+
// so the schema and the TS types templates' own hooks import can never drift apart.
|
|
11
|
+
function loadTemplateModule(templateDir) {
|
|
12
|
+
const templateModulePath = path.join(templateDir, 'dist', 'template.js');
|
|
13
|
+
const { template, configSchema } = createRequire(import.meta.url)(templateModulePath);
|
|
14
|
+
return {
|
|
15
|
+
template,
|
|
16
|
+
// draft-7 is arbitrary here (nothing re-validates against it) — just a reasonably standard,
|
|
17
|
+
// widely-understood dialect for whatever reads `templates --json`'s output.
|
|
18
|
+
configSchema: z.toJSONSchema(configSchema, { target: 'draft-7' }),
|
|
19
|
+
validateConfig: input => {
|
|
20
|
+
const result = configSchema.safeParse(input);
|
|
21
|
+
return result.success
|
|
22
|
+
? { success: true, data: result.data }
|
|
23
|
+
: { success: false, error: z.prettifyError(result.error) };
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
function findTemplate(id) {
|
|
28
|
+
const templates = loadDashboardTemplatesCatalog();
|
|
29
|
+
const template = templates.find(t => t.id === id);
|
|
30
|
+
if (!template) {
|
|
31
|
+
const known = templates.map(t => t.id).join(', ') || '(none)';
|
|
32
|
+
throw new Error(`Unknown template "${id}". Available: ${known}.`);
|
|
33
|
+
}
|
|
34
|
+
return template;
|
|
35
|
+
}
|
|
36
|
+
function loadDashboardTemplatesCatalog() {
|
|
37
|
+
const catalogDir = path.dirname(createRequire(import.meta.url).resolve('@mondaydotcomorg/z2h-dashboard-templates/package.json'));
|
|
38
|
+
const templatesRoot = path.join(catalogDir, 'templates');
|
|
39
|
+
if (!fs.existsSync(templatesRoot)) {
|
|
40
|
+
return [];
|
|
41
|
+
}
|
|
42
|
+
return fs
|
|
43
|
+
.readdirSync(templatesRoot, { withFileTypes: true })
|
|
44
|
+
.filter(entry => entry.isDirectory())
|
|
45
|
+
.flatMap(entry => {
|
|
46
|
+
const templateDir = path.join(templatesRoot, entry.name);
|
|
47
|
+
if (!fs.existsSync(path.join(templateDir, 'template.ts'))) {
|
|
48
|
+
return [];
|
|
49
|
+
}
|
|
50
|
+
const { template, configSchema, validateConfig } = loadTemplateModule(templateDir);
|
|
51
|
+
return [{ ...template, templateDir, configSchema, validateConfig }];
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export { findTemplate, loadDashboardTemplatesCatalog };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export type PatchedConfig = Record<string, unknown>;
|
|
2
|
+
export declare function patchOneFile(src: string, config: PatchedConfig): string | null;
|
|
3
|
+
/**
|
|
4
|
+
* Reads a built `.zth/build` directory, patches every MF entrypoint's config-object literal
|
|
5
|
+
* in place with real data, and writes the result to `outDir` (does NOT mutate `sourceBuildDir`
|
|
6
|
+
* — safe to call against a shared/reused prebuilt bundle). Throws if the placeholder shape
|
|
7
|
+
* isn't found in ANY entrypoint, since that means the anchor is stale and nothing was patched.
|
|
8
|
+
*/
|
|
9
|
+
export declare function patchBuiltBundle(sourceBuildDir: string, outDir: string, config: PatchedConfig): {
|
|
10
|
+
patchedFiles: string[];
|
|
11
|
+
};
|
|
12
|
+
//# sourceMappingURL=patch-bundle.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"patch-bundle.d.ts","sourceRoot":"","sources":["../../../../src/util/dashboard-templates/patch-bundle.ts"],"names":[],"mappings":"AAwBA,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAoDpD,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,GAAG,MAAM,GAAG,IAAI,CAO9E;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,cAAc,EAAE,MAAM,EACtB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,aAAa,GACpB;IAAE,YAAY,EAAE,MAAM,EAAE,CAAA;CAAE,CA+B5B"}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
|
|
4
|
+
// Swaps a template's placeholder config object directly into an ALREADY-BUILT MF bundle by
|
|
5
|
+
// string-patching the minified JS, instead of rerunning `z2h-cli build`. The config object is
|
|
6
|
+
// marked by a `/*! Z2H_CONFIG_V1 */` comment immediately before it — comments are inert to a
|
|
7
|
+
// minifier's dead-code elimination (unlike an object property, which gets stripped the moment
|
|
8
|
+
// nothing in the app statically reads it — see this package's README for how that bit us), and
|
|
9
|
+
// Terser's default `output.comments` setting (`some`) specifically preserves "bang" comments
|
|
10
|
+
// (`/*!` ...) while dropping ordinary ones, which is why the marker must use that exact form.
|
|
11
|
+
//
|
|
12
|
+
// Anchor is shape-agnostic by design: every template in @mondaydotcomorg/z2h-dashboard-templates'
|
|
13
|
+
// catalog must place this comment directly before its OWN placeholder config object, regardless
|
|
14
|
+
// of that template's real configSchema (which varies per template — title+widgets for one
|
|
15
|
+
// template, something else entirely for another) — see that package's README for the contract.
|
|
16
|
+
// This is the one constant every template shares, so this file needs no per-template logic and
|
|
17
|
+
// never reads any of the config's fields itself.
|
|
18
|
+
// Comment content collapses whitespace during minification (`/*!Z2H_CONFIG_V1*/` is also valid),
|
|
19
|
+
// hence \s* rather than a literal single space.
|
|
20
|
+
const ANCHOR_RE = /\/\*!\s*Z2H_CONFIG_V1\s*\*\//;
|
|
21
|
+
// The anchor comment sits immediately before the config object (`= /*! Z2H_CONFIG_V1 */ {...}`),
|
|
22
|
+
// so unlike a property-based anchor nested inside the object, this never needs to scan backward
|
|
23
|
+
// to find where the object starts — just forward from the end of the comment match to the next
|
|
24
|
+
// "{", then a standard string-aware brace-depth scan to its matching "}".
|
|
25
|
+
function findObjectAfterAnchor(src, anchorEnd) {
|
|
26
|
+
let start = anchorEnd;
|
|
27
|
+
while (start < src.length && src[start] !== '{') {
|
|
28
|
+
start++;
|
|
29
|
+
}
|
|
30
|
+
if (start >= src.length) {
|
|
31
|
+
throw new Error('patch-bundle: no "{" found after the anchor comment — anchor may be stale');
|
|
32
|
+
}
|
|
33
|
+
let braceDepth = 0;
|
|
34
|
+
let inString = false;
|
|
35
|
+
let quoteChar = '';
|
|
36
|
+
let end = -1;
|
|
37
|
+
for (let i = start; i < src.length; i++) {
|
|
38
|
+
const ch = src[i];
|
|
39
|
+
const prev = src[i - 1];
|
|
40
|
+
if (inString) {
|
|
41
|
+
if (ch === quoteChar && prev !== '\\') {
|
|
42
|
+
inString = false;
|
|
43
|
+
}
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
if (ch === '"' || ch === "'") {
|
|
47
|
+
inString = true;
|
|
48
|
+
quoteChar = ch;
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
if (ch === '{') {
|
|
52
|
+
braceDepth++;
|
|
53
|
+
}
|
|
54
|
+
else if (ch === '}') {
|
|
55
|
+
braceDepth--;
|
|
56
|
+
if (braceDepth === 0) {
|
|
57
|
+
end = i;
|
|
58
|
+
break;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
if (end === -1) {
|
|
63
|
+
throw new Error('patch-bundle: could not find matching "}" for the config object — malformed scan');
|
|
64
|
+
}
|
|
65
|
+
return { start, end: end + 1 };
|
|
66
|
+
}
|
|
67
|
+
// Finds the anchor comment and swaps its immediately-following object literal wholesale. Returns
|
|
68
|
+
// null if this particular source doesn't contain the anchor (not every MF entrypoint does; the
|
|
69
|
+
// caller decides whether that's fatal).
|
|
70
|
+
function patchOneFile(src, config) {
|
|
71
|
+
const match = ANCHOR_RE.exec(src);
|
|
72
|
+
if (match === null) {
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
const { start, end } = findObjectAfterAnchor(src, match.index + match[0].length);
|
|
76
|
+
return src.slice(0, start) + JSON.stringify(config) + src.slice(end);
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Reads a built `.zth/build` directory, patches every MF entrypoint's config-object literal
|
|
80
|
+
* in place with real data, and writes the result to `outDir` (does NOT mutate `sourceBuildDir`
|
|
81
|
+
* — safe to call against a shared/reused prebuilt bundle). Throws if the placeholder shape
|
|
82
|
+
* isn't found in ANY entrypoint, since that means the anchor is stale and nothing was patched.
|
|
83
|
+
*/
|
|
84
|
+
function patchBuiltBundle(sourceBuildDir, outDir, config) {
|
|
85
|
+
const manifestPath = path.join(sourceBuildDir, 'asset-manifest.json');
|
|
86
|
+
const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
|
|
87
|
+
const jsEntries = [...manifest.entrypoints, ...manifest.nonExternalsEntrypoints].filter(f => f.endsWith('.js'));
|
|
88
|
+
fs.rmSync(outDir, { recursive: true, force: true });
|
|
89
|
+
fs.cpSync(sourceBuildDir, outDir, { recursive: true });
|
|
90
|
+
const patchedFiles = [];
|
|
91
|
+
for (const rel of jsEntries) {
|
|
92
|
+
const outPath = path.join(outDir, rel);
|
|
93
|
+
const src = fs.readFileSync(outPath, 'utf8');
|
|
94
|
+
const patched = patchOneFile(src, config);
|
|
95
|
+
if (patched === null) {
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
new Function(patched); // throws SyntaxError if the patch produced malformed JS — fail loud, not silently
|
|
99
|
+
fs.writeFileSync(outPath, patched);
|
|
100
|
+
patchedFiles.push(rel);
|
|
101
|
+
}
|
|
102
|
+
if (patchedFiles.length === 0) {
|
|
103
|
+
throw new Error(`patch-bundle: patched 0 of ${jsEntries.length} entrypoint(s) — anchor ${ANCHOR_RE} not found in any of them`);
|
|
104
|
+
}
|
|
105
|
+
return { patchedFiles };
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export { patchBuiltBundle, patchOneFile };
|
package/dist/index.js
CHANGED
|
@@ -11,6 +11,8 @@ const commands_delete = require('./commands/delete.js');
|
|
|
11
11
|
const commands_grant = require('./commands/grant.js');
|
|
12
12
|
const commands_createWorkspace = require('./commands/create-workspace.js');
|
|
13
13
|
const commands_create = require('./commands/create.js');
|
|
14
|
+
const commands_generate = require('./commands/generate.js');
|
|
15
|
+
const commands_templates = require('./commands/templates.js');
|
|
14
16
|
const commands_generateZ2hToken = require('./commands/generate-z2h-token.js');
|
|
15
17
|
const commands_migrate = require('./commands/migrate.js');
|
|
16
18
|
const commands_tag = require('./commands/tag.js');
|
|
@@ -96,6 +98,7 @@ async function main() {
|
|
|
96
98
|
.option('--remote <type>', 'First deploy only: source control remote to initialise — s3 (shared storage, recommended, auto-backed-up) or github (manage it yourself in your own repo). Error if the app already has a git remote.')
|
|
97
99
|
.option('--repo-url <url>', 'First deploy only: GitHub repo URL — required when --remote=github. Error if the app already has a git remote.')
|
|
98
100
|
.option('--description <text>', 'short (<=200 char) description of the app')
|
|
101
|
+
.option('--prebuilt-dir <path>', 'internal — used by `generate-app-template`: skip the build step and deploy this already-built directory as-is')
|
|
99
102
|
.action(util_runCommand.runCommand({
|
|
100
103
|
// A preview is a real deploy for observability, tracked as its own event since
|
|
101
104
|
// the command name alone (`deploy`) can't distinguish it from a live deploy.
|
|
@@ -123,7 +126,7 @@ async function main() {
|
|
|
123
126
|
.action(util_runCommand.runCommand({}, (opts) => commands_generateZ2hToken.generateZ2HTokenCommand(opts)));
|
|
124
127
|
program
|
|
125
128
|
.command('create <app-name>')
|
|
126
|
-
.description(`Scaffold a
|
|
129
|
+
.description(`Scaffold a blank Z2H consumer app inside ${util_workspace.getWorkspaceHome()}/ using a built-in template (default | html-embed). If a catalog template already fits what you're building, use \`generate-app-template\` instead.`)
|
|
127
130
|
.option('--template <name>', 'Template name (default | html-embed)')
|
|
128
131
|
.option('--html-file <path>', 'Path to an HTML file to embed (implies --template html-embed)')
|
|
129
132
|
.option('--remote <type>', 'Source control remote: s3 (shared storage, recommended, auto-backed-up) or github (manage it yourself in your own repo)')
|
|
@@ -135,6 +138,18 @@ async function main() {
|
|
|
135
138
|
remote: opts.remote ?? 'unknown',
|
|
136
139
|
}),
|
|
137
140
|
}, (appName, opts) => commands_create.createCommand(appName, opts)));
|
|
141
|
+
program
|
|
142
|
+
.command('templates')
|
|
143
|
+
.description("List the BigBrain Studio (Z2H) template catalog — id, title, description, and each template's widget schema")
|
|
144
|
+
.action(util_runCommand.runCommand({}, () => commands_templates.templatesCommand()));
|
|
145
|
+
program
|
|
146
|
+
.command('generate-app-template <app-name>')
|
|
147
|
+
.description(`Scaffold + preview a Z2H app/dashboard from a templates catalog entry inside ${util_workspace.getWorkspaceHome()}/ — copies a prebuilt template, patches in real widget data, and deploys a preview. No build, no yarn install, no live deploy — run \`z2h-cli deploy\` yourself from the app dir once you're happy with it.`)
|
|
148
|
+
.requiredOption('--template <id>', 'catalog template id — see `z2h-cli templates --json`')
|
|
149
|
+
.requiredOption('--input <json>', "JSON string — shape is template-defined, validated wholesale against the template's configSchema (see `z2h-cli templates --json`)")
|
|
150
|
+
.action(util_runCommand.runCommand({
|
|
151
|
+
data: ([appName, opts]) => ({ app_name: appName, template: opts.template }),
|
|
152
|
+
}, (appName, opts) => commands_generate.generateCommand(appName, opts)));
|
|
138
153
|
program
|
|
139
154
|
.command('edit <app-name>')
|
|
140
155
|
.description(`Pull the latest version of an app into ${util_workspace.getWorkspaceHome()}/<app-name>, cloning it first if needed`)
|
package/dist/util/app-name.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
2
|
|
|
3
|
-
const
|
|
3
|
+
const fs = require('node:fs');
|
|
4
4
|
const constants = require('../constants.js');
|
|
5
5
|
|
|
6
6
|
/**
|
|
@@ -12,7 +12,7 @@ function cleanAppName(name) {
|
|
|
12
12
|
}
|
|
13
13
|
function getCwdAppName() {
|
|
14
14
|
try {
|
|
15
|
-
return JSON.parse(
|
|
15
|
+
return JSON.parse(fs.readFileSync('package.json', 'utf8')).name;
|
|
16
16
|
}
|
|
17
17
|
catch {
|
|
18
18
|
return undefined;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export type ValidateConfigResult = {
|
|
2
|
+
success: true;
|
|
3
|
+
data: unknown;
|
|
4
|
+
} | {
|
|
5
|
+
success: false;
|
|
6
|
+
error: string;
|
|
7
|
+
};
|
|
8
|
+
export interface DashboardTemplateEntry {
|
|
9
|
+
id: string;
|
|
10
|
+
title: string;
|
|
11
|
+
description: string;
|
|
12
|
+
/** Absolute path to this template's dir — source + its already-built .zth/build. */
|
|
13
|
+
templateDir: string;
|
|
14
|
+
/** JSON Schema for this template's whole `--input` config object — shape is template-defined. */
|
|
15
|
+
configSchema: Record<string, unknown>;
|
|
16
|
+
/** Validates --input against this template's actual zod schema — the JSON Schema above is
|
|
17
|
+
* display-only (catalog listing), this is what `generate` really validates against. */
|
|
18
|
+
validateConfig: (input: unknown) => ValidateConfigResult;
|
|
19
|
+
}
|
|
20
|
+
export declare function findTemplate(id: string): DashboardTemplateEntry;
|
|
21
|
+
export declare function loadDashboardTemplatesCatalog(): DashboardTemplateEntry[];
|
|
22
|
+
//# sourceMappingURL=load-catalog.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"load-catalog.d.ts","sourceRoot":"","sources":["../../../src/util/dashboard-templates/load-catalog.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,oBAAoB,GAAG;IAAE,OAAO,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAE,GAAG;IAAE,OAAO,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAExG,MAAM,WAAW,sBAAsB;IACrC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,oFAAoF;IACpF,WAAW,EAAE,MAAM,CAAC;IACpB,iGAAiG;IACjG,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACtC;4FACwF;IACxF,cAAc,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,oBAAoB,CAAC;CAC1D;AA+BD,wBAAgB,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,sBAAsB,CAQ/D;AAED,wBAAgB,6BAA6B,IAAI,sBAAsB,EAAE,CAoBxE"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
+
|
|
3
|
+
const path = require('node:path');
|
|
4
|
+
const fs = require('node:fs');
|
|
5
|
+
const node_module = require('node:module');
|
|
6
|
+
const zod = require('zod');
|
|
7
|
+
|
|
8
|
+
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
9
|
+
const _interopDefault = e => e && e.__esModule ? e : { default: e };
|
|
10
|
+
|
|
11
|
+
const path__default = /*#__PURE__*/_interopDefault(path);
|
|
12
|
+
const fs__default = /*#__PURE__*/_interopDefault(fs);
|
|
13
|
+
|
|
14
|
+
// Each template defines its catalog metadata and its config shape once, in template.ts (compiled
|
|
15
|
+
// to dist/template.js by dashboard-templates' build script) — the JSON Schema used for catalog
|
|
16
|
+
// listing is derived from its zod configSchema here rather than hand-duplicated as a separate JSON
|
|
17
|
+
// literal, and --input validation goes through the same zod schema directly (see validateConfig),
|
|
18
|
+
// so the schema and the TS types templates' own hooks import can never drift apart.
|
|
19
|
+
function loadTemplateModule(templateDir) {
|
|
20
|
+
const templateModulePath = path__default.default.join(templateDir, 'dist', 'template.js');
|
|
21
|
+
const { template, configSchema } = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('util/dashboard-templates/load-catalog.js', document.baseURI).href)))(templateModulePath);
|
|
22
|
+
return {
|
|
23
|
+
template,
|
|
24
|
+
// draft-7 is arbitrary here (nothing re-validates against it) — just a reasonably standard,
|
|
25
|
+
// widely-understood dialect for whatever reads `templates --json`'s output.
|
|
26
|
+
configSchema: zod.z.toJSONSchema(configSchema, { target: 'draft-7' }),
|
|
27
|
+
validateConfig: input => {
|
|
28
|
+
const result = configSchema.safeParse(input);
|
|
29
|
+
return result.success
|
|
30
|
+
? { success: true, data: result.data }
|
|
31
|
+
: { success: false, error: zod.z.prettifyError(result.error) };
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
function findTemplate(id) {
|
|
36
|
+
const templates = loadDashboardTemplatesCatalog();
|
|
37
|
+
const template = templates.find(t => t.id === id);
|
|
38
|
+
if (!template) {
|
|
39
|
+
const known = templates.map(t => t.id).join(', ') || '(none)';
|
|
40
|
+
throw new Error(`Unknown template "${id}". Available: ${known}.`);
|
|
41
|
+
}
|
|
42
|
+
return template;
|
|
43
|
+
}
|
|
44
|
+
function loadDashboardTemplatesCatalog() {
|
|
45
|
+
const catalogDir = path__default.default.dirname(node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('util/dashboard-templates/load-catalog.js', document.baseURI).href))).resolve('@mondaydotcomorg/z2h-dashboard-templates/package.json'));
|
|
46
|
+
const templatesRoot = path__default.default.join(catalogDir, 'templates');
|
|
47
|
+
if (!fs__default.default.existsSync(templatesRoot)) {
|
|
48
|
+
return [];
|
|
49
|
+
}
|
|
50
|
+
return fs__default.default
|
|
51
|
+
.readdirSync(templatesRoot, { withFileTypes: true })
|
|
52
|
+
.filter(entry => entry.isDirectory())
|
|
53
|
+
.flatMap(entry => {
|
|
54
|
+
const templateDir = path__default.default.join(templatesRoot, entry.name);
|
|
55
|
+
if (!fs__default.default.existsSync(path__default.default.join(templateDir, 'template.ts'))) {
|
|
56
|
+
return [];
|
|
57
|
+
}
|
|
58
|
+
const { template, configSchema, validateConfig } = loadTemplateModule(templateDir);
|
|
59
|
+
return [{ ...template, templateDir, configSchema, validateConfig }];
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
exports.findTemplate = findTemplate;
|
|
64
|
+
exports.loadDashboardTemplatesCatalog = loadDashboardTemplatesCatalog;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export type PatchedConfig = Record<string, unknown>;
|
|
2
|
+
export declare function patchOneFile(src: string, config: PatchedConfig): string | null;
|
|
3
|
+
/**
|
|
4
|
+
* Reads a built `.zth/build` directory, patches every MF entrypoint's config-object literal
|
|
5
|
+
* in place with real data, and writes the result to `outDir` (does NOT mutate `sourceBuildDir`
|
|
6
|
+
* — safe to call against a shared/reused prebuilt bundle). Throws if the placeholder shape
|
|
7
|
+
* isn't found in ANY entrypoint, since that means the anchor is stale and nothing was patched.
|
|
8
|
+
*/
|
|
9
|
+
export declare function patchBuiltBundle(sourceBuildDir: string, outDir: string, config: PatchedConfig): {
|
|
10
|
+
patchedFiles: string[];
|
|
11
|
+
};
|
|
12
|
+
//# sourceMappingURL=patch-bundle.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"patch-bundle.d.ts","sourceRoot":"","sources":["../../../src/util/dashboard-templates/patch-bundle.ts"],"names":[],"mappings":"AAwBA,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAoDpD,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,GAAG,MAAM,GAAG,IAAI,CAO9E;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,cAAc,EAAE,MAAM,EACtB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,aAAa,GACpB;IAAE,YAAY,EAAE,MAAM,EAAE,CAAA;CAAE,CA+B5B"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
+
|
|
3
|
+
const fs = require('node:fs');
|
|
4
|
+
const path = require('node:path');
|
|
5
|
+
|
|
6
|
+
const _interopDefault = e => e && e.__esModule ? e : { default: e };
|
|
7
|
+
|
|
8
|
+
const fs__default = /*#__PURE__*/_interopDefault(fs);
|
|
9
|
+
const path__default = /*#__PURE__*/_interopDefault(path);
|
|
10
|
+
|
|
11
|
+
// Swaps a template's placeholder config object directly into an ALREADY-BUILT MF bundle by
|
|
12
|
+
// string-patching the minified JS, instead of rerunning `z2h-cli build`. The config object is
|
|
13
|
+
// marked by a `/*! Z2H_CONFIG_V1 */` comment immediately before it — comments are inert to a
|
|
14
|
+
// minifier's dead-code elimination (unlike an object property, which gets stripped the moment
|
|
15
|
+
// nothing in the app statically reads it — see this package's README for how that bit us), and
|
|
16
|
+
// Terser's default `output.comments` setting (`some`) specifically preserves "bang" comments
|
|
17
|
+
// (`/*!` ...) while dropping ordinary ones, which is why the marker must use that exact form.
|
|
18
|
+
//
|
|
19
|
+
// Anchor is shape-agnostic by design: every template in @mondaydotcomorg/z2h-dashboard-templates'
|
|
20
|
+
// catalog must place this comment directly before its OWN placeholder config object, regardless
|
|
21
|
+
// of that template's real configSchema (which varies per template — title+widgets for one
|
|
22
|
+
// template, something else entirely for another) — see that package's README for the contract.
|
|
23
|
+
// This is the one constant every template shares, so this file needs no per-template logic and
|
|
24
|
+
// never reads any of the config's fields itself.
|
|
25
|
+
// Comment content collapses whitespace during minification (`/*!Z2H_CONFIG_V1*/` is also valid),
|
|
26
|
+
// hence \s* rather than a literal single space.
|
|
27
|
+
const ANCHOR_RE = /\/\*!\s*Z2H_CONFIG_V1\s*\*\//;
|
|
28
|
+
// The anchor comment sits immediately before the config object (`= /*! Z2H_CONFIG_V1 */ {...}`),
|
|
29
|
+
// so unlike a property-based anchor nested inside the object, this never needs to scan backward
|
|
30
|
+
// to find where the object starts — just forward from the end of the comment match to the next
|
|
31
|
+
// "{", then a standard string-aware brace-depth scan to its matching "}".
|
|
32
|
+
function findObjectAfterAnchor(src, anchorEnd) {
|
|
33
|
+
let start = anchorEnd;
|
|
34
|
+
while (start < src.length && src[start] !== '{') {
|
|
35
|
+
start++;
|
|
36
|
+
}
|
|
37
|
+
if (start >= src.length) {
|
|
38
|
+
throw new Error('patch-bundle: no "{" found after the anchor comment — anchor may be stale');
|
|
39
|
+
}
|
|
40
|
+
let braceDepth = 0;
|
|
41
|
+
let inString = false;
|
|
42
|
+
let quoteChar = '';
|
|
43
|
+
let end = -1;
|
|
44
|
+
for (let i = start; i < src.length; i++) {
|
|
45
|
+
const ch = src[i];
|
|
46
|
+
const prev = src[i - 1];
|
|
47
|
+
if (inString) {
|
|
48
|
+
if (ch === quoteChar && prev !== '\\') {
|
|
49
|
+
inString = false;
|
|
50
|
+
}
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
if (ch === '"' || ch === "'") {
|
|
54
|
+
inString = true;
|
|
55
|
+
quoteChar = ch;
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
if (ch === '{') {
|
|
59
|
+
braceDepth++;
|
|
60
|
+
}
|
|
61
|
+
else if (ch === '}') {
|
|
62
|
+
braceDepth--;
|
|
63
|
+
if (braceDepth === 0) {
|
|
64
|
+
end = i;
|
|
65
|
+
break;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
if (end === -1) {
|
|
70
|
+
throw new Error('patch-bundle: could not find matching "}" for the config object — malformed scan');
|
|
71
|
+
}
|
|
72
|
+
return { start, end: end + 1 };
|
|
73
|
+
}
|
|
74
|
+
// Finds the anchor comment and swaps its immediately-following object literal wholesale. Returns
|
|
75
|
+
// null if this particular source doesn't contain the anchor (not every MF entrypoint does; the
|
|
76
|
+
// caller decides whether that's fatal).
|
|
77
|
+
function patchOneFile(src, config) {
|
|
78
|
+
const match = ANCHOR_RE.exec(src);
|
|
79
|
+
if (match === null) {
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
const { start, end } = findObjectAfterAnchor(src, match.index + match[0].length);
|
|
83
|
+
return src.slice(0, start) + JSON.stringify(config) + src.slice(end);
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Reads a built `.zth/build` directory, patches every MF entrypoint's config-object literal
|
|
87
|
+
* in place with real data, and writes the result to `outDir` (does NOT mutate `sourceBuildDir`
|
|
88
|
+
* — safe to call against a shared/reused prebuilt bundle). Throws if the placeholder shape
|
|
89
|
+
* isn't found in ANY entrypoint, since that means the anchor is stale and nothing was patched.
|
|
90
|
+
*/
|
|
91
|
+
function patchBuiltBundle(sourceBuildDir, outDir, config) {
|
|
92
|
+
const manifestPath = path__default.default.join(sourceBuildDir, 'asset-manifest.json');
|
|
93
|
+
const manifest = JSON.parse(fs__default.default.readFileSync(manifestPath, 'utf8'));
|
|
94
|
+
const jsEntries = [...manifest.entrypoints, ...manifest.nonExternalsEntrypoints].filter(f => f.endsWith('.js'));
|
|
95
|
+
fs__default.default.rmSync(outDir, { recursive: true, force: true });
|
|
96
|
+
fs__default.default.cpSync(sourceBuildDir, outDir, { recursive: true });
|
|
97
|
+
const patchedFiles = [];
|
|
98
|
+
for (const rel of jsEntries) {
|
|
99
|
+
const outPath = path__default.default.join(outDir, rel);
|
|
100
|
+
const src = fs__default.default.readFileSync(outPath, 'utf8');
|
|
101
|
+
const patched = patchOneFile(src, config);
|
|
102
|
+
if (patched === null) {
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
new Function(patched); // throws SyntaxError if the patch produced malformed JS — fail loud, not silently
|
|
106
|
+
fs__default.default.writeFileSync(outPath, patched);
|
|
107
|
+
patchedFiles.push(rel);
|
|
108
|
+
}
|
|
109
|
+
if (patchedFiles.length === 0) {
|
|
110
|
+
throw new Error(`patch-bundle: patched 0 of ${jsEntries.length} entrypoint(s) — anchor ${ANCHOR_RE} not found in any of them`);
|
|
111
|
+
}
|
|
112
|
+
return { patchedFiles };
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
exports.patchBuiltBundle = patchBuiltBundle;
|
|
116
|
+
exports.patchOneFile = patchOneFile;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mondaydotcomorg/z2h-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.26.0",
|
|
4
4
|
"bin": "./bin/z2h-cli.js",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -51,6 +51,7 @@
|
|
|
51
51
|
],
|
|
52
52
|
"dependencies": {
|
|
53
53
|
"@aws-sdk/client-s3": "^3.706.0",
|
|
54
|
+
"@mondaydotcomorg/z2h-dashboard-templates": "^0.3.0",
|
|
54
55
|
"@mondaydotcomorg/z2h-shared-utils": "^0.4.3",
|
|
55
56
|
"chokidar": "^3.6.0",
|
|
56
57
|
"commander": "^12.1.0",
|
|
@@ -62,7 +63,8 @@
|
|
|
62
63
|
"p-map": "^7.0.2",
|
|
63
64
|
"picocolors": "^1.1.1",
|
|
64
65
|
"semver": "^7.6.0",
|
|
65
|
-
"tsx": "^4.19.2"
|
|
66
|
+
"tsx": "^4.19.2",
|
|
67
|
+
"zod": "^4.1.11"
|
|
66
68
|
},
|
|
67
69
|
"devDependencies": {
|
|
68
70
|
"@mondaydotcomorg/trident-library": "^1.2.7",
|
package/src/commands/deploy.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import os from 'node:os';
|
|
2
|
-
import
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { copy, ensureDir, readJson } from 'fs-extra';
|
|
3
4
|
import { info, warn, output, getOutputMode } from '../util/logger';
|
|
4
5
|
import { resolveConsumerPaths } from '../shadow/paths';
|
|
5
6
|
import { fetchAppTags, fetchTagCatalog, setAppTags } from '../util/tags';
|
|
@@ -27,7 +28,7 @@ import { deployBackend } from './backend';
|
|
|
27
28
|
import { buildCommand } from './build';
|
|
28
29
|
import { promptForTags } from './tag';
|
|
29
30
|
import type { ConsumerPaths, DeployFailureReason } from '../types';
|
|
30
|
-
import type { ManifestEntry } from '../util/manifest';
|
|
31
|
+
import type { ManifestEntry, AssetManifestFile } from '../util/manifest';
|
|
31
32
|
|
|
32
33
|
/** Who is publishing this version — the machine identity, else the OS user. */
|
|
33
34
|
function whoDeployed(): string {
|
|
@@ -42,6 +43,10 @@ export interface DeployOptions {
|
|
|
42
43
|
preview?: boolean;
|
|
43
44
|
open?: boolean;
|
|
44
45
|
description?: string;
|
|
46
|
+
// Used by `generate-app-template`: skip `buildCommand()` entirely and reuse this
|
|
47
|
+
// already-built (string-patched) directory as the shadow build output instead. Only ever
|
|
48
|
+
// populated by the generate pipeline — never set on a normal human/CI deploy.
|
|
49
|
+
prebuiltDir?: string;
|
|
45
50
|
}
|
|
46
51
|
|
|
47
52
|
interface DeployContext {
|
|
@@ -91,8 +96,16 @@ async function buildAndStamp(opts: {
|
|
|
91
96
|
publicUrl: string;
|
|
92
97
|
nextVersion: number;
|
|
93
98
|
gitRemote: string;
|
|
99
|
+
prebuiltDir?: string;
|
|
94
100
|
}): Promise<ManifestEntry> {
|
|
95
|
-
|
|
101
|
+
let assetManifest: AssetManifestFile;
|
|
102
|
+
if (opts.prebuiltDir) {
|
|
103
|
+
info(`skipping build — reusing prebuilt bundle from ${opts.prebuiltDir}`);
|
|
104
|
+
await copy(opts.prebuiltDir, opts.paths.shadowBuild, { overwrite: true });
|
|
105
|
+
assetManifest = await readJson(path.join(opts.paths.shadowBuild, 'asset-manifest.json'));
|
|
106
|
+
} else {
|
|
107
|
+
({ assetManifest } = await buildCommand({ publicUrl: opts.publicUrl }));
|
|
108
|
+
}
|
|
96
109
|
const deployedBy = whoDeployed();
|
|
97
110
|
|
|
98
111
|
return {
|
|
@@ -156,7 +169,13 @@ async function deployPreview({ paths, consumerName, appName, token, opts }: Depl
|
|
|
156
169
|
const nextVersion = (await fetchDeployVersion(previewAppName)) + 1;
|
|
157
170
|
|
|
158
171
|
info('building');
|
|
159
|
-
const entry = await buildAndStamp({
|
|
172
|
+
const entry = await buildAndStamp({
|
|
173
|
+
paths,
|
|
174
|
+
publicUrl: url,
|
|
175
|
+
nextVersion,
|
|
176
|
+
gitRemote: '',
|
|
177
|
+
prebuiltDir: opts.prebuiltDir,
|
|
178
|
+
});
|
|
160
179
|
|
|
161
180
|
info('getting sts credentials');
|
|
162
181
|
const creds = await brokerCredentialProvider({ appName: previewAppName, previewId })();
|
|
@@ -245,7 +264,7 @@ async function deployLive({ paths, consumerName, appName, token, opts }: DeployC
|
|
|
245
264
|
const url = `${BUCKET_READ_DNS_URL}/${keyPrefix}`;
|
|
246
265
|
|
|
247
266
|
info('building');
|
|
248
|
-
const entry = await buildAndStamp({ paths, publicUrl: url, nextVersion, gitRemote });
|
|
267
|
+
const entry = await buildAndStamp({ paths, publicUrl: url, nextVersion, gitRemote, prebuiltDir: opts.prebuiltDir });
|
|
249
268
|
|
|
250
269
|
if (opts.dryRun) {
|
|
251
270
|
output(`[z2h-cli] dry-run: would upload to s3://${BUCKET_WRITE_NAME}/${keyPrefix}/ as v${version}`, {
|