@mondaydotcomorg/z2h-cli 0.10.0 → 0.11.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/__tests__/edit.test.d.ts +2 -0
- package/dist/commands/__tests__/edit.test.d.ts.map +1 -0
- package/dist/commands/create.d.ts +2 -2
- package/dist/commands/create.d.ts.map +1 -1
- package/dist/commands/create.js +14 -34
- package/dist/commands/deploy.d.ts +3 -0
- package/dist/commands/deploy.d.ts.map +1 -1
- package/dist/commands/deploy.js +123 -23
- package/dist/commands/edit.d.ts +5 -0
- package/dist/commands/edit.d.ts.map +1 -0
- package/dist/commands/edit.js +61 -0
- package/dist/commands/grant.d.ts +12 -0
- package/dist/commands/grant.d.ts.map +1 -0
- package/dist/commands/grant.js +94 -0
- package/dist/constants.d.ts +1 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +7 -0
- package/dist/esm/commands/__tests__/edit.test.d.ts +2 -0
- package/dist/esm/commands/__tests__/edit.test.d.ts.map +1 -0
- package/dist/esm/commands/create.d.ts +2 -2
- package/dist/esm/commands/create.d.ts.map +1 -1
- package/dist/esm/commands/create.mjs +16 -35
- package/dist/esm/commands/deploy.d.ts +3 -0
- package/dist/esm/commands/deploy.d.ts.map +1 -1
- package/dist/esm/commands/deploy.mjs +124 -24
- package/dist/esm/commands/edit.d.ts +5 -0
- package/dist/esm/commands/edit.d.ts.map +1 -0
- package/dist/esm/commands/edit.mjs +55 -0
- package/dist/esm/commands/grant.d.ts +12 -0
- package/dist/esm/commands/grant.d.ts.map +1 -0
- package/dist/esm/commands/grant.mjs +90 -0
- package/dist/esm/constants.d.ts +1 -0
- package/dist/esm/constants.d.ts.map +1 -1
- package/dist/esm/constants.mjs +7 -1
- package/dist/esm/index.mjs +67 -10
- package/dist/esm/shadow/prepare.d.ts +1 -1
- package/dist/esm/shadow/prepare.d.ts.map +1 -1
- package/dist/esm/shadow/prepare.mjs +2 -2
- package/dist/esm/util/app-name.d.ts +1 -0
- package/dist/esm/util/app-name.d.ts.map +1 -1
- package/dist/esm/util/app-name.mjs +11 -1
- package/dist/esm/util/auth/auth-store.d.ts.map +1 -1
- package/dist/esm/util/auth/auth-store.mjs +10 -0
- package/dist/esm/util/auth/broker-credential-provider.d.ts +10 -2
- package/dist/esm/util/auth/broker-credential-provider.d.ts.map +1 -1
- package/dist/esm/util/auth/broker-credential-provider.mjs +35 -13
- package/dist/esm/util/broker/app.d.ts +14 -0
- package/dist/esm/util/broker/app.d.ts.map +1 -0
- package/dist/esm/util/broker/app.mjs +27 -0
- package/dist/esm/util/git/git-env.d.ts +9 -0
- package/dist/esm/util/git/git-env.d.ts.map +1 -0
- package/dist/esm/util/git/git-env.mjs +22 -0
- package/dist/esm/util/git/remote-options.d.ts +17 -0
- package/dist/esm/util/git/remote-options.d.ts.map +1 -0
- package/dist/esm/util/git/remote-options.mjs +30 -0
- package/dist/esm/util/git/repo.d.ts +21 -3
- package/dist/esm/util/git/repo.d.ts.map +1 -1
- package/dist/esm/util/git/repo.mjs +103 -47
- package/dist/esm/util/machine-identity.d.ts +9 -0
- package/dist/esm/util/machine-identity.d.ts.map +1 -0
- package/dist/esm/util/machine-identity.mjs +12 -0
- package/dist/esm/util/s3/client.d.ts +2 -7
- package/dist/esm/util/s3/client.d.ts.map +1 -1
- package/dist/esm/util/s3/client.mjs +3 -11
- package/dist/index.js +69 -12
- package/dist/shadow/prepare.d.ts +1 -1
- package/dist/shadow/prepare.d.ts.map +1 -1
- package/dist/shadow/prepare.js +2 -2
- package/dist/util/app-name.d.ts +1 -0
- package/dist/util/app-name.d.ts.map +1 -1
- package/dist/util/app-name.js +11 -0
- package/dist/util/auth/auth-store.d.ts.map +1 -1
- package/dist/util/auth/auth-store.js +10 -0
- package/dist/util/auth/broker-credential-provider.d.ts +10 -2
- package/dist/util/auth/broker-credential-provider.d.ts.map +1 -1
- package/dist/util/auth/broker-credential-provider.js +35 -11
- package/dist/util/broker/app.d.ts +14 -0
- package/dist/util/broker/app.d.ts.map +1 -0
- package/dist/util/broker/app.js +29 -0
- package/dist/util/git/git-env.d.ts +9 -0
- package/dist/util/git/git-env.d.ts.map +1 -0
- package/dist/util/git/git-env.js +24 -0
- package/dist/util/git/remote-options.d.ts +17 -0
- package/dist/util/git/remote-options.d.ts.map +1 -0
- package/dist/util/git/remote-options.js +34 -0
- package/dist/util/git/repo.d.ts +21 -3
- package/dist/util/git/repo.d.ts.map +1 -1
- package/dist/util/git/repo.js +104 -47
- package/dist/util/machine-identity.d.ts +9 -0
- package/dist/util/machine-identity.d.ts.map +1 -0
- package/dist/util/machine-identity.js +14 -0
- package/dist/util/s3/client.d.ts +2 -7
- package/dist/util/s3/client.d.ts.map +1 -1
- package/dist/util/s3/client.js +3 -11
- package/package.json +1 -1
- package/src/commands/__tests__/create.test.ts +9 -7
- package/src/commands/__tests__/edit.test.ts +184 -0
- package/src/commands/create.ts +15 -33
- package/src/commands/deploy.ts +147 -33
- package/src/commands/edit.ts +63 -0
- package/src/commands/grant.ts +115 -0
- package/src/constants.ts +7 -0
- package/src/index.ts +83 -13
- package/src/shadow/prepare.ts +2 -2
- package/src/templates/app/CLAUDE.md +15 -0
- package/src/util/app-name.ts +10 -0
- package/src/util/auth/__tests__/broker-credential-provider.test.ts +34 -2
- package/src/util/auth/auth-store.ts +12 -0
- package/src/util/auth/broker-credential-provider.ts +43 -15
- package/src/util/broker/app.ts +34 -0
- package/src/util/git/__tests__/repo.test.ts +108 -90
- package/src/util/git/git-env.ts +23 -0
- package/src/util/git/remote-options.ts +37 -0
- package/src/util/git/repo.ts +121 -47
- package/src/util/machine-identity.ts +10 -0
- package/src/util/s3/client.ts +4 -11
package/dist/esm/index.mjs
CHANGED
|
@@ -1,19 +1,22 @@
|
|
|
1
1
|
import { createRequire } from 'node:module';
|
|
2
|
-
import { readFileSync } from 'node:fs';
|
|
3
2
|
import os from 'node:os';
|
|
4
3
|
import path from 'node:path';
|
|
5
4
|
import { Command } from 'commander';
|
|
6
5
|
import { execa } from 'execa';
|
|
6
|
+
import { getWorkspaceHome } from './util/workspace.mjs';
|
|
7
7
|
import { devCommand } from './commands/dev.mjs';
|
|
8
8
|
import { buildCommand } from './commands/build.mjs';
|
|
9
9
|
import { cleanCommand } from './commands/clean.mjs';
|
|
10
10
|
import { deployCommand } from './commands/deploy.mjs';
|
|
11
|
+
import { grantCommand, revokeCommand, transferOwnerCommand } from './commands/grant.mjs';
|
|
11
12
|
import { createWorkspaceCommand } from './commands/create-workspace.mjs';
|
|
12
13
|
import { createCommand } from './commands/create.mjs';
|
|
13
14
|
import { generateZ2HTokenCommand } from './commands/generate-z2h-token.mjs';
|
|
14
15
|
import { migrateCommand } from './commands/migrate.mjs';
|
|
16
|
+
import { editCommand } from './commands/edit.mjs';
|
|
15
17
|
import { fail, errorLog, getOutputMode } from './util/logger.mjs';
|
|
16
18
|
import { trackDuration } from './util/tracker.mjs';
|
|
19
|
+
import { getCwdAppName } from './util/app-name.mjs';
|
|
17
20
|
|
|
18
21
|
const { version } = createRequire(import.meta.url)('../package.json');
|
|
19
22
|
const UPDATE_SCRIPT = path.join(os.homedir(), 'Development', 'bigbrain-z2h', 'z2h', 'setup', 'update.sh');
|
|
@@ -28,15 +31,14 @@ function selfUpdate() {
|
|
|
28
31
|
errorLog(`Z2H auto-update failed to start: ${err.message}`);
|
|
29
32
|
}
|
|
30
33
|
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
catch {
|
|
36
|
-
return undefined;
|
|
34
|
+
const CONFLICTING_ENV_VARS = ['AWS_PROFILE'];
|
|
35
|
+
function stripConflictingEnvVars() {
|
|
36
|
+
for (const name of CONFLICTING_ENV_VARS) {
|
|
37
|
+
delete process.env[name];
|
|
37
38
|
}
|
|
38
39
|
}
|
|
39
40
|
async function main() {
|
|
41
|
+
stripConflictingEnvVars();
|
|
40
42
|
const program = new Command();
|
|
41
43
|
program
|
|
42
44
|
.name('z2h-cli')
|
|
@@ -91,9 +93,11 @@ async function main() {
|
|
|
91
93
|
});
|
|
92
94
|
program
|
|
93
95
|
.command('deploy')
|
|
94
|
-
.description('Build, upload
|
|
96
|
+
.description('Build, upload to S3, and register the app with the Z2H backend')
|
|
95
97
|
.option('--dry-run', 'print what would happen without uploading anything')
|
|
96
98
|
.option('--json', 'emit structured JSON on stdout')
|
|
99
|
+
.option('--remote <type>', 'First deploy only: source control remote to initialise — s3 (shared storage) or github (your repo). Error if the app already has a git remote.')
|
|
100
|
+
.option('--repo-url <url>', 'First deploy only: GitHub repo URL — required when --remote=github. Error if the app already has a git remote.')
|
|
97
101
|
.action(async (opts) => {
|
|
98
102
|
try {
|
|
99
103
|
await trackDuration('z2h_app_deploy_success', () => deployCommand(opts), {
|
|
@@ -106,7 +110,7 @@ async function main() {
|
|
|
106
110
|
});
|
|
107
111
|
program
|
|
108
112
|
.command('create-workspace')
|
|
109
|
-
.description(
|
|
113
|
+
.description(`Bootstrap the ${getWorkspaceHome()}/ yarn workspace (one-time setup)`)
|
|
110
114
|
.option('--json', 'emit structured JSON on stdout')
|
|
111
115
|
.action(async (opts) => {
|
|
112
116
|
try {
|
|
@@ -132,7 +136,7 @@ async function main() {
|
|
|
132
136
|
});
|
|
133
137
|
program
|
|
134
138
|
.command('create <app-name>')
|
|
135
|
-
.description(
|
|
139
|
+
.description(`Scaffold a new Z2H consumer app inside ${getWorkspaceHome()}/`)
|
|
136
140
|
.option('--template <name>', 'Template name (default | html-embed)')
|
|
137
141
|
.option('--html-file <path>', 'Path to an HTML file to embed (implies --template html-embed)')
|
|
138
142
|
.option('--remote <type>', 'Source control remote: s3 (shared storage) or github (your repo)')
|
|
@@ -150,6 +154,59 @@ async function main() {
|
|
|
150
154
|
await fail(`create failed: ${err.message}`, { command: 'create' }, 1);
|
|
151
155
|
}
|
|
152
156
|
});
|
|
157
|
+
program
|
|
158
|
+
.command('edit <app-name>')
|
|
159
|
+
.description(`Pull the latest version of an app into ${getWorkspaceHome()}/<app-name>, cloning it first if needed`)
|
|
160
|
+
.option('--json', 'emit structured JSON on stdout')
|
|
161
|
+
.action(async (appName, opts) => {
|
|
162
|
+
try {
|
|
163
|
+
await trackDuration('z2h_app_edit_pulled', () => editCommand(appName, opts), {
|
|
164
|
+
app_name: appName,
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
catch (err) {
|
|
168
|
+
await fail(`edit failed: ${err.message}`, { command: 'edit' }, 1);
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
program
|
|
172
|
+
.command('grant [email]')
|
|
173
|
+
.description('Grant access to the current app (email, --public, or both)')
|
|
174
|
+
.option('--public', 'make the app visible to all monday.com employees')
|
|
175
|
+
.option('--level <level>', 'access level for user grants: owner, editor, or viewer (default: viewer)')
|
|
176
|
+
.option('--json', 'emit structured JSON on stdout')
|
|
177
|
+
.action(async (email, opts) => {
|
|
178
|
+
try {
|
|
179
|
+
await grantCommand(email, opts);
|
|
180
|
+
}
|
|
181
|
+
catch (err) {
|
|
182
|
+
await fail(`grant failed: ${err.message}`, { command: 'grant' }, 1);
|
|
183
|
+
}
|
|
184
|
+
});
|
|
185
|
+
program
|
|
186
|
+
.command('revoke [email]')
|
|
187
|
+
.description('Revoke access to the current app (email or --public; owners/admins only)')
|
|
188
|
+
.option('--public', 'remove the public grant, making the app visible to owners/admins only')
|
|
189
|
+
.option('--json', 'emit structured JSON on stdout')
|
|
190
|
+
.action(async (email, opts) => {
|
|
191
|
+
try {
|
|
192
|
+
await revokeCommand(email, opts);
|
|
193
|
+
}
|
|
194
|
+
catch (err) {
|
|
195
|
+
await fail(`revoke failed: ${err.message}`, { command: 'revoke' }, 1);
|
|
196
|
+
}
|
|
197
|
+
});
|
|
198
|
+
program
|
|
199
|
+
.command('transfer-owner [email]')
|
|
200
|
+
.description('Transfer ownership of the current app to another monday.com user')
|
|
201
|
+
.option('--json', 'emit structured JSON on stdout')
|
|
202
|
+
.action(async (email, opts) => {
|
|
203
|
+
try {
|
|
204
|
+
await transferOwnerCommand(email, opts);
|
|
205
|
+
}
|
|
206
|
+
catch (err) {
|
|
207
|
+
await fail(`transfer-owner failed: ${err.message}`, { command: 'transfer-owner' }, 1);
|
|
208
|
+
}
|
|
209
|
+
});
|
|
153
210
|
program
|
|
154
211
|
.command('migrate')
|
|
155
212
|
.description('Run pending workspace migrations')
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prepare.d.ts","sourceRoot":"","sources":["../../../src/shadow/prepare.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAA8B,cAAc,EAAkB,MAAM,UAAU,CAAC;AAE3F,wBAAsB,aAAa,
|
|
1
|
+
{"version":3,"file":"prepare.d.ts","sourceRoot":"","sources":["../../../src/shadow/prepare.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAA8B,cAAc,EAAkB,MAAM,UAAU,CAAC;AAE3F,wBAAsB,aAAa,CAAC,WAAW,GAAE,MAAsB,GAAG,OAAO,CAAC,cAAc,CAAC,CAgChG"}
|
|
@@ -9,8 +9,8 @@ import { readMetadata, writeMetadata } from './metadata.mjs';
|
|
|
9
9
|
import { isPortFree, pickPort } from './port.mjs';
|
|
10
10
|
import { syncShadow } from './sync.mjs';
|
|
11
11
|
|
|
12
|
-
async function prepareShadow() {
|
|
13
|
-
const paths = resolveConsumerPaths(
|
|
12
|
+
async function prepareShadow(consumerDir = process.cwd()) {
|
|
13
|
+
const paths = resolveConsumerPaths(consumerDir);
|
|
14
14
|
if (!(await pathExists(paths.consumerPkg))) {
|
|
15
15
|
throw new Error(`No package.json found in ${paths.consumerDir}`);
|
|
16
16
|
}
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* e.g. `@trident/customer-viewer` → `customer-viewer`, `foo` → `foo`.
|
|
4
4
|
*/
|
|
5
5
|
export declare function cleanAppName(name: string): string;
|
|
6
|
+
export declare function getCwdAppName(): string | undefined;
|
|
6
7
|
/**
|
|
7
8
|
* Canonical MF bundle name: the de-scoped app name with an `mf-` prefix.
|
|
8
9
|
* This matches the trident convention (shadow pkg is `@trident/mf-<app>`,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app-name.d.ts","sourceRoot":"","sources":["../../../src/util/app-name.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"app-name.d.ts","sourceRoot":"","sources":["../../../src/util/app-name.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED,wBAAgB,aAAa,IAAI,MAAM,GAAG,SAAS,CAMlD;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE9C"}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* Strip any npm scope (`@scope/`) from a package name.
|
|
3
5
|
* e.g. `@trident/customer-viewer` → `customer-viewer`, `foo` → `foo`.
|
|
@@ -5,6 +7,14 @@
|
|
|
5
7
|
function cleanAppName(name) {
|
|
6
8
|
return name.replace(/^@[^/]+\//, '');
|
|
7
9
|
}
|
|
10
|
+
function getCwdAppName() {
|
|
11
|
+
try {
|
|
12
|
+
return JSON.parse(readFileSync('package.json', 'utf8')).name;
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
return undefined;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
8
18
|
/**
|
|
9
19
|
* Canonical MF bundle name: the de-scoped app name with an `mf-` prefix.
|
|
10
20
|
* This matches the trident convention (shadow pkg is `@trident/mf-<app>`,
|
|
@@ -14,4 +24,4 @@ function mfAppName(name) {
|
|
|
14
24
|
return `mf-${cleanAppName(name)}`;
|
|
15
25
|
}
|
|
16
26
|
|
|
17
|
-
export { cleanAppName, mfAppName };
|
|
27
|
+
export { cleanAppName, getCwdAppName, mfAppName };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth-store.d.ts","sourceRoot":"","sources":["../../../../src/util/auth/auth-store.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,YAAY,QAAkC,CAAC;AAC5D,eAAO,MAAM,aAAa,QAAuC,CAAC;AAElE,MAAM,WAAW,OAAO;IACtB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,qBAAa,mBAAoB,SAAQ,KAAK;aAChB,YAAY,EAAE,MAAM;gBAApB,YAAY,EAAE,MAAM;CAIjD;AAED,wBAAsB,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC,
|
|
1
|
+
{"version":3,"file":"auth-store.d.ts","sourceRoot":"","sources":["../../../../src/util/auth/auth-store.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,YAAY,QAAkC,CAAC;AAC5D,eAAO,MAAM,aAAa,QAAuC,CAAC;AAElE,MAAM,WAAW,OAAO;IACtB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,qBAAa,mBAAoB,SAAQ,KAAK;aAChB,YAAY,EAAE,MAAM;gBAApB,YAAY,EAAE,MAAM;CAIjD;AAED,wBAAsB,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC,CAkBpD;AAED;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,GAAG,IAAI,CAUpD"}
|
|
@@ -16,6 +16,13 @@ class Z2hAuthMissingError extends Error {
|
|
|
16
16
|
}
|
|
17
17
|
}
|
|
18
18
|
async function readZthAuth() {
|
|
19
|
+
if (process.env.Z2H_AUTH_TOKEN) {
|
|
20
|
+
const token = process.env.Z2H_AUTH_TOKEN;
|
|
21
|
+
if (!/^[\w-]+\.[\w-]+\.[\w-]+$/.test(token)) {
|
|
22
|
+
throw new Error('Z2H_AUTH_TOKEN is not a valid JWT (expected three dot-separated segments). Please re-set the environment variable.');
|
|
23
|
+
}
|
|
24
|
+
return { token };
|
|
25
|
+
}
|
|
19
26
|
if (!(await pathExists(Z2H_AUTH_FILE))) {
|
|
20
27
|
throw new Z2hAuthMissingError(Z2H_AUTH_FILE);
|
|
21
28
|
}
|
|
@@ -35,6 +42,9 @@ async function readZthAuth() {
|
|
|
35
42
|
* blow up — and where an inline sync read keeps the spawn call site simple.
|
|
36
43
|
*/
|
|
37
44
|
function tryReadAuthTokenSync() {
|
|
45
|
+
if (process.env.Z2H_AUTH_TOKEN) {
|
|
46
|
+
return process.env.Z2H_AUTH_TOKEN;
|
|
47
|
+
}
|
|
38
48
|
try {
|
|
39
49
|
const parsed = readJsonSync(Z2H_AUTH_FILE);
|
|
40
50
|
return parsed?.token ?? null;
|
|
@@ -1,9 +1,17 @@
|
|
|
1
1
|
import type { AwsCredentialIdentityProvider } from '@aws-sdk/types';
|
|
2
2
|
export declare const STS_BROKER_PATH = "/z2h-cli/sts/credentials";
|
|
3
|
+
export declare const DEPLOY_VERSION_PATH = "/z2h-cli/apps/version";
|
|
4
|
+
/**
|
|
5
|
+
* Reserve the version this deploy will write to. Split out of the STS
|
|
6
|
+
* credentials call so version derivation lives on its own endpoint — the CLI
|
|
7
|
+
* asks for the version first, then requests credentials scoped to it.
|
|
8
|
+
*/
|
|
9
|
+
export declare function fetchDeployVersion(appName: string): Promise<number>;
|
|
3
10
|
/**
|
|
4
11
|
* AWS SDK credential provider that fetches short-lived deploy credentials
|
|
5
|
-
* from the bigbrain-zth STS broker
|
|
6
|
-
* 5 minutes before expiry; concurrent calls share a
|
|
12
|
+
* from the bigbrain-zth STS broker for a specific version. Credentials are
|
|
13
|
+
* cached in memory until 5 minutes before expiry; concurrent calls share a
|
|
14
|
+
* single in-flight fetch.
|
|
7
15
|
*/
|
|
8
16
|
export declare function brokerCredentialProvider({ appName }: {
|
|
9
17
|
appName: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"broker-credential-provider.d.ts","sourceRoot":"","sources":["../../../../src/util/auth/broker-credential-provider.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAyB,6BAA6B,EAAE,MAAM,gBAAgB,CAAC;AAE3F,eAAO,MAAM,eAAe,6BAA6B,CAAC;
|
|
1
|
+
{"version":3,"file":"broker-credential-provider.d.ts","sourceRoot":"","sources":["../../../../src/util/auth/broker-credential-provider.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAyB,6BAA6B,EAAE,MAAM,gBAAgB,CAAC;AAE3F,eAAO,MAAM,eAAe,6BAA6B,CAAC;AAC1D,eAAO,MAAM,mBAAmB,0BAA0B,CAAC;AA4C3D;;;;GAIG;AACH,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAUzE;AAuBD;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,EAAE,OAAO,EAAE,EAAE;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG,6BAA6B,CAuBxG"}
|
|
@@ -1,32 +1,53 @@
|
|
|
1
|
-
import { brokerBaseUrl } from '../../constants.mjs';
|
|
1
|
+
import { brokerBaseUrl, routingHeaders } from '../../constants.mjs';
|
|
2
2
|
import { readZthAuth } from './auth-store.mjs';
|
|
3
3
|
|
|
4
4
|
const STS_BROKER_PATH = '/z2h-cli/sts/credentials';
|
|
5
|
+
const DEPLOY_VERSION_PATH = '/z2h-cli/apps/version';
|
|
5
6
|
// Refresh the cached credentials this many ms before they expire so the next
|
|
6
7
|
// AWS API call doesn't race the broker round-trip against a hard expiry.
|
|
7
8
|
const REFRESH_BUFFER_MS = 5 * 60 * 1000;
|
|
8
|
-
async function
|
|
9
|
+
async function postToBroker(path, body) {
|
|
9
10
|
const { token } = await readZthAuth();
|
|
10
|
-
const url = `${brokerBaseUrl()}${STS_BROKER_PATH}`;
|
|
11
|
-
let res;
|
|
12
11
|
try {
|
|
13
|
-
|
|
12
|
+
return await fetch(`${brokerBaseUrl()}${path}`, {
|
|
14
13
|
method: 'POST',
|
|
15
14
|
headers: {
|
|
16
15
|
Authorization: `Bearer ${token}`,
|
|
17
16
|
'Content-Type': 'application/json',
|
|
18
17
|
Accept: 'application/json',
|
|
18
|
+
...routingHeaders(),
|
|
19
19
|
},
|
|
20
|
-
body: JSON.stringify(
|
|
20
|
+
body: JSON.stringify(body),
|
|
21
21
|
});
|
|
22
22
|
}
|
|
23
23
|
catch (err) {
|
|
24
24
|
const message = err instanceof Error ? err.message : String(err);
|
|
25
25
|
throw new Error(`Z2H deploy broker request failed: ${message}`);
|
|
26
26
|
}
|
|
27
|
+
}
|
|
28
|
+
function assertBrokerOk(res) {
|
|
27
29
|
if (res.status === 401 || res.status === 403) {
|
|
28
30
|
throw new Error(`Z2H deploy token rejected by the broker (${res.status}). Refresh user token by running 'z2h-cli generate-z2h-token'.`);
|
|
29
31
|
}
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Reserve the version this deploy will write to. Split out of the STS
|
|
35
|
+
* credentials call so version derivation lives on its own endpoint — the CLI
|
|
36
|
+
* asks for the version first, then requests credentials scoped to it.
|
|
37
|
+
*/
|
|
38
|
+
async function fetchDeployVersion(appName) {
|
|
39
|
+
const res = await postToBroker(DEPLOY_VERSION_PATH, { appName });
|
|
40
|
+
assertBrokerOk(res);
|
|
41
|
+
if (!res.ok) {
|
|
42
|
+
const text = await res.text();
|
|
43
|
+
throw new Error(`Z2H deploy broker returned ${res.status}: ${text.slice(0, 1024)}`);
|
|
44
|
+
}
|
|
45
|
+
const body = (await res.json());
|
|
46
|
+
return body.version ?? 0;
|
|
47
|
+
}
|
|
48
|
+
async function fetchStsOnce(appName) {
|
|
49
|
+
const res = await postToBroker(STS_BROKER_PATH, { appName });
|
|
50
|
+
assertBrokerOk(res);
|
|
30
51
|
if (!res.ok) {
|
|
31
52
|
const text = await res.text();
|
|
32
53
|
throw new Error(`Z2H deploy broker returned ${res.status}: ${text.slice(0, 1024)}`);
|
|
@@ -44,8 +65,9 @@ async function fetchCredentialsOnce(appName) {
|
|
|
44
65
|
}
|
|
45
66
|
/**
|
|
46
67
|
* AWS SDK credential provider that fetches short-lived deploy credentials
|
|
47
|
-
* from the bigbrain-zth STS broker
|
|
48
|
-
* 5 minutes before expiry; concurrent calls share a
|
|
68
|
+
* from the bigbrain-zth STS broker for a specific version. Credentials are
|
|
69
|
+
* cached in memory until 5 minutes before expiry; concurrent calls share a
|
|
70
|
+
* single in-flight fetch.
|
|
49
71
|
*/
|
|
50
72
|
function brokerCredentialProvider({ appName }) {
|
|
51
73
|
let cached;
|
|
@@ -58,10 +80,10 @@ function brokerCredentialProvider({ appName }) {
|
|
|
58
80
|
if (inflight) {
|
|
59
81
|
return inflight;
|
|
60
82
|
}
|
|
61
|
-
inflight =
|
|
62
|
-
.then(
|
|
63
|
-
cached =
|
|
64
|
-
return
|
|
83
|
+
inflight = fetchStsOnce(appName)
|
|
84
|
+
.then(credentials => {
|
|
85
|
+
cached = credentials;
|
|
86
|
+
return credentials;
|
|
65
87
|
})
|
|
66
88
|
.finally(() => {
|
|
67
89
|
inflight = undefined;
|
|
@@ -70,4 +92,4 @@ function brokerCredentialProvider({ appName }) {
|
|
|
70
92
|
};
|
|
71
93
|
}
|
|
72
94
|
|
|
73
|
-
export { STS_BROKER_PATH, brokerCredentialProvider };
|
|
95
|
+
export { DEPLOY_VERSION_PATH, STS_BROKER_PATH, brokerCredentialProvider, fetchDeployVersion };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export interface AppInfo {
|
|
2
|
+
appName: string;
|
|
3
|
+
version: number;
|
|
4
|
+
entry: Record<string, unknown>;
|
|
5
|
+
deployedBy: string;
|
|
6
|
+
gitRemote: string;
|
|
7
|
+
createdBy: string;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Fetches a single app's current state from the broker.
|
|
11
|
+
* Returns null if the app has never been deployed (404).
|
|
12
|
+
*/
|
|
13
|
+
export declare function fetchApp(appName: string): Promise<AppInfo | null>;
|
|
14
|
+
//# sourceMappingURL=app.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../../../../src/util/broker/app.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,OAAO;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;GAGG;AACH,wBAAsB,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAiBvE"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { brokerBaseUrl, routingHeaders } from '../../constants.mjs';
|
|
2
|
+
import { readZthAuth } from '../auth/auth-store.mjs';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Fetches a single app's current state from the broker.
|
|
6
|
+
* Returns null if the app has never been deployed (404).
|
|
7
|
+
*/
|
|
8
|
+
async function fetchApp(appName) {
|
|
9
|
+
const { token } = await readZthAuth();
|
|
10
|
+
const res = await fetch(`${brokerBaseUrl()}/z2h-cli/apps/${encodeURIComponent(appName)}`, {
|
|
11
|
+
headers: {
|
|
12
|
+
Authorization: `Bearer ${token}`,
|
|
13
|
+
Accept: 'application/json',
|
|
14
|
+
...routingHeaders(),
|
|
15
|
+
},
|
|
16
|
+
});
|
|
17
|
+
if (res.status === 404) {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
if (!res.ok) {
|
|
21
|
+
const text = await res.text();
|
|
22
|
+
throw new Error(`Z2H app lookup failed (${res.status}): ${text.slice(0, 512)}`);
|
|
23
|
+
}
|
|
24
|
+
return res.json();
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export { fetchApp };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Builds the AWS_* environment that `git-remote-s3` needs to talk to an S3-backed
|
|
3
|
+
* git remote, by minting short-lived broker credentials scoped to the app.
|
|
4
|
+
*
|
|
5
|
+
* Returns `undefined` for non-S3 remotes (GitHub apps ride the user's own git
|
|
6
|
+
* credential helper) and when there is no remote at all.
|
|
7
|
+
*/
|
|
8
|
+
export declare function resolveGitEnv(appName: string, gitRemote: string | undefined): Promise<Record<string, string> | undefined>;
|
|
9
|
+
//# sourceMappingURL=git-env.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git-env.d.ts","sourceRoot":"","sources":["../../../../src/util/git/git-env.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,wBAAsB,aAAa,CACjC,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,GAAG,SAAS,GAC5B,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CAAC,CAU7C"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { brokerCredentialProvider } from '../auth/broker-credential-provider.mjs';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Builds the AWS_* environment that `git-remote-s3` needs to talk to an S3-backed
|
|
5
|
+
* git remote, by minting short-lived broker credentials scoped to the app.
|
|
6
|
+
*
|
|
7
|
+
* Returns `undefined` for non-S3 remotes (GitHub apps ride the user's own git
|
|
8
|
+
* credential helper) and when there is no remote at all.
|
|
9
|
+
*/
|
|
10
|
+
async function resolveGitEnv(appName, gitRemote) {
|
|
11
|
+
if (!gitRemote?.startsWith('s3://')) {
|
|
12
|
+
return undefined;
|
|
13
|
+
}
|
|
14
|
+
const creds = await brokerCredentialProvider({ appName })();
|
|
15
|
+
return {
|
|
16
|
+
AWS_ACCESS_KEY_ID: creds.accessKeyId,
|
|
17
|
+
AWS_SECRET_ACCESS_KEY: creds.secretAccessKey,
|
|
18
|
+
AWS_SESSION_TOKEN: creds.sessionToken ?? '',
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export { resolveGitEnv };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export declare const REMOTE_TYPES: readonly ["s3", "github"];
|
|
2
|
+
export type RemoteType = (typeof REMOTE_TYPES)[number];
|
|
3
|
+
export interface RemoteOptions {
|
|
4
|
+
remote?: RemoteType;
|
|
5
|
+
repoUrl?: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Validates --remote and --repo-url option values.
|
|
9
|
+
* Pass `requireRemote: true` when the flag is mandatory (e.g. create).
|
|
10
|
+
*/
|
|
11
|
+
export declare function validateRemoteOptions(opts: RemoteOptions, requireRemote?: boolean): void;
|
|
12
|
+
/**
|
|
13
|
+
* Resolves the git remote URL from --remote / --repo-url options.
|
|
14
|
+
* Call after validateRemoteOptions.
|
|
15
|
+
*/
|
|
16
|
+
export declare function resolveRemoteUrl(remote: RemoteType, appName: string, repoUrl?: string): string;
|
|
17
|
+
//# sourceMappingURL=remote-options.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"remote-options.d.ts","sourceRoot":"","sources":["../../../../src/util/git/remote-options.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,YAAY,2BAA4B,CAAC;AAEtD,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC;AAEvD,MAAM,WAAW,aAAa;IAC5B,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,aAAa,EAAE,aAAa,UAAQ,GAAG,IAAI,CAatF;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAE9F"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { defaultS3Remote } from './repo.mjs';
|
|
2
|
+
|
|
3
|
+
const REMOTE_TYPES = ['s3', 'github'];
|
|
4
|
+
/**
|
|
5
|
+
* Validates --remote and --repo-url option values.
|
|
6
|
+
* Pass `requireRemote: true` when the flag is mandatory (e.g. create).
|
|
7
|
+
*/
|
|
8
|
+
function validateRemoteOptions(opts, requireRemote = false) {
|
|
9
|
+
if (!opts.remote) {
|
|
10
|
+
if (requireRemote) {
|
|
11
|
+
throw new Error(`--remote is required. Use --remote=s3 (shared storage) or --remote=github (your GitHub repo).`);
|
|
12
|
+
}
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
if (!REMOTE_TYPES.includes(opts.remote)) {
|
|
16
|
+
throw new Error(`Unknown remote "${opts.remote}". Use ${REMOTE_TYPES.join(' or ')}.`);
|
|
17
|
+
}
|
|
18
|
+
if (opts.remote === 'github' && !opts.repoUrl) {
|
|
19
|
+
throw new Error('--repo-url is required when using --remote=github.');
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Resolves the git remote URL from --remote / --repo-url options.
|
|
24
|
+
* Call after validateRemoteOptions.
|
|
25
|
+
*/
|
|
26
|
+
function resolveRemoteUrl(remote, appName, repoUrl) {
|
|
27
|
+
return remote === 's3' ? defaultS3Remote(appName) : repoUrl;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export { REMOTE_TYPES, resolveRemoteUrl, validateRemoteOptions };
|
|
@@ -1,13 +1,31 @@
|
|
|
1
1
|
export declare class GitConflictError extends Error {
|
|
2
2
|
constructor(message: string);
|
|
3
3
|
}
|
|
4
|
+
export interface ConflictInfo {
|
|
5
|
+
localCommits: string[];
|
|
6
|
+
remoteCommits: string[];
|
|
7
|
+
conflictingFiles: string[];
|
|
8
|
+
}
|
|
4
9
|
export declare function defaultS3Remote(app: string): string;
|
|
5
10
|
export declare function initRepo(dir: string, remote: string): Promise<void>;
|
|
6
11
|
export declare function getRemoteUrl(dir: string): Promise<string | undefined>;
|
|
7
|
-
|
|
12
|
+
/**
|
|
13
|
+
* Throws if the working tree has uncommitted changes. Call only on a known git
|
|
14
|
+
* repo (e.g. guarded by a resolved remote) — a failing `git status` propagates
|
|
15
|
+
* rather than being silently treated as "clean".
|
|
16
|
+
*/
|
|
17
|
+
export declare function guardCleanTree(dir: string): Promise<void>;
|
|
18
|
+
export declare function cloneRepo(remote: string, dir: string, env?: Record<string, string>): Promise<void>;
|
|
8
19
|
export declare function safeBackupIfDirty(dir: string): Promise<void>;
|
|
9
|
-
export declare function pullAndResolve(dir: string): Promise<void>;
|
|
20
|
+
export declare function pullAndResolve(dir: string, env?: Record<string, string>): Promise<void>;
|
|
21
|
+
/**
|
|
22
|
+
* Pushes the local master branch to origin. On a rejected (non-fast-forward) push —
|
|
23
|
+
* i.e. a deploy landed while we were building — gathers structured conflict info and
|
|
24
|
+
* throws GitConflictError so the deploy stops before anything goes live (spec: push
|
|
25
|
+
* must stop the deploy before the bundle upload). The skill re-resolves and re-runs,
|
|
26
|
+
* which rebuilds against the latest. Non-conflict push errors re-throw as-is.
|
|
27
|
+
*/
|
|
28
|
+
export declare function pushToRemote(dir: string, env?: Record<string, string>): Promise<void>;
|
|
10
29
|
export declare function remoteHead(dir: string): Promise<string>;
|
|
11
30
|
export declare function localHead(dir: string): Promise<string>;
|
|
12
|
-
export declare function commitDetailedAndPush(dir: string, version: number): Promise<void>;
|
|
13
31
|
//# sourceMappingURL=repo.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"repo.d.ts","sourceRoot":"","sources":["../../../../src/util/git/repo.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"repo.d.ts","sourceRoot":"","sources":["../../../../src/util/git/repo.ts"],"names":[],"mappings":"AAkBA,qBAAa,gBAAiB,SAAQ,KAAK;gBAC7B,OAAO,EAAE,MAAM;CAI5B;AAED,MAAM,WAAW,YAAY;IAC3B,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,gBAAgB,EAAE,MAAM,EAAE,CAAC;CAC5B;AAKD,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED,wBAAsB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAOzE;AAED,wBAAsB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAI3E;AAED;;;;GAIG;AACH,wBAAsB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAK/D;AAED,wBAAsB,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAG5G;AAED,wBAAsB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAclE;AAED,wBAAsB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAe7F;AAED;;;;;;GAMG;AACH,wBAAsB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAqB3F;AAED,wBAAsB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAO7D;AAED,wBAAsB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAG5D"}
|