run402 4.109.1 → 4.110.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/README.md +1 -1
- package/lib/deploy-v2.mjs +12 -4
- package/package.json +1 -1
- package/sdk/dist/namespaces/deploy.d.ts.map +1 -1
- package/sdk/dist/namespaces/deploy.js +50 -26
- package/sdk/dist/namespaces/deploy.js.map +1 -1
- package/sdk/dist/namespaces/deploy.types.d.ts +30 -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/namespaces/site-removal-summary.d.ts +13 -3
- package/sdk/dist/namespaces/site-removal-summary.d.ts.map +1 -1
- package/sdk/dist/namespaces/site-removal-summary.js +8 -3
- package/sdk/dist/namespaces/site-removal-summary.js.map +1 -1
- package/sdk/dist/node/deploy-manifest.d.ts +12 -0
- package/sdk/dist/node/deploy-manifest.d.ts.map +1 -1
- package/sdk/dist/node/deploy-manifest.js +16 -3
- package/sdk/dist/node/deploy-manifest.js.map +1 -1
- package/sdk/dist/type-contract.d.ts.map +1 -1
- package/sdk/dist/type-contract.js +7 -0
- package/sdk/dist/type-contract.js.map +1 -1
- package/vault-surface.json +1 -1
package/README.md
CHANGED
|
@@ -253,7 +253,7 @@ import { db, adminDb, auth, email, ai } from "@run402/functions";
|
|
|
253
253
|
|
|
254
254
|
### Same-origin web routes
|
|
255
255
|
|
|
256
|
-
`run402 deploy` accepts `site.public_paths` for clean static browser URLs and `routes.replace` for function ingress or exact method-aware static aliases. Release asset paths such as `events.html` are distinct from public paths such as `/events`: prefer `{ "site": { "replace": { "events.html": { "data": "<h1>Events</h1>" } }, "public_paths": { "mode": "explicit", "replace": { "/events": { "asset": "events.html" } } } } }` for ordinary clean static URLs. In explicit mode `/events.html` is not public unless separately declared; `mode: "implicit"` restores filename-derived reachability and can widen access. `site.embedding.frame_ancestors` (catalog keys, e.g. `["localhost"]`, never raw origins) lets the named embedders put the site in an iframe: the gateway sends `Content-Security-Policy: frame-ancestors http://localhost:* http://127.0.0.1:*` and drops `X-Frame-Options` on every response of the host; omitted on a later apply carries the previous declaration forward, `null` returns to deny, unknown keys fail `INVALID_SPEC` naming the valid ones, and `/_run402/config.json` discloses the effective policy cross-origin so an embedder can check before framing. `site.sign_in_path` (e.g. `"/join"`) names the app's own same-origin sign-in page: a signed-out user reaching MCP authorization (`/_run402/oauth/authorize`) is sent there with `returnTo` appended instead of the hosted `/auth/sign-in`; omitted carries forward, `null` returns to the hosted page, and a value with a query/fragment, `//`, `://`, or a `/_run402/` or `/auth/` prefix fails `INVALID_SPEC` on `site.sign_in_path`. `routes.replace` is an array of route entries, not a path-keyed map. Use exact `/admin` plus final-wildcard `/admin/*` for a routed section root, narrow `/api/*` methods such as `["GET","POST","OPTIONS"]`, POST-only `/login` function routes, and exact static route targets like `{ "pattern": "/events", "methods": ["GET","HEAD"], "target": { "type": "static", "file": "events.html" } }` only for route-table alias behavior. Static route `file` is a release asset path, not a public path, URL, CAS hash, rewrite, or redirect. Recipe — static home page + SPA shell: a root alias `{ "pattern": "/", "target": { "type": "static", "file": "home.html" } }` (with `home.html` at the site root) serves real static bytes at `GET /` (`route_static_alias`) while unmatched app routes keep the `index.html` shell (`spa_fallback`); expect non-blocking `STATIC_ALIAS_SHADOWS_STATIC_PATH` (warn) / `STATIC_ALIAS_DUPLICATE_CANONICAL_URL` (info) plan lints and verify with `run402 deploy resolve --url https://<your-site>/ --method GET`. Routed functions use Node 22 Fetch Request -> Response; `req.url` is the full public URL on managed subdomains, deployment hosts, and verified custom domains. Direct `/functions/v1/:name` remains API-key protected. Known resolve literals include `host_missing`, `manifest_missing`, `active_release_missing`, `unsupported_manifest_version`, `path_error`, `none`, `static_exact`, `static_index`, `spa_fallback`, `spa_fallback_missing`, `route_function`, `route_static_alias`, and `route_method_miss`; known `authorization_result` values include `authorized`, `not_public`, `not_applicable`, `manifest_missing`, `target_missing`, `active_release_missing`, `unsupported_manifest_version`, `path_error`, `missing_cas_object`, `unfinalized_or_deleting_cas_object`, `size_mismatch`, and `unauthorized_cas_object`. Known `fallback_state` values include `active_release_missing`, `unsupported_manifest_version`, and `negative_cache_hit`; preserve unknown future strings. Release inventories may include `static_public_paths` with `public_path`, `asset_path`, `reachability_authority`, and `direct`; resolve may return the same reachability fields plus `authorization_result`, `cas_object`, `response_variant`, and route/static fields like `allow`, `route_pattern`, `target_type`, `target_name`, and `target_file`. Static route target warnings include `STATIC_ALIAS_SHADOWS_STATIC_PATH`, `STATIC_ALIAS_RELATIVE_ASSET_RISK`, `STATIC_ALIAS_DUPLICATE_CANONICAL_URL`, `STATIC_ALIAS_EXTENSIONLESS_NON_HTML`, and `STATIC_ALIAS_TABLE_NEAR_LIMIT`; inspect active routes, `static_public_paths`, and the backing `asset_path`. Runtime route failure codes to branch on: `ROUTE_MANIFEST_LOAD_FAILED`, `ROUTED_INVOKE_WORKER_SECRET_MISSING`, `ROUTED_INVOKE_AUTH_FAILED`, `ROUTED_ROUTE_STALE`, `ROUTE_METHOD_NOT_ALLOWED`, and `ROUTED_RESPONSE_TOO_LARGE`.
|
|
256
|
+
`run402 deploy` accepts `site.public_paths` for clean static browser URLs and `routes.replace` for function ingress or exact method-aware static aliases. Release asset paths such as `events.html` are distinct from public paths such as `/events`: prefer `{ "site": { "replace": { "events.html": { "data": "<h1>Events</h1>" } }, "public_paths": { "mode": "explicit", "replace": { "/events": { "asset": "events.html" } } } } }` for ordinary clean static URLs. In explicit mode `/events.html` is not public unless separately declared; `mode: "implicit"` restores filename-derived reachability and can widen access. `site.embedding.frame_ancestors` (catalog keys, e.g. `["localhost"]`, never raw origins) lets the named embedders put the site in an iframe: the gateway sends `Content-Security-Policy: frame-ancestors http://localhost:* http://127.0.0.1:*` and drops `X-Frame-Options` on every response of the host; omitted on a later apply carries the previous declaration forward, `null` returns to deny, unknown keys fail `INVALID_SPEC` naming the valid ones, and `/_run402/config.json` discloses the effective policy cross-origin so an embedder can check before framing. `site.sign_in_path` (e.g. `"/join"`) names the app's own same-origin sign-in page: a signed-out user reaching MCP authorization (`/_run402/oauth/authorize`) is sent there with `returnTo` appended instead of the hosted `/auth/sign-in`; omitted carries forward, `null` returns to the hosted page, and a value with a query/fragment, `//`, `://`, or a `/_run402/` or `/auth/` prefix fails `INVALID_SPEC` on `site.sign_in_path`. `site.noindex: true` adds `X-Robots-Tag: noindex, nofollow, nosnippet` to every response of the host; omitted carries forward, `false` or `null` makes the host indexable again, and anything but a boolean or `null` fails `INVALID_SPEC` on `site.noindex`. `routes.replace` is an array of route entries, not a path-keyed map. Use exact `/admin` plus final-wildcard `/admin/*` for a routed section root, narrow `/api/*` methods such as `["GET","POST","OPTIONS"]`, POST-only `/login` function routes, and exact static route targets like `{ "pattern": "/events", "methods": ["GET","HEAD"], "target": { "type": "static", "file": "events.html" } }` only for route-table alias behavior. Static route `file` is a release asset path, not a public path, URL, CAS hash, rewrite, or redirect. Recipe — static home page + SPA shell: a root alias `{ "pattern": "/", "target": { "type": "static", "file": "home.html" } }` (with `home.html` at the site root) serves real static bytes at `GET /` (`route_static_alias`) while unmatched app routes keep the `index.html` shell (`spa_fallback`); expect non-blocking `STATIC_ALIAS_SHADOWS_STATIC_PATH` (warn) / `STATIC_ALIAS_DUPLICATE_CANONICAL_URL` (info) plan lints and verify with `run402 deploy resolve --url https://<your-site>/ --method GET`. Routed functions use Node 22 Fetch Request -> Response; `req.url` is the full public URL on managed subdomains, deployment hosts, and verified custom domains. Direct `/functions/v1/:name` remains API-key protected. Known resolve literals include `host_missing`, `manifest_missing`, `active_release_missing`, `unsupported_manifest_version`, `path_error`, `none`, `static_exact`, `static_index`, `spa_fallback`, `spa_fallback_missing`, `route_function`, `route_static_alias`, and `route_method_miss`; known `authorization_result` values include `authorized`, `not_public`, `not_applicable`, `manifest_missing`, `target_missing`, `active_release_missing`, `unsupported_manifest_version`, `path_error`, `missing_cas_object`, `unfinalized_or_deleting_cas_object`, `size_mismatch`, and `unauthorized_cas_object`. Known `fallback_state` values include `active_release_missing`, `unsupported_manifest_version`, and `negative_cache_hit`; preserve unknown future strings. Release inventories may include `static_public_paths` with `public_path`, `asset_path`, `reachability_authority`, and `direct`; resolve may return the same reachability fields plus `authorization_result`, `cas_object`, `response_variant`, and route/static fields like `allow`, `route_pattern`, `target_type`, `target_name`, and `target_file`. Static route target warnings include `STATIC_ALIAS_SHADOWS_STATIC_PATH`, `STATIC_ALIAS_RELATIVE_ASSET_RISK`, `STATIC_ALIAS_DUPLICATE_CANONICAL_URL`, `STATIC_ALIAS_EXTENSIONLESS_NON_HTML`, and `STATIC_ALIAS_TABLE_NEAR_LIMIT`; inspect active routes, `static_public_paths`, and the backing `asset_path`. Runtime route failure codes to branch on: `ROUTE_MANIFEST_LOAD_FAILED`, `ROUTED_INVOKE_WORKER_SECRET_MISSING`, `ROUTED_INVOKE_AUTH_FAILED`, `ROUTED_ROUTE_STALE`, `ROUTE_METHOD_NOT_ALLOWED`, and `ROUTED_RESPONSE_TOO_LARGE`.
|
|
257
257
|
|
|
258
258
|
### Secrets
|
|
259
259
|
|
package/lib/deploy-v2.mjs
CHANGED
|
@@ -1589,21 +1589,29 @@ const SITE_BULK_REMOVAL_CODE = "DESTRUCTIVE_SITE_BULK_REMOVAL";
|
|
|
1589
1589
|
|
|
1590
1590
|
/**
|
|
1591
1591
|
* Reads the SDK's `details.removed_paths_summary` on a bulk site-removal
|
|
1592
|
-
* warning and says whether the
|
|
1593
|
-
* content-hashed build bundles
|
|
1592
|
+
* warning and says whether the counted removals drop pages or are only
|
|
1593
|
+
* content-hashed build bundles.
|
|
1594
|
+
*
|
|
1595
|
+
* A gateway that sends `details.replaced_fingerprinted` has already left
|
|
1596
|
+
* out bundles the build replaces in the same directory (renames), so any
|
|
1597
|
+
* hashed bundle still counted has no replacement there. An older gateway
|
|
1598
|
+
* or a Core target counts renames too.
|
|
1594
1599
|
*/
|
|
1595
1600
|
function siteRemovalGuidance(warnings) {
|
|
1596
1601
|
const warning = warnings?.find((w) => w?.code === SITE_BULK_REMOVAL_CODE);
|
|
1597
1602
|
if (!warning) return null;
|
|
1598
1603
|
const summary = warning.details?.removed_paths_summary;
|
|
1599
|
-
const where = "Per-path detail is in warnings[].affected and warnings[].details.
|
|
1604
|
+
const where = "Per-path detail is in warnings[].affected and warnings[].details.";
|
|
1600
1605
|
if (!summary || typeof summary.total !== "number") {
|
|
1601
1606
|
return { hint: `This deploy removes more than ten percent of the live site's paths. ${where} Acknowledge ${SITE_BULK_REMOVAL_CODE} only if those removals are intended.` };
|
|
1602
1607
|
}
|
|
1603
1608
|
if (summary.only_content_hashed_build_assets) {
|
|
1604
1609
|
const example = Array.isArray(warning.affected) && warning.affected[0] ? ` (e.g. ${warning.affected[0]})` : "";
|
|
1610
|
+
const gatewayPairsRenames = typeof warning.details?.replaced_fingerprinted === "number";
|
|
1605
1611
|
return {
|
|
1606
|
-
hint:
|
|
1612
|
+
hint: gatewayPairsRenames
|
|
1613
|
+
? `All ${summary.total} counted removals are content-hashed build assets${example} that this build does not replace in the same directory; no HTML pages are removed. That is usually a rebuild that merged or dropped bundles. Acknowledge ${SITE_BULK_REMOVAL_CODE} once nothing outside this build still loads them. ${where}`
|
|
1614
|
+
: `All ${summary.total} removed site paths are content-hashed build assets${example}, which a rebuild renames or merges; no HTML pages are removed. If this deploy is a rebuild of the same site, acknowledging ${SITE_BULK_REMOVAL_CODE} is safe. ${where}`,
|
|
1607
1615
|
};
|
|
1608
1616
|
}
|
|
1609
1617
|
const pageList = Array.isArray(summary.page_paths) && summary.page_paths.length > 0
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "run402",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.110.1",
|
|
4
4
|
"description": "CLI for Run402 — full-stack backend infrastructure for AI agents: Postgres, auth, storage, serverless functions and atomic deploys. Paid with x402/MPP. Includes $0.03 image generation.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deploy.d.ts","sourceRoot":"","sources":["../../src/namespaces/deploy.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"deploy.d.ts","sourceRoot":"","sources":["../../src/namespaces/deploy.ts"],"names":[],"mappings":"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"}
|
|
@@ -1103,22 +1103,26 @@ function siteToCoreSpec(site) {
|
|
|
1103
1103
|
...(site.public_paths ? { public_paths: site.public_paths } : {}),
|
|
1104
1104
|
};
|
|
1105
1105
|
}
|
|
1106
|
-
// tenant-site-embedding and site.
|
|
1107
|
-
// gateway-owned and core validates site keys against
|
|
1106
|
+
// tenant-site-embedding, site.sign_in_path, and site.noindex never reach
|
|
1107
|
+
// core: all three are gateway-owned and core validates site keys against
|
|
1108
|
+
// its own list.
|
|
1108
1109
|
return site.public_paths ? { public_paths: site.public_paths } : {};
|
|
1109
1110
|
}
|
|
1110
1111
|
function siteToWire(site) {
|
|
1111
1112
|
// tenant-site-embedding: `null` is a meaningful value on the wire (clear), so
|
|
1112
1113
|
// it is carried whenever the key is present, unlike public_paths.
|
|
1113
|
-
// site.sign_in_path follows the same rule (`null` clears back to the hosted page)
|
|
1114
|
+
// site.sign_in_path follows the same rule (`null` clears back to the hosted page),
|
|
1115
|
+
// and so does site.noindex (`false` or `null` clears back to indexable).
|
|
1114
1116
|
const embedding = "embedding" in site && site.embedding !== undefined ? { embedding: site.embedding } : {};
|
|
1115
1117
|
const signInPath = "sign_in_path" in site && site.sign_in_path !== undefined ? { sign_in_path: site.sign_in_path } : {};
|
|
1118
|
+
const noindex = "noindex" in site && site.noindex !== undefined ? { noindex: site.noindex } : {};
|
|
1116
1119
|
if ("replace" in site && site.replace) {
|
|
1117
1120
|
return {
|
|
1118
1121
|
replace: fileSetToWire(site.replace),
|
|
1119
1122
|
...(site.public_paths ? { public_paths: site.public_paths } : {}),
|
|
1120
1123
|
...embedding,
|
|
1121
1124
|
...signInPath,
|
|
1125
|
+
...noindex,
|
|
1122
1126
|
};
|
|
1123
1127
|
}
|
|
1124
1128
|
if ("patch" in site && site.patch) {
|
|
@@ -1130,12 +1134,14 @@ function siteToWire(site) {
|
|
|
1130
1134
|
...(site.public_paths ? { public_paths: site.public_paths } : {}),
|
|
1131
1135
|
...embedding,
|
|
1132
1136
|
...signInPath,
|
|
1137
|
+
...noindex,
|
|
1133
1138
|
};
|
|
1134
1139
|
}
|
|
1135
1140
|
return {
|
|
1136
1141
|
...(site.public_paths ? { public_paths: site.public_paths } : {}),
|
|
1137
1142
|
...embedding,
|
|
1138
1143
|
...signInPath,
|
|
1144
|
+
...noindex,
|
|
1139
1145
|
};
|
|
1140
1146
|
}
|
|
1141
1147
|
function i18nToWire(i18n) {
|
|
@@ -1654,7 +1660,7 @@ async function commitInternal(client, planId, idempotencyKey, project, requiredP
|
|
|
1654
1660
|
: {}),
|
|
1655
1661
|
context: "committing deploy",
|
|
1656
1662
|
});
|
|
1657
|
-
return await
|
|
1663
|
+
return await sendCommitWithRetry(send, tries);
|
|
1658
1664
|
}
|
|
1659
1665
|
catch (err) {
|
|
1660
1666
|
const translated = translateDeployError(err, "commit", planId, operationId ?? null);
|
|
@@ -1667,38 +1673,34 @@ async function commitInternal(client, planId, idempotencyKey, project, requiredP
|
|
|
1667
1673
|
}
|
|
1668
1674
|
}
|
|
1669
1675
|
/**
|
|
1670
|
-
* Send a deploy commit,
|
|
1671
|
-
* loses the response.
|
|
1672
|
-
*
|
|
1673
|
-
*
|
|
1674
|
-
*
|
|
1675
|
-
*
|
|
1676
|
-
*
|
|
1677
|
-
* `tries.attempts` counts the commits sent, for the error's retry metadata.
|
|
1676
|
+
* Send a deploy commit, re-sending when a 502/503/504 or a dropped connection
|
|
1677
|
+
* loses the response. Re-sending is safe because a plan commits once: the
|
|
1678
|
+
* gateway answers a commit of a plan whose operation is already running with
|
|
1679
|
+
* `status: "running"` (the caller follows the operation) and a finished one
|
|
1680
|
+
* with its stored result, and Run402 Core answers `commit_in_progress` while
|
|
1681
|
+
* the first commit runs, which is re-sent the same way. `tries.attempts`
|
|
1682
|
+
* counts the commits sent, for the error's retry metadata.
|
|
1678
1683
|
*/
|
|
1679
|
-
async function
|
|
1684
|
+
async function sendCommitWithRetry(send, tries) {
|
|
1680
1685
|
for (let attempt = 1;; attempt++) {
|
|
1681
1686
|
tries.attempts = attempt;
|
|
1682
1687
|
try {
|
|
1683
1688
|
return await send();
|
|
1684
1689
|
}
|
|
1685
1690
|
catch (err) {
|
|
1686
|
-
if (!
|
|
1691
|
+
if (!isRetryableCommitFailure(err) || attempt >= DEPLOY_COMMIT_MAX_ATTEMPTS)
|
|
1687
1692
|
throw err;
|
|
1688
1693
|
await sleep(DEPLOY_COMMIT_RETRY_BASE_DELAY_MS * 2 ** (attempt - 1));
|
|
1689
|
-
let snapshot;
|
|
1690
|
-
try {
|
|
1691
|
-
snapshot = await client.request(`/apply/v1/operations/${encodeURIComponent(operationId)}`, { headers: await apikeyHeaders(client, projectId), context: "fetching deploy operation" });
|
|
1692
|
-
}
|
|
1693
|
-
catch {
|
|
1694
|
-
throw err;
|
|
1695
|
-
}
|
|
1696
|
-
if (snapshot.status !== "planning" && snapshot.status !== "uploading") {
|
|
1697
|
-
return { operation_id: operationId, status: "running" };
|
|
1698
|
-
}
|
|
1699
1694
|
}
|
|
1700
1695
|
}
|
|
1701
1696
|
}
|
|
1697
|
+
function isRetryableCommitFailure(err) {
|
|
1698
|
+
if (isTransientGatewayFailure(err))
|
|
1699
|
+
return true;
|
|
1700
|
+
// Run402 Core: another commit of this plan is still running.
|
|
1701
|
+
return isRun402Error(err) && err.status === 409 &&
|
|
1702
|
+
err.body?.error === "commit_in_progress";
|
|
1703
|
+
}
|
|
1702
1704
|
async function uploadMissing(client, projectId, presence, byteReaders, emit) {
|
|
1703
1705
|
// Surface CAS dedup hits so agents can distinguish "N files were already
|
|
1704
1706
|
// present" from "nothing happened". The gateway reports both present and
|
|
@@ -2371,7 +2373,7 @@ const FUNCTION_SPEC_FIELDS = new Set([
|
|
|
2371
2373
|
const FUNCTION_CONFIG_FIELDS = new Set(["timeoutSeconds", "memoryMb"]);
|
|
2372
2374
|
const FUNCTION_TRIGGER_FIELDS = new Set(["id", "type", "cron", "timezone", "misfire_policy", "overlap_policy", "mailbox", "events", "run"]);
|
|
2373
2375
|
const FUNCTION_TRIGGER_RUN_FIELDS = new Set(["event_type", "payload", "retry", "expires_after_seconds"]);
|
|
2374
|
-
const SITE_SPEC_FIELDS = new Set(["replace", "patch", "public_paths", "embedding", "sign_in_path"]);
|
|
2376
|
+
const SITE_SPEC_FIELDS = new Set(["replace", "patch", "public_paths", "embedding", "sign_in_path", "noindex"]);
|
|
2375
2377
|
const SITE_PATCH_FIELDS = new Set(["put", "delete"]);
|
|
2376
2378
|
const SITE_PUBLIC_PATHS_FIELDS = new Set(["mode", "replace"]);
|
|
2377
2379
|
const PUBLIC_STATIC_PATH_FIELDS = new Set(["asset", "cache_class"]);
|
|
@@ -2710,6 +2712,17 @@ function validateSiteSpec(site) {
|
|
|
2710
2712
|
if (obj.sign_in_path !== undefined) {
|
|
2711
2713
|
validateSiteSignInPath(obj.sign_in_path, "site.sign_in_path");
|
|
2712
2714
|
}
|
|
2715
|
+
if (obj.noindex !== undefined) {
|
|
2716
|
+
validateSiteNoindex(obj.noindex, "site.noindex");
|
|
2717
|
+
}
|
|
2718
|
+
}
|
|
2719
|
+
/** site.noindex. `true` = every response of the host carries
|
|
2720
|
+
* `X-Robots-Tag: noindex, nofollow, nosnippet`; `false` or `null` clears back
|
|
2721
|
+
* to indexable; omitted carries forward. */
|
|
2722
|
+
function validateSiteNoindex(value, resource) {
|
|
2723
|
+
if (value === null || typeof value === "boolean")
|
|
2724
|
+
return;
|
|
2725
|
+
throw invalidSpec(`ReleaseSpec.${resource} must be true, false, or null; send true to add X-Robots-Tag: noindex, nofollow, nosnippet to every response of the host, false or null to make it indexable again, or omit ${resource} to carry the previous value forward`, resource);
|
|
2713
2726
|
}
|
|
2714
2727
|
/** site.sign_in_path. Structural check only (the gateway is authoritative on
|
|
2715
2728
|
* the reserved prefixes and the full rule set): a same-origin absolute path
|
|
@@ -3089,6 +3102,10 @@ function hasSiteContent(site) {
|
|
|
3089
3102
|
if (site && typeof site === "object" && "sign_in_path" in site && site.sign_in_path !== undefined) {
|
|
3090
3103
|
return true;
|
|
3091
3104
|
}
|
|
3105
|
+
// site.noindex: same rule, true/false/null is content.
|
|
3106
|
+
if (site && typeof site === "object" && "noindex" in site && site.noindex !== undefined) {
|
|
3107
|
+
return true;
|
|
3108
|
+
}
|
|
3092
3109
|
if (!isRecord(site))
|
|
3093
3110
|
return false;
|
|
3094
3111
|
if (hasRecordEntries(site.replace))
|
|
@@ -3545,6 +3562,10 @@ async function normalizeReleaseSpec(client, spec, opts = {}) {
|
|
|
3545
3562
|
const signInPath = "sign_in_path" in spec.site && spec.site.sign_in_path !== undefined
|
|
3546
3563
|
? { sign_in_path: spec.site.sign_in_path }
|
|
3547
3564
|
: {};
|
|
3565
|
+
// site.noindex: present (boolean or null) travels as-is.
|
|
3566
|
+
const noindex = "noindex" in spec.site && spec.site.noindex !== undefined
|
|
3567
|
+
? { noindex: spec.site.noindex }
|
|
3568
|
+
: {};
|
|
3548
3569
|
if ("replace" in spec.site && spec.site.replace) {
|
|
3549
3570
|
const map = await normalizeFileSet(spec.site.replace, rememberRelease);
|
|
3550
3571
|
// Re-check post-expansion so `dir("dist")` (a LocalDirRef whose keys are
|
|
@@ -3555,6 +3576,7 @@ async function normalizeReleaseSpec(client, spec, opts = {}) {
|
|
|
3555
3576
|
...(publicPaths ? { public_paths: publicPaths } : {}),
|
|
3556
3577
|
...embedding,
|
|
3557
3578
|
...signInPath,
|
|
3579
|
+
...noindex,
|
|
3558
3580
|
};
|
|
3559
3581
|
}
|
|
3560
3582
|
else if ("patch" in spec.site && spec.site.patch) {
|
|
@@ -3570,13 +3592,15 @@ async function normalizeReleaseSpec(client, spec, opts = {}) {
|
|
|
3570
3592
|
...(publicPaths ? { public_paths: publicPaths } : {}),
|
|
3571
3593
|
...embedding,
|
|
3572
3594
|
...signInPath,
|
|
3595
|
+
...noindex,
|
|
3573
3596
|
};
|
|
3574
3597
|
}
|
|
3575
|
-
else if (publicPaths || "embedding" in embedding || "sign_in_path" in signInPath) {
|
|
3598
|
+
else if (publicPaths || "embedding" in embedding || "sign_in_path" in signInPath || "noindex" in noindex) {
|
|
3576
3599
|
normalized.site = {
|
|
3577
3600
|
...(publicPaths ? { public_paths: publicPaths } : {}),
|
|
3578
3601
|
...embedding,
|
|
3579
3602
|
...signInPath,
|
|
3603
|
+
...noindex,
|
|
3580
3604
|
};
|
|
3581
3605
|
}
|
|
3582
3606
|
}
|