@ze-norm/cli 0.13.0 → 0.14.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/api/client.d.ts.map +1 -1
- package/dist/api/client.js +16 -6
- package/dist/auth/device-flow.d.ts.map +1 -1
- package/dist/auth/device-flow.js +11 -0
- package/dist/auth/store.d.ts.map +1 -1
- package/dist/auth/store.js +7 -1
- package/dist/config/environments.d.ts +31 -0
- package/dist/config/environments.d.ts.map +1 -0
- package/dist/config/environments.js +65 -0
- package/package.json +1 -1
package/dist/api/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"AA0BA,kFAAkF;AAClF,wBAAgB,qBAAqB,IAAI,IAAI,CAE5C;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAiCD,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,qBAAa,YAAY;IACvB,OAAO,CAAC,OAAO,CAAS;IAIxB,OAAO,CAAC,aAAa,CAAgB;gBAEzB,IAAI,CAAC,EAAE,gBAAgB;IAKnC,wEAAwE;YAC1D,mBAAmB;IAMjC,OAAO,CAAC,YAAY;IA0BpB,OAAO,CAAC,cAAc;IAStB,2EAA2E;IAC3E,gBAAgB,IAAI,OAAO;IAI3B,uEAAuE;IACvE,qBAAqB,IAAI,OAAO;IAYhC,OAAO,CAAC,2BAA2B;YAIrB,QAAQ;YAqBR,OAAO;IAqEf,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC;IAIhC,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC;IAIjD,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC;IAIhD,KAAK,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC;IAIlD,MAAM,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC;IAIzC;;OAEG;IACG,cAAc,IAAI,OAAO,CAAC,WAAW,CAAC;CAG7C"}
|
package/dist/api/client.js
CHANGED
|
@@ -3,6 +3,7 @@ import { join } from "node:path";
|
|
|
3
3
|
import { ApiError, AuthError, UpgradeRequiredError } from "../util/errors.js";
|
|
4
4
|
import { forceRefreshToken, hasRefreshableCredentials, resolveValidToken, } from "../auth/store.js";
|
|
5
5
|
import { PRODUCTION_API_URL } from "../config/defaults.js";
|
|
6
|
+
import { resolveEnvironment, ZENORM_CLI_ENV_VAR } from "../config/environments.js";
|
|
6
7
|
import { getCliVersion } from "../util/package.js";
|
|
7
8
|
import { log } from "../util/logger.js";
|
|
8
9
|
const UPGRADE_COMMAND = "npm install -g @ze-norm/cli@latest";
|
|
@@ -23,11 +24,17 @@ function resolveBaseUrl(explicit) {
|
|
|
23
24
|
// 1. Explicit option
|
|
24
25
|
if (explicit)
|
|
25
26
|
return explicit;
|
|
26
|
-
// 2.
|
|
27
|
+
// 2. Named environment via ZENORM_CLI. A selected environment is an explicit
|
|
28
|
+
// "talk to this stack" intent, so its API URL wins over a stray
|
|
29
|
+
// ZENORM_API_URL / .zenorm.json left over from another workflow.
|
|
30
|
+
if (process.env[ZENORM_CLI_ENV_VAR]) {
|
|
31
|
+
return resolveEnvironment().apiUrl;
|
|
32
|
+
}
|
|
33
|
+
// 3. Environment variable
|
|
27
34
|
const envUrl = process.env["ZENORM_API_URL"];
|
|
28
35
|
if (envUrl)
|
|
29
36
|
return envUrl;
|
|
30
|
-
//
|
|
37
|
+
// 4. .zenorm.json config file in cwd
|
|
31
38
|
const configPath = join(process.cwd(), ".zenorm.json");
|
|
32
39
|
if (existsSync(configPath)) {
|
|
33
40
|
const raw = readFileSync(configPath, "utf-8");
|
|
@@ -35,7 +42,7 @@ function resolveBaseUrl(explicit) {
|
|
|
35
42
|
if (config.apiUrl)
|
|
36
43
|
return config.apiUrl;
|
|
37
44
|
}
|
|
38
|
-
//
|
|
45
|
+
// 5. Public CLI default
|
|
39
46
|
return PRODUCTION_API_URL;
|
|
40
47
|
}
|
|
41
48
|
export class ZenormClient {
|
|
@@ -95,9 +102,12 @@ export class ZenormClient {
|
|
|
95
102
|
}
|
|
96
103
|
/** True when requests will intentionally ignore stored credentials. */
|
|
97
104
|
isUsingLocalDevBypass() {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
105
|
+
// Selecting the `local` environment implies dev-bypass — that is what the
|
|
106
|
+
// local stack is (no real Clerk sign-in, dev-bypass headers). An explicit
|
|
107
|
+
// ZENORM_LOCAL_DEV_BYPASS_AUTH still enables it for a raw localhost URL.
|
|
108
|
+
const bypassEnabled = process.env["ZENORM_LOCAL_DEV_BYPASS_AUTH"] === "true" ||
|
|
109
|
+
resolveEnvironment().name === "local";
|
|
110
|
+
return (this.isLocalBaseUrl() && bypassEnabled && !process.env["ZENORM_API_TOKEN"]);
|
|
101
111
|
}
|
|
102
112
|
shouldBypassAuthForLocalDev() {
|
|
103
113
|
return this.isUsingLocalDevBypass();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"device-flow.d.ts","sourceRoot":"","sources":["../../src/auth/device-flow.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"device-flow.d.ts","sourceRoot":"","sources":["../../src/auth/device-flow.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AA6UpD;;;;;;;;GAQG;AACH,wBAAsB,kBAAkB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC;IACtE,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC,CAuBD;AAED;;;;;;;;;GASG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,iBAAiB,CAAC,CAkDpE"}
|
package/dist/auth/device-flow.js
CHANGED
|
@@ -5,6 +5,7 @@ import { platform } from "node:os";
|
|
|
5
5
|
import { URL, URLSearchParams } from "node:url";
|
|
6
6
|
import { log } from "../util/logger.js";
|
|
7
7
|
import { CLI_CALLBACK_PORTS, PRODUCTION_CLERK_CLIENT_ID, PRODUCTION_CLERK_ISSUER, } from "../config/defaults.js";
|
|
8
|
+
import { resolveEnvironment, ZENORM_CLI_ENV_VAR } from "../config/environments.js";
|
|
8
9
|
/**
|
|
9
10
|
* Find the first pre-registered callback port that is free to bind. Clerk
|
|
10
11
|
* matches redirect_uris exactly, so the local listener must use one of the
|
|
@@ -26,6 +27,11 @@ async function pickFreeCallbackPort() {
|
|
|
26
27
|
`Free one of them and run \`zenorm login\` again.`);
|
|
27
28
|
}
|
|
28
29
|
function getClerkIssuer() {
|
|
30
|
+
// A named environment (ZENORM_CLI) selects the whole Clerk instance, so it
|
|
31
|
+
// wins over a stray ZENORM_CLERK_ISSUER from another workflow.
|
|
32
|
+
if (process.env[ZENORM_CLI_ENV_VAR]) {
|
|
33
|
+
return resolveEnvironment().clerkIssuer;
|
|
34
|
+
}
|
|
29
35
|
return process.env["ZENORM_CLERK_ISSUER"] ?? PRODUCTION_CLERK_ISSUER;
|
|
30
36
|
}
|
|
31
37
|
/** Escape user-influenced text before interpolating into the result page HTML. */
|
|
@@ -38,6 +44,11 @@ function escapeHtml(value) {
|
|
|
38
44
|
.replace(/'/g, "'");
|
|
39
45
|
}
|
|
40
46
|
function getClerkClientId() {
|
|
47
|
+
// A named environment (ZENORM_CLI) selects the whole Clerk instance, so it
|
|
48
|
+
// wins over stray ZENORM_CLERK_CLIENT_ID / VITE_CLERK_PUBLISHABLE_KEY vars.
|
|
49
|
+
if (process.env[ZENORM_CLI_ENV_VAR]) {
|
|
50
|
+
return resolveEnvironment().clerkClientId;
|
|
51
|
+
}
|
|
41
52
|
return (process.env["ZENORM_CLERK_CLIENT_ID"] ??
|
|
42
53
|
process.env["VITE_CLERK_PUBLISHABLE_KEY"] ??
|
|
43
54
|
PRODUCTION_CLERK_CLIENT_ID);
|
package/dist/auth/store.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/auth/store.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/auth/store.ts"],"names":[],"mappings":"AAWA,MAAM,WAAW,iBAAiB;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAmBD,wBAAgB,eAAe,IAAI,iBAAiB,GAAG,IAAI,CAO1D;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,iBAAiB,GAAG,IAAI,CAM9D;AAED,wBAAgB,iBAAiB,IAAI,OAAO,CAO3C;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,IAAI,MAAM,GAAG,IAAI,CAU5C;AAWD;;;;;;;;;;GAUG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAwBhE;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,IAAI,OAAO,CAInD;AAED;;;;;;GAMG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,MAAM,CAAC,CAezD"}
|
package/dist/auth/store.js
CHANGED
|
@@ -2,12 +2,18 @@ import { existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync } from "
|
|
|
2
2
|
import { homedir } from "node:os";
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
import { refreshAccessToken } from "./device-flow.js";
|
|
5
|
+
import { resolveEnvironment } from "../config/environments.js";
|
|
5
6
|
import { log } from "../util/logger.js";
|
|
6
7
|
// Refresh the access token this many ms before it actually expires, so an
|
|
7
8
|
// in-flight request never races the expiry boundary.
|
|
8
9
|
const EXPIRY_SKEW_MS = 60_000;
|
|
10
|
+
// Credentials are scoped per environment so a prod login and a dev login can
|
|
11
|
+
// coexist instead of overwriting each other. Prod keeps the historical
|
|
12
|
+
// `credentials.json` filename for back-compat; other stacks get a suffix.
|
|
9
13
|
function getCredentialsPath() {
|
|
10
|
-
|
|
14
|
+
const env = resolveEnvironment();
|
|
15
|
+
const filename = env.name === "prod" ? "credentials.json" : `credentials.${env.name}.json`;
|
|
16
|
+
return join(homedir(), ".zenorm", filename);
|
|
11
17
|
}
|
|
12
18
|
function ensureDir() {
|
|
13
19
|
const dir = join(homedir(), ".zenorm");
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A named CLI environment: the full bundle of endpoints the CLI talks to.
|
|
3
|
+
* Selecting one via the `ZENORM_CLI` env var switches API + Clerk together, so
|
|
4
|
+
* you never have to keep `ZENORM_API_URL`, `ZENORM_CLERK_ISSUER`, and
|
|
5
|
+
* `ZENORM_CLERK_CLIENT_ID` in sync by hand.
|
|
6
|
+
*
|
|
7
|
+
* IMPORTANT: only the **prod** preset is baked into this (published) module.
|
|
8
|
+
* The non-prod stacks point at an internal Clerk instance whose identifiers
|
|
9
|
+
* must NOT ship in the public npm tarball (the publish pipeline greps the
|
|
10
|
+
* package for them and blocks the release). Those stacks are launched by the
|
|
11
|
+
* non-shipped source entries (`local.ts` / `dev.ts`, run via their repo shims),
|
|
12
|
+
* which inject `ZENORM_API_URL` + `ZENORM_CLERK_*` before importing the CLI.
|
|
13
|
+
* When `ZENORM_CLI` selects a non-prod stack, this resolver reads those
|
|
14
|
+
* injected vars instead of baking the endpoints in.
|
|
15
|
+
*/
|
|
16
|
+
export interface CliEnvironment {
|
|
17
|
+
readonly name: "prod" | "dev" | "local";
|
|
18
|
+
readonly apiUrl: string;
|
|
19
|
+
readonly clerkIssuer: string;
|
|
20
|
+
readonly clerkClientId: string;
|
|
21
|
+
}
|
|
22
|
+
export declare const ZENORM_CLI_ENV_VAR = "ZENORM_CLI";
|
|
23
|
+
/**
|
|
24
|
+
* Resolve the active CLI environment from `ZENORM_CLI`.
|
|
25
|
+
*
|
|
26
|
+
* Unset → production (the public default). A set-but-unrecognized value is a
|
|
27
|
+
* loud error rather than a silent fallback: a typo like `ZENORM_CLI=prd` must
|
|
28
|
+
* not quietly send `zenorm` commands at the wrong stack.
|
|
29
|
+
*/
|
|
30
|
+
export declare function resolveEnvironment(): CliEnvironment;
|
|
31
|
+
//# sourceMappingURL=environments.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"environments.d.ts","sourceRoot":"","sources":["../../src/config/environments.ts"],"names":[],"mappings":"AAOA;;;;;;;;;;;;;;GAcG;AACH,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,KAAK,GAAG,OAAO,CAAC;IACxC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;CAChC;AASD,eAAO,MAAM,kBAAkB,eAAe,CAAC;AAyC/C;;;;;;GAMG;AACH,wBAAgB,kBAAkB,IAAI,cAAc,CAiBnD"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { CliError } from "../util/errors.js";
|
|
2
|
+
import { PRODUCTION_API_URL, PRODUCTION_CLERK_CLIENT_ID, PRODUCTION_CLERK_ISSUER, } from "./defaults.js";
|
|
3
|
+
const PROD_ENVIRONMENT = {
|
|
4
|
+
name: "prod",
|
|
5
|
+
apiUrl: PRODUCTION_API_URL,
|
|
6
|
+
clerkIssuer: PRODUCTION_CLERK_ISSUER,
|
|
7
|
+
clerkClientId: PRODUCTION_CLERK_CLIENT_ID,
|
|
8
|
+
};
|
|
9
|
+
export const ZENORM_CLI_ENV_VAR = "ZENORM_CLI";
|
|
10
|
+
const ENV_NAMES = ["prod", "dev", "local"];
|
|
11
|
+
/**
|
|
12
|
+
* Normalize a raw `ZENORM_CLI` value to a canonical env name. Accepts the bare
|
|
13
|
+
* name (`prod`/`dev`/`local`), `production`, and each name with a `-zenorm`
|
|
14
|
+
* suffix (constructed here so the suffixed literal is never a static token).
|
|
15
|
+
*/
|
|
16
|
+
function parseEnvName(raw) {
|
|
17
|
+
const key = raw.trim().toLowerCase();
|
|
18
|
+
if (key === "production")
|
|
19
|
+
return "prod";
|
|
20
|
+
for (const name of ENV_NAMES) {
|
|
21
|
+
if (key === name || key === `${name}-zenorm`)
|
|
22
|
+
return name;
|
|
23
|
+
}
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Build a non-prod environment from the endpoint env vars injected by the
|
|
28
|
+
* repo launchers. Fails loud if they are missing — that means the public
|
|
29
|
+
* `zenorm` was pointed at an internal stack without the launcher that carries
|
|
30
|
+
* its (non-shipped) endpoints, and we must not silently fall back to prod.
|
|
31
|
+
*/
|
|
32
|
+
function environmentFromInjectedVars(name) {
|
|
33
|
+
const apiUrl = process.env["ZENORM_API_URL"];
|
|
34
|
+
const clerkIssuer = process.env["ZENORM_CLERK_ISSUER"];
|
|
35
|
+
const clerkClientId = process.env["ZENORM_CLERK_CLIENT_ID"];
|
|
36
|
+
if (!apiUrl || !clerkIssuer || !clerkClientId) {
|
|
37
|
+
const shim = `${name}${"-zenorm"}`;
|
|
38
|
+
throw new CliError(`${ZENORM_CLI_ENV_VAR}=${name} needs the ${name} endpoints, which are not ` +
|
|
39
|
+
`bundled in the public CLI. Launch it with \`${shim}\` (from the repo), ` +
|
|
40
|
+
`or set ZENORM_API_URL, ZENORM_CLERK_ISSUER, and ZENORM_CLERK_CLIENT_ID.`);
|
|
41
|
+
}
|
|
42
|
+
return { name, apiUrl, clerkIssuer, clerkClientId };
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Resolve the active CLI environment from `ZENORM_CLI`.
|
|
46
|
+
*
|
|
47
|
+
* Unset → production (the public default). A set-but-unrecognized value is a
|
|
48
|
+
* loud error rather than a silent fallback: a typo like `ZENORM_CLI=prd` must
|
|
49
|
+
* not quietly send `zenorm` commands at the wrong stack.
|
|
50
|
+
*/
|
|
51
|
+
export function resolveEnvironment() {
|
|
52
|
+
const raw = process.env[ZENORM_CLI_ENV_VAR];
|
|
53
|
+
if (raw === undefined || raw.trim() === "") {
|
|
54
|
+
return PROD_ENVIRONMENT;
|
|
55
|
+
}
|
|
56
|
+
const name = parseEnvName(raw);
|
|
57
|
+
if (!name) {
|
|
58
|
+
const allowed = ENV_NAMES.join(", ");
|
|
59
|
+
throw new CliError(`Invalid ${ZENORM_CLI_ENV_VAR}=${JSON.stringify(raw)}. ` +
|
|
60
|
+
`Expected one of: ${allowed} (or a "-zenorm" suffixed form).`);
|
|
61
|
+
}
|
|
62
|
+
if (name === "prod")
|
|
63
|
+
return PROD_ENVIRONMENT;
|
|
64
|
+
return environmentFromInjectedVars(name);
|
|
65
|
+
}
|