@mondaydotcomorg/z2h-cli 0.2.0 → 0.3.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.
- package/dist/commands/create-workspace.js +3 -3
- package/dist/commands/create.d.ts.map +1 -1
- package/dist/commands/create.js +10 -3
- package/dist/commands/deploy.d.ts.map +1 -1
- package/dist/commands/deploy.js +19 -24
- package/dist/commands/generate-z2h-token.d.ts +16 -0
- package/dist/commands/generate-z2h-token.d.ts.map +1 -0
- package/dist/commands/generate-z2h-token.js +107 -0
- package/dist/constants.d.ts +8 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +28 -0
- package/dist/esm/commands/create-workspace.mjs +3 -3
- package/dist/esm/commands/create.d.ts.map +1 -1
- package/dist/esm/commands/create.mjs +10 -3
- package/dist/esm/commands/deploy.d.ts.map +1 -1
- package/dist/esm/commands/deploy.mjs +16 -21
- package/dist/esm/commands/generate-z2h-token.d.ts +16 -0
- package/dist/esm/commands/generate-z2h-token.d.ts.map +1 -0
- package/dist/esm/commands/generate-z2h-token.mjs +99 -0
- package/dist/esm/constants.d.ts +8 -0
- package/dist/esm/constants.d.ts.map +1 -1
- package/dist/esm/constants.mjs +21 -1
- package/dist/esm/index.mjs +18 -1
- package/dist/esm/util/auth/__tests__/auth-store.test.d.ts +2 -0
- package/dist/esm/util/auth/__tests__/auth-store.test.d.ts.map +1 -0
- package/dist/esm/util/auth/__tests__/broker-credential-provider.test.d.ts +2 -0
- package/dist/esm/util/auth/__tests__/broker-credential-provider.test.d.ts.map +1 -0
- package/dist/esm/util/auth/__tests__/loopback-server.test.d.ts +2 -0
- package/dist/esm/util/auth/__tests__/loopback-server.test.d.ts.map +1 -0
- package/dist/esm/util/auth/__tests__/write-auth.test.d.ts +2 -0
- package/dist/esm/util/auth/__tests__/write-auth.test.d.ts.map +1 -0
- package/dist/esm/util/auth/auth-store.d.ts +11 -0
- package/dist/esm/util/auth/auth-store.d.ts.map +1 -0
- package/dist/esm/util/auth/auth-store.mjs +29 -0
- package/dist/esm/util/auth/broker-credential-provider.d.ts +12 -0
- package/dist/esm/util/auth/broker-credential-provider.d.ts.map +1 -0
- package/dist/esm/util/auth/broker-credential-provider.mjs +76 -0
- package/dist/esm/util/auth/loopback-server.d.ts +12 -0
- package/dist/esm/util/auth/loopback-server.d.ts.map +1 -0
- package/dist/esm/util/auth/loopback-server.mjs +87 -0
- package/dist/esm/util/auth/write-auth.d.ts +11 -0
- package/dist/esm/util/auth/write-auth.d.ts.map +1 -0
- package/dist/esm/util/auth/write-auth.mjs +22 -0
- package/dist/esm/util/manifest.d.ts.map +1 -1
- package/dist/esm/util/manifest.mjs +2 -1
- package/dist/esm/util/s3/client.d.ts +7 -8
- package/dist/esm/util/s3/client.d.ts.map +1 -1
- package/dist/esm/util/s3/client.mjs +15 -30
- package/dist/esm/util/s3/upload.d.ts.map +1 -1
- package/dist/esm/util/s3/upload.mjs +2 -1
- package/dist/index.js +19 -1
- package/dist/util/auth/__tests__/auth-store.test.d.ts +2 -0
- package/dist/util/auth/__tests__/auth-store.test.d.ts.map +1 -0
- package/dist/util/auth/__tests__/broker-credential-provider.test.d.ts +2 -0
- package/dist/util/auth/__tests__/broker-credential-provider.test.d.ts.map +1 -0
- package/dist/util/auth/__tests__/loopback-server.test.d.ts +2 -0
- package/dist/util/auth/__tests__/loopback-server.test.d.ts.map +1 -0
- package/dist/util/auth/__tests__/write-auth.test.d.ts +2 -0
- package/dist/util/auth/__tests__/write-auth.test.d.ts.map +1 -0
- package/dist/util/auth/auth-store.d.ts +11 -0
- package/dist/util/auth/auth-store.d.ts.map +1 -0
- package/dist/util/auth/auth-store.js +39 -0
- package/dist/util/auth/broker-credential-provider.d.ts +12 -0
- package/dist/util/auth/broker-credential-provider.d.ts.map +1 -0
- package/dist/util/auth/broker-credential-provider.js +80 -0
- package/dist/util/auth/loopback-server.d.ts +12 -0
- package/dist/util/auth/loopback-server.d.ts.map +1 -0
- package/dist/util/auth/loopback-server.js +94 -0
- package/dist/util/auth/write-auth.d.ts +11 -0
- package/dist/util/auth/write-auth.d.ts.map +1 -0
- package/dist/util/auth/write-auth.js +26 -0
- package/dist/util/manifest.d.ts.map +1 -1
- package/dist/util/manifest.js +5 -4
- package/dist/util/s3/client.d.ts +7 -8
- package/dist/util/s3/client.d.ts.map +1 -1
- package/dist/util/s3/client.js +14 -36
- package/dist/util/s3/upload.d.ts.map +1 -1
- package/dist/util/s3/upload.js +2 -1
- package/package.json +10 -1
- package/src/commands/__tests__/create-workspace.test.ts +1 -1
- package/src/commands/__tests__/create.test.ts +1 -5
- package/src/commands/create-workspace.ts +3 -3
- package/src/commands/create.ts +12 -3
- package/src/commands/deploy.ts +18 -31
- package/src/commands/generate-z2h-token.ts +124 -0
- package/src/constants.ts +25 -0
- package/src/index.ts +21 -1
- package/src/util/auth/__tests__/auth-store.test.ts +50 -0
- package/src/util/auth/__tests__/broker-credential-provider.test.ts +115 -0
- package/src/util/auth/__tests__/loopback-server.test.ts +85 -0
- package/src/util/auth/__tests__/write-auth.test.ts +79 -0
- package/src/util/auth/auth-store.ts +31 -0
- package/src/util/auth/broker-credential-provider.ts +93 -0
- package/src/util/auth/loopback-server.ts +103 -0
- package/src/util/auth/write-auth.ts +24 -0
- package/src/util/manifest.ts +2 -1
- package/src/util/s3/client.ts +15 -32
- package/src/util/s3/upload.ts +2 -1
|
@@ -37,7 +37,7 @@ async function createWorkspaceCommand(opts) {
|
|
|
37
37
|
if (await fsExtra.pathExists(home)) {
|
|
38
38
|
const entries = await fsExtra.readdir(home);
|
|
39
39
|
if (entries.length > 0) {
|
|
40
|
-
throw new Error(
|
|
40
|
+
throw new Error(`Workspace already exists at ${home}. Remove it and try again.`);
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
43
|
else {
|
|
@@ -66,12 +66,12 @@ async function createWorkspaceCommand(opts) {
|
|
|
66
66
|
fsExtra.copy(path__default.default.join(wsTemplatesDir, 'README.md'), path__default.default.join(home, 'README.md')),
|
|
67
67
|
fsExtra.copy(path__default.default.join(wsTemplatesDir, 'yarn-releases', 'yarn-4.5.1.cjs'), path__default.default.join(home, '.yarn', 'releases', 'yarn-4.5.1.cjs')),
|
|
68
68
|
]);
|
|
69
|
-
util_logger.info(`
|
|
69
|
+
util_logger.info(`setting up your Z2H workspace — this may take a minute...`);
|
|
70
70
|
await execa.execa('yarn', ['install'], {
|
|
71
71
|
cwd: home,
|
|
72
72
|
stdio: 'inherit',
|
|
73
73
|
});
|
|
74
|
-
util_logger.output(`
|
|
74
|
+
util_logger.output(`Your workspace is ready! 🚀 Apps will live at ${home}`, {
|
|
75
75
|
ok: true,
|
|
76
76
|
workspace: home,
|
|
77
77
|
z2hCliVersion: cliVersion,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../src/commands/create.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../src/commands/create.ts"],"names":[],"mappings":"AAWA,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AA6BD,wBAAsB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAqFvF"}
|
package/dist/commands/create.js
CHANGED
|
@@ -9,12 +9,16 @@ const util_workspace = require('../util/workspace.js');
|
|
|
9
9
|
const util_templates = require('../util/templates.js');
|
|
10
10
|
const util_manifest = require('../util/manifest.js');
|
|
11
11
|
const util_appName = require('../util/app-name.js');
|
|
12
|
+
const constants = require('../constants.js');
|
|
12
13
|
|
|
13
14
|
const _interopDefault = e => e && e.__esModule ? e : { default: e };
|
|
14
15
|
|
|
15
16
|
const path__default = /*#__PURE__*/_interopDefault(path);
|
|
16
17
|
|
|
17
|
-
|
|
18
|
+
// Names reserved by the host MF (mf-bigbrain-zth) for platform pages under
|
|
19
|
+
// /bigbrain-vibe/<name>. Creating an app with one of these would shadow the
|
|
20
|
+
// platform page in the URL, so we refuse upfront.
|
|
21
|
+
const RESERVED_APP_NAMES = new Set(['generate-z2h-token']);
|
|
18
22
|
/**
|
|
19
23
|
* Convert kebab-case to PascalCase. `demo-app` → `DemoApp`.
|
|
20
24
|
*/
|
|
@@ -42,7 +46,10 @@ async function createCommand(appName, opts) {
|
|
|
42
46
|
// Validate workspace.
|
|
43
47
|
const workspace = await util_workspace.assertWorkspace();
|
|
44
48
|
// Validate app name.
|
|
45
|
-
if (
|
|
49
|
+
if (RESERVED_APP_NAMES.has(appName)) {
|
|
50
|
+
throw new Error(`App name "${appName}" is reserved by the Z2H host for a platform page under /bigbrain-vibe/${appName}. Pick a different name.`);
|
|
51
|
+
}
|
|
52
|
+
if (!constants.APP_NAME_PATTERN.test(appName)) {
|
|
46
53
|
throw new Error(`App name "${appName}" is invalid. Use lowercase kebab-case (a-z, 0-9, -), ` +
|
|
47
54
|
`2-50 chars, starting with a letter.`);
|
|
48
55
|
}
|
|
@@ -88,7 +95,7 @@ async function createCommand(appName, opts) {
|
|
|
88
95
|
if (template === 'html-embed' && opts.htmlFile) {
|
|
89
96
|
await fsExtra.copy(opts.htmlFile, path__default.default.join(appDir, 'src', 'page.html'));
|
|
90
97
|
}
|
|
91
|
-
util_logger.info(`installing
|
|
98
|
+
util_logger.info(`installing dependencies for ${appName}...`);
|
|
92
99
|
await execa.execa('yarn', ['install'], {
|
|
93
100
|
cwd: workspace,
|
|
94
101
|
stdio: 'inherit',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deploy.d.ts","sourceRoot":"","sources":["../../src/commands/deploy.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"deploy.d.ts","sourceRoot":"","sources":["../../src/commands/deploy.ts"],"names":[],"mappings":"AAoBA,MAAM,WAAW,aAAa;IAC5B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,wBAAsB,aAAa,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CA+EtE"}
|
package/dist/commands/deploy.js
CHANGED
|
@@ -3,12 +3,13 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
3
3
|
const path = require('node:path');
|
|
4
4
|
const os = require('node:os');
|
|
5
5
|
const fsExtra = require('fs-extra');
|
|
6
|
-
require('execa');
|
|
7
6
|
const util_logger = require('../util/logger.js');
|
|
8
7
|
const shadow_paths = require('../shadow/paths.js');
|
|
9
8
|
const util_manifest = require('../util/manifest.js');
|
|
10
9
|
const util_s3_upload = require('../util/s3/upload.js');
|
|
10
|
+
const constants = require('../constants.js');
|
|
11
11
|
const util_s3_client = require('../util/s3/client.js');
|
|
12
|
+
const util_auth_authStore = require('../util/auth/auth-store.js');
|
|
12
13
|
const util_appName = require('../util/app-name.js');
|
|
13
14
|
const commands_build = require('./build.js');
|
|
14
15
|
|
|
@@ -17,30 +18,25 @@ const _interopDefault = e => e && e.__esModule ? e : { default: e };
|
|
|
17
18
|
const path__default = /*#__PURE__*/_interopDefault(path);
|
|
18
19
|
const os__default = /*#__PURE__*/_interopDefault(os);
|
|
19
20
|
|
|
20
|
-
const APONO_BUNDLE = '<APONO_BUNDLE_NAME>'; // TODO: replace with actual bundle name once infra setup is complete
|
|
21
|
-
async function requestAponoAccess() {
|
|
22
|
-
{
|
|
23
|
-
util_logger.warn(`skipping Apono request — APONO_BUNDLE is still a placeholder ("${APONO_BUNDLE}"). Set it in deploy.ts before relying on auto-grant.`);
|
|
24
|
-
return;
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
21
|
async function deployCommand(opts) {
|
|
28
22
|
if (opts.json) {
|
|
29
23
|
util_logger.setOutputMode('json');
|
|
30
24
|
}
|
|
31
|
-
util_logger.info('checking S3 bucket');
|
|
32
|
-
await util_s3_client.assertBucketExists();
|
|
33
25
|
const paths = shadow_paths.resolveConsumerPaths(process.cwd());
|
|
34
26
|
const consumerPkg = (await fsExtra.readJson(paths.consumerPkg));
|
|
35
27
|
if (!consumerPkg.name) {
|
|
36
28
|
throw new Error('Consumer package.json must have a "name" field');
|
|
37
29
|
}
|
|
38
30
|
const appName = util_appName.mfAppName(consumerPkg.name);
|
|
31
|
+
// Validate the user's deploy token is on disk before doing any expensive
|
|
32
|
+
// work. Throws Z2hAuthMissingError with a remediation hint if not.
|
|
33
|
+
await util_auth_authStore.readZthAuth();
|
|
34
|
+
util_s3_client.setupS3Client({ appName });
|
|
39
35
|
util_logger.info('reading current Z2H manifest');
|
|
40
36
|
const manifest = await util_manifest.readManifest();
|
|
41
37
|
const version = util_manifest.nextVersion(manifest, appName);
|
|
42
38
|
const keyPrefix = `${appName}/${version}`;
|
|
43
|
-
const url = `${
|
|
39
|
+
const url = `${constants.BUCKET_READ_DNS_URL}/${keyPrefix}`;
|
|
44
40
|
util_logger.info('building');
|
|
45
41
|
await commands_build.buildCommand({ json: opts.json, publicUrl: url });
|
|
46
42
|
if (!(await fsExtra.pathExists(paths.shadowBuild))) {
|
|
@@ -52,28 +48,27 @@ async function deployCommand(opts) {
|
|
|
52
48
|
throw new Error(`Missing asset-manifest.json at ${assetManifestPath}.`);
|
|
53
49
|
}
|
|
54
50
|
const assetManifest = (await fsExtra.readJson(assetManifestPath));
|
|
51
|
+
const deployedBy = os__default.default.userInfo().username;
|
|
52
|
+
const entry = {
|
|
53
|
+
...assetManifest,
|
|
54
|
+
version,
|
|
55
|
+
url,
|
|
56
|
+
deployedBy,
|
|
57
|
+
};
|
|
55
58
|
if (opts.dryRun) {
|
|
56
|
-
util_logger.output(`[z2h-cli] dry-run: would upload to s3://${
|
|
59
|
+
util_logger.output(`[z2h-cli] dry-run: would upload to s3://${constants.BUCKET_WRITE_NAME}/${keyPrefix}/ as v${version}`, {
|
|
57
60
|
ok: true,
|
|
58
61
|
dryRun: true,
|
|
59
62
|
appName,
|
|
60
63
|
version,
|
|
61
|
-
bucket:
|
|
64
|
+
bucket: constants.BUCKET_WRITE_NAME,
|
|
62
65
|
keyPrefix,
|
|
63
66
|
url,
|
|
64
|
-
entry
|
|
67
|
+
entry,
|
|
65
68
|
});
|
|
66
69
|
return;
|
|
67
70
|
}
|
|
68
|
-
|
|
69
|
-
const deployedBy = os__default.default.userInfo().username;
|
|
70
|
-
const entry = {
|
|
71
|
-
...assetManifest,
|
|
72
|
-
version,
|
|
73
|
-
url,
|
|
74
|
-
deployedBy,
|
|
75
|
-
};
|
|
76
|
-
util_logger.info(`uploading build → s3://${util_s3_client.BUCKET_WRITE_NAME}/${keyPrefix}/`);
|
|
71
|
+
util_logger.info(`uploading build → s3://${constants.BUCKET_WRITE_NAME}/${keyPrefix}/`);
|
|
77
72
|
await util_s3_upload.uploadDir(paths.shadowBuild, keyPrefix);
|
|
78
73
|
util_logger.info(`updating manifest entry "${appName}" → v${version}`);
|
|
79
74
|
await util_manifest.writeManifest(util_manifest.upsertEntry(manifest, appName, entry));
|
|
@@ -85,7 +80,7 @@ async function deployCommand(opts) {
|
|
|
85
80
|
ok: true,
|
|
86
81
|
appName,
|
|
87
82
|
version,
|
|
88
|
-
bucket:
|
|
83
|
+
bucket: constants.BUCKET_WRITE_NAME,
|
|
89
84
|
keyPrefix,
|
|
90
85
|
url,
|
|
91
86
|
liveUrl,
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export declare const DEFAULT_TOKEN_PAGE_URL = "https://bigbrain.me/bigbrain-vibe/generate-z2h-token";
|
|
2
|
+
export declare const LOOPBACK_TIMEOUT_MS = 120000;
|
|
3
|
+
export interface GenerateZ2HTokenOptions {
|
|
4
|
+
/**
|
|
5
|
+
* Skip browser auto-open AND skip the loopback callback. Prints the URL
|
|
6
|
+
* for the user to open manually, then waits for them to paste the token
|
|
7
|
+
* into the prompt. Use for SSH sessions, CI, or when the loopback can't
|
|
8
|
+
* reach the CLI for any reason.
|
|
9
|
+
*/
|
|
10
|
+
noBrowser?: boolean;
|
|
11
|
+
/** Override the page URL — useful when pointing at staging. */
|
|
12
|
+
url?: string;
|
|
13
|
+
json?: boolean;
|
|
14
|
+
}
|
|
15
|
+
export declare function generateZ2HTokenCommand(opts?: GenerateZ2HTokenOptions): Promise<void>;
|
|
16
|
+
//# sourceMappingURL=generate-z2h-token.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate-z2h-token.d.ts","sourceRoot":"","sources":["../../src/commands/generate-z2h-token.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,sBAAsB,yDAAyD,CAAC;AAC7F,eAAO,MAAM,mBAAmB,SAAU,CAAC;AAE3C,MAAM,WAAW,uBAAuB;IACtC;;;;;OAKG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,+DAA+D;IAC/D,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAuED,wBAAsB,uBAAuB,CAAC,IAAI,GAAE,uBAA4B,GAAG,OAAO,CAAC,IAAI,CAAC,CA+B/F"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
+
|
|
3
|
+
const readline = require('node:readline/promises');
|
|
4
|
+
const node_process = require('node:process');
|
|
5
|
+
const execa = require('execa');
|
|
6
|
+
const util_logger = require('../util/logger.js');
|
|
7
|
+
const util_auth_writeAuth = require('../util/auth/write-auth.js');
|
|
8
|
+
const util_auth_loopbackServer = require('../util/auth/loopback-server.js');
|
|
9
|
+
|
|
10
|
+
const _interopDefault = e => e && e.__esModule ? e : { default: e };
|
|
11
|
+
|
|
12
|
+
const readline__default = /*#__PURE__*/_interopDefault(readline);
|
|
13
|
+
|
|
14
|
+
const DEFAULT_TOKEN_PAGE_URL = 'https://bigbrain.me/bigbrain-vibe/generate-z2h-token';
|
|
15
|
+
const LOOPBACK_TIMEOUT_MS = 120_000;
|
|
16
|
+
function browserOpenCommand() {
|
|
17
|
+
switch (process.platform) {
|
|
18
|
+
case 'darwin':
|
|
19
|
+
return 'open';
|
|
20
|
+
case 'win32':
|
|
21
|
+
return 'start';
|
|
22
|
+
default:
|
|
23
|
+
return 'xdg-open';
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
async function openInBrowser(url) {
|
|
27
|
+
await execa.execa(browserOpenCommand(), [url], { stdio: 'ignore' });
|
|
28
|
+
}
|
|
29
|
+
async function promptForToken() {
|
|
30
|
+
const rl = readline__default.default.createInterface({ input: node_process.stdin, output: node_process.stdout });
|
|
31
|
+
try {
|
|
32
|
+
const raw = await rl.question('Paste your token here, then press Enter:\n> ');
|
|
33
|
+
return raw.trim();
|
|
34
|
+
}
|
|
35
|
+
finally {
|
|
36
|
+
rl.close();
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
function withQueryParam(url, key, value) {
|
|
40
|
+
const sep = url.includes('?') ? '&' : '?';
|
|
41
|
+
return `${url}${sep}${key}=${encodeURIComponent(value)}`;
|
|
42
|
+
}
|
|
43
|
+
async function runManualFlow(pageUrl) {
|
|
44
|
+
util_logger.info(`open this URL in your browser to mint a Z2H deploy token:\n` +
|
|
45
|
+
` ${pageUrl}\n\n` +
|
|
46
|
+
`1. Click "Generate token" on the page.\n` +
|
|
47
|
+
`2. Copy the token shown.\n` +
|
|
48
|
+
`3. Paste it below and press Enter.\n`);
|
|
49
|
+
const token = await promptForToken();
|
|
50
|
+
if (!token) {
|
|
51
|
+
throw new Error('No token entered.');
|
|
52
|
+
}
|
|
53
|
+
return token;
|
|
54
|
+
}
|
|
55
|
+
async function runLoopbackFlow(pageUrl) {
|
|
56
|
+
const loopback = await util_auth_loopbackServer.startLoopbackServer();
|
|
57
|
+
const fullUrl = withQueryParam(pageUrl, 'cli_callback', loopback.callbackUrl);
|
|
58
|
+
util_logger.info('opening your browser to mint a Z2H deploy token');
|
|
59
|
+
util_logger.info(` ${fullUrl}`);
|
|
60
|
+
try {
|
|
61
|
+
await openInBrowser(fullUrl);
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
util_logger.warn('could not auto-open the browser. please visit the URL above manually.');
|
|
65
|
+
}
|
|
66
|
+
util_logger.info('waiting for the page to send the token (Ctrl+C to fall back to manual paste)…');
|
|
67
|
+
try {
|
|
68
|
+
return await loopback.waitForToken(LOOPBACK_TIMEOUT_MS);
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
finally {
|
|
74
|
+
loopback.close();
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
async function generateZ2HTokenCommand(opts = {}) {
|
|
78
|
+
if (opts.json) {
|
|
79
|
+
util_logger.setOutputMode('json');
|
|
80
|
+
}
|
|
81
|
+
const pageUrl = opts.url ?? process.env.Z2H_TOKEN_PAGE_URL ?? DEFAULT_TOKEN_PAGE_URL;
|
|
82
|
+
// --no-browser bypasses both auto-open and the loopback round-trip — the
|
|
83
|
+
// user opens the URL themselves and pastes the token. Useful when the
|
|
84
|
+
// loopback can't be reached (SSH, CI, locked-down browsers).
|
|
85
|
+
let token = null;
|
|
86
|
+
if (!opts.noBrowser) {
|
|
87
|
+
token = await runLoopbackFlow(pageUrl);
|
|
88
|
+
if (!token) {
|
|
89
|
+
util_logger.warn('loopback flow timed out or was cancelled — falling back to manual paste.');
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
if (!token) {
|
|
93
|
+
token = await runManualFlow(pageUrl);
|
|
94
|
+
}
|
|
95
|
+
if (!util_auth_writeAuth.validateJwtPattern(token)) {
|
|
96
|
+
throw new Error('That does not look like a JWT (expected three dot-separated segments).');
|
|
97
|
+
}
|
|
98
|
+
const { filePath } = await util_auth_writeAuth.writeZthAuth({ token });
|
|
99
|
+
util_logger.output(`[z2h-cli] token saved ✅ ${filePath}`, {
|
|
100
|
+
ok: true,
|
|
101
|
+
filePath,
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
exports.DEFAULT_TOKEN_PAGE_URL = DEFAULT_TOKEN_PAGE_URL;
|
|
106
|
+
exports.LOOPBACK_TIMEOUT_MS = LOOPBACK_TIMEOUT_MS;
|
|
107
|
+
exports.generateZ2HTokenCommand = generateZ2HTokenCommand;
|
package/dist/constants.d.ts
CHANGED
|
@@ -9,4 +9,12 @@ export declare const MIN_PORT = 13000;
|
|
|
9
9
|
export declare const MAX_PORT = 19999;
|
|
10
10
|
export declare const GITIGNORE_ENTRIES: string[];
|
|
11
11
|
export declare const YARNRC_LINES: string[];
|
|
12
|
+
export declare const BUCKET_WRITE_NAME = "prod-use1-bigbrain-zth-mf-assets";
|
|
13
|
+
export declare const REGION = "us-east-1";
|
|
14
|
+
export declare const BUCKET_WRITE_URL = "https://prod-use1-bigbrain-zth-mf-assets.s3.us-east-1.amazonaws.com";
|
|
15
|
+
export declare const BUCKET_READ_DNS_NAME = "bigbrain-zth-mf-assets";
|
|
16
|
+
export declare const BUCKET_READ_DNS_URL = "https://bigbrain-zth-mf-assets.bigbrain.me";
|
|
17
|
+
export declare const MANIFEST_KEY = "mf-assets";
|
|
18
|
+
export declare const MANIFEST_READ_URL = "https://bigbrain-zth-mf-assets.bigbrain.me/mf-assets";
|
|
19
|
+
export declare const APP_NAME_PATTERN: RegExp;
|
|
12
20
|
//# sourceMappingURL=constants.d.ts.map
|
package/dist/constants.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,eAAO,MAAM,eAAe,SAAS,CAAC;AAGtC,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAGjD,CAAC;AAQF,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAElD,CAAC;AAMF,eAAO,MAAM,QAAQ,QAAQ,CAAC;AAC9B,eAAO,MAAM,QAAQ,QAAQ,CAAC;AAG9B,eAAO,MAAM,iBAAiB,UAAY,CAAC;AAG3C,eAAO,MAAM,YAAY,UAIxB,CAAC"}
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,eAAO,MAAM,eAAe,SAAS,CAAC;AAGtC,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAGjD,CAAC;AAQF,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAElD,CAAC;AAMF,eAAO,MAAM,QAAQ,QAAQ,CAAC;AAC9B,eAAO,MAAM,QAAQ,QAAQ,CAAC;AAG9B,eAAO,MAAM,iBAAiB,UAAY,CAAC;AAG3C,eAAO,MAAM,YAAY,UAIxB,CAAC;AAQF,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;AAM1E,eAAO,MAAM,gBAAgB,QAA2B,CAAC"}
|
package/dist/constants.js
CHANGED
|
@@ -34,10 +34,38 @@ const YARNRC_LINES = [
|
|
|
34
34
|
"npmAuthToken: '${NPM_TOKEN}'",
|
|
35
35
|
"npmRegistryServer: 'https://registry.npmjs.org/'",
|
|
36
36
|
];
|
|
37
|
+
// ─────────── Z2H deploy bucket / contract ─────────
|
|
38
|
+
// Source of truth for the bucket layout. The CLI uses these when configuring
|
|
39
|
+
// the S3 client + uploading; bigbrain-zth's STS broker imports them via
|
|
40
|
+
// `@mondaydotcomorg/z2h-cli/constants` to scope the per-deploy session
|
|
41
|
+
// policy to the same bucket + manifest key.
|
|
42
|
+
const BUCKET_WRITE_NAME = 'prod-use1-bigbrain-zth-mf-assets';
|
|
43
|
+
const REGION = 'us-east-1';
|
|
44
|
+
const BUCKET_WRITE_URL = `https://${BUCKET_WRITE_NAME}.s3.${REGION}.amazonaws.com`;
|
|
45
|
+
const BUCKET_READ_DNS_NAME = 'bigbrain-zth-mf-assets';
|
|
46
|
+
const BUCKET_READ_DNS_URL = `https://${BUCKET_READ_DNS_NAME}.bigbrain.me`;
|
|
47
|
+
// No `.json` extension — TridentSkeleton's `mfUrl` API appends `/mf-assets`
|
|
48
|
+
// to the bucket base when fetching, so the manifest must live at this exact
|
|
49
|
+
// key. See microfrontends/mf-bigbrain-zth/.../ZeroToHeroHost.tsx.
|
|
50
|
+
const MANIFEST_KEY = 'mf-assets';
|
|
51
|
+
const MANIFEST_READ_URL = `${BUCKET_READ_DNS_URL}/${MANIFEST_KEY}`;
|
|
52
|
+
// ─────────── App-name slug — backend & CLI both honor this ─────
|
|
53
|
+
// Lowercase kebab-case, must start with a letter, 2-50 chars total. The
|
|
54
|
+
// backend STS broker rejects anything else with 400; the CLI can validate
|
|
55
|
+
// upfront for friendlier errors.
|
|
56
|
+
const APP_NAME_PATTERN = /^[a-z][a-z0-9-]{1,49}$/;
|
|
37
57
|
|
|
58
|
+
exports.APP_NAME_PATTERN = APP_NAME_PATTERN;
|
|
59
|
+
exports.BUCKET_READ_DNS_NAME = BUCKET_READ_DNS_NAME;
|
|
60
|
+
exports.BUCKET_READ_DNS_URL = BUCKET_READ_DNS_URL;
|
|
61
|
+
exports.BUCKET_WRITE_NAME = BUCKET_WRITE_NAME;
|
|
62
|
+
exports.BUCKET_WRITE_URL = BUCKET_WRITE_URL;
|
|
38
63
|
exports.GITIGNORE_ENTRIES = GITIGNORE_ENTRIES;
|
|
64
|
+
exports.MANIFEST_KEY = MANIFEST_KEY;
|
|
65
|
+
exports.MANIFEST_READ_URL = MANIFEST_READ_URL;
|
|
39
66
|
exports.MAX_PORT = MAX_PORT;
|
|
40
67
|
exports.MIN_PORT = MIN_PORT;
|
|
68
|
+
exports.REGION = REGION;
|
|
41
69
|
exports.SHADOW_DEV_DEPS = SHADOW_DEV_DEPS;
|
|
42
70
|
exports.SHADOW_DIR_NAME = SHADOW_DIR_NAME;
|
|
43
71
|
exports.SHADOW_SCRIPTS = SHADOW_SCRIPTS;
|
|
@@ -31,7 +31,7 @@ async function createWorkspaceCommand(opts) {
|
|
|
31
31
|
if (await pathExists(home)) {
|
|
32
32
|
const entries = await readdir(home);
|
|
33
33
|
if (entries.length > 0) {
|
|
34
|
-
throw new Error(
|
|
34
|
+
throw new Error(`Workspace already exists at ${home}. Remove it and try again.`);
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
37
|
else {
|
|
@@ -60,12 +60,12 @@ async function createWorkspaceCommand(opts) {
|
|
|
60
60
|
copy(path.join(wsTemplatesDir, 'README.md'), path.join(home, 'README.md')),
|
|
61
61
|
copy(path.join(wsTemplatesDir, 'yarn-releases', 'yarn-4.5.1.cjs'), path.join(home, '.yarn', 'releases', 'yarn-4.5.1.cjs')),
|
|
62
62
|
]);
|
|
63
|
-
info(`
|
|
63
|
+
info(`setting up your Z2H workspace — this may take a minute...`);
|
|
64
64
|
await execa('yarn', ['install'], {
|
|
65
65
|
cwd: home,
|
|
66
66
|
stdio: 'inherit',
|
|
67
67
|
});
|
|
68
|
-
output(`
|
|
68
|
+
output(`Your workspace is ready! 🚀 Apps will live at ${home}`, {
|
|
69
69
|
ok: true,
|
|
70
70
|
workspace: home,
|
|
71
71
|
z2hCliVersion: cliVersion,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../../src/commands/create.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../../src/commands/create.ts"],"names":[],"mappings":"AAWA,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AA6BD,wBAAsB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAqFvF"}
|
|
@@ -7,8 +7,12 @@ import { assertWorkspace } from '../util/workspace.mjs';
|
|
|
7
7
|
import { APP_TEMPLATES, getTemplatesDir, renderTemplate } from '../util/templates.mjs';
|
|
8
8
|
import { readManifest } from '../util/manifest.mjs';
|
|
9
9
|
import { mfAppName } from '../util/app-name.mjs';
|
|
10
|
+
import { APP_NAME_PATTERN } from '../constants.mjs';
|
|
10
11
|
|
|
11
|
-
|
|
12
|
+
// Names reserved by the host MF (mf-bigbrain-zth) for platform pages under
|
|
13
|
+
// /bigbrain-vibe/<name>. Creating an app with one of these would shadow the
|
|
14
|
+
// platform page in the URL, so we refuse upfront.
|
|
15
|
+
const RESERVED_APP_NAMES = new Set(['generate-z2h-token']);
|
|
12
16
|
/**
|
|
13
17
|
* Convert kebab-case to PascalCase. `demo-app` → `DemoApp`.
|
|
14
18
|
*/
|
|
@@ -36,7 +40,10 @@ async function createCommand(appName, opts) {
|
|
|
36
40
|
// Validate workspace.
|
|
37
41
|
const workspace = await assertWorkspace();
|
|
38
42
|
// Validate app name.
|
|
39
|
-
if (
|
|
43
|
+
if (RESERVED_APP_NAMES.has(appName)) {
|
|
44
|
+
throw new Error(`App name "${appName}" is reserved by the Z2H host for a platform page under /bigbrain-vibe/${appName}. Pick a different name.`);
|
|
45
|
+
}
|
|
46
|
+
if (!APP_NAME_PATTERN.test(appName)) {
|
|
40
47
|
throw new Error(`App name "${appName}" is invalid. Use lowercase kebab-case (a-z, 0-9, -), ` +
|
|
41
48
|
`2-50 chars, starting with a letter.`);
|
|
42
49
|
}
|
|
@@ -82,7 +89,7 @@ async function createCommand(appName, opts) {
|
|
|
82
89
|
if (template === 'html-embed' && opts.htmlFile) {
|
|
83
90
|
await copy(opts.htmlFile, path.join(appDir, 'src', 'page.html'));
|
|
84
91
|
}
|
|
85
|
-
info(`installing
|
|
92
|
+
info(`installing dependencies for ${appName}...`);
|
|
86
93
|
await execa('yarn', ['install'], {
|
|
87
94
|
cwd: workspace,
|
|
88
95
|
stdio: 'inherit',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deploy.d.ts","sourceRoot":"","sources":["../../../src/commands/deploy.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"deploy.d.ts","sourceRoot":"","sources":["../../../src/commands/deploy.ts"],"names":[],"mappings":"AAoBA,MAAM,WAAW,aAAa;IAC5B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,wBAAsB,aAAa,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CA+EtE"}
|
|
@@ -1,34 +1,30 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
2
|
import os from 'node:os';
|
|
3
3
|
import { readJson, pathExists } from 'fs-extra';
|
|
4
|
-
import '
|
|
5
|
-
import { setOutputMode, info, output, warn } from '../util/logger.mjs';
|
|
4
|
+
import { setOutputMode, info, output } from '../util/logger.mjs';
|
|
6
5
|
import { resolveConsumerPaths } from '../shadow/paths.mjs';
|
|
7
6
|
import { readManifest, nextVersion, writeManifest, upsertEntry } from '../util/manifest.mjs';
|
|
8
7
|
import { uploadDir } from '../util/s3/upload.mjs';
|
|
9
|
-
import {
|
|
8
|
+
import { BUCKET_WRITE_NAME, BUCKET_READ_DNS_URL } from '../constants.mjs';
|
|
9
|
+
import { setupS3Client } from '../util/s3/client.mjs';
|
|
10
|
+
import { readZthAuth } from '../util/auth/auth-store.mjs';
|
|
10
11
|
import { mfAppName, cleanAppName } from '../util/app-name.mjs';
|
|
11
12
|
import { buildCommand } from './build.mjs';
|
|
12
13
|
|
|
13
|
-
const APONO_BUNDLE = '<APONO_BUNDLE_NAME>'; // TODO: replace with actual bundle name once infra setup is complete
|
|
14
|
-
async function requestAponoAccess() {
|
|
15
|
-
{
|
|
16
|
-
warn(`skipping Apono request — APONO_BUNDLE is still a placeholder ("${APONO_BUNDLE}"). Set it in deploy.ts before relying on auto-grant.`);
|
|
17
|
-
return;
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
14
|
async function deployCommand(opts) {
|
|
21
15
|
if (opts.json) {
|
|
22
16
|
setOutputMode('json');
|
|
23
17
|
}
|
|
24
|
-
info('checking S3 bucket');
|
|
25
|
-
await assertBucketExists();
|
|
26
18
|
const paths = resolveConsumerPaths(process.cwd());
|
|
27
19
|
const consumerPkg = (await readJson(paths.consumerPkg));
|
|
28
20
|
if (!consumerPkg.name) {
|
|
29
21
|
throw new Error('Consumer package.json must have a "name" field');
|
|
30
22
|
}
|
|
31
23
|
const appName = mfAppName(consumerPkg.name);
|
|
24
|
+
// Validate the user's deploy token is on disk before doing any expensive
|
|
25
|
+
// work. Throws Z2hAuthMissingError with a remediation hint if not.
|
|
26
|
+
await readZthAuth();
|
|
27
|
+
setupS3Client({ appName });
|
|
32
28
|
info('reading current Z2H manifest');
|
|
33
29
|
const manifest = await readManifest();
|
|
34
30
|
const version = nextVersion(manifest, appName);
|
|
@@ -45,6 +41,13 @@ async function deployCommand(opts) {
|
|
|
45
41
|
throw new Error(`Missing asset-manifest.json at ${assetManifestPath}.`);
|
|
46
42
|
}
|
|
47
43
|
const assetManifest = (await readJson(assetManifestPath));
|
|
44
|
+
const deployedBy = os.userInfo().username;
|
|
45
|
+
const entry = {
|
|
46
|
+
...assetManifest,
|
|
47
|
+
version,
|
|
48
|
+
url,
|
|
49
|
+
deployedBy,
|
|
50
|
+
};
|
|
48
51
|
if (opts.dryRun) {
|
|
49
52
|
output(`[z2h-cli] dry-run: would upload to s3://${BUCKET_WRITE_NAME}/${keyPrefix}/ as v${version}`, {
|
|
50
53
|
ok: true,
|
|
@@ -54,18 +57,10 @@ async function deployCommand(opts) {
|
|
|
54
57
|
bucket: BUCKET_WRITE_NAME,
|
|
55
58
|
keyPrefix,
|
|
56
59
|
url,
|
|
57
|
-
entry
|
|
60
|
+
entry,
|
|
58
61
|
});
|
|
59
62
|
return;
|
|
60
63
|
}
|
|
61
|
-
await requestAponoAccess();
|
|
62
|
-
const deployedBy = os.userInfo().username;
|
|
63
|
-
const entry = {
|
|
64
|
-
...assetManifest,
|
|
65
|
-
version,
|
|
66
|
-
url,
|
|
67
|
-
deployedBy,
|
|
68
|
-
};
|
|
69
64
|
info(`uploading build → s3://${BUCKET_WRITE_NAME}/${keyPrefix}/`);
|
|
70
65
|
await uploadDir(paths.shadowBuild, keyPrefix);
|
|
71
66
|
info(`updating manifest entry "${appName}" → v${version}`);
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export declare const DEFAULT_TOKEN_PAGE_URL = "https://bigbrain.me/bigbrain-vibe/generate-z2h-token";
|
|
2
|
+
export declare const LOOPBACK_TIMEOUT_MS = 120000;
|
|
3
|
+
export interface GenerateZ2HTokenOptions {
|
|
4
|
+
/**
|
|
5
|
+
* Skip browser auto-open AND skip the loopback callback. Prints the URL
|
|
6
|
+
* for the user to open manually, then waits for them to paste the token
|
|
7
|
+
* into the prompt. Use for SSH sessions, CI, or when the loopback can't
|
|
8
|
+
* reach the CLI for any reason.
|
|
9
|
+
*/
|
|
10
|
+
noBrowser?: boolean;
|
|
11
|
+
/** Override the page URL — useful when pointing at staging. */
|
|
12
|
+
url?: string;
|
|
13
|
+
json?: boolean;
|
|
14
|
+
}
|
|
15
|
+
export declare function generateZ2HTokenCommand(opts?: GenerateZ2HTokenOptions): Promise<void>;
|
|
16
|
+
//# sourceMappingURL=generate-z2h-token.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate-z2h-token.d.ts","sourceRoot":"","sources":["../../../src/commands/generate-z2h-token.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,sBAAsB,yDAAyD,CAAC;AAC7F,eAAO,MAAM,mBAAmB,SAAU,CAAC;AAE3C,MAAM,WAAW,uBAAuB;IACtC;;;;;OAKG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,+DAA+D;IAC/D,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAuED,wBAAsB,uBAAuB,CAAC,IAAI,GAAE,uBAA4B,GAAG,OAAO,CAAC,IAAI,CAAC,CA+B/F"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import readline from 'node:readline/promises';
|
|
2
|
+
import { stdin, stdout } from 'node:process';
|
|
3
|
+
import { execa } from 'execa';
|
|
4
|
+
import { setOutputMode, warn, output, info } from '../util/logger.mjs';
|
|
5
|
+
import { validateJwtPattern, writeZthAuth } from '../util/auth/write-auth.mjs';
|
|
6
|
+
import { startLoopbackServer } from '../util/auth/loopback-server.mjs';
|
|
7
|
+
|
|
8
|
+
const DEFAULT_TOKEN_PAGE_URL = 'https://bigbrain.me/bigbrain-vibe/generate-z2h-token';
|
|
9
|
+
const LOOPBACK_TIMEOUT_MS = 120_000;
|
|
10
|
+
function browserOpenCommand() {
|
|
11
|
+
switch (process.platform) {
|
|
12
|
+
case 'darwin':
|
|
13
|
+
return 'open';
|
|
14
|
+
case 'win32':
|
|
15
|
+
return 'start';
|
|
16
|
+
default:
|
|
17
|
+
return 'xdg-open';
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
async function openInBrowser(url) {
|
|
21
|
+
await execa(browserOpenCommand(), [url], { stdio: 'ignore' });
|
|
22
|
+
}
|
|
23
|
+
async function promptForToken() {
|
|
24
|
+
const rl = readline.createInterface({ input: stdin, output: stdout });
|
|
25
|
+
try {
|
|
26
|
+
const raw = await rl.question('Paste your token here, then press Enter:\n> ');
|
|
27
|
+
return raw.trim();
|
|
28
|
+
}
|
|
29
|
+
finally {
|
|
30
|
+
rl.close();
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
function withQueryParam(url, key, value) {
|
|
34
|
+
const sep = url.includes('?') ? '&' : '?';
|
|
35
|
+
return `${url}${sep}${key}=${encodeURIComponent(value)}`;
|
|
36
|
+
}
|
|
37
|
+
async function runManualFlow(pageUrl) {
|
|
38
|
+
info(`open this URL in your browser to mint a Z2H deploy token:\n` +
|
|
39
|
+
` ${pageUrl}\n\n` +
|
|
40
|
+
`1. Click "Generate token" on the page.\n` +
|
|
41
|
+
`2. Copy the token shown.\n` +
|
|
42
|
+
`3. Paste it below and press Enter.\n`);
|
|
43
|
+
const token = await promptForToken();
|
|
44
|
+
if (!token) {
|
|
45
|
+
throw new Error('No token entered.');
|
|
46
|
+
}
|
|
47
|
+
return token;
|
|
48
|
+
}
|
|
49
|
+
async function runLoopbackFlow(pageUrl) {
|
|
50
|
+
const loopback = await startLoopbackServer();
|
|
51
|
+
const fullUrl = withQueryParam(pageUrl, 'cli_callback', loopback.callbackUrl);
|
|
52
|
+
info('opening your browser to mint a Z2H deploy token');
|
|
53
|
+
info(` ${fullUrl}`);
|
|
54
|
+
try {
|
|
55
|
+
await openInBrowser(fullUrl);
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
warn('could not auto-open the browser. please visit the URL above manually.');
|
|
59
|
+
}
|
|
60
|
+
info('waiting for the page to send the token (Ctrl+C to fall back to manual paste)…');
|
|
61
|
+
try {
|
|
62
|
+
return await loopback.waitForToken(LOOPBACK_TIMEOUT_MS);
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
finally {
|
|
68
|
+
loopback.close();
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
async function generateZ2HTokenCommand(opts = {}) {
|
|
72
|
+
if (opts.json) {
|
|
73
|
+
setOutputMode('json');
|
|
74
|
+
}
|
|
75
|
+
const pageUrl = opts.url ?? process.env.Z2H_TOKEN_PAGE_URL ?? DEFAULT_TOKEN_PAGE_URL;
|
|
76
|
+
// --no-browser bypasses both auto-open and the loopback round-trip — the
|
|
77
|
+
// user opens the URL themselves and pastes the token. Useful when the
|
|
78
|
+
// loopback can't be reached (SSH, CI, locked-down browsers).
|
|
79
|
+
let token = null;
|
|
80
|
+
if (!opts.noBrowser) {
|
|
81
|
+
token = await runLoopbackFlow(pageUrl);
|
|
82
|
+
if (!token) {
|
|
83
|
+
warn('loopback flow timed out or was cancelled — falling back to manual paste.');
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
if (!token) {
|
|
87
|
+
token = await runManualFlow(pageUrl);
|
|
88
|
+
}
|
|
89
|
+
if (!validateJwtPattern(token)) {
|
|
90
|
+
throw new Error('That does not look like a JWT (expected three dot-separated segments).');
|
|
91
|
+
}
|
|
92
|
+
const { filePath } = await writeZthAuth({ token });
|
|
93
|
+
output(`[z2h-cli] token saved ✅ ${filePath}`, {
|
|
94
|
+
ok: true,
|
|
95
|
+
filePath,
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export { DEFAULT_TOKEN_PAGE_URL, LOOPBACK_TIMEOUT_MS, generateZ2HTokenCommand };
|
package/dist/esm/constants.d.ts
CHANGED
|
@@ -9,4 +9,12 @@ export declare const MIN_PORT = 13000;
|
|
|
9
9
|
export declare const MAX_PORT = 19999;
|
|
10
10
|
export declare const GITIGNORE_ENTRIES: string[];
|
|
11
11
|
export declare const YARNRC_LINES: string[];
|
|
12
|
+
export declare const BUCKET_WRITE_NAME = "prod-use1-bigbrain-zth-mf-assets";
|
|
13
|
+
export declare const REGION = "us-east-1";
|
|
14
|
+
export declare const BUCKET_WRITE_URL = "https://prod-use1-bigbrain-zth-mf-assets.s3.us-east-1.amazonaws.com";
|
|
15
|
+
export declare const BUCKET_READ_DNS_NAME = "bigbrain-zth-mf-assets";
|
|
16
|
+
export declare const BUCKET_READ_DNS_URL = "https://bigbrain-zth-mf-assets.bigbrain.me";
|
|
17
|
+
export declare const MANIFEST_KEY = "mf-assets";
|
|
18
|
+
export declare const MANIFEST_READ_URL = "https://bigbrain-zth-mf-assets.bigbrain.me/mf-assets";
|
|
19
|
+
export declare const APP_NAME_PATTERN: RegExp;
|
|
12
20
|
//# sourceMappingURL=constants.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,eAAO,MAAM,eAAe,SAAS,CAAC;AAGtC,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAGjD,CAAC;AAQF,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAElD,CAAC;AAMF,eAAO,MAAM,QAAQ,QAAQ,CAAC;AAC9B,eAAO,MAAM,QAAQ,QAAQ,CAAC;AAG9B,eAAO,MAAM,iBAAiB,UAAY,CAAC;AAG3C,eAAO,MAAM,YAAY,UAIxB,CAAC"}
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,eAAO,MAAM,eAAe,SAAS,CAAC;AAGtC,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAGjD,CAAC;AAQF,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAElD,CAAC;AAMF,eAAO,MAAM,QAAQ,QAAQ,CAAC;AAC9B,eAAO,MAAM,QAAQ,QAAQ,CAAC;AAG9B,eAAO,MAAM,iBAAiB,UAAY,CAAC;AAG3C,eAAO,MAAM,YAAY,UAIxB,CAAC;AAQF,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;AAM1E,eAAO,MAAM,gBAAgB,QAA2B,CAAC"}
|