@spacefast/common 0.2.2 → 0.4.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.
Files changed (226) hide show
  1. package/dist/agents/marketplace-prompts.d.ts +1 -0
  2. package/dist/agents/marketplace-prompts.js +6 -0
  3. package/dist/agents/registry/core.d.ts +4 -12
  4. package/dist/agents/registry/core.js +7 -28
  5. package/dist/config/domains.d.ts +10 -8
  6. package/dist/config/domains.js +4 -7
  7. package/dist/contracts/access-core.d.ts +135 -0
  8. package/dist/contracts/access-core.js +242 -0
  9. package/dist/contracts/access-profiles.d.ts +8 -8
  10. package/dist/contracts/access-profiles.js +8 -8
  11. package/dist/contracts/access.d.ts +14 -103
  12. package/dist/contracts/access.js +10 -210
  13. package/dist/contracts/activity.d.ts +54 -55
  14. package/dist/contracts/activity.js +38 -9
  15. package/dist/contracts/api-keys.d.ts +69 -26
  16. package/dist/contracts/api-keys.js +29 -2
  17. package/dist/contracts/application-journal.d.ts +197 -4
  18. package/dist/contracts/application-journal.js +97 -16
  19. package/dist/contracts/auth.d.ts +20 -0
  20. package/dist/contracts/auth.js +18 -0
  21. package/dist/contracts/beta.d.ts +13 -0
  22. package/dist/contracts/beta.js +28 -0
  23. package/dist/contracts/billing.d.ts +2 -2
  24. package/dist/contracts/bootstrap.d.ts +23 -6
  25. package/dist/contracts/builds.d.ts +18 -4
  26. package/dist/contracts/builds.js +7 -4
  27. package/dist/contracts/channels.d.ts +43 -0
  28. package/dist/contracts/channels.js +22 -6
  29. package/dist/contracts/comments.d.ts +49 -0
  30. package/dist/contracts/comments.js +61 -2
  31. package/dist/contracts/commerce.d.ts +19 -13
  32. package/dist/contracts/connector-access.d.ts +28 -0
  33. package/dist/contracts/connector-access.js +31 -0
  34. package/dist/contracts/connectors.d.ts +2382 -0
  35. package/dist/contracts/connectors.js +941 -0
  36. package/dist/contracts/content-contract-verification.d.ts +112 -58
  37. package/dist/contracts/content-contract-verification.js +42 -54
  38. package/dist/contracts/content-model-emit.d.ts +97 -0
  39. package/dist/contracts/content-model-emit.js +306 -0
  40. package/dist/contracts/content-model-sdk.d.ts +101 -0
  41. package/dist/contracts/content-model-sdk.js +232 -0
  42. package/dist/contracts/{content-program.d.ts → content-model.d.ts} +338 -82
  43. package/dist/contracts/{content-program.js → content-model.js} +291 -63
  44. package/dist/contracts/content-platform-fixture.d.ts +380 -110
  45. package/dist/contracts/content-platform-fixture.js +8 -8
  46. package/dist/contracts/content-sync.d.ts +197 -74
  47. package/dist/contracts/content-sync.js +98 -37
  48. package/dist/contracts/content.d.ts +30 -422
  49. package/dist/contracts/content.js +34 -294
  50. package/dist/contracts/dashboard-prefs.d.ts +10 -3
  51. package/dist/contracts/dashboard-prefs.js +6 -3
  52. package/dist/contracts/data-location.d.ts +9 -0
  53. package/dist/contracts/data-location.js +7 -0
  54. package/dist/contracts/deployment-comparison.d.ts +67 -0
  55. package/dist/contracts/deployment-comparison.js +68 -0
  56. package/dist/contracts/device-auth.d.ts +55 -11
  57. package/dist/contracts/domains.d.ts +40 -16
  58. package/dist/contracts/domains.js +23 -0
  59. package/dist/contracts/enums.d.ts +1 -10
  60. package/dist/contracts/enums.js +0 -15
  61. package/dist/contracts/error-code-meta.d.ts +384 -20
  62. package/dist/contracts/error-code-meta.js +200 -5
  63. package/dist/contracts/error-codes.d.ts +17 -4
  64. package/dist/contracts/error-codes.js +108 -10
  65. package/dist/contracts/events.d.ts +5 -0
  66. package/dist/contracts/events.js +12 -3
  67. package/dist/contracts/execution.d.ts +5 -1
  68. package/dist/contracts/execution.js +4 -0
  69. package/dist/contracts/feature-lifecycle.d.ts +53 -20
  70. package/dist/contracts/feature-lifecycle.js +65 -23
  71. package/dist/contracts/features.d.ts +57 -31
  72. package/dist/contracts/features.js +0 -1
  73. package/dist/contracts/feedback.d.ts +124 -0
  74. package/dist/contracts/feedback.js +64 -0
  75. package/dist/contracts/fixtures/content-model-sdk-v1.generated.d.ts +129 -0
  76. package/dist/contracts/fixtures/content-model-sdk-v1.generated.js +48 -0
  77. package/dist/contracts/fixtures/content-platform-v1.json +101 -49
  78. package/dist/contracts/frame-session.d.ts +60 -10
  79. package/dist/contracts/frame-session.js +52 -12
  80. package/dist/contracts/functions.d.ts +28 -2
  81. package/dist/contracts/functions.js +25 -2
  82. package/dist/contracts/grant-copy.d.ts +2 -0
  83. package/dist/contracts/grant-copy.js +2 -0
  84. package/dist/contracts/grants-core.d.ts +95 -0
  85. package/dist/contracts/grants-core.js +435 -0
  86. package/dist/contracts/grants.d.ts +13 -84
  87. package/dist/contracts/grants.js +21 -369
  88. package/dist/contracts/ids-core.d.ts +11 -0
  89. package/dist/contracts/ids-core.js +14 -0
  90. package/dist/contracts/ids.d.ts +7 -4
  91. package/dist/contracts/ids.js +12 -4
  92. package/dist/contracts/internal.d.ts +18 -0
  93. package/dist/contracts/internal.js +19 -0
  94. package/dist/contracts/mcp.d.ts +8 -18
  95. package/dist/contracts/mcp.js +2 -23
  96. package/dist/contracts/notifications.d.ts +4 -1
  97. package/dist/contracts/notifications.js +1 -0
  98. package/dist/contracts/oauth-resources.d.ts +46 -9
  99. package/dist/contracts/oauth-resources.js +50 -1
  100. package/dist/contracts/oauth-scope-actions.d.ts +27 -3
  101. package/dist/contracts/oauth-scope-actions.js +18 -8
  102. package/dist/contracts/operations.d.ts +1 -1
  103. package/dist/contracts/partner-account.d.ts +629 -0
  104. package/dist/contracts/partner-account.js +18 -0
  105. package/dist/contracts/principal-assertion.d.ts +74 -1
  106. package/dist/contracts/principal-assertion.js +67 -3
  107. package/dist/contracts/publish-archive.d.ts +22 -1
  108. package/dist/contracts/push-new.d.ts +3 -3
  109. package/dist/contracts/push-new.js +1 -1
  110. package/dist/contracts/quotas.js +2 -1
  111. package/dist/contracts/repository-connections.d.ts +10 -6
  112. package/dist/contracts/repository-connections.js +15 -0
  113. package/dist/contracts/resources.d.ts +6 -5
  114. package/dist/contracts/resources.js +7 -0
  115. package/dist/contracts/route-inventory.d.ts +74 -19
  116. package/dist/contracts/route-inventory.js +20 -6
  117. package/dist/contracts/runtime-api.d.ts +415 -4
  118. package/dist/contracts/runtime-api.js +60 -15
  119. package/dist/contracts/runtime-app.d.ts +6 -1
  120. package/dist/contracts/runtime-components.d.ts +646 -18
  121. package/dist/contracts/runtime-components.js +304 -188
  122. package/dist/contracts/runtime-services.d.ts +15 -0
  123. package/dist/contracts/runtime-services.js +25 -0
  124. package/dist/contracts/runtime-storage.d.ts +32 -0
  125. package/dist/contracts/runtime-storage.js +37 -0
  126. package/dist/contracts/source-workspaces.d.ts +511 -0
  127. package/dist/contracts/source-workspaces.js +276 -0
  128. package/dist/contracts/space-config-spacefast.d.ts +394 -0
  129. package/dist/contracts/space-config-spacefast.js +70 -0
  130. package/dist/contracts/space-config.d.ts +177 -90
  131. package/dist/contracts/space-config.js +77 -92
  132. package/dist/contracts/spaces.d.ts +132 -24
  133. package/dist/contracts/spaces.js +77 -13
  134. package/dist/contracts/superadmin-connectors.d.ts +371 -0
  135. package/dist/contracts/superadmin-connectors.js +61 -0
  136. package/dist/contracts/superadmin-emails.d.ts +1 -1
  137. package/dist/contracts/superadmin-emails.js +1 -1
  138. package/dist/contracts/superadmin-entities.d.ts +105 -0
  139. package/dist/contracts/superadmin-entities.js +64 -0
  140. package/dist/contracts/superadmin-runtime.d.ts +35 -116
  141. package/dist/contracts/superadmin-runtime.js +13 -69
  142. package/dist/contracts/superadmin-search.d.ts +12 -14
  143. package/dist/contracts/superadmin-search.js +2 -2
  144. package/dist/contracts/superadmin-spaces.d.ts +15 -72
  145. package/dist/contracts/superadmin-spaces.js +2 -7
  146. package/dist/contracts/superadmin-teams.d.ts +12 -0
  147. package/dist/contracts/superadmin-teams.js +7 -1
  148. package/dist/contracts/superadmin-tenants.d.ts +44 -16
  149. package/dist/contracts/superadmin.d.ts +2 -2
  150. package/dist/contracts/tags.d.ts +12 -12
  151. package/dist/contracts/teams.d.ts +29 -1
  152. package/dist/contracts/teams.js +24 -2
  153. package/dist/contracts/tenants.d.ts +98 -0
  154. package/dist/contracts/tenants.js +20 -0
  155. package/dist/contracts/transfers.d.ts +92 -0
  156. package/dist/contracts/transfers.js +37 -0
  157. package/dist/contracts/usage.d.ts +9 -1
  158. package/dist/contracts/usage.js +2 -0
  159. package/dist/contracts/visual-review.d.ts +448 -0
  160. package/dist/contracts/visual-review.js +156 -0
  161. package/dist/contracts/wordpress-php-toolkit.json +9 -0
  162. package/dist/contracts/work-mode.d.ts +24 -0
  163. package/dist/contracts/work-mode.js +17 -0
  164. package/dist/contracts/wp-cli.d.ts +66 -0
  165. package/dist/contracts/wp-cli.js +68 -0
  166. package/dist/contracts/zero-catalog.d.ts +29 -0
  167. package/dist/contracts/zero-catalog.js +55 -0
  168. package/dist/contracts/zero-platform-abilities.generated.d.ts +31 -0
  169. package/dist/contracts/zero-platform-abilities.generated.js +373 -0
  170. package/dist/contracts/zero-spacefast.d.ts +444 -0
  171. package/dist/contracts/zero-spacefast.js +149 -0
  172. package/dist/contracts/zero-types.d.ts +47 -0
  173. package/dist/contracts/zero-types.js +263 -0
  174. package/dist/contracts/zero.d.ts +781 -14
  175. package/dist/contracts/zero.js +204 -10
  176. package/dist/dashboard-paths/index.d.ts +2 -2
  177. package/dist/dashboard-paths/route-reservations.generated.d.ts +2 -2
  178. package/dist/dashboard-paths/route-reservations.generated.js +5 -0
  179. package/dist/docs/agent-prose.d.ts +1 -1
  180. package/dist/docs/agent-prose.js +15 -18
  181. package/dist/docs/agent-setup.d.ts +1 -1
  182. package/dist/docs/agent-setup.js +5 -13
  183. package/dist/docs/catalog.d.ts +64 -28
  184. package/dist/docs/catalog.js +155 -28
  185. package/dist/docs/error-docs.d.ts +361 -17
  186. package/dist/docs/error-docs.js +365 -21
  187. package/dist/docs/reference-urls.js +1 -1
  188. package/dist/docs/skills.d.ts +84 -84
  189. package/dist/docs/skills.js +66 -47
  190. package/dist/docs/start-prompts.d.ts +14 -0
  191. package/dist/docs/start-prompts.js +20 -0
  192. package/dist/utils/account-labels.d.ts +7 -0
  193. package/dist/utils/account-labels.js +15 -0
  194. package/dist/utils/auth.d.ts +1 -0
  195. package/dist/utils/auth.js +1 -0
  196. package/dist/utils/credential-policy.d.ts +22 -1
  197. package/dist/utils/credential-policy.js +55 -6
  198. package/dist/utils/local-space-state.d.ts +7 -0
  199. package/dist/utils/local-space-state.js +7 -0
  200. package/dist/utils/logger.d.ts +34 -0
  201. package/dist/utils/logger.js +144 -0
  202. package/dist/utils/page-routes.d.ts +9 -0
  203. package/dist/utils/page-routes.js +82 -0
  204. package/dist/utils/pages.d.ts +2 -0
  205. package/dist/utils/pages.js +7 -0
  206. package/dist/utils/publish-form-data.d.ts +2 -0
  207. package/dist/utils/publish-form-data.js +2 -0
  208. package/dist/utils/publish-policy-spacefast.d.ts +13 -0
  209. package/dist/utils/publish-policy-spacefast.js +117 -0
  210. package/dist/utils/publish-policy.d.ts +22 -16
  211. package/dist/utils/publish-policy.fixtures.json +15 -0
  212. package/dist/utils/publish-policy.js +62 -139
  213. package/dist/utils/query-client.js +9 -1
  214. package/dist/utils/runtime-upload.d.ts +4 -0
  215. package/dist/utils/runtime-upload.js +5 -0
  216. package/dist/utils/space-config.d.ts +2 -3
  217. package/dist/utils/space-config.js +1 -1
  218. package/dist/utils/uploaded-source.d.ts +4 -0
  219. package/dist/utils/uploaded-source.js +12 -0
  220. package/dist/visual-review.d.ts +4 -0
  221. package/dist/visual-review.js +208 -0
  222. package/dist/vocabulary.d.ts +38 -0
  223. package/dist/vocabulary.js +55 -0
  224. package/package.json +7 -2
  225. package/dist/agents/registry/deeplink-probes.d.ts +0 -23
  226. package/dist/agents/registry/deeplink-probes.js +0 -18
@@ -0,0 +1,144 @@
1
+ /* oxlint-disable anti-slop/no-unsafe-dictionary-type, anti-slop/no-runtime-typeof, anti-slop/no-known-value-widening, anti-slop/no-unknown-parameters, anti-slop/no-unknown-returns -- Log fields are an open bag of arbitrary application values by contract; this module's job is to serialize any runtime value safely, so the open dictionary and runtime kind checks are the boundary itself (same rationale as the Sentry processor in apps/control-plane/src/lib/sentry.ts). */
2
+ import { inspect } from "node:util";
3
+ const LEVEL_WEIGHT = {
4
+ debug: 10,
5
+ info: 20,
6
+ warn: 30,
7
+ error: 40,
8
+ silent: Number.POSITIVE_INFINITY,
9
+ };
10
+ function isConfigurableLevel(value) {
11
+ return (value === "debug" ||
12
+ value === "info" ||
13
+ value === "warn" ||
14
+ value === "error" ||
15
+ value === "silent");
16
+ }
17
+ function defaultLevel() {
18
+ const raw = process.env.LOG_LEVEL?.toLowerCase();
19
+ if (isConfigurableLevel(raw))
20
+ return raw;
21
+ return process.env.NODE_ENV === "production" ? "info" : "debug";
22
+ }
23
+ function defaultFormat() {
24
+ return process.env.NODE_ENV === "production" || process.env.LOG_FORMAT === "json"
25
+ ? "json"
26
+ : "pretty";
27
+ }
28
+ function normalizeValue(value, projectError, seen, depth = 0) {
29
+ if (typeof value !== "object" || value === null)
30
+ return value;
31
+ if (seen.has(value))
32
+ return "[Circular]";
33
+ if (depth >= 12)
34
+ return "[Truncated]";
35
+ seen.add(value);
36
+ if (value instanceof Error) {
37
+ const projected = projectError?.(value);
38
+ if (projected)
39
+ return projected;
40
+ const record = {
41
+ ...value,
42
+ name: value.name,
43
+ message: value.message,
44
+ stack: value.stack,
45
+ };
46
+ if (value.cause !== undefined)
47
+ record.cause = value.cause;
48
+ if (value instanceof AggregateError)
49
+ record.errors = value.errors;
50
+ return normalizeValue(record, projectError, seen, depth + 1);
51
+ }
52
+ if (Array.isArray(value)) {
53
+ return value.map((entry) => normalizeValue(entry, projectError, seen, depth + 1));
54
+ }
55
+ if (Object.getPrototypeOf(value) !== Object.prototype && Object.getPrototypeOf(value) !== null) {
56
+ return value;
57
+ }
58
+ return Object.fromEntries(Object.entries(value).map(([key, entry]) => [
59
+ key,
60
+ normalizeValue(entry, projectError, seen, depth + 1),
61
+ ]));
62
+ }
63
+ function normalizeFields(fields, projectError) {
64
+ if (!fields)
65
+ return undefined;
66
+ return Object.fromEntries(Object.entries(fields).map(([key, value]) => [
67
+ key,
68
+ normalizeValue(value, projectError, new WeakSet()),
69
+ ]));
70
+ }
71
+ function safeJsonStringify(record) {
72
+ const seen = new WeakSet();
73
+ return (JSON.stringify(record, (_key, value) => {
74
+ if (typeof value === "bigint")
75
+ return value.toString();
76
+ if (typeof value === "object" && value !== null) {
77
+ if (seen.has(value))
78
+ return "[Circular]";
79
+ seen.add(value);
80
+ }
81
+ return value;
82
+ }) ?? "null");
83
+ }
84
+ const AUTO_STREAM = {
85
+ debug: "log",
86
+ info: "log",
87
+ warn: "warn",
88
+ error: "error",
89
+ };
90
+ function emit(options, level, message, fields) {
91
+ if (LEVEL_WEIGHT[level] < options.minWeight)
92
+ return;
93
+ const timestamp = new Date().toISOString();
94
+ const payload = normalizeFields(fields, options.projectError);
95
+ const stream = options.stream === "stderr" ? "error" : AUTO_STREAM[level];
96
+ if (options.format === "json") {
97
+ console[stream](safeJsonStringify({ ts: timestamp, level, message, ...payload }));
98
+ }
99
+ else {
100
+ const prefix = `${timestamp} ${level.toUpperCase().padEnd(5, " ")}`;
101
+ if (!payload || Object.keys(payload).length === 0) {
102
+ console[stream](`${prefix} ${message}`);
103
+ }
104
+ else {
105
+ const rendered = inspect(payload, { depth: 6, colors: true, breakLength: 120 });
106
+ console[stream](`${prefix} ${message} ${rendered}`);
107
+ }
108
+ }
109
+ if (options.onEmit) {
110
+ try {
111
+ options.onEmit(level, message, payload);
112
+ }
113
+ catch {
114
+ // Logging must never make application code fail.
115
+ }
116
+ }
117
+ }
118
+ function build(options, bindings) {
119
+ const hasBindings = Object.keys(bindings).length > 0;
120
+ function merge(fields) {
121
+ if (!fields)
122
+ return hasBindings ? { ...bindings } : undefined;
123
+ return { ...bindings, ...fields };
124
+ }
125
+ return {
126
+ debug: (message, fields) => emit(options, "debug", message, merge(fields)),
127
+ info: (message, fields) => emit(options, "info", message, merge(fields)),
128
+ warn: (message, fields) => emit(options, "warn", message, merge(fields)),
129
+ error: (message, fields) => emit(options, "error", message, merge(fields)),
130
+ child: (extraBindings) => build(options, { ...bindings, ...extraBindings }),
131
+ };
132
+ }
133
+ export function createLogger(options = {}) {
134
+ const resolved = {
135
+ minWeight: LEVEL_WEIGHT[options.level ?? defaultLevel()],
136
+ format: options.format ?? defaultFormat(),
137
+ stream: options.stream ?? "auto",
138
+ onEmit: options.onEmit,
139
+ projectError: options.projectError,
140
+ };
141
+ return build(resolved, options.bindings ?? {});
142
+ }
143
+ /** Env-configured logger for processes that own their stdout. */
144
+ export const logger = createLogger();
@@ -0,0 +1,9 @@
1
+ export declare function matchPagePath(pattern: string, pathname: string): Record<string, string> | null;
2
+ export declare function comparePagePaths(left: string, right: string): number;
3
+ export declare function resolvePageRoute<T extends {
4
+ path: string;
5
+ }>(pages: readonly T[], pathname: string): {
6
+ page: T;
7
+ params: Record<string, string>;
8
+ } | null;
9
+ export declare function pageRoutesOverlap(left: string, right: string): boolean;
@@ -0,0 +1,82 @@
1
+ function segments(path) {
2
+ return path
3
+ .replace(/^\/+|\/+$/g, "")
4
+ .split("/")
5
+ .filter(Boolean);
6
+ }
7
+ export function matchPagePath(pattern, pathname) {
8
+ const expected = segments(pattern);
9
+ const encoded = segments(pathname);
10
+ let actual;
11
+ try {
12
+ actual = encoded.map((segment) => decodeURIComponent(segment));
13
+ }
14
+ catch {
15
+ return null;
16
+ }
17
+ if (actual.some((segment) => segment.includes("/") || segment.includes("\\") || segment.includes("\0")))
18
+ return null;
19
+ const params = {};
20
+ for (const [index, segment] of expected.entries()) {
21
+ if (segment.startsWith("*")) {
22
+ if (index !== expected.length - 1 || index >= actual.length)
23
+ return null;
24
+ Object.defineProperty(params, segment.slice(1), {
25
+ value: actual.slice(index).join("/"),
26
+ enumerable: true,
27
+ });
28
+ return params;
29
+ }
30
+ const value = actual[index];
31
+ if (value === undefined)
32
+ return null;
33
+ if (segment.startsWith(":")) {
34
+ Object.defineProperty(params, segment.slice(1), { value, enumerable: true });
35
+ }
36
+ else if (segment !== value) {
37
+ return null;
38
+ }
39
+ }
40
+ return actual.length === expected.length ? params : null;
41
+ }
42
+ export function comparePagePaths(left, right) {
43
+ const a = segments(left);
44
+ const b = segments(right);
45
+ const rank = (segment) => (segment.startsWith("*") ? 1 : segment.startsWith(":") ? 2 : 3);
46
+ for (let index = 0; index < Math.min(a.length, b.length); index++) {
47
+ const x = a[index] ?? "";
48
+ const y = b[index] ?? "";
49
+ const priority = rank(y) - rank(x);
50
+ if (priority !== 0)
51
+ return priority;
52
+ if (rank(x) === 3 && x !== y)
53
+ return x < y ? -1 : 1;
54
+ }
55
+ return a.length - b.length || (left < right ? -1 : left > right ? 1 : 0);
56
+ }
57
+ export function resolvePageRoute(pages, pathname) {
58
+ let selected = null;
59
+ for (const page of pages) {
60
+ const params = matchPagePath(page.path, pathname);
61
+ if (params !== null &&
62
+ (selected === null || comparePagePaths(page.path, selected.page.path) < 0)) {
63
+ selected = { page, params };
64
+ }
65
+ }
66
+ return selected;
67
+ }
68
+ export function pageRoutesOverlap(left, right) {
69
+ const a = segments(left);
70
+ const b = segments(right);
71
+ for (let index = 0; index < Math.max(a.length, b.length); index++) {
72
+ const x = a[index];
73
+ const y = b[index];
74
+ if (x === undefined || y === undefined)
75
+ return false;
76
+ if (x.startsWith("*") || y.startsWith("*") || x === ":splat" || y === ":splat")
77
+ return true;
78
+ if (!x.startsWith(":") && !y.startsWith(":") && x !== y)
79
+ return false;
80
+ }
81
+ return true;
82
+ }
@@ -51,6 +51,8 @@ export declare function escapePageHtml(value: string): string;
51
51
  * dashboard preview paints the same tokens from an unsaved draft.
52
52
  */
53
53
  export declare function pageThemeCss(theme: PageTheme, derived?: DerivedPageColors): string;
54
+ /** Site-wide theme tokens plus low-priority defaults that authored CSS can override. */
55
+ export declare function siteThemeCss(theme: PageTheme): string;
54
56
  export declare function expandPageHtml(source: string, context: PageExpansionContext): string;
55
57
  export declare function validatePageSources(input: {
56
58
  pages: Readonly<Record<string, string>>;
@@ -61,6 +61,13 @@ export function pageThemeCss(theme, derived = derivePageColors(theme)) {
61
61
  const darkBlock = dark.length > 0 ? `@media(prefers-color-scheme:dark){:root{${dark.join(";")}}}` : "";
62
62
  return `:root{${root.join(";")}}${darkBlock}`;
63
63
  }
64
+ /** Site-wide theme tokens plus low-priority defaults that authored CSS can override. */
65
+ export function siteThemeCss(theme) {
66
+ const tokens = pageThemeCss(theme);
67
+ if (tokens === "")
68
+ return "";
69
+ return `${tokens}@layer spacefast-theme{body{background:var(--sf-bg,Canvas);color:var(--sf-fg,CanvasText);font-family:var(--sf-font,system-ui,sans-serif)}a{color:var(--sf-link,var(--sf-accent,LinkText))}}`;
70
+ }
64
71
  function themeStyle(theme) {
65
72
  const css = pageThemeCss(theme);
66
73
  return css ? `<style>${css}</style>` : "";
@@ -20,6 +20,8 @@ export declare function createPublishFormData(input: {
20
20
  slug?: string | undefined;
21
21
  title?: string | undefined;
22
22
  description?: string | undefined;
23
+ /** Initial root access for a new team-owned Space. */
24
+ access?: "private" | "team" | "public" | undefined;
23
25
  /** Live promotion intent for archive builds; null produces an unpromoted ready version. */
24
26
  channel?: "live" | null | undefined;
25
27
  /**
@@ -5,6 +5,8 @@ export function createPublishFormData(input) {
5
5
  form.append("spaceId", input.spaceId);
6
6
  if (input.teamId)
7
7
  form.append("teamId", input.teamId);
8
+ if (input.access)
9
+ form.append("access", input.access);
8
10
  if (input.description)
9
11
  form.append("description", input.description);
10
12
  if (input.sourceMetadata || input.buildLog || input.channel !== undefined) {
@@ -0,0 +1,13 @@
1
+ export declare const ANONYMOUS_SERVE_CONTENT_TYPES: readonly ["text/*", "image/*", "font/*", "application/json", "application/manifest+json", "application/javascript", "application/gzip", "application/xml", "application/rss+xml", "application/atom+xml"];
2
+ export type FreePlanContentPolicyOptions = {
3
+ claimedSpace?: boolean;
4
+ };
5
+ export declare function freePlanCanUploadPath(filePath: string, options?: FreePlanContentPolicyOptions): boolean;
6
+ export declare function freePlanCanUploadContentType(contentType: string | undefined): boolean;
7
+ export declare function filterFreePlanManifest<T extends {
8
+ path: string;
9
+ contentType?: string | undefined;
10
+ }>(files: readonly T[], options?: FreePlanContentPolicyOptions): {
11
+ allowed: T[];
12
+ ignored: string[];
13
+ };
@@ -0,0 +1,117 @@
1
+ import { SPACE_CONFIG_PRIVATE_FILES } from "../contracts/space-config.js";
2
+ import { normalizePublishPath, publishPathIsConvention } from "./publish-policy.js";
3
+ // Free-plan publish content policy (spec "Plans And Limits"). What a plan lets a
4
+ // space publish and serve is Spacefast's commerce model, not the publish format,
5
+ // so it extends the shared static policy in `./publish-policy.js` rather than
6
+ // living inside it.
7
+ const FREE_PLAN_ALLOWED_UPLOAD_EXTENSIONS = new Set([
8
+ ".html",
9
+ ".htm",
10
+ ".css",
11
+ ".js",
12
+ ".mjs",
13
+ ".cjs",
14
+ ".json",
15
+ ".map",
16
+ ".webmanifest",
17
+ ".txt",
18
+ ".md",
19
+ ".csv",
20
+ // Migration fixtures, served as application/octet-stream.
21
+ ".customtype",
22
+ ".xml",
23
+ ".svg",
24
+ ".png",
25
+ ".jpg",
26
+ ".jpeg",
27
+ ".gif",
28
+ ".webp",
29
+ ".avif",
30
+ ".ico",
31
+ ".woff",
32
+ ".woff2",
33
+ ".ttf",
34
+ ".otf",
35
+ ]);
36
+ // THE anonymous content enforcement: uploads are accepted like any free
37
+ // publish, but until the space is claimed the runtime serves only these types,
38
+ // pushed as the route-config `content_types` allowlist. Web-page content only.
39
+ // Gzip is the one archive, because pagefind search indexes need it.
40
+ export const ANONYMOUS_SERVE_CONTENT_TYPES = [
41
+ "text/*",
42
+ "image/*",
43
+ "font/*",
44
+ "application/json",
45
+ "application/manifest+json",
46
+ "application/javascript",
47
+ "application/gzip",
48
+ "application/xml",
49
+ "application/rss+xml",
50
+ "application/atom+xml",
51
+ ];
52
+ function extensionForPath(filePath) {
53
+ const normalized = normalizePublishPath(filePath).toLowerCase();
54
+ const fileName = normalized.split("/").at(-1) ?? normalized;
55
+ const extensionIndex = fileName.lastIndexOf(".");
56
+ return extensionIndex > 0 ? fileName.slice(extensionIndex) : "";
57
+ }
58
+ function freePlanDeniedExecutablePath(filePath) {
59
+ return normalizePublishPath(filePath)
60
+ .toLowerCase()
61
+ .split("/")
62
+ .some((segment) => segment === "bin");
63
+ }
64
+ // Acceptance is deliberately identical for claimed-free and unclaimed spaces:
65
+ // rejecting types at upload adds no safety, since the bytes reach us before
66
+ // any scan either way. ANONYMOUS_SERVE_CONTENT_TYPES is what keeps opaque
67
+ // binaries dark until the space is claimed.
68
+ export function freePlanCanUploadPath(filePath, options) {
69
+ const path = normalizePublishPath(filePath);
70
+ // Platform machinery, not user content: same lifecycle as
71
+ // `_redirects`/`_headers`, so the content-extension gate must never eat them.
72
+ if (SPACE_CONFIG_PRIVATE_FILES.some((privateFile) => privateFile === path)) {
73
+ return true;
74
+ }
75
+ if (freePlanDeniedExecutablePath(path)) {
76
+ return false;
77
+ }
78
+ const extension = extensionForPath(path);
79
+ return (publishPathIsConvention(path) ||
80
+ extension === "" ||
81
+ FREE_PLAN_ALLOWED_UPLOAD_EXTENSIONS.has(extension) ||
82
+ (options?.claimedSpace === true && extension === ".sh"));
83
+ }
84
+ export function freePlanCanUploadContentType(contentType) {
85
+ const normalized = contentType?.split(";")[0]?.trim().toLowerCase();
86
+ return (normalized === "text/html" ||
87
+ normalized === "text/plain" ||
88
+ normalized === "text/css" ||
89
+ normalized === "text/csv" ||
90
+ normalized === "text/markdown" ||
91
+ normalized === "text/javascript" ||
92
+ normalized === "application/javascript" ||
93
+ normalized === "application/json" ||
94
+ normalized === "application/manifest+json" ||
95
+ // pagefind ships gzip fragments, and ClamAV decompresses gzip when scanning.
96
+ normalized === "application/gzip" ||
97
+ normalized === "image/svg+xml" ||
98
+ normalized === "application/xml" ||
99
+ normalized === "text/xml" ||
100
+ normalized?.startsWith("image/") ||
101
+ normalized?.startsWith("font/") ||
102
+ false);
103
+ }
104
+ export function filterFreePlanManifest(files, options) {
105
+ const allowed = [];
106
+ const ignored = [];
107
+ for (const file of files) {
108
+ if (freePlanCanUploadPath(file.path, options) ||
109
+ freePlanCanUploadContentType(file.contentType)) {
110
+ allowed.push(file);
111
+ }
112
+ else {
113
+ ignored.push(file.path);
114
+ }
115
+ }
116
+ return { allowed, ignored };
117
+ }
@@ -3,6 +3,12 @@ export declare const MANIFEST_MAX_FILES_CEILING = 100000;
3
3
  export declare const MANIFEST_MAX_PATH_BYTES = 1024;
4
4
  export declare const MANIFEST_MAX_BODY_BYTES: number;
5
5
  export declare const MAX_VERSION_FILE_SIZE_BYTES: number;
6
+ /**
7
+ * Per-version artifact ceiling, summed over file bytes at manifest intake. The
8
+ * abuse table in `contracts/quotas.js` names this same value as
9
+ * `maxArtifactBytes` by importing it, so the ceiling has one literal without the
10
+ * shared validator depending on the host's quota model.
11
+ */
6
12
  export declare const MAX_VERSION_TOTAL_BYTES: number;
7
13
  export declare const STATIC_EXECUTION_CONTROL_FILES: string[];
8
14
  export declare const STATIC_RUNTIME_CONTROL_SEGMENT_PREFIXES: string[];
@@ -23,7 +29,12 @@ export declare const PUBLISHABLE_BUILD_ARTIFACT_PREFIX = "__spacefast/functions/
23
29
  export declare const PUBLISHABLE_SEED_ARTIFACT_PREFIX = "__spacefast/functions/seeds/";
24
30
  export declare function publishPathIgnored(relativePath: string): boolean;
25
31
  export declare function publishPathIsConvention(relativePath: string): boolean;
26
- export declare function providerRuntimeFeatureWarnings(paths: readonly string[]): PublishManifestWarning[];
32
+ /**
33
+ * `productName` is the host's own name, injected: the warning tells an author
34
+ * which platform will not execute the file it found. It defaults to the
35
+ * compiled-in Spacefast name, checked against `brand.js` by this module's test.
36
+ */
37
+ export declare function providerRuntimeFeatureWarnings(paths: readonly string[], productName?: string): PublishManifestWarning[];
27
38
  export type StaticUploadPolicyOptions = {
28
39
  reservedRuntimeControlFiles?: Iterable<string>;
29
40
  };
@@ -78,6 +89,13 @@ export type PublishRouteOwnership = {
78
89
  requestedRoute: string;
79
90
  artifactPath: string;
80
91
  };
92
+ export type PublishRouteArtifact = {
93
+ path: string;
94
+ size: number;
95
+ sha256?: string | undefined;
96
+ contentType?: string | undefined;
97
+ };
98
+ export declare function isEquivalentHtmlDirectoryIndexCollision(collision: PublishRouteAnalysis["collisions"][number], filesByPath: ReadonlyMap<string, PublishRouteArtifact>, directoryIndex: string | false): boolean;
81
99
  /**
82
100
  * Canonicalizes a route expanded from an already-canonical manifest path.
83
101
  * Manifest intake has decoded percent escapes exactly once, so this must not
@@ -86,12 +104,13 @@ export type PublishRouteOwnership = {
86
104
  export declare function canonicalizePublishRequestedRoute(route: string): string;
87
105
  /**
88
106
  * Expands artifact paths into the request routes they can serve: literal
89
- * files, directory indexes and clean `.html` aliases. Two artifacts owning one
90
- * route is rejected at publish rather than left to lookup order.
107
+ * files, directory indexes and clean `.html` aliases. Multiple artifacts owning
108
+ * one route are reported so finalize can reject ambiguous content.
91
109
  * `routeOwnership` restates the expansion in canonical access-route form.
92
110
  */
93
111
  export declare function analyzePublishRoutes(paths: readonly string[], options?: {
94
112
  index?: string | false;
113
+ directoryIndex?: string;
95
114
  cleanUrls?: boolean;
96
115
  }): PublishRouteAnalysis;
97
116
  export declare function resolveManifestFileCap(maxFiles?: number | null): number;
@@ -99,16 +118,3 @@ export declare function validatePublishManifest<T extends {
99
118
  path: string;
100
119
  size: number;
101
120
  }>(files: readonly T[], caps?: PublishManifestCaps): PublishManifestResult<T>;
102
- export declare const ANONYMOUS_SERVE_CONTENT_TYPES: readonly ["text/*", "image/*", "font/*", "application/json", "application/manifest+json", "application/javascript", "application/gzip", "application/xml", "application/rss+xml", "application/atom+xml"];
103
- export type FreePlanContentPolicyOptions = {
104
- claimedSpace?: boolean;
105
- };
106
- export declare function freePlanCanUploadPath(filePath: string, options?: FreePlanContentPolicyOptions): boolean;
107
- export declare function freePlanCanUploadContentType(contentType: string | undefined): boolean;
108
- export declare function filterFreePlanManifest<T extends {
109
- path: string;
110
- contentType?: string | undefined;
111
- }>(files: readonly T[], options?: FreePlanContentPolicyOptions): {
112
- allowed: T[];
113
- ignored: string[];
114
- };
@@ -98,6 +98,21 @@
98
98
  "path": "nested/__span/x.json",
99
99
  "expected": null
100
100
  },
101
+ {
102
+ "path": "__zero/config",
103
+ "expected": "static_runtime_control_path_not_supported",
104
+ "why": "the front door claims the whole /__zero control namespace"
105
+ },
106
+ {
107
+ "path": "__zeroed/index.html",
108
+ "expected": null,
109
+ "why": "the Zero namespace is a whole segment, not a string prefix"
110
+ },
111
+ {
112
+ "path": "assets/__zero-client.js",
113
+ "expected": null,
114
+ "why": "reserved at the root only, exactly as far as the front door reaches"
115
+ },
101
116
  {
102
117
  "path": "__spacefast/x.txt",
103
118
  "expected": "static_runtime_control_path_not_supported"