run402 2.5.1 → 2.7.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/lib/contracts.mjs +60 -0
- package/lib/deploy-v2.mjs +12 -1
- package/package.json +1 -1
- package/sdk/dist/namespaces/contracts.d.ts +42 -0
- package/sdk/dist/namespaces/contracts.d.ts.map +1 -1
- package/sdk/dist/namespaces/contracts.js +51 -0
- package/sdk/dist/namespaces/contracts.js.map +1 -1
- package/sdk/dist/namespaces/deploy.js +91 -1
- package/sdk/dist/namespaces/deploy.js.map +1 -1
- package/sdk/dist/namespaces/deploy.types.d.ts +59 -0
- package/sdk/dist/namespaces/deploy.types.d.ts.map +1 -1
- package/sdk/dist/namespaces/deploy.types.js.map +1 -1
- package/sdk/dist/node/deploy-manifest.d.ts +5 -2
- package/sdk/dist/node/deploy-manifest.d.ts.map +1 -1
- package/sdk/dist/node/deploy-manifest.js +27 -0
- package/sdk/dist/node/deploy-manifest.js.map +1 -1
- package/sdk/dist/scoped.d.ts +2 -1
- package/sdk/dist/scoped.d.ts.map +1 -1
- package/sdk/dist/scoped.js +3 -0
- package/sdk/dist/scoped.js.map +1 -1
package/lib/contracts.mjs
CHANGED
|
@@ -31,6 +31,8 @@ Subcommands:
|
|
|
31
31
|
Set the low-balance alert threshold (in wei).
|
|
32
32
|
call <project_id> <wallet_id> --to 0x... --abi <json> --fn <name> --args <json> [--value-wei <n>] [--idempotency-key <k>]
|
|
33
33
|
Submit a contract write call (chain gas + $0.000005 KMS sign fee).
|
|
34
|
+
deploy <project_id> <wallet_id> --bytecode 0x... [--chain <base-mainnet|base-sepolia>] [--value-wei <n>] [--idempotency-key <k>]
|
|
35
|
+
Deploy a contract (chain gas + $0.000005 KMS sign fee). Returns deterministic CREATE address synchronously.
|
|
34
36
|
read --chain <chain> --to 0x... --abi <json> --fn <name> --args <json>
|
|
35
37
|
Read-only contract call (free).
|
|
36
38
|
status <project_id> <call_id>
|
|
@@ -74,6 +76,28 @@ Usage:
|
|
|
74
76
|
Usage:
|
|
75
77
|
run402 contracts call <project_id> <wallet_id> --to 0x... --abi <json>
|
|
76
78
|
--fn <name> --args <json> [options]
|
|
79
|
+
`,
|
|
80
|
+
deploy: `run402 contracts deploy — Deploy a smart contract from a KMS wallet
|
|
81
|
+
|
|
82
|
+
KMS-signs a contract-creation transaction (to: null + data: bytecode) and broadcasts.
|
|
83
|
+
Returns the deterministic CREATE address synchronously — known from (wallet, nonce)
|
|
84
|
+
before the tx confirms. Cost: chain gas at-cost + $0.000005 KMS sign fee.
|
|
85
|
+
|
|
86
|
+
Usage:
|
|
87
|
+
run402 contracts deploy <project_id> <wallet_id> --bytecode 0x... [options]
|
|
88
|
+
|
|
89
|
+
Options:
|
|
90
|
+
--bytecode 0x... Full creation calldata as 0x-prefixed hex (creation
|
|
91
|
+
bytecode + ABI-encoded constructor args, concatenated
|
|
92
|
+
client-side via viem/ethers). Required. ≤ 128 KB.
|
|
93
|
+
--chain <chain> base-mainnet (default) or base-sepolia. Must match
|
|
94
|
+
the wallet's chain.
|
|
95
|
+
--value-wei <n> Optional native-token value in wei to attach.
|
|
96
|
+
--idempotency-key <k> Optional. Same key + same bytecode returns the
|
|
97
|
+
existing call without re-broadcasting.
|
|
98
|
+
|
|
99
|
+
run402 does NOT compile Solidity — bring your own bytecode (compile via
|
|
100
|
+
hardhat/foundry/solc then concat constructor args via viem/ethers).
|
|
77
101
|
`,
|
|
78
102
|
read: `run402 contracts read — Read-only contract call (free)
|
|
79
103
|
|
|
@@ -313,6 +337,41 @@ async function call(projectId, walletId, args) {
|
|
|
313
337
|
}
|
|
314
338
|
}
|
|
315
339
|
|
|
340
|
+
async function deploy(projectId, walletId, args) {
|
|
341
|
+
const parsedArgs = normalizeArgv(args);
|
|
342
|
+
const valueFlags = ["--bytecode", "--value-wei", "--chain", "--idempotency-key"];
|
|
343
|
+
assertKnownFlags(parsedArgs, [...valueFlags, "--help", "-h"], valueFlags);
|
|
344
|
+
const extra = positionalArgs(parsedArgs, valueFlags);
|
|
345
|
+
if (extra.length > 0) {
|
|
346
|
+
fail({ code: "BAD_USAGE", message: `Unexpected argument for contracts deploy: ${extra[0]}` });
|
|
347
|
+
}
|
|
348
|
+
const bytecode = flagValue(parsedArgs, "--bytecode");
|
|
349
|
+
const value = flagValue(parsedArgs, "--value-wei");
|
|
350
|
+
const chain = flagValue(parsedArgs, "--chain") || "base-mainnet";
|
|
351
|
+
const idempotency = flagValue(parsedArgs, "--idempotency-key");
|
|
352
|
+
if (!bytecode) {
|
|
353
|
+
fail({
|
|
354
|
+
code: "BAD_USAGE",
|
|
355
|
+
message: "Required flag: --bytecode (0x-prefixed hex; full creation calldata = creation bytecode + ABI-encoded constructor args, concatenated client-side).",
|
|
356
|
+
hint: "Cost: chain gas + $0.000005 KMS sign fee. Returns deterministic CREATE address synchronously.",
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
assertAllowedValue(chain, ["base-mainnet", "base-sepolia"], "--chain");
|
|
360
|
+
if (value !== null) validateWeiFlag("--value-wei", value);
|
|
361
|
+
try {
|
|
362
|
+
const data = await getSdk().contracts.deploy(projectId, {
|
|
363
|
+
walletId,
|
|
364
|
+
chain,
|
|
365
|
+
bytecode,
|
|
366
|
+
value: value ?? undefined,
|
|
367
|
+
idempotencyKey: idempotency ?? undefined,
|
|
368
|
+
});
|
|
369
|
+
console.log(JSON.stringify(data, null, 2));
|
|
370
|
+
} catch (err) {
|
|
371
|
+
reportSdkError(err);
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
|
|
316
375
|
async function read(args) {
|
|
317
376
|
const parsedArgs = normalizeArgv(args);
|
|
318
377
|
const valueFlags = ["--chain", "--to", "--abi", "--fn", "--args"];
|
|
@@ -418,6 +477,7 @@ export async function run(sub, args) {
|
|
|
418
477
|
case "set-recovery": await setRecovery(args[0], args[1], args.slice(2)); break;
|
|
419
478
|
case "set-alert": await setAlert(args[0], args[1], args.slice(2)); break;
|
|
420
479
|
case "call": await call(args[0], args[1], args.slice(2)); break;
|
|
480
|
+
case "deploy": await deploy(args[0], args[1], args.slice(2)); break;
|
|
421
481
|
case "read": await read(args); break;
|
|
422
482
|
case "status": await status(args[0], args[1], args.slice(2)); break;
|
|
423
483
|
case "drain": await drain(args[0], args[1], args.slice(2)); break;
|
package/lib/deploy-v2.mjs
CHANGED
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
* | { "public_paths": { "mode": "explicit", "replace": {} } },
|
|
15
15
|
* "subdomains": { "set": ["..."], "add": [...], "remove": [...] },
|
|
16
16
|
* "routes": { "replace": [{ "pattern": "/api/*", "methods": ["GET", "POST"], "target": { "type": "function", "name": "api" } }] },
|
|
17
|
+
* "i18n": { "defaultLocale": "en", "locales": ["en", "es"], "detect": ["cookie:wl_locale", "accept-language"] },
|
|
17
18
|
* "idempotency_key": "..."
|
|
18
19
|
* }
|
|
19
20
|
*
|
|
@@ -112,6 +113,14 @@ Routes:
|
|
|
112
113
|
Routed functions use Node 22 Fetch Request -> Response. req.url is the full public URL on managed domains, deployment hosts, and verified custom domains.
|
|
113
114
|
Routes activate atomically with the release. Direct /functions/v1/:name remains API-key protected.
|
|
114
115
|
Runtime route failure codes: ROUTE_MANIFEST_LOAD_FAILED, ROUTED_INVOKE_WORKER_SECRET_MISSING, ROUTED_INVOKE_AUTH_FAILED, ROUTED_ROUTE_STALE, ROUTE_METHOD_NOT_ALLOWED, ROUTED_RESPONSE_TOO_LARGE.
|
|
116
|
+
|
|
117
|
+
Internationalization (routed functions):
|
|
118
|
+
"i18n": { "defaultLocale": "en", "locales": ["en", "es", "fr"], "detect": ["cookie:wl_locale", "accept-language"] }
|
|
119
|
+
Omit i18n to carry forward from base release; pass "i18n": null to clear the slice on the new release.
|
|
120
|
+
defaultLocale MUST be byte-identical to one entry in locales[]. Locale tags must match /^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/, max 50 tags; no BCP-47 semantic validation.
|
|
121
|
+
detect[] (default ["accept-language"], max 10, [] means "always default"): walked in order, first match wins. Sources: "accept-language" and "cookie:<name>" (RFC 6265 cookie-name grammar).
|
|
122
|
+
Routed functions read the negotiated locale via request headers: req.headers.get("x-run402-locale") and req.headers.get("x-run402-default-locale"). Headers are omitted when no i18n slice is active.
|
|
123
|
+
Static-route hits do NOT receive locale negotiation; only routed HTTP function invocations do. Run402 does NOT inject Vary headers.
|
|
115
124
|
`;
|
|
116
125
|
|
|
117
126
|
const RESUME_HELP = `run402 deploy resume — Resume a stuck deploy operation
|
|
@@ -418,7 +427,7 @@ async function applyCmd(args) {
|
|
|
418
427
|
// For object-typed sections the "container is non-empty" check isn't enough
|
|
419
428
|
// — `site:{replace:{}}` has one key but ships nothing. We recurse one level
|
|
420
429
|
// so any object whose own values are all empty containers is still empty.
|
|
421
|
-
const meaningful = ["database", "site", "functions", "secrets", "subdomains", "routes", "checks"];
|
|
430
|
+
const meaningful = ["database", "site", "functions", "secrets", "subdomains", "routes", "checks", "i18n"];
|
|
422
431
|
function hasContent(v) {
|
|
423
432
|
if (v == null) return false;
|
|
424
433
|
if (Array.isArray(v)) return v.length > 0;
|
|
@@ -435,6 +444,8 @@ async function applyCmd(args) {
|
|
|
435
444
|
Object.prototype.hasOwnProperty.call(value, "replace") && Array.isArray(value.replace)) {
|
|
436
445
|
return true;
|
|
437
446
|
}
|
|
447
|
+
// `i18n: null` clears the slice — that's a valid deploy on its own.
|
|
448
|
+
if (key === "i18n" && value === null) return true;
|
|
438
449
|
return hasContent(value);
|
|
439
450
|
}
|
|
440
451
|
const hasMeaningfulContent = spec && typeof spec === "object" && !Array.isArray(spec) &&
|
package/package.json
CHANGED
|
@@ -73,6 +73,33 @@ export interface ContractCallOptions {
|
|
|
73
73
|
value?: string;
|
|
74
74
|
idempotencyKey?: string;
|
|
75
75
|
}
|
|
76
|
+
export interface ContractDeployOptions {
|
|
77
|
+
/** The cwlt_… ID of the KMS wallet that will sign + own the new contract. */
|
|
78
|
+
walletId: string;
|
|
79
|
+
/** The chain to deploy to. Must match the wallet's chain. */
|
|
80
|
+
chain: EvmChain;
|
|
81
|
+
/**
|
|
82
|
+
* Full creation calldata as a 0x-prefixed hex string: creation bytecode
|
|
83
|
+
* concatenated with ABI-encoded constructor args (the caller does the
|
|
84
|
+
* encoding via viem/ethers etc.). Non-empty, even-length, ≤ 128 KB.
|
|
85
|
+
*
|
|
86
|
+
* run402 does NOT compile Solidity — bring your own bytecode.
|
|
87
|
+
*/
|
|
88
|
+
bytecode: string;
|
|
89
|
+
/** Optional native-token value to attach to the deploy tx (in wei). */
|
|
90
|
+
value?: string;
|
|
91
|
+
/** Optional idempotency key — same key + same payload returns the existing call. */
|
|
92
|
+
idempotencyKey?: string;
|
|
93
|
+
}
|
|
94
|
+
export interface ContractDeployResult extends ContractCallResult {
|
|
95
|
+
/**
|
|
96
|
+
* The deterministic CREATE address derived from `(wallet.address, nonce)`.
|
|
97
|
+
* Returned synchronously — the caller knows where the new contract will
|
|
98
|
+
* live without waiting for confirmation. The reconciler verifies this
|
|
99
|
+
* matches the on-chain receipt's `contractAddress` on confirmation.
|
|
100
|
+
*/
|
|
101
|
+
contract_address: string;
|
|
102
|
+
}
|
|
76
103
|
export interface ContractReadOptions {
|
|
77
104
|
chain: EvmChain;
|
|
78
105
|
contractAddress?: string;
|
|
@@ -101,6 +128,21 @@ export declare class Contracts {
|
|
|
101
128
|
setLowBalanceAlert(projectId: string, walletId: string, thresholdWei: string): Promise<void>;
|
|
102
129
|
/** Submit a smart-contract write call. Idempotent on `idempotencyKey`. */
|
|
103
130
|
call(projectId: string, opts: ContractCallOptions): Promise<ContractCallResult>;
|
|
131
|
+
/**
|
|
132
|
+
* Deploy a contract from the wallet (KMS-signs a contract-creation tx).
|
|
133
|
+
*
|
|
134
|
+
* The `bytecode` is the full creation calldata — creation bytecode
|
|
135
|
+
* concatenated with ABI-encoded constructor args (the caller does the
|
|
136
|
+
* encoding via viem/ethers etc.; run402 does NOT compile Solidity).
|
|
137
|
+
*
|
|
138
|
+
* Returns synchronously with the deterministic CREATE address derived
|
|
139
|
+
* from `(wallet.address, nonce)` — no need to wait for confirmation
|
|
140
|
+
* to know where the contract will live. Reconciler verifies on receipt.
|
|
141
|
+
*
|
|
142
|
+
* Same pricing as `call`: chain gas at-cost + $0.000005 KMS sign fee.
|
|
143
|
+
* Idempotent on `idempotencyKey`.
|
|
144
|
+
*/
|
|
145
|
+
deploy(projectId: string, opts: ContractDeployOptions): Promise<ContractDeployResult>;
|
|
104
146
|
/** Read-only smart-contract call (view/pure). No auth, no gas, no billing. */
|
|
105
147
|
read(opts: ContractReadOptions): Promise<ContractReadResult>;
|
|
106
148
|
/** Look up a previously submitted call by id. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contracts.d.ts","sourceRoot":"","sources":["../../src/namespaces/contracts.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"contracts.d.ts","sourceRoot":"","sources":["../../src/namespaces/contracts.ts"],"names":[],"mappings":"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"}
|
|
@@ -130,6 +130,57 @@ export class Contracts {
|
|
|
130
130
|
context: "submitting contract call",
|
|
131
131
|
});
|
|
132
132
|
}
|
|
133
|
+
/**
|
|
134
|
+
* Deploy a contract from the wallet (KMS-signs a contract-creation tx).
|
|
135
|
+
*
|
|
136
|
+
* The `bytecode` is the full creation calldata — creation bytecode
|
|
137
|
+
* concatenated with ABI-encoded constructor args (the caller does the
|
|
138
|
+
* encoding via viem/ethers etc.; run402 does NOT compile Solidity).
|
|
139
|
+
*
|
|
140
|
+
* Returns synchronously with the deterministic CREATE address derived
|
|
141
|
+
* from `(wallet.address, nonce)` — no need to wait for confirmation
|
|
142
|
+
* to know where the contract will live. Reconciler verifies on receipt.
|
|
143
|
+
*
|
|
144
|
+
* Same pricing as `call`: chain gas at-cost + $0.000005 KMS sign fee.
|
|
145
|
+
* Idempotent on `idempotencyKey`.
|
|
146
|
+
*/
|
|
147
|
+
async deploy(projectId, opts) {
|
|
148
|
+
if (typeof opts.bytecode !== "string" || opts.bytecode.length === 0) {
|
|
149
|
+
throw new LocalError("contracts.deploy requires non-empty bytecode (hex string)", "deploying contract");
|
|
150
|
+
}
|
|
151
|
+
if (!/^0x[0-9a-fA-F]+$/.test(opts.bytecode)) {
|
|
152
|
+
throw new LocalError("contracts.deploy bytecode must be 0x-prefixed hex", "deploying contract");
|
|
153
|
+
}
|
|
154
|
+
if (opts.bytecode.length % 2 !== 0) {
|
|
155
|
+
throw new LocalError("contracts.deploy bytecode must be even-length hex", "deploying contract");
|
|
156
|
+
}
|
|
157
|
+
const MAX_BYTES = 128 * 1024;
|
|
158
|
+
if ((opts.bytecode.length - 2) / 2 > MAX_BYTES) {
|
|
159
|
+
throw new LocalError(`contracts.deploy bytecode exceeds ${MAX_BYTES}-byte cap`, "deploying contract");
|
|
160
|
+
}
|
|
161
|
+
assertStringInSet(opts.chain, EVM_CHAINS, "chain", "deploying contract");
|
|
162
|
+
const project = await this.client.getProject(projectId);
|
|
163
|
+
if (!project)
|
|
164
|
+
throw new ProjectNotFound(projectId, "deploying contract");
|
|
165
|
+
const headers = { Authorization: `Bearer ${project.service_key}` };
|
|
166
|
+
if (opts.idempotencyKey)
|
|
167
|
+
headers["Idempotency-Key"] = opts.idempotencyKey;
|
|
168
|
+
const body = {
|
|
169
|
+
wallet_id: opts.walletId,
|
|
170
|
+
chain: opts.chain,
|
|
171
|
+
bytecode: opts.bytecode,
|
|
172
|
+
};
|
|
173
|
+
if (opts.value !== undefined) {
|
|
174
|
+
assertWeiString(opts.value, "value", "deploying contract");
|
|
175
|
+
body.value = opts.value;
|
|
176
|
+
}
|
|
177
|
+
return this.client.request("/contracts/v1/deploy", {
|
|
178
|
+
method: "POST",
|
|
179
|
+
headers,
|
|
180
|
+
body,
|
|
181
|
+
context: "deploying contract",
|
|
182
|
+
});
|
|
183
|
+
}
|
|
133
184
|
/** Read-only smart-contract call (view/pure). No auth, no gas, no billing. */
|
|
134
185
|
async read(opts) {
|
|
135
186
|
const contractAddress = opts.contractAddress ?? opts.to;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contracts.js","sourceRoot":"","sources":["../../src/namespaces/contracts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC3D,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAGxF,MAAM,UAAU,GAAwB,CAAC,cAAc,EAAE,cAAc,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"contracts.js","sourceRoot":"","sources":["../../src/namespaces/contracts.ts"],"names":[],"mappings":"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"}
|
|
@@ -1433,6 +1433,7 @@ const RELEASE_SPEC_FIELDS = new Set([
|
|
|
1433
1433
|
"routes",
|
|
1434
1434
|
"checks",
|
|
1435
1435
|
"assets", // v1.48 unified-apply
|
|
1436
|
+
"i18n", // v2.5 routed-locale-context
|
|
1436
1437
|
]);
|
|
1437
1438
|
const DEPLOYABLE_SPEC_FIELDS = [
|
|
1438
1439
|
"assets", // v1.48 unified-apply
|
|
@@ -1443,6 +1444,7 @@ const DEPLOYABLE_SPEC_FIELDS = [
|
|
|
1443
1444
|
"subdomains",
|
|
1444
1445
|
"routes",
|
|
1445
1446
|
"checks",
|
|
1447
|
+
"i18n", // v2.5 routed-locale-context
|
|
1446
1448
|
];
|
|
1447
1449
|
const BASE_SPEC_FIELDS = new Set(["release", "release_id"]);
|
|
1448
1450
|
const DATABASE_SPEC_FIELDS = new Set(["migrations", "expose", "zero_downtime"]);
|
|
@@ -1468,6 +1470,11 @@ const ROUTE_ENTRY_FIELDS = new Set(["pattern", "methods", "target", "acknowledge
|
|
|
1468
1470
|
const FUNCTION_ROUTE_TARGET_FIELDS = new Set(["type", "name"]);
|
|
1469
1471
|
const STATIC_ROUTE_TARGET_FIELDS = new Set(["type", "file"]);
|
|
1470
1472
|
const ROUTE_METHOD_SET = new Set(ROUTE_HTTP_METHODS);
|
|
1473
|
+
const I18N_SPEC_FIELDS = new Set(["defaultLocale", "locales", "detect"]);
|
|
1474
|
+
const I18N_LOCALE_TAG_REGEX = /^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/;
|
|
1475
|
+
const I18N_COOKIE_NAME_REGEX = /^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/;
|
|
1476
|
+
const I18N_MAX_LOCALES = 50;
|
|
1477
|
+
const I18N_MAX_DETECT_SOURCES = 10;
|
|
1471
1478
|
function validateSpec(spec) {
|
|
1472
1479
|
if (!spec || typeof spec !== "object") {
|
|
1473
1480
|
throw new Run402DeployError("ReleaseSpec must be an object", {
|
|
@@ -1502,6 +1509,7 @@ function validateSpec(spec) {
|
|
|
1502
1509
|
validateRoutesSpec(raw.routes);
|
|
1503
1510
|
validateChecksSpec(raw.checks);
|
|
1504
1511
|
validateSecretsSpec(raw.secrets);
|
|
1512
|
+
validateI18nSpec(raw.i18n);
|
|
1505
1513
|
const subdomains = raw.subdomains;
|
|
1506
1514
|
const set = subdomains?.set;
|
|
1507
1515
|
if (set && set.length > 1) {
|
|
@@ -1788,6 +1796,79 @@ function validateChecksSpec(checks) {
|
|
|
1788
1796
|
throw invalidSpec("ReleaseSpec.checks must be an array", "checks");
|
|
1789
1797
|
}
|
|
1790
1798
|
}
|
|
1799
|
+
function validateI18nSpec(i18n) {
|
|
1800
|
+
if (i18n === undefined)
|
|
1801
|
+
return;
|
|
1802
|
+
if (i18n === null)
|
|
1803
|
+
return;
|
|
1804
|
+
const obj = requireObject(i18n, "i18n");
|
|
1805
|
+
validateKnownFields(obj, "i18n", I18N_SPEC_FIELDS, {
|
|
1806
|
+
default_locale: "Use `defaultLocale` (camelCase) in i18n.",
|
|
1807
|
+
default: "Use `defaultLocale` in i18n.",
|
|
1808
|
+
locale: "Use `locales` (plural array) in i18n.",
|
|
1809
|
+
});
|
|
1810
|
+
if (typeof obj.defaultLocale !== "string" || obj.defaultLocale.length === 0) {
|
|
1811
|
+
throw invalidSpec("ReleaseSpec.i18n.defaultLocale is required and must be a non-empty string", "i18n.defaultLocale");
|
|
1812
|
+
}
|
|
1813
|
+
if (!I18N_LOCALE_TAG_REGEX.test(obj.defaultLocale)) {
|
|
1814
|
+
throw invalidSpec(`ReleaseSpec.i18n.defaultLocale ${JSON.stringify(obj.defaultLocale)} must match /^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/`, "i18n.defaultLocale");
|
|
1815
|
+
}
|
|
1816
|
+
if (!Array.isArray(obj.locales)) {
|
|
1817
|
+
throw invalidSpec("ReleaseSpec.i18n.locales is required and must be a non-empty array of locale tags", "i18n.locales");
|
|
1818
|
+
}
|
|
1819
|
+
if (obj.locales.length === 0) {
|
|
1820
|
+
throw invalidSpec("ReleaseSpec.i18n.locales must contain at least one entry", "i18n.locales");
|
|
1821
|
+
}
|
|
1822
|
+
if (obj.locales.length > I18N_MAX_LOCALES) {
|
|
1823
|
+
throw invalidSpec(`ReleaseSpec.i18n.locales accepts at most ${I18N_MAX_LOCALES} entries (got ${obj.locales.length})`, "i18n.locales");
|
|
1824
|
+
}
|
|
1825
|
+
const seenLocales = new Set();
|
|
1826
|
+
for (let i = 0; i < obj.locales.length; i++) {
|
|
1827
|
+
const tag = obj.locales[i];
|
|
1828
|
+
const path = `i18n.locales.${i}`;
|
|
1829
|
+
if (typeof tag !== "string" || tag.length === 0) {
|
|
1830
|
+
throw invalidSpec(`ReleaseSpec.${path} must be a non-empty string`, path);
|
|
1831
|
+
}
|
|
1832
|
+
if (!I18N_LOCALE_TAG_REGEX.test(tag)) {
|
|
1833
|
+
throw invalidSpec(`ReleaseSpec.${path} (${JSON.stringify(tag)}) must match /^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/`, path);
|
|
1834
|
+
}
|
|
1835
|
+
if (seenLocales.has(tag)) {
|
|
1836
|
+
throw invalidSpec(`ReleaseSpec.i18n.locales contains duplicate entry ${JSON.stringify(tag)}`, path);
|
|
1837
|
+
}
|
|
1838
|
+
seenLocales.add(tag);
|
|
1839
|
+
}
|
|
1840
|
+
if (!seenLocales.has(obj.defaultLocale)) {
|
|
1841
|
+
throw invalidSpec(`ReleaseSpec.i18n.defaultLocale (${JSON.stringify(obj.defaultLocale)}) must be byte-identical to one entry in i18n.locales`, "i18n.defaultLocale");
|
|
1842
|
+
}
|
|
1843
|
+
if (obj.detect !== undefined) {
|
|
1844
|
+
if (!Array.isArray(obj.detect)) {
|
|
1845
|
+
throw invalidSpec("ReleaseSpec.i18n.detect must be an array of detect sources", "i18n.detect");
|
|
1846
|
+
}
|
|
1847
|
+
if (obj.detect.length > I18N_MAX_DETECT_SOURCES) {
|
|
1848
|
+
throw invalidSpec(`ReleaseSpec.i18n.detect accepts at most ${I18N_MAX_DETECT_SOURCES} entries (got ${obj.detect.length})`, "i18n.detect");
|
|
1849
|
+
}
|
|
1850
|
+
for (let i = 0; i < obj.detect.length; i++) {
|
|
1851
|
+
const source = obj.detect[i];
|
|
1852
|
+
const path = `i18n.detect.${i}`;
|
|
1853
|
+
if (typeof source !== "string" || source.length === 0) {
|
|
1854
|
+
throw invalidSpec(`ReleaseSpec.${path} must be a non-empty string ("accept-language" or "cookie:<name>")`, path);
|
|
1855
|
+
}
|
|
1856
|
+
if (source === "accept-language")
|
|
1857
|
+
continue;
|
|
1858
|
+
if (source.startsWith("cookie:")) {
|
|
1859
|
+
const cookieName = source.slice("cookie:".length);
|
|
1860
|
+
if (cookieName.length === 0) {
|
|
1861
|
+
throw invalidSpec(`ReleaseSpec.${path} cookie source is missing the cookie name (use "cookie:<name>")`, path);
|
|
1862
|
+
}
|
|
1863
|
+
if (!I18N_COOKIE_NAME_REGEX.test(cookieName)) {
|
|
1864
|
+
throw invalidSpec(`ReleaseSpec.${path} cookie name ${JSON.stringify(cookieName)} must match the RFC 6265 cookie-name grammar /^[!#$%&'*+\\-.^_\`|~0-9A-Za-z]+$/`, path);
|
|
1865
|
+
}
|
|
1866
|
+
continue;
|
|
1867
|
+
}
|
|
1868
|
+
throw invalidSpec(`ReleaseSpec.${path} must be "accept-language" or "cookie:<name>" (got ${JSON.stringify(source)})`, path);
|
|
1869
|
+
}
|
|
1870
|
+
}
|
|
1871
|
+
}
|
|
1791
1872
|
function validateKnownFields(obj, resource, allowed, hints = {}) {
|
|
1792
1873
|
for (const key of Object.keys(obj)) {
|
|
1793
1874
|
if (allowed.has(key))
|
|
@@ -1826,7 +1907,13 @@ function hasDeployableContent(spec) {
|
|
|
1826
1907
|
hasSubdomainsContent(spec.subdomains) ||
|
|
1827
1908
|
hasRecordEntries(spec.routes) ||
|
|
1828
1909
|
hasArrayEntries(spec.checks) ||
|
|
1829
|
-
hasAssetsContent(spec.assets)
|
|
1910
|
+
hasAssetsContent(spec.assets) ||
|
|
1911
|
+
hasI18nContent(spec.i18n));
|
|
1912
|
+
}
|
|
1913
|
+
function hasI18nContent(i18n) {
|
|
1914
|
+
if (i18n === null)
|
|
1915
|
+
return true;
|
|
1916
|
+
return isRecord(i18n);
|
|
1830
1917
|
}
|
|
1831
1918
|
function hasAssetsContent(assets) {
|
|
1832
1919
|
if (!isRecord(assets))
|
|
@@ -2180,6 +2267,9 @@ async function normalizeReleaseSpec(client, spec) {
|
|
|
2180
2267
|
if (hasOwn(spec, "routes")) {
|
|
2181
2268
|
normalized.routes = spec.routes;
|
|
2182
2269
|
}
|
|
2270
|
+
if (hasOwn(spec, "i18n")) {
|
|
2271
|
+
normalized.i18n = spec.i18n;
|
|
2272
|
+
}
|
|
2183
2273
|
if (spec.checks)
|
|
2184
2274
|
normalized.checks = spec.checks;
|
|
2185
2275
|
if (spec.secrets)
|