@spacefast/common 0.0.13 → 0.0.17
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/agents/client-registry.d.ts +22 -0
- package/dist/agents/client-registry.js +41 -0
- package/dist/agents/connect-targets.d.ts +51 -6
- package/dist/agents/connect-targets.js +93 -28
- package/dist/brand.d.ts +0 -11
- package/dist/brand.js +0 -20
- package/dist/config/domains.d.ts +15 -6
- package/dist/config/domains.js +24 -10
- package/dist/config/postgres-budget.d.ts +3 -0
- package/dist/config/postgres-budget.js +6 -1
- package/dist/config/postgres-budget.json +2 -1
- package/dist/contracts/abuse.js +1 -1
- package/dist/contracts/access.d.ts +149 -44
- package/dist/contracts/access.js +94 -8
- package/dist/contracts/activity.js +5 -1
- package/dist/contracts/api-keys.js +9 -9
- package/dist/contracts/archives.js +11 -11
- package/dist/contracts/beta.js +1 -1
- package/dist/contracts/builds.js +14 -14
- package/dist/contracts/channels.js +2 -2
- package/dist/contracts/comments.d.ts +86 -15
- package/dist/contracts/comments.js +116 -20
- package/dist/contracts/common.d.ts +12 -12
- package/dist/contracts/common.js +33 -30
- package/dist/contracts/continuation.js +5 -5
- package/dist/contracts/data-source-routes.js +1 -1
- package/dist/contracts/device-auth.d.ts +6 -6
- package/dist/contracts/device-auth.js +12 -12
- package/dist/contracts/docs.d.ts +10 -10
- package/dist/contracts/domains.js +39 -33
- package/dist/contracts/enums.d.ts +2 -10
- package/dist/contracts/enums.js +0 -2
- package/dist/contracts/error-code-meta.d.ts +116 -47
- package/dist/contracts/error-code-meta.js +37 -16
- package/dist/contracts/error-codes.d.ts +7 -4
- package/dist/contracts/error-codes.js +46 -21
- package/dist/contracts/events.d.ts +10 -3
- package/dist/contracts/events.js +33 -5
- package/dist/contracts/execution.d.ts +26 -0
- package/dist/contracts/execution.js +21 -0
- package/dist/contracts/feature-lifecycle.d.ts +21 -24
- package/dist/contracts/feature-lifecycle.js +28 -26
- package/dist/contracts/features.js +4 -4
- package/dist/contracts/functions.d.ts +8 -140
- package/dist/contracts/functions.js +9 -19
- package/dist/contracts/git.d.ts +1 -1
- package/dist/contracts/grants.d.ts +96 -79
- package/dist/contracts/grants.js +130 -43
- package/dist/contracts/ids.d.ts +2 -2
- package/dist/contracts/ids.js +2 -4
- package/dist/contracts/internal.js +2 -2
- package/dist/contracts/mcp.d.ts +17 -556
- package/dist/contracts/mcp.js +9 -103
- package/dist/contracts/me.js +3 -4
- package/dist/contracts/notifications.d.ts +108 -0
- package/dist/contracts/notifications.js +54 -0
- package/dist/contracts/oauth-resources.d.ts +18 -1
- package/dist/contracts/oauth-resources.js +22 -2
- package/dist/contracts/operations.d.ts +2 -50
- package/dist/contracts/operations.js +0 -19
- package/dist/contracts/pages.d.ts +8 -4
- package/dist/contracts/pages.js +16 -3
- package/dist/contracts/platform.js +10 -8
- package/dist/contracts/problem-document.d.ts +14 -0
- package/dist/contracts/problem-document.js +35 -0
- package/dist/contracts/push-new.d.ts +21 -6
- package/dist/contracts/push-new.js +3 -7
- package/dist/contracts/resources.d.ts +8 -7
- package/dist/contracts/resources.js +9 -6
- package/dist/contracts/runtime-api.d.ts +162 -92
- package/dist/contracts/runtime-api.js +99 -27
- package/dist/contracts/runtime-app.d.ts +41 -11
- package/dist/contracts/runtime-app.js +22 -1
- package/dist/contracts/runtime-db.d.ts +424 -0
- package/dist/contracts/runtime-db.js +108 -0
- package/dist/contracts/runtime-storage.d.ts +120 -0
- package/dist/contracts/runtime-storage.js +40 -0
- package/dist/contracts/sf-config-v1.d.ts +49 -1
- package/dist/contracts/sf-config-v1.js +2 -2
- package/dist/contracts/sites.d.ts +1 -0
- package/dist/contracts/sites.js +20 -12
- package/dist/contracts/space-config.d.ts +62 -22
- package/dist/contracts/space-config.js +173 -47
- package/dist/contracts/spaces.d.ts +79 -45
- package/dist/contracts/spaces.js +66 -50
- package/dist/contracts/superadmin-spaces.d.ts +13 -2
- package/dist/contracts/superadmin-spaces.js +15 -0
- package/dist/contracts/superadmin-tenants.js +4 -4
- package/dist/contracts/superadmin.d.ts +4 -0
- package/dist/contracts/superadmin.js +14 -1
- package/dist/contracts/tags.d.ts +17 -17
- package/dist/contracts/tags.js +1 -1
- package/dist/contracts/teams.js +25 -16
- package/dist/contracts/theme-json.js +1 -1
- package/dist/contracts/transfers.js +4 -4
- package/dist/contracts/variables.js +3 -3
- package/dist/contracts/zero.d.ts +204 -338
- package/dist/contracts/zero.js +94 -98
- package/dist/dashboard-paths/index.d.ts +16 -1
- package/dist/dashboard-paths/index.js +18 -0
- package/dist/docs/agent-handoff-document.d.ts +2 -2
- package/dist/docs/agent-handoff-document.js +8 -7
- package/dist/docs/agent-prose.d.ts +22 -3
- package/dist/docs/agent-prose.js +221 -51
- package/dist/docs/agent-setup.d.ts +13 -10
- package/dist/docs/agent-setup.js +279 -53
- package/dist/docs/agent-solutions.d.ts +6 -6
- package/dist/docs/agent-solutions.js +23 -21
- package/dist/docs/catalog.d.ts +29 -74
- package/dist/docs/catalog.js +65 -92
- package/dist/docs/error-docs.js +293 -221
- package/dist/docs/skill-distribution.d.ts +2 -0
- package/dist/docs/skill-distribution.js +7 -4
- package/dist/docs/skills.d.ts +546 -0
- package/dist/docs/skills.js +340 -0
- package/dist/utils/browser-credential.d.ts +19 -0
- package/dist/utils/browser-credential.js +62 -0
- package/dist/utils/comment-avatars.d.ts +7 -0
- package/dist/utils/comment-avatars.js +42 -0
- package/dist/utils/content-type.d.ts +3 -3
- package/dist/utils/content-type.js +38 -61
- package/dist/utils/domain-diagnostics.d.ts +5 -5
- package/dist/utils/domain-diagnostics.js +21 -10
- package/dist/utils/local-space-state.d.ts +78 -4
- package/dist/utils/local-space-state.js +383 -82
- package/dist/utils/one-shot-replay.d.ts +14 -0
- package/dist/utils/one-shot-replay.js +21 -0
- package/dist/utils/page-preview.d.ts +7 -0
- package/dist/utils/page-preview.js +9 -0
- package/dist/utils/pages.d.ts +2 -11
- package/dist/utils/pages.js +58 -14
- package/dist/utils/publish-form-data.d.ts +22 -0
- package/dist/utils/publish-form-data.js +26 -0
- package/dist/utils/publish-policy.js +20 -4
- package/dist/utils/query-keys.d.ts +7 -4
- package/dist/utils/query-keys.js +13 -4
- package/dist/utils/runtime-paths.d.ts +3 -0
- package/dist/utils/runtime-paths.js +7 -0
- package/dist/utils/secure-local-file.d.ts +73 -0
- package/dist/utils/secure-local-file.js +1373 -0
- package/dist/utils/space-config.d.ts +13 -4
- package/dist/utils/space-config.js +123 -15
- package/dist/utils/storage-policy.d.ts +20 -0
- package/dist/utils/storage-policy.fixtures.json +174 -0
- package/dist/utils/storage-policy.js +193 -0
- package/dist/utils/upload-session.d.ts +12 -1
- package/dist/utils/upload-session.js +37 -2
- package/dist/utils/version-file-browser.d.ts +13 -0
- package/dist/utils/version-file-browser.js +59 -0
- package/package.json +19 -1
- package/dist/contracts/mounts.d.ts +0 -142
- package/dist/contracts/mounts.js +0 -56
- package/dist/utils/asset-fingerprint.d.ts +0 -64
- package/dist/utils/asset-fingerprint.js +0 -620
|
@@ -3,6 +3,11 @@ export declare const SF_CONFIG_V1_CANONICAL_FILE = "sf.jsonc";
|
|
|
3
3
|
export declare const SF_CONFIG_V1_FILES: readonly ["sf.jsonc", "spacefast.jsonc", "spacefast.json", "sf.json", ".sf/sf.json", ".sf/config.jsonc", ".sf/config.json"];
|
|
4
4
|
/** Published JSON Schema URL for the strict `sf.jsonc` v1 contract. */
|
|
5
5
|
export declare const SF_CONFIG_V1_SCHEMA_URL: `${string}/schemas/sf.v1.json`;
|
|
6
|
+
/**
|
|
7
|
+
* How a redirect answers. Omitting it means 302. There is no 200: a rule that
|
|
8
|
+
* serves other content under the requested URL is a `rewrites` entry.
|
|
9
|
+
*/
|
|
10
|
+
export type SfConfigV1RedirectStatus = 301 | 302 | 303 | 307 | 308;
|
|
6
11
|
export type SfConfigV1 = {
|
|
7
12
|
$schema?: typeof SF_CONFIG_V1_SCHEMA_URL;
|
|
8
13
|
version: 1;
|
|
@@ -19,6 +24,38 @@ export type SfConfigV1 = {
|
|
|
19
24
|
cleanUrls?: boolean;
|
|
20
25
|
directoryListing?: boolean;
|
|
21
26
|
};
|
|
27
|
+
/**
|
|
28
|
+
* Browser redirect rules, in the same matcher grammar as `_redirects`. The
|
|
29
|
+
* files match first; config rules add behavior where the files are silent.
|
|
30
|
+
*/
|
|
31
|
+
redirects?: {
|
|
32
|
+
source: string;
|
|
33
|
+
destination: string;
|
|
34
|
+
status?: SfConfigV1RedirectStatus;
|
|
35
|
+
}[];
|
|
36
|
+
/**
|
|
37
|
+
* Rewrite and proxy rules: the URL stays, the content comes from the
|
|
38
|
+
* destination. A path destination rewrites, an absolute URL proxies — the
|
|
39
|
+
* same 200 rules `_redirects` writes as `/from /to 200`, which is why they
|
|
40
|
+
* carry no status of their own.
|
|
41
|
+
*/
|
|
42
|
+
rewrites?: {
|
|
43
|
+
source: string;
|
|
44
|
+
destination: string;
|
|
45
|
+
/** Let shared caches store the proxy response. Absolute-URL destinations only. */
|
|
46
|
+
cache?: "shared";
|
|
47
|
+
}[];
|
|
48
|
+
/**
|
|
49
|
+
* Response headers to set on matching requests. Headers are a list, not a
|
|
50
|
+
* map, so repeated names (Set-Cookie) survive.
|
|
51
|
+
*/
|
|
52
|
+
headers?: {
|
|
53
|
+
source: string;
|
|
54
|
+
headers: {
|
|
55
|
+
key: string;
|
|
56
|
+
value: string;
|
|
57
|
+
}[];
|
|
58
|
+
}[];
|
|
22
59
|
metadata?: {
|
|
23
60
|
title?: string;
|
|
24
61
|
description?: string;
|
|
@@ -43,12 +80,23 @@ export type EffectiveConfigV1 = {
|
|
|
43
80
|
cleanUrls: boolean;
|
|
44
81
|
directoryListing: boolean;
|
|
45
82
|
};
|
|
83
|
+
/** Every rule states its status; an omitted one resolves to 302. */
|
|
84
|
+
redirects?: (NonNullable<SfConfigV1["redirects"]>[number] & {
|
|
85
|
+
status: SfConfigV1RedirectStatus;
|
|
86
|
+
})[];
|
|
87
|
+
rewrites?: SfConfigV1["rewrites"];
|
|
88
|
+
headers?: SfConfigV1["headers"];
|
|
46
89
|
metadata?: SfConfigV1["metadata"];
|
|
47
90
|
substitute?: SfConfigV1["substitute"];
|
|
48
91
|
grants?: Grant[];
|
|
49
92
|
};
|
|
93
|
+
/**
|
|
94
|
+
* Config-shape problems use the `config_*` codes; a bad routing rule reports
|
|
95
|
+
* the same code the `_redirects` / `_headers` compiler would give it, because
|
|
96
|
+
* it is the same grammar and the same compiler.
|
|
97
|
+
*/
|
|
50
98
|
export type SfConfigV1Issue = {
|
|
51
|
-
code: "config_alias" | "config_conflict" | "config_identity_moved" | "config_invalid" | "config_key_removed" | "config_unknown_key" | "serve_index_required" | "template_syntax_retired";
|
|
99
|
+
code: "config_alias" | "config_conflict" | "config_identity_moved" | "config_invalid" | "config_key_removed" | "config_unknown_key" | "header_basic_auth_unsupported" | "header_cache_control_platform_managed" | "header_cdn_cache_unsupported" | "header_name_invalid" | "header_name_unsupported" | "header_path_invalid" | "header_pattern_invalid" | "header_port_unsupported" | "header_value_invalid" | "redirect_cache_directive_invalid" | "redirect_cache_not_proxy" | "redirect_destination_invalid" | "redirect_destination_missing" | "redirect_host_invalid" | "redirect_loop_invalid" | "redirect_pattern_invalid" | "redirect_rewrite_destination_invalid" | "redirect_source_invalid" | "redirect_status_unsupported" | "redirect_status_use_rewrites" | "serve_index_required" | "template_syntax_retired";
|
|
52
100
|
severity: "error" | "warning";
|
|
53
101
|
path: string;
|
|
54
102
|
line: number;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { serviceOrigin } from "../config/domains.js";
|
|
2
2
|
import { SPACE_CONFIG_ACCEPTED_FILES, SPACE_CONFIG_CANONICAL_FILE } from "./space-config.js";
|
|
3
3
|
export const SF_CONFIG_V1_CANONICAL_FILE = SPACE_CONFIG_CANONICAL_FILE;
|
|
4
4
|
export const SF_CONFIG_V1_FILES = SPACE_CONFIG_ACCEPTED_FILES;
|
|
5
5
|
/** Published JSON Schema URL for the strict `sf.jsonc` v1 contract. */
|
|
6
|
-
export const SF_CONFIG_V1_SCHEMA_URL = `${
|
|
6
|
+
export const SF_CONFIG_V1_SCHEMA_URL = `${serviceOrigin("www", "prod")}/schemas/sf.v1.json`;
|
|
@@ -104,6 +104,7 @@ export declare const operatorSiteProvisioningSchema: z.ZodOptional<z.ZodObject<{
|
|
|
104
104
|
}, z.core.$strip>>;
|
|
105
105
|
export declare const tenantSiteProvisioningSchema: z.ZodOptional<z.ZodObject<{}, z.core.$strict>>;
|
|
106
106
|
export declare const siteCreateSchema: z.ZodObject<{
|
|
107
|
+
teamId: z.ZodOptional<z.ZodString>;
|
|
107
108
|
kind: z.ZodDefault<z.ZodEnum<{
|
|
108
109
|
static_runtime: "static_runtime";
|
|
109
110
|
}>>;
|
package/dist/contracts/sites.js
CHANGED
|
@@ -11,7 +11,7 @@ export const SiteCapacitySchema = z
|
|
|
11
11
|
.int()
|
|
12
12
|
.nonnegative()
|
|
13
13
|
.optional()
|
|
14
|
-
.describe("Maximum spaces this site
|
|
14
|
+
.describe("Maximum number of spaces this site can host."),
|
|
15
15
|
usedSpaces: z
|
|
16
16
|
.number()
|
|
17
17
|
.int()
|
|
@@ -56,8 +56,8 @@ export const SitePressureSchema = z
|
|
|
56
56
|
// Provider linkage (`providerClientId`, `providerRef`) is operator-only and
|
|
57
57
|
// never appears in this tenant-facing shape.
|
|
58
58
|
export const SiteSchema = z.object({
|
|
59
|
-
id: z.string().describe("
|
|
60
|
-
tenantId: z.string().describe("
|
|
59
|
+
id: z.string().describe("The site id (`site_...`)."),
|
|
60
|
+
tenantId: z.string().describe("The owning tenant id (`ten_...`)."),
|
|
61
61
|
principal: PrincipalRefSchema.nullable().describe("Owning principal within the tenant; null for tenant-level and pool sites."),
|
|
62
62
|
kind: siteKind.describe("Runtime kind. Only the Spacefast static runtime exists today."),
|
|
63
63
|
isolation: siteIsolation.describe("Whether settings/access default to the site or to each space."),
|
|
@@ -67,7 +67,7 @@ export const SiteSchema = z.object({
|
|
|
67
67
|
.string()
|
|
68
68
|
.nullable()
|
|
69
69
|
.describe("Hostname the control plane manages the site runtime through."),
|
|
70
|
-
runtimeInstanceId: z.string().nullable().describe("Runtime instance
|
|
70
|
+
runtimeInstanceId: z.string().nullable().describe("Runtime instance id for this site."),
|
|
71
71
|
provider: z.literal("wpcloud").describe("Hosting provider."),
|
|
72
72
|
capacity: SiteCapacitySchema.nullable().describe("Capacity accounting; null when the site has no explicit budget."),
|
|
73
73
|
operation: AsyncOperationSchema.nullable(),
|
|
@@ -84,7 +84,7 @@ export const operatorSiteProvisioningSchema = z
|
|
|
84
84
|
.trim()
|
|
85
85
|
.min(1)
|
|
86
86
|
.optional()
|
|
87
|
-
.describe("Import an existing WP.Cloud site by its atomic_site_id (operator flows)."),
|
|
87
|
+
.describe("Import an existing WP.Cloud site by its `atomic_site_id` (operator flows)."),
|
|
88
88
|
})
|
|
89
89
|
.optional();
|
|
90
90
|
// An explicit empty object requests fresh provider provisioning while keeping
|
|
@@ -92,9 +92,15 @@ export const operatorSiteProvisioningSchema = z
|
|
|
92
92
|
export const tenantSiteProvisioningSchema = z.object({}).strict().optional();
|
|
93
93
|
export const siteCreateSchema = z
|
|
94
94
|
.object({
|
|
95
|
+
teamId: z
|
|
96
|
+
.string()
|
|
97
|
+
.trim()
|
|
98
|
+
.min(1)
|
|
99
|
+
.optional()
|
|
100
|
+
.describe("Team id or slug that will own the site. If omitted, the server infers it from the principal."),
|
|
95
101
|
kind: siteKind.default("static_runtime"),
|
|
96
102
|
isolation: siteIsolation.default("site"),
|
|
97
|
-
region: z.string().trim().min(1).optional().describe('Placement region
|
|
103
|
+
region: z.string().trim().min(1).optional().describe('Placement region. Defaults to `"auto"`.'),
|
|
98
104
|
provisioning: tenantSiteProvisioningSchema,
|
|
99
105
|
})
|
|
100
106
|
.strict();
|
|
@@ -113,14 +119,16 @@ export const SuperadminSiteSchema = SiteSchema.extend({
|
|
|
113
119
|
.string()
|
|
114
120
|
.nullable()
|
|
115
121
|
.describe("WP.Cloud client identity (`pvc_...`) the site is provisioned under."),
|
|
116
|
-
providerRef: z.string().nullable().describe("WP.Cloud atomic_site_id
|
|
122
|
+
providerRef: z.string().nullable().describe("WP.Cloud `atomic_site_id`."),
|
|
117
123
|
});
|
|
118
124
|
export const SuperadminSiteListSchema = z.object({
|
|
119
125
|
sites: z.array(SuperadminSiteSchema),
|
|
120
126
|
});
|
|
121
127
|
// Superadmin site create targets an explicit tenant (the tenant-facing
|
|
122
128
|
// `siteCreateSchema` derives the tenant from the principal).
|
|
123
|
-
export const superadminSiteCreateSchema = siteCreateSchema
|
|
129
|
+
export const superadminSiteCreateSchema = siteCreateSchema
|
|
130
|
+
.omit({ provisioning: true, teamId: true })
|
|
131
|
+
.extend({
|
|
124
132
|
tenantId: z.string().trim().min(1),
|
|
125
133
|
provisioning: operatorSiteProvisioningSchema,
|
|
126
134
|
});
|
|
@@ -133,12 +141,12 @@ export const siteRebalanceRequestSchema = z
|
|
|
133
141
|
.array(z.string().trim().min(1))
|
|
134
142
|
.max(100)
|
|
135
143
|
.optional()
|
|
136
|
-
.describe("Limit the rebalance to these space ids
|
|
144
|
+
.describe("Limit the rebalance to these space ids. If omitted, the server rebalances every live space on the site."),
|
|
137
145
|
})
|
|
138
146
|
.describe("Operator-only rebalance trigger: move spaces off this site. This is the ONLY path that relocates an existing Space, and it is not free — see the reverification warning on the result.");
|
|
139
147
|
export const SiteRebalanceResultSchema = z
|
|
140
148
|
.object({
|
|
141
|
-
siteId: z.string().describe("The site spaces are being moved off."),
|
|
149
|
+
siteId: z.string().describe("The site id that spaces are being moved off."),
|
|
142
150
|
moves: z
|
|
143
151
|
.array(z.object({
|
|
144
152
|
spaceId: z.string().describe("Space queued to move."),
|
|
@@ -147,7 +155,7 @@ export const SiteRebalanceResultSchema = z
|
|
|
147
155
|
.describe("One queued move operation per affected space."),
|
|
148
156
|
warning: z
|
|
149
157
|
.string()
|
|
150
|
-
.describe("Consequence of relocating these
|
|
158
|
+
.describe("Consequence of relocating these spaces. Each hostname moves to another provider site. The provider re-runs its domain-exclusivity check and rejects the move unless the ownership TXT record is still live in DNS."),
|
|
151
159
|
domainsRequiringReverification: z
|
|
152
160
|
.array(z.object({
|
|
153
161
|
spaceId: z.string().describe("Space the hostname serves."),
|
|
@@ -155,6 +163,6 @@ export const SiteRebalanceResultSchema = z
|
|
|
155
163
|
.string()
|
|
156
164
|
.describe("Custom hostname whose provider ownership check re-runs during the move."),
|
|
157
165
|
}))
|
|
158
|
-
.describe("Live custom hostnames on the moved
|
|
166
|
+
.describe("Live custom hostnames on the moved spaces. Empty means no customer-visible hostname is at risk."),
|
|
159
167
|
})
|
|
160
168
|
.describe("Queued rebalance moves; track each operation for completion.");
|
|
@@ -25,6 +25,8 @@ export declare const SPACE_CONFIG_CAPS: {
|
|
|
25
25
|
readonly themeLogoChars: 2000;
|
|
26
26
|
/** Max `theme.name` display-name length. */
|
|
27
27
|
readonly themeNameChars: 120;
|
|
28
|
+
/** Max top-level `name` (space display name) length. Matches the stored column. */
|
|
29
|
+
readonly nameChars: 255;
|
|
28
30
|
};
|
|
29
31
|
/** Published JSON Schema URL for `sf.jsonc` ($schema autocomplete). */
|
|
30
32
|
export declare const SPACE_CONFIG_SCHEMA_URL: string;
|
|
@@ -70,7 +72,7 @@ export declare const wordpressDataSourceSchema: z.ZodObject<{
|
|
|
70
72
|
url: z.ZodString;
|
|
71
73
|
}, z.core.$strict>;
|
|
72
74
|
export type WordPressDataSource = z.infer<typeof wordpressDataSourceSchema>;
|
|
73
|
-
export declare const spaceDataSourcesSchema: z.
|
|
75
|
+
export declare const spaceDataSourcesSchema: z.ZodPipe<z.ZodUnknown, z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
74
76
|
kind: z.ZodLiteral<"wordpress">;
|
|
75
77
|
url: z.ZodString;
|
|
76
78
|
}, z.core.$strict>>>;
|
|
@@ -152,7 +154,7 @@ export declare const spaceConfigSchema: z.ZodObject<{
|
|
|
152
154
|
bodyEnd: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
153
155
|
noscript: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
154
156
|
}, z.core.$strip>>;
|
|
155
|
-
dataSources: z.ZodOptional<z.
|
|
157
|
+
dataSources: z.ZodOptional<z.ZodPipe<z.ZodUnknown, z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
156
158
|
kind: z.ZodLiteral<"wordpress">;
|
|
157
159
|
url: z.ZodString;
|
|
158
160
|
}, z.core.$strict>>>>;
|
|
@@ -162,28 +164,61 @@ export type SpaceConfig = z.infer<typeof spaceConfigSchema>;
|
|
|
162
164
|
export declare function compareDataSourceNames(left: string, right: string): number;
|
|
163
165
|
export declare function resolveDefaultDataSourceName(config: Pick<SpaceConfig, "dataSources" | "defaultDataSource"> | null | undefined): string | null;
|
|
164
166
|
export declare function spaceSuperpowersEnabled(config: SpaceConfig | null | undefined): boolean;
|
|
165
|
-
export declare const
|
|
166
|
-
|
|
167
|
-
}, z.
|
|
168
|
-
export type SpacePublishOptions = z.infer<typeof spacePublishOptionsSchema>;
|
|
169
|
-
export declare const spaceConfigFileAccessSchema: z.ZodObject<{
|
|
167
|
+
export declare const spaceConfigFileAccessSchema: z.ZodUnion<readonly [z.ZodPipe<z.ZodLiteral<"public">, z.ZodTransform<{
|
|
168
|
+
public: string[];
|
|
169
|
+
}, "public">>, z.ZodObject<{
|
|
170
170
|
public: z.ZodArray<z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>>;
|
|
171
|
-
}, z.core.$strict>;
|
|
171
|
+
}, z.core.$strict>]>;
|
|
172
172
|
export type SpaceConfigFileAccess = z.infer<typeof spaceConfigFileAccessSchema>;
|
|
173
173
|
/**
|
|
174
|
-
*
|
|
174
|
+
* Zero: a transactional app with its own database.
|
|
175
|
+
*
|
|
176
|
+
* Both entries are required because Zero is never inferred. A runtime that owns
|
|
177
|
+
* a database must not spring into existence from a directory shape, so the only
|
|
178
|
+
* way to get one is to say so — and once said, a server or client that cannot
|
|
179
|
+
* be resolved fails the publish rather than degrading to static files.
|
|
180
|
+
*/
|
|
181
|
+
export declare const spaceRuntimeZeroSchema: z.ZodObject<{
|
|
182
|
+
kind: z.ZodLiteral<"zero">;
|
|
183
|
+
server: z.ZodString;
|
|
184
|
+
client: z.ZodString;
|
|
185
|
+
}, z.core.$strip>;
|
|
186
|
+
/**
|
|
187
|
+
* Functions: the worker `sf publish` compiles.
|
|
175
188
|
*
|
|
176
|
-
* Every field is optional because the normal case is detection: a
|
|
177
|
-
* `handler.ts` or an OpenNext build needs no configuration at all.
|
|
178
|
-
* for the layouts detection cannot guess — a worker somewhere
|
|
179
|
-
* compatibility date the author wants pinned rather than
|
|
189
|
+
* Every field beyond `kind` is optional because the normal case is detection: a
|
|
190
|
+
* project with `handler.ts` or an OpenNext build needs no configuration at all.
|
|
191
|
+
* These exist for the layouts detection cannot guess — a worker somewhere
|
|
192
|
+
* unusual, or a compatibility date the author wants pinned rather than
|
|
193
|
+
* defaulted.
|
|
180
194
|
*/
|
|
181
|
-
export declare const
|
|
195
|
+
export declare const spaceRuntimeFunctionsSchema: z.ZodObject<{
|
|
196
|
+
kind: z.ZodLiteral<"functions">;
|
|
182
197
|
entry: z.ZodOptional<z.ZodString>;
|
|
183
198
|
database: z.ZodDefault<z.ZodBoolean>;
|
|
184
199
|
compatibilityDate: z.ZodOptional<z.ZodString>;
|
|
185
200
|
}, z.core.$strip>;
|
|
186
|
-
|
|
201
|
+
/**
|
|
202
|
+
* The one runtime declaration, discriminated on `kind`.
|
|
203
|
+
*
|
|
204
|
+
* One block, one kind — a version cannot express two runtimes at once, so the
|
|
205
|
+
* ambiguity never has to be resolved downstream. File-only on purpose: a
|
|
206
|
+
* runtime is a fact about the content of a version, so it rolls forward and
|
|
207
|
+
* back with the version instead of being set through the API config overlay.
|
|
208
|
+
*/
|
|
209
|
+
export declare const spaceRuntimeSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
210
|
+
kind: z.ZodLiteral<"zero">;
|
|
211
|
+
server: z.ZodString;
|
|
212
|
+
client: z.ZodString;
|
|
213
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
214
|
+
kind: z.ZodLiteral<"functions">;
|
|
215
|
+
entry: z.ZodOptional<z.ZodString>;
|
|
216
|
+
database: z.ZodDefault<z.ZodBoolean>;
|
|
217
|
+
compatibilityDate: z.ZodOptional<z.ZodString>;
|
|
218
|
+
}, z.core.$strip>], "kind">;
|
|
219
|
+
export type SpaceRuntimeZeroConfig = z.infer<typeof spaceRuntimeZeroSchema>;
|
|
220
|
+
export type SpaceRuntimeFunctionsConfig = z.infer<typeof spaceRuntimeFunctionsSchema>;
|
|
221
|
+
export type SpaceRuntimeConfig = z.infer<typeof spaceRuntimeSchema>;
|
|
187
222
|
export declare const spaceConfigFileSchema: z.ZodObject<{
|
|
188
223
|
index: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodLiteral<false>]>>;
|
|
189
224
|
fallback: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
|
|
@@ -264,17 +299,22 @@ export declare const spaceConfigFileSchema: z.ZodObject<{
|
|
|
264
299
|
}, z.core.$strip>>;
|
|
265
300
|
$schema: z.ZodOptional<z.ZodString>;
|
|
266
301
|
space: z.ZodOptional<z.ZodString>;
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
302
|
+
name: z.ZodOptional<z.ZodString>;
|
|
303
|
+
access: z.ZodOptional<z.ZodUnion<readonly [z.ZodPipe<z.ZodLiteral<"public">, z.ZodTransform<{
|
|
304
|
+
public: string[];
|
|
305
|
+
}, "public">>, z.ZodObject<{
|
|
271
306
|
public: z.ZodArray<z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>>;
|
|
272
|
-
}, z.core.$strict>>;
|
|
273
|
-
|
|
307
|
+
}, z.core.$strict>]>>;
|
|
308
|
+
runtime: z.ZodOptional<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
309
|
+
kind: z.ZodLiteral<"zero">;
|
|
310
|
+
server: z.ZodString;
|
|
311
|
+
client: z.ZodString;
|
|
312
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
313
|
+
kind: z.ZodLiteral<"functions">;
|
|
274
314
|
entry: z.ZodOptional<z.ZodString>;
|
|
275
315
|
database: z.ZodDefault<z.ZodBoolean>;
|
|
276
316
|
compatibilityDate: z.ZodOptional<z.ZodString>;
|
|
277
|
-
}, z.core.$strip>>;
|
|
317
|
+
}, z.core.$strip>], "kind">>;
|
|
278
318
|
}, z.core.$strip>;
|
|
279
319
|
export type SpaceConfigFile = z.infer<typeof spaceConfigFileSchema>;
|
|
280
320
|
/**
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import {
|
|
2
|
+
import { serviceOrigin } from "../config/domains.js";
|
|
3
3
|
import { normalizedSiteClass } from "./enums.js";
|
|
4
4
|
import { GRANT_RESOURCE_PATTERN_LIMIT, normalizeGrantResourcePattern } from "./grants.js";
|
|
5
5
|
export const SPACE_CONFIG_CANONICAL_FILE = "sf.jsonc";
|
|
@@ -43,9 +43,11 @@ export const SPACE_CONFIG_CAPS = {
|
|
|
43
43
|
themeLogoChars: 2000,
|
|
44
44
|
/** Max `theme.name` display-name length. */
|
|
45
45
|
themeNameChars: 120,
|
|
46
|
+
/** Max top-level `name` (space display name) length. Matches the stored column. */
|
|
47
|
+
nameChars: 255,
|
|
46
48
|
};
|
|
47
49
|
/** Published JSON Schema URL for `sf.jsonc` ($schema autocomplete). */
|
|
48
|
-
export const SPACE_CONFIG_SCHEMA_URL = `${
|
|
50
|
+
export const SPACE_CONFIG_SCHEMA_URL = `${serviceOrigin("www", "prod")}/schemas/sf.json`;
|
|
49
51
|
// Pages theme tokens: visual values consumed by publish-rendered site pages.
|
|
50
52
|
// Presentation only — never layout, behavior, or protocol.
|
|
51
53
|
// Color grammar accepts hex/rgb(a)/hsl(a)/
|
|
@@ -317,17 +319,16 @@ export const wordpressDataSourceSchema = z
|
|
|
317
319
|
})
|
|
318
320
|
.strict()
|
|
319
321
|
.describe("A public WordPress site exposed to repository builds as a content source.");
|
|
320
|
-
function
|
|
321
|
-
|
|
322
|
+
function hasNoReservedDataSourceRecordKeys(value) {
|
|
323
|
+
return !(typeof value === "object" &&
|
|
322
324
|
value !== null &&
|
|
323
325
|
!Array.isArray(value) &&
|
|
324
|
-
Object.keys(value).some((name) => RESERVED_DATA_SOURCE_NAMES.has(name)))
|
|
325
|
-
return null;
|
|
326
|
-
}
|
|
327
|
-
return value;
|
|
326
|
+
Object.keys(value).some((name) => RESERVED_DATA_SOURCE_NAMES.has(name)));
|
|
328
327
|
}
|
|
329
328
|
export const spaceDataSourcesSchema = z
|
|
330
|
-
.
|
|
329
|
+
.unknown()
|
|
330
|
+
.refine(hasNoReservedDataSourceRecordKeys, { message: "dataSources contains a reserved name." })
|
|
331
|
+
.pipe(z
|
|
331
332
|
.record(dataSourceNameSchema, wordpressDataSourceSchema)
|
|
332
333
|
.refine((sources) => Object.keys(sources).length <= SPACE_CONFIG_CAPS.dataSources, {
|
|
333
334
|
message: `dataSources supports up to ${SPACE_CONFIG_CAPS.dataSources} entries.`,
|
|
@@ -365,11 +366,11 @@ const spaceConfigBaseSchema = z.object({
|
|
|
365
366
|
}),
|
|
366
367
|
])
|
|
367
368
|
.optional()
|
|
368
|
-
.describe('Fallback document
|
|
369
|
+
.describe('Fallback document. "/index.html" means SPA. Defaults to the nearest 404.html.'),
|
|
369
370
|
cleanUrls: z
|
|
370
371
|
.boolean()
|
|
371
372
|
.optional()
|
|
372
|
-
.describe("Serve flat `<name>.html` files at their extensionless URL (
|
|
373
|
+
.describe("Serve flat `<name>.html` files at their extensionless URL (`/about` serves `about.html`). Defaults to on, unless a 200-status SPA fallback is configured."),
|
|
373
374
|
listing: z.boolean().optional().describe("Enable automatic directory listings."),
|
|
374
375
|
meta: z
|
|
375
376
|
.object({
|
|
@@ -470,7 +471,7 @@ export const spaceConfigSchema = spaceConfigBaseSchema
|
|
|
470
471
|
.describe(`Named public WordPress sources exposed to repository builds; at most ${SPACE_CONFIG_CAPS.dataSources} entries.`),
|
|
471
472
|
defaultDataSource: dataSourceNameSchema
|
|
472
473
|
.optional()
|
|
473
|
-
.describe("Name of the configured source exposed through WORDPRESS_URL
|
|
474
|
+
.describe("Name of the configured source exposed through `WORDPRESS_URL`. It must match a `dataSources` entry. When omitted, the first source in bytewise name order is used."),
|
|
474
475
|
})
|
|
475
476
|
.superRefine(refineDefaultDataSource);
|
|
476
477
|
export function compareDataSourceNames(left, right) {
|
|
@@ -491,22 +492,9 @@ export function spaceSuperpowersEnabled(config) {
|
|
|
491
492
|
// The `sf.jsonc` FILE shape (internal-docs/platform.md "Space
|
|
492
493
|
// Configuration Files"): SpaceConfig plus the editor `$schema` pointer and the
|
|
493
494
|
// optional `space` link (slug or `spc_` id) resolved by CLI/publish flows.
|
|
494
|
-
// Routing
|
|
495
|
-
//
|
|
496
|
-
//
|
|
497
|
-
// publish tooling before upload, never by the runtime — like `$schema` and
|
|
498
|
-
// `space`, this key lives only in the FILE shape and never reaches the space
|
|
499
|
-
// `config` overlay.
|
|
500
|
-
export const spacePublishOptionsSchema = z
|
|
501
|
-
.object({
|
|
502
|
-
fingerprint: z
|
|
503
|
-
.boolean()
|
|
504
|
-
.optional()
|
|
505
|
-
.describe("Publish-time asset fingerprinting: adds content-hashed immutable aliases " +
|
|
506
|
-
"(name.<sha256-8>.ext) for stable assets and rewrites exact HTML/CSS references. " +
|
|
507
|
-
"Originals keep serving unchanged. Default off."),
|
|
508
|
-
})
|
|
509
|
-
.describe("Client publish-time options consumed by the Spacefast CLI, not the runtime.");
|
|
495
|
+
// Routing rules (`redirects`/`rewrites`/`headers`) are sf.jsonc keys too, but they belong
|
|
496
|
+
// to the routing compiler, not to this shape: it resolves serving, they compile
|
|
497
|
+
// into the canonical rules and merge behind `_redirects`/`_headers`.
|
|
510
498
|
const spaceConfigPublicPatternSchema = z
|
|
511
499
|
.string()
|
|
512
500
|
.min(1)
|
|
@@ -525,7 +513,7 @@ const spaceConfigPublicPatternSchema = z
|
|
|
525
513
|
return z.NEVER;
|
|
526
514
|
}
|
|
527
515
|
});
|
|
528
|
-
|
|
516
|
+
const spaceConfigFileAccessObjectSchema = z
|
|
529
517
|
.object({
|
|
530
518
|
public: z
|
|
531
519
|
.array(spaceConfigPublicPatternSchema)
|
|
@@ -555,39 +543,79 @@ export const spaceConfigFileAccessSchema = z
|
|
|
555
543
|
message: "access.public requires at least one inclusion pattern.",
|
|
556
544
|
});
|
|
557
545
|
}
|
|
546
|
+
});
|
|
547
|
+
export const spaceConfigFileAccessSchema = z
|
|
548
|
+
.union([
|
|
549
|
+
z
|
|
550
|
+
.literal("public")
|
|
551
|
+
.describe('Shorthand for { "public": ["/**"] }: the whole live space is public.')
|
|
552
|
+
.transform(() => ({ public: ["/**"] })),
|
|
553
|
+
spaceConfigFileAccessObjectSchema,
|
|
554
|
+
])
|
|
555
|
+
.describe("File-only public access declaration. It is inactive until the space is claimed.");
|
|
556
|
+
/**
|
|
557
|
+
* Zero: a transactional app with its own database.
|
|
558
|
+
*
|
|
559
|
+
* Both entries are required because Zero is never inferred. A runtime that owns
|
|
560
|
+
* a database must not spring into existence from a directory shape, so the only
|
|
561
|
+
* way to get one is to say so — and once said, a server or client that cannot
|
|
562
|
+
* be resolved fails the publish rather than degrading to static files.
|
|
563
|
+
*/
|
|
564
|
+
export const spaceRuntimeZeroSchema = z
|
|
565
|
+
.object({
|
|
566
|
+
kind: z.literal("zero"),
|
|
567
|
+
server: z
|
|
568
|
+
.string()
|
|
569
|
+
.trim()
|
|
570
|
+
.min(1)
|
|
571
|
+
.describe("Path to the server entry module, relative to the published directory."),
|
|
572
|
+
client: z
|
|
573
|
+
.string()
|
|
574
|
+
.trim()
|
|
575
|
+
.min(1)
|
|
576
|
+
.describe("Path to the client entry module, relative to the published directory."),
|
|
558
577
|
})
|
|
559
|
-
.describe("
|
|
578
|
+
.describe("Zero: a transactional app with its own database, compiled at publish time.");
|
|
560
579
|
/**
|
|
561
|
-
*
|
|
580
|
+
* Functions: the worker `sf publish` compiles.
|
|
562
581
|
*
|
|
563
|
-
* Every field is optional because the normal case is detection: a
|
|
564
|
-
* `handler.ts` or an OpenNext build needs no configuration at all.
|
|
565
|
-
* for the layouts detection cannot guess — a worker somewhere
|
|
566
|
-
* compatibility date the author wants pinned rather than
|
|
582
|
+
* Every field beyond `kind` is optional because the normal case is detection: a
|
|
583
|
+
* project with `handler.ts` or an OpenNext build needs no configuration at all.
|
|
584
|
+
* These exist for the layouts detection cannot guess — a worker somewhere
|
|
585
|
+
* unusual, or a compatibility date the author wants pinned rather than
|
|
586
|
+
* defaulted.
|
|
567
587
|
*/
|
|
568
|
-
export const
|
|
588
|
+
export const spaceRuntimeFunctionsSchema = z
|
|
569
589
|
.object({
|
|
590
|
+
kind: z.literal("functions"),
|
|
570
591
|
entry: z
|
|
571
592
|
.string()
|
|
572
593
|
.optional()
|
|
573
594
|
.describe("Path to the worker entry module, relative to the published directory. " +
|
|
574
|
-
"
|
|
575
|
-
"rather than a silent static publish."),
|
|
595
|
+
"When absent, the server detects it automatically. Naming an entry that does not exist is an error, not a silent static publish."),
|
|
576
596
|
database: z
|
|
577
597
|
.boolean()
|
|
578
598
|
.default(false)
|
|
579
599
|
.describe("Give the worker `env.DB`, a D1-shaped binding to this space's database. " +
|
|
580
|
-
"
|
|
581
|
-
"authority they cannot see, and reading it out of minified build output " +
|
|
582
|
-
"would be a guess. Off by default, so a worker reaches nothing until it says so."),
|
|
600
|
+
"This capability is declared, not detected. A capability an author did not request is authority they cannot see. Reading it from minified build output is a guess. Defaults to off, so a worker reaches nothing until it says so."),
|
|
583
601
|
compatibilityDate: z
|
|
584
602
|
.string()
|
|
585
603
|
.regex(/^\d{4}-\d{2}-\d{2}$/)
|
|
586
604
|
.optional()
|
|
587
|
-
.describe("Runtime compatibility date this worker was written against. Pinning it makes "
|
|
588
|
-
"rollback honest: promoting an old version restores the semantics it was built with."),
|
|
605
|
+
.describe("Runtime compatibility date this worker was written against. Pinning it makes rollback honest. Promoting an old version restores the semantics it was built with."),
|
|
589
606
|
})
|
|
590
|
-
.describe("
|
|
607
|
+
.describe("Functions: a worker compiled at publish time.");
|
|
608
|
+
/**
|
|
609
|
+
* The one runtime declaration, discriminated on `kind`.
|
|
610
|
+
*
|
|
611
|
+
* One block, one kind — a version cannot express two runtimes at once, so the
|
|
612
|
+
* ambiguity never has to be resolved downstream. File-only on purpose: a
|
|
613
|
+
* runtime is a fact about the content of a version, so it rolls forward and
|
|
614
|
+
* back with the version instead of being set through the API config overlay.
|
|
615
|
+
*/
|
|
616
|
+
export const spaceRuntimeSchema = z
|
|
617
|
+
.discriminatedUnion("kind", [spaceRuntimeZeroSchema, spaceRuntimeFunctionsSchema])
|
|
618
|
+
.describe("Runtime this version's code runs on. Omit it for a static space. Functions is also detected from the published directory when it is not stated.");
|
|
591
619
|
export const spaceConfigFileSchema = spaceConfigBaseSchema.extend({
|
|
592
620
|
$schema: z
|
|
593
621
|
.string()
|
|
@@ -598,9 +626,17 @@ export const spaceConfigFileSchema = spaceConfigBaseSchema.extend({
|
|
|
598
626
|
.min(1)
|
|
599
627
|
.optional()
|
|
600
628
|
.describe("Optional space link: a space slug or spc_ id this project publishes to."),
|
|
601
|
-
|
|
629
|
+
// File-owned naming: the live version's config decides the display name, so
|
|
630
|
+
// it rolls forward and back with the version like every other content fact.
|
|
631
|
+
name: z
|
|
632
|
+
.string()
|
|
633
|
+
.trim()
|
|
634
|
+
.min(1)
|
|
635
|
+
.max(SPACE_CONFIG_CAPS.nameChars)
|
|
636
|
+
.optional()
|
|
637
|
+
.describe("Display name for this space. While set, the API refuses to rename the space."),
|
|
602
638
|
access: spaceConfigFileAccessSchema.optional(),
|
|
603
|
-
|
|
639
|
+
runtime: spaceRuntimeSchema.optional(),
|
|
604
640
|
});
|
|
605
641
|
/**
|
|
606
642
|
* The published JSON Schema artifact for `sf.jsonc`, generated from the
|
|
@@ -608,12 +644,102 @@ export const spaceConfigFileSchema = spaceConfigBaseSchema.extend({
|
|
|
608
644
|
* autocomplete and validation.
|
|
609
645
|
*/
|
|
610
646
|
export function spaceConfigJsonSchema() {
|
|
611
|
-
|
|
647
|
+
const schema = stripHiddenSpaceConfigKeys({
|
|
612
648
|
...z.toJSONSchema(spaceConfigFileSchema, { target: "draft-7", io: "input" }),
|
|
613
649
|
$id: SPACE_CONFIG_SCHEMA_URL,
|
|
614
650
|
title: "Spacefast space configuration (sf.jsonc)",
|
|
615
651
|
});
|
|
652
|
+
// `redirects`, `rewrites` and `headers` are real sf.jsonc keys, owned by the routing
|
|
653
|
+
// compiler rather than by the serving shape above — which is why they are
|
|
654
|
+
// described here instead of in the zod schema that resolves serving. An editor
|
|
655
|
+
// reading this file still has to know they exist, or the documented routing
|
|
656
|
+
// examples read as unknown keys.
|
|
657
|
+
return {
|
|
658
|
+
...schema,
|
|
659
|
+
properties: {
|
|
660
|
+
...schema.properties,
|
|
661
|
+
...SPACE_CONFIG_ROUTING_SCHEMA_PROPERTIES,
|
|
662
|
+
},
|
|
663
|
+
};
|
|
616
664
|
}
|
|
665
|
+
const SPACE_CONFIG_ROUTING_SCHEMA_PROPERTIES = {
|
|
666
|
+
redirects: {
|
|
667
|
+
type: "array",
|
|
668
|
+
description: "Browser redirect rules. Same matcher grammar as _redirects, and _redirects rules match first.",
|
|
669
|
+
items: {
|
|
670
|
+
type: "object",
|
|
671
|
+
properties: {
|
|
672
|
+
source: {
|
|
673
|
+
type: "string",
|
|
674
|
+
minLength: 1,
|
|
675
|
+
description: "Request path to match. * is a splat, :name captures a segment.",
|
|
676
|
+
},
|
|
677
|
+
destination: {
|
|
678
|
+
type: "string",
|
|
679
|
+
minLength: 1,
|
|
680
|
+
description: "Path or absolute URL. :splat and :name from the source are substituted.",
|
|
681
|
+
},
|
|
682
|
+
status: {
|
|
683
|
+
enum: [301, 302, 303, 307, 308],
|
|
684
|
+
default: 302,
|
|
685
|
+
description: "Redirect status. To serve other content under this URL, use rewrites.",
|
|
686
|
+
},
|
|
687
|
+
},
|
|
688
|
+
required: ["source", "destination"],
|
|
689
|
+
additionalProperties: false,
|
|
690
|
+
},
|
|
691
|
+
},
|
|
692
|
+
rewrites: {
|
|
693
|
+
type: "array",
|
|
694
|
+
description: "Rewrite and proxy rules: the URL stays, the content comes from the destination. _redirects rules match first, then redirects.",
|
|
695
|
+
items: {
|
|
696
|
+
type: "object",
|
|
697
|
+
properties: {
|
|
698
|
+
source: {
|
|
699
|
+
type: "string",
|
|
700
|
+
minLength: 1,
|
|
701
|
+
description: "Request path to match. * is a splat, :name captures a segment.",
|
|
702
|
+
},
|
|
703
|
+
destination: {
|
|
704
|
+
type: "string",
|
|
705
|
+
minLength: 1,
|
|
706
|
+
description: "Path to serve under this URL, or an absolute URL to proxy. :splat and :name from the source are substituted.",
|
|
707
|
+
},
|
|
708
|
+
cache: {
|
|
709
|
+
const: "shared",
|
|
710
|
+
description: "Let shared caches store the proxy response. Absolute-URL destinations only.",
|
|
711
|
+
},
|
|
712
|
+
},
|
|
713
|
+
required: ["source", "destination"],
|
|
714
|
+
additionalProperties: false,
|
|
715
|
+
},
|
|
716
|
+
},
|
|
717
|
+
headers: {
|
|
718
|
+
type: "array",
|
|
719
|
+
description: "Response headers to set on matching requests. A _headers rule wins on the same header name.",
|
|
720
|
+
items: {
|
|
721
|
+
type: "object",
|
|
722
|
+
properties: {
|
|
723
|
+
source: { type: "string", minLength: 1, description: "Request path to match." },
|
|
724
|
+
headers: {
|
|
725
|
+
type: "array",
|
|
726
|
+
minItems: 1,
|
|
727
|
+
items: {
|
|
728
|
+
type: "object",
|
|
729
|
+
properties: {
|
|
730
|
+
key: { type: "string", minLength: 1 },
|
|
731
|
+
value: { type: "string" },
|
|
732
|
+
},
|
|
733
|
+
required: ["key", "value"],
|
|
734
|
+
additionalProperties: false,
|
|
735
|
+
},
|
|
736
|
+
},
|
|
737
|
+
},
|
|
738
|
+
required: ["source", "headers"],
|
|
739
|
+
additionalProperties: false,
|
|
740
|
+
},
|
|
741
|
+
},
|
|
742
|
+
};
|
|
617
743
|
/*
|
|
618
744
|
* Hidden-feature discipline (internal-docs/build-pipeline-plan.md): the
|
|
619
745
|
* `experimental_gutenberg` flag and its `inject` companion are ACCEPTED by the
|