@spacefast/common 0.0.21 → 0.0.24
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/connect-targets.d.ts +9 -6
- package/dist/agents/connect-targets.js +9 -6
- package/dist/config/domains.d.ts +1 -1
- package/dist/config/domains.js +1 -0
- package/dist/config/index.d.ts +0 -1
- package/dist/config/index.js +0 -1
- package/dist/contracts/abuse.d.ts +2 -0
- package/dist/contracts/abuse.js +12 -0
- package/dist/contracts/access.d.ts +121 -9
- package/dist/contracts/access.js +73 -9
- package/dist/contracts/activity.d.ts +1 -1
- package/dist/contracts/activity.js +0 -9
- package/dist/contracts/api-keys.d.ts +21 -21
- package/dist/contracts/beta.js +1 -1
- package/dist/contracts/billing.d.ts +1 -34
- package/dist/contracts/billing.js +4 -53
- package/dist/contracts/builds.d.ts +8 -8
- package/dist/contracts/builds.js +10 -3
- package/dist/contracts/cli.d.ts +10 -0
- package/dist/contracts/cli.js +10 -0
- package/dist/contracts/collab-public.d.ts +63 -0
- package/dist/contracts/collab-public.js +46 -0
- package/dist/contracts/comments.d.ts +283 -54
- package/dist/contracts/comments.js +173 -52
- package/dist/contracts/common.d.ts +3 -3
- package/dist/contracts/device-auth.d.ts +6 -6
- package/dist/contracts/device-auth.js +1 -1
- package/dist/contracts/docs.d.ts +5 -5
- package/dist/contracts/domains.d.ts +36 -36
- package/dist/contracts/enums.d.ts +33 -30
- package/dist/contracts/enums.js +52 -38
- package/dist/contracts/error-code-meta.d.ts +37 -126
- package/dist/contracts/error-code-meta.js +12 -41
- package/dist/contracts/error-codes.d.ts +1 -1
- package/dist/contracts/error-codes.js +10 -32
- package/dist/contracts/execution.d.ts +35 -57
- package/dist/contracts/execution.js +41 -40
- package/dist/contracts/feature-lifecycle-core.d.ts +0 -6
- package/dist/contracts/feature-lifecycle-core.js +2 -31
- package/dist/contracts/feature-lifecycle.d.ts +8 -38
- package/dist/contracts/feature-lifecycle.js +16 -48
- package/dist/contracts/features.d.ts +15 -13
- package/dist/contracts/features.js +39 -38
- package/dist/contracts/functions.d.ts +97 -70
- package/dist/contracts/functions.js +101 -34
- package/dist/contracts/git.d.ts +1 -1
- package/dist/contracts/grants.d.ts +7 -3
- package/dist/contracts/grants.js +18 -9
- package/dist/contracts/internal.d.ts +14 -1
- package/dist/contracts/internal.js +17 -7
- package/dist/contracts/oauth-resources.d.ts +4 -3
- package/dist/contracts/oauth-resources.js +12 -3
- package/dist/contracts/operations.d.ts +90 -5
- package/dist/contracts/operations.js +75 -1
- package/dist/contracts/pages.d.ts +6 -1
- package/dist/contracts/pages.js +24 -1
- package/dist/contracts/plan-policy.d.ts +1 -3
- package/dist/contracts/plan-policy.js +1 -2
- package/dist/contracts/platform.d.ts +61 -148
- package/dist/contracts/platform.js +70 -126
- package/dist/contracts/publish-archive.d.ts +498 -0
- package/dist/contracts/publish-archive.js +25 -0
- package/dist/contracts/resources.d.ts +12 -24
- package/dist/contracts/resources.js +32 -12
- package/dist/contracts/runtime-api.d.ts +369 -175
- package/dist/contracts/runtime-api.js +372 -348
- package/dist/contracts/runtime-app.d.ts +127 -120
- package/dist/contracts/runtime-app.js +19 -10
- package/dist/contracts/runtime-db.d.ts +1 -1
- package/dist/contracts/runtime-services.d.ts +219 -0
- package/dist/contracts/runtime-services.js +437 -0
- package/dist/contracts/runtime-storage.d.ts +45 -32
- package/dist/contracts/runtime-storage.js +30 -8
- package/dist/contracts/space-config.d.ts +10 -16
- package/dist/contracts/space-config.js +14 -10
- package/dist/contracts/spaces.d.ts +241 -436
- package/dist/contracts/spaces.js +128 -145
- package/dist/contracts/superadmin-activity.d.ts +57 -4
- package/dist/contracts/superadmin-activity.js +48 -2
- package/dist/contracts/superadmin-search.d.ts +126 -0
- package/dist/contracts/superadmin-search.js +61 -0
- package/dist/contracts/superadmin-spaces.d.ts +358 -89
- package/dist/contracts/superadmin-spaces.js +97 -24
- package/dist/contracts/superadmin-teams.d.ts +28 -10
- package/dist/contracts/superadmin-teams.js +5 -8
- package/dist/contracts/superadmin.d.ts +0 -32
- package/dist/contracts/superadmin.js +3 -11
- package/dist/contracts/tags.d.ts +9 -9
- package/dist/contracts/teams.d.ts +44 -2
- package/dist/contracts/teams.js +43 -23
- package/dist/contracts/transfers.d.ts +0 -49
- package/dist/contracts/transfers.js +2 -6
- package/dist/contracts/usage.d.ts +61 -0
- package/dist/contracts/usage.js +64 -0
- package/dist/contracts/variables.d.ts +2 -7
- package/dist/contracts/variables.js +6 -5
- package/dist/contracts/webhooks.d.ts +2 -2
- package/dist/contracts/zero.d.ts +87 -56
- package/dist/contracts/zero.js +82 -20
- package/dist/dashboard-paths/index.d.ts +1 -1
- package/dist/dashboard-paths/index.js +1 -0
- package/dist/docs/agent-prose.d.ts +1 -1
- package/dist/docs/agent-prose.js +62 -66
- package/dist/docs/agent-setup.js +49 -23
- package/dist/docs/agent-solutions.d.ts +4 -4
- package/dist/docs/agent-solutions.js +8 -8
- package/dist/docs/catalog.d.ts +19 -19
- package/dist/docs/catalog.js +30 -19
- package/dist/docs/error-docs.js +63 -151
- package/dist/docs/skills.d.ts +3 -3
- package/dist/docs/skills.js +1 -1
- package/dist/test-helpers/fetch-stub.d.ts +16 -0
- package/dist/test-helpers/fetch-stub.js +24 -0
- package/dist/utils/build-settings.js +9 -3
- package/dist/utils/canonical-json.d.ts +10 -0
- package/dist/utils/canonical-json.js +21 -0
- package/dist/utils/cast-transport.d.ts +28 -0
- package/dist/utils/cast-transport.js +52 -0
- package/dist/utils/claim-token.d.ts +0 -8
- package/dist/utils/claim-token.js +3 -15
- package/dist/utils/credential-policy.d.ts +1 -1
- package/dist/utils/env-file.d.ts +17 -0
- package/dist/utils/env-file.js +96 -0
- package/dist/utils/error-code.d.ts +2 -0
- package/dist/utils/error-code.js +7 -0
- package/dist/utils/generate-space-name.d.ts +8 -10
- package/dist/utils/generate-space-name.js +206 -21
- package/dist/utils/grant-decision.fixtures.json +2938 -0
- package/dist/utils/grants.d.ts +2 -0
- package/dist/utils/grants.js +25 -2
- package/dist/utils/gravatar.d.ts +9 -0
- package/dist/utils/gravatar.js +31 -0
- package/dist/utils/idempotency.d.ts +6 -0
- package/dist/utils/idempotency.js +28 -0
- package/dist/utils/local-space-state.d.ts +1 -5
- package/dist/utils/local-space-state.js +7 -26
- package/dist/utils/page-fonts.d.ts +2 -2
- package/dist/utils/page-fonts.js +22 -4
- package/dist/utils/pages.d.ts +1 -2
- package/dist/utils/pages.js +21 -5
- package/dist/utils/publish-form-data.d.ts +12 -0
- package/dist/utils/publish-form-data.js +10 -0
- package/dist/utils/publish-policy.d.ts +20 -0
- package/dist/utils/publish-policy.fixtures.json +397 -0
- package/dist/utils/publish-policy.js +36 -19
- package/dist/utils/push-new.d.ts +7 -0
- package/dist/utils/push-new.js +7 -0
- package/dist/utils/query-keys.d.ts +0 -1
- package/dist/utils/query-keys.js +0 -1
- package/dist/utils/runtime-paths.d.ts +5 -0
- package/dist/utils/runtime-paths.js +5 -0
- package/dist/utils/runtime-upload-batch.d.ts +0 -5
- package/dist/utils/runtime-upload-batch.js +1 -27
- package/dist/utils/runtime-upload.d.ts +3 -13
- package/dist/utils/runtime-upload.js +4 -14
- package/dist/utils/space-config.d.ts +0 -33
- package/dist/utils/space-config.js +5 -326
- package/dist/utils/storage-policy.d.ts +1 -1
- package/dist/utils/storage-policy.js +3 -1
- package/dist/utils/structured-error.d.ts +14 -0
- package/dist/utils/structured-error.js +22 -0
- package/dist/utils/version-path.js +12 -3
- package/dist/vocabulary.d.ts +5 -3
- package/dist/vocabulary.js +13 -10
- package/package.json +10 -5
- package/dist/config/postgres-budget.d.ts +0 -129
- package/dist/config/postgres-budget.js +0 -140
- package/dist/config/postgres-budget.json +0 -51
- package/dist/contracts/archives.d.ts +0 -331
- package/dist/contracts/archives.js +0 -120
- package/dist/contracts/deployments.d.ts +0 -574
- package/dist/contracts/deployments.js +0 -97
- package/dist/contracts/sites.d.ts +0 -416
- package/dist/contracts/sites.js +0 -168
- package/dist/contracts/superadmin-queues.d.ts +0 -414
- package/dist/contracts/superadmin-queues.js +0 -202
- package/dist/contracts/superadmin-runtime.d.ts +0 -27
- package/dist/contracts/superadmin-runtime.js +0 -38
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -1
- package/dist/utils/api.d.ts +0 -4
- package/dist/utils/api.js +0 -13
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* How a client addresses Cast over Phoenix. Both Spacefast clients — the
|
|
3
|
+
* dashboard's notice subscription and the injected Collab SDK — build their
|
|
4
|
+
* socket and their topics here, and nowhere else.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* `~n` escapes, the inverse of `CastWeb.ApiContext.decode_path_segment/1`.
|
|
8
|
+
* `~` goes first in intent: the map is applied in one pass, so an already
|
|
9
|
+
* escaped marker can never be escaped twice.
|
|
10
|
+
*/
|
|
11
|
+
const ESCAPED = new Map([
|
|
12
|
+
["~", "~0"],
|
|
13
|
+
["/", "~1"],
|
|
14
|
+
[":", "~2"],
|
|
15
|
+
["\\", "~3"],
|
|
16
|
+
["%", "~4"],
|
|
17
|
+
["\0", "~5"],
|
|
18
|
+
]);
|
|
19
|
+
/**
|
|
20
|
+
* The Phoenix topic a Cast room's messages travel on.
|
|
21
|
+
*
|
|
22
|
+
* Phoenix routes a broadcast by the *literal* topic string. Cast broadcasts
|
|
23
|
+
* anything computed outside a channel process — Space notices, REST-published
|
|
24
|
+
* room events — to the topic `Cast.RoomTopic.for/2` builds, so a client that
|
|
25
|
+
* encodes the room key any other way joins a real and permanently silent room.
|
|
26
|
+
* Both sides therefore encode exactly once, here and in that module: the `~n`
|
|
27
|
+
* table first (it survives round-tripping a key that itself contains `~` or
|
|
28
|
+
* `%`), then `encodeURIComponent`.
|
|
29
|
+
*
|
|
30
|
+
* Proven by delivery, not by inspection: `./cast-transport.test.ts` pins the
|
|
31
|
+
* strings, and on the other side `room_channel_notice_test.exs` and
|
|
32
|
+
* `spacefast_inbox_fanout_test.exs` join those literal topics and assert a real
|
|
33
|
+
* Cast broadcast arrives on them.
|
|
34
|
+
*/
|
|
35
|
+
export function castRoomTopic(resourceKey, roomKey) {
|
|
36
|
+
let escaped = "";
|
|
37
|
+
for (const character of roomKey)
|
|
38
|
+
escaped += ESCAPED.get(character) ?? character;
|
|
39
|
+
return `room:${resourceKey}:${encodeURIComponent(escaped)}`;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Phoenix's own `Socket` appends `/websocket` to whatever endpoint it is given,
|
|
43
|
+
* so a configured URL that already carries the suffix would otherwise become
|
|
44
|
+
* `/websocket/websocket`.
|
|
45
|
+
*/
|
|
46
|
+
export function phoenixEndpoint(url) {
|
|
47
|
+
const parsed = new URL(url);
|
|
48
|
+
if (parsed.pathname.endsWith("/websocket")) {
|
|
49
|
+
parsed.pathname = parsed.pathname.slice(0, -"/websocket".length);
|
|
50
|
+
}
|
|
51
|
+
return parsed.href.replace(/\/$/, "");
|
|
52
|
+
}
|
|
@@ -1,9 +1 @@
|
|
|
1
|
-
export type ClaimCredential = {
|
|
2
|
-
kind: "token";
|
|
3
|
-
claimToken: string;
|
|
4
|
-
} | {
|
|
5
|
-
kind: "nonce";
|
|
6
|
-
nonce: string;
|
|
7
|
-
};
|
|
8
|
-
export declare function classifyClaimCredential(raw: string | null | undefined): ClaimCredential | undefined;
|
|
9
1
|
export declare function normalizeClaimToken(token: string | null | undefined): string | undefined;
|
|
@@ -1,18 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
if (!trimmed) {
|
|
5
|
-
return undefined;
|
|
6
|
-
}
|
|
7
|
-
if (trimmed.startsWith("sfc_")) {
|
|
8
|
-
return { kind: "token", claimToken: trimmed };
|
|
9
|
-
}
|
|
10
|
-
const normalized = normalizeClaimToken(trimmed);
|
|
11
|
-
if (normalized && LEGACY_WORD_TOKEN_SHAPE.test(normalized)) {
|
|
12
|
-
return { kind: "token", claimToken: normalized };
|
|
13
|
-
}
|
|
14
|
-
return { kind: "nonce", nonce: trimmed };
|
|
15
|
-
}
|
|
1
|
+
// The space key (`sfc_…`, or the legacy five-word form) is the one claim
|
|
2
|
+
// credential; it authenticates as a `Bearer` header and rides claim-link
|
|
3
|
+
// fragments verbatim.
|
|
16
4
|
export function normalizeClaimToken(token) {
|
|
17
5
|
const trimmed = token?.trim();
|
|
18
6
|
if (!trimmed) {
|
|
@@ -16,7 +16,7 @@ export type PolicyAuthorizeInput = {
|
|
|
16
16
|
resource: string | readonly string[];
|
|
17
17
|
conditions?: RequestCondition;
|
|
18
18
|
};
|
|
19
|
-
export declare const publishActions: ("spaces:read" | "spaces:write" | "spaces:
|
|
19
|
+
export declare const publishActions: ("spaces:read" | "spaces:write" | "spaces:publish" | "builds:trigger" | "spaces:create" | "versions:read" | "versions:promote" | "versions:download" | "builds:read" | "builds:create")[];
|
|
20
20
|
export declare function compileApiKeyPreset(preset: ApiKeyPreset, input: PolicyCompileInput): ApiCredentialPolicy;
|
|
21
21
|
/** Expand a named API-key preset into the finite permissions sent on the public wire contract. */
|
|
22
22
|
export declare function apiKeyPresetPermissions(preset: ApiKeyPreset): StatticAction[];
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export type ParsedEnvFileEntry = {
|
|
2
|
+
name: string;
|
|
3
|
+
value: string;
|
|
4
|
+
line: number;
|
|
5
|
+
};
|
|
6
|
+
type ValidationErrorFactory = (message: string) => Error;
|
|
7
|
+
export declare function parseEnvFile(content: string, options?: {
|
|
8
|
+
reservedStatticPrefix?: boolean;
|
|
9
|
+
validationError?: ValidationErrorFactory;
|
|
10
|
+
}): ParsedEnvFileEntry[];
|
|
11
|
+
export declare function loadEnvFileSource<const File extends string>(root: string, files: readonly File[], options?: {
|
|
12
|
+
validationError?: ValidationErrorFactory;
|
|
13
|
+
}): Promise<{
|
|
14
|
+
file: File;
|
|
15
|
+
content: string;
|
|
16
|
+
} | null>;
|
|
17
|
+
export {};
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { variableNameSchema } from "../contracts/variables.js";
|
|
4
|
+
import { hasErrorCode } from "./error-code.js";
|
|
5
|
+
import { structuredValidationError } from "./structured-error.js";
|
|
6
|
+
const localEnvNamePattern = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
7
|
+
function stripInlineComment(value) {
|
|
8
|
+
let quoted = null;
|
|
9
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
10
|
+
const char = value[index];
|
|
11
|
+
if (quoted) {
|
|
12
|
+
if (char === "\\" && quoted === '"')
|
|
13
|
+
index += 1;
|
|
14
|
+
else if (char === quoted)
|
|
15
|
+
quoted = null;
|
|
16
|
+
continue;
|
|
17
|
+
}
|
|
18
|
+
if (char === "'" || char === '"')
|
|
19
|
+
quoted = char;
|
|
20
|
+
else if (char === "#" && (index === 0 || /\s/.test(value[index - 1] ?? ""))) {
|
|
21
|
+
return value.slice(0, index).trimEnd();
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return value.trimEnd();
|
|
25
|
+
}
|
|
26
|
+
function unescapeDoubleQuotedValue(value) {
|
|
27
|
+
return value.replace(/\\([nrt"\\$])/g, (_, escaped) => {
|
|
28
|
+
if (escaped === "n")
|
|
29
|
+
return "\n";
|
|
30
|
+
if (escaped === "r")
|
|
31
|
+
return "\r";
|
|
32
|
+
if (escaped === "t")
|
|
33
|
+
return "\t";
|
|
34
|
+
return escaped;
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
function parseEnvValue(rawValue, line, error) {
|
|
38
|
+
const value = stripInlineComment(rawValue.trim());
|
|
39
|
+
if (value.startsWith('"')) {
|
|
40
|
+
if (!value.endsWith('"') || value.length === 1) {
|
|
41
|
+
throw error(`Invalid .env value on line ${line}: missing closing double quote.`);
|
|
42
|
+
}
|
|
43
|
+
return unescapeDoubleQuotedValue(value.slice(1, -1));
|
|
44
|
+
}
|
|
45
|
+
if (value.startsWith("'")) {
|
|
46
|
+
if (!value.endsWith("'") || value.length === 1) {
|
|
47
|
+
throw error(`Invalid .env value on line ${line}: missing closing single quote.`);
|
|
48
|
+
}
|
|
49
|
+
return value.slice(1, -1);
|
|
50
|
+
}
|
|
51
|
+
return value;
|
|
52
|
+
}
|
|
53
|
+
export function parseEnvFile(content, options = { reservedStatticPrefix: true }) {
|
|
54
|
+
const error = options.validationError ?? structuredValidationError;
|
|
55
|
+
const entries = new Map();
|
|
56
|
+
const lines = content.replace(/^\uFEFF/, "").split(/\r?\n/);
|
|
57
|
+
for (const [index, rawLine] of lines.entries()) {
|
|
58
|
+
const line = index + 1;
|
|
59
|
+
const trimmed = rawLine.trim();
|
|
60
|
+
if (!trimmed || trimmed.startsWith("#"))
|
|
61
|
+
continue;
|
|
62
|
+
const withoutExport = trimmed.startsWith("export ")
|
|
63
|
+
? trimmed.slice("export ".length).trim()
|
|
64
|
+
: trimmed;
|
|
65
|
+
const equalsIndex = withoutExport.indexOf("=");
|
|
66
|
+
if (equalsIndex < 0)
|
|
67
|
+
throw error(`Invalid .env entry on line ${line}: expected NAME=value.`);
|
|
68
|
+
const name = withoutExport.slice(0, equalsIndex).trim();
|
|
69
|
+
const validName = options.reservedStatticPrefix === false
|
|
70
|
+
? localEnvNamePattern.test(name)
|
|
71
|
+
: variableNameSchema.safeParse(name).success;
|
|
72
|
+
if (!validName)
|
|
73
|
+
throw error(`Invalid .env variable name on line ${line}: ${name}.`);
|
|
74
|
+
const value = parseEnvValue(withoutExport.slice(equalsIndex + 1), line, error);
|
|
75
|
+
if (value.length === 0) {
|
|
76
|
+
throw error(`Invalid .env value on line ${line}: empty values are not supported yet.`);
|
|
77
|
+
}
|
|
78
|
+
entries.set(name, { name, value, line });
|
|
79
|
+
}
|
|
80
|
+
return [...entries.values()];
|
|
81
|
+
}
|
|
82
|
+
export async function loadEnvFileSource(root, files, options = {}) {
|
|
83
|
+
const error = options.validationError ?? structuredValidationError;
|
|
84
|
+
const candidates = await Promise.all(files.map(async (file) => {
|
|
85
|
+
const content = await readFile(path.join(root, file), "utf8").catch((reason) => {
|
|
86
|
+
if (hasErrorCode(reason, "ENOENT"))
|
|
87
|
+
return null;
|
|
88
|
+
throw reason;
|
|
89
|
+
});
|
|
90
|
+
return content === null ? null : { file, content };
|
|
91
|
+
}));
|
|
92
|
+
const present = candidates.filter((candidate) => candidate !== null);
|
|
93
|
+
if (present.length > 1)
|
|
94
|
+
throw error(`Use either ${files[0]} or ${files[1]}, not both.`);
|
|
95
|
+
return present[0] ?? null;
|
|
96
|
+
}
|
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Generates a
|
|
2
|
+
* Generates a short, readable space title.
|
|
3
3
|
*
|
|
4
|
-
* The pool mixes WordPress
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* requirement is that two back-to-back calls almost never collide.
|
|
4
|
+
* The pool mixes a little WordPress and web flavor with broad nature, color,
|
|
5
|
+
* motion, and craft vocabulary. The result should suit any site instead of
|
|
6
|
+
* reading like a CMS inside joke, while staying compact enough for a hostname.
|
|
8
7
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* unlikely. The generator is intentionally dependency-free so it can be
|
|
12
|
-
* shared by the control-plane, the CLI, and any future surface.
|
|
8
|
+
* The generator is intentionally dependency-free so it can be shared by the
|
|
9
|
+
* control-plane, dashboard, CLI, and future publishing surfaces.
|
|
13
10
|
*/
|
|
14
|
-
export declare
|
|
11
|
+
export declare const SPACE_TITLE_COMBINATION_COUNT: number;
|
|
12
|
+
export declare function generateSpaceTitle(random?: () => number): string;
|
|
@@ -1,15 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Generates a
|
|
2
|
+
* Generates a short, readable space title.
|
|
3
3
|
*
|
|
4
|
-
* The pool mixes WordPress
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* requirement is that two back-to-back calls almost never collide.
|
|
4
|
+
* The pool mixes a little WordPress and web flavor with broad nature, color,
|
|
5
|
+
* motion, and craft vocabulary. The result should suit any site instead of
|
|
6
|
+
* reading like a CMS inside joke, while staying compact enough for a hostname.
|
|
8
7
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* unlikely. The generator is intentionally dependency-free so it can be
|
|
12
|
-
* shared by the control-plane, the CLI, and any future surface.
|
|
8
|
+
* The generator is intentionally dependency-free so it can be shared by the
|
|
9
|
+
* control-plane, dashboard, CLI, and future publishing surfaces.
|
|
13
10
|
*/
|
|
14
11
|
const ADJECTIVES = [
|
|
15
12
|
"Atomic",
|
|
@@ -44,6 +41,102 @@ const ADJECTIVES = [
|
|
|
44
41
|
"Templated",
|
|
45
42
|
"Responsive",
|
|
46
43
|
"Trackbacked",
|
|
44
|
+
"Agile",
|
|
45
|
+
"Amber",
|
|
46
|
+
"Ancient",
|
|
47
|
+
"Arctic",
|
|
48
|
+
"Azure",
|
|
49
|
+
"Balanced",
|
|
50
|
+
"Bold",
|
|
51
|
+
"Bright",
|
|
52
|
+
"Brisk",
|
|
53
|
+
"Calm",
|
|
54
|
+
"Candid",
|
|
55
|
+
"Celestial",
|
|
56
|
+
"Clever",
|
|
57
|
+
"Coastal",
|
|
58
|
+
"Composed",
|
|
59
|
+
"Cosmic",
|
|
60
|
+
"Crisp",
|
|
61
|
+
"Curious",
|
|
62
|
+
"Daring",
|
|
63
|
+
"Deep",
|
|
64
|
+
"Electric",
|
|
65
|
+
"Elegant",
|
|
66
|
+
"Emerald",
|
|
67
|
+
"Endless",
|
|
68
|
+
"Evergreen",
|
|
69
|
+
"Fluid",
|
|
70
|
+
"Focused",
|
|
71
|
+
"Gentle",
|
|
72
|
+
"Golden",
|
|
73
|
+
"Grand",
|
|
74
|
+
"Harmonic",
|
|
75
|
+
"Hidden",
|
|
76
|
+
"Honest",
|
|
77
|
+
"Indigo",
|
|
78
|
+
"Infinite",
|
|
79
|
+
"Keen",
|
|
80
|
+
"Kind",
|
|
81
|
+
"Lively",
|
|
82
|
+
"Lucid",
|
|
83
|
+
"Lunar",
|
|
84
|
+
"Magnetic",
|
|
85
|
+
"Mellow",
|
|
86
|
+
"Modern",
|
|
87
|
+
"Nimble",
|
|
88
|
+
"Northern",
|
|
89
|
+
"Open",
|
|
90
|
+
"Pacific",
|
|
91
|
+
"Patient",
|
|
92
|
+
"Polished",
|
|
93
|
+
"Prime",
|
|
94
|
+
"Quiet",
|
|
95
|
+
"Radiant",
|
|
96
|
+
"Rapid",
|
|
97
|
+
"Rare",
|
|
98
|
+
"Ready",
|
|
99
|
+
"Regal",
|
|
100
|
+
"Remote",
|
|
101
|
+
"Restless",
|
|
102
|
+
"Robust",
|
|
103
|
+
"Royal",
|
|
104
|
+
"Sable",
|
|
105
|
+
"Silent",
|
|
106
|
+
"Simple",
|
|
107
|
+
"Solar",
|
|
108
|
+
"Steady",
|
|
109
|
+
"Stellar",
|
|
110
|
+
"Still",
|
|
111
|
+
"Swift",
|
|
112
|
+
"Tactile",
|
|
113
|
+
"Tidy",
|
|
114
|
+
"Timeless",
|
|
115
|
+
"Tranquil",
|
|
116
|
+
"True",
|
|
117
|
+
"Vivid",
|
|
118
|
+
"Warm",
|
|
119
|
+
"Wild",
|
|
120
|
+
"Wise",
|
|
121
|
+
"Woven",
|
|
122
|
+
"Young",
|
|
123
|
+
"Zealous",
|
|
124
|
+
"Airy",
|
|
125
|
+
"Autumn",
|
|
126
|
+
"Blue",
|
|
127
|
+
"Clear",
|
|
128
|
+
"Copper",
|
|
129
|
+
"Distant",
|
|
130
|
+
"Early",
|
|
131
|
+
"Fresh",
|
|
132
|
+
"Glowing",
|
|
133
|
+
"Green",
|
|
134
|
+
"Light",
|
|
135
|
+
"Misty",
|
|
136
|
+
"Neon",
|
|
137
|
+
"Silver",
|
|
138
|
+
"Spring",
|
|
139
|
+
"Summer",
|
|
47
140
|
];
|
|
48
141
|
const NOUNS = [
|
|
49
142
|
"Codex",
|
|
@@ -78,18 +171,110 @@ const NOUNS = [
|
|
|
78
171
|
"Gravatar",
|
|
79
172
|
"Reblog",
|
|
80
173
|
"Opengraph",
|
|
174
|
+
"Acre",
|
|
175
|
+
"Arcade",
|
|
176
|
+
"Atlas",
|
|
177
|
+
"Beacon",
|
|
178
|
+
"Birch",
|
|
179
|
+
"Bloom",
|
|
180
|
+
"Bridge",
|
|
181
|
+
"Brook",
|
|
182
|
+
"Canyon",
|
|
183
|
+
"Cedar",
|
|
184
|
+
"Circuit",
|
|
185
|
+
"Cloud",
|
|
186
|
+
"Coast",
|
|
187
|
+
"Comet",
|
|
188
|
+
"Cove",
|
|
189
|
+
"Creek",
|
|
190
|
+
"Delta",
|
|
191
|
+
"Dune",
|
|
192
|
+
"Echo",
|
|
193
|
+
"Ember",
|
|
194
|
+
"Field",
|
|
195
|
+
"Fjord",
|
|
196
|
+
"Forest",
|
|
197
|
+
"Forge",
|
|
198
|
+
"Garden",
|
|
199
|
+
"Grove",
|
|
200
|
+
"Harbor",
|
|
201
|
+
"Haven",
|
|
202
|
+
"Hill",
|
|
203
|
+
"Horizon",
|
|
204
|
+
"Island",
|
|
205
|
+
"Junction",
|
|
206
|
+
"Kite",
|
|
207
|
+
"Lake",
|
|
208
|
+
"Lantern",
|
|
209
|
+
"Meadow",
|
|
210
|
+
"Mesa",
|
|
211
|
+
"Moon",
|
|
212
|
+
"Nest",
|
|
213
|
+
"Oak",
|
|
214
|
+
"Ocean",
|
|
215
|
+
"Orchard",
|
|
216
|
+
"Peak",
|
|
217
|
+
"Pine",
|
|
218
|
+
"Plain",
|
|
219
|
+
"Pond",
|
|
220
|
+
"Prairie",
|
|
221
|
+
"Prism",
|
|
222
|
+
"Reef",
|
|
223
|
+
"Ridge",
|
|
224
|
+
"River",
|
|
225
|
+
"Road",
|
|
226
|
+
"Rock",
|
|
227
|
+
"Sage",
|
|
228
|
+
"Shore",
|
|
229
|
+
"Signal",
|
|
230
|
+
"Sky",
|
|
231
|
+
"Spark",
|
|
232
|
+
"Star",
|
|
233
|
+
"Stone",
|
|
234
|
+
"Studio",
|
|
235
|
+
"Summit",
|
|
236
|
+
"Sun",
|
|
237
|
+
"Trail",
|
|
238
|
+
"Vale",
|
|
239
|
+
"Valley",
|
|
240
|
+
"Vault",
|
|
241
|
+
"Wave",
|
|
242
|
+
"Willow",
|
|
243
|
+
"Wind",
|
|
244
|
+
"Window",
|
|
245
|
+
"Wood",
|
|
246
|
+
"Bay",
|
|
247
|
+
"Branch",
|
|
248
|
+
"Breeze",
|
|
249
|
+
"Canvas",
|
|
250
|
+
"Castle",
|
|
251
|
+
"Cavern",
|
|
252
|
+
"Cliff",
|
|
253
|
+
"Dawn",
|
|
254
|
+
"Drift",
|
|
255
|
+
"Falcon",
|
|
256
|
+
"Flame",
|
|
257
|
+
"Glade",
|
|
258
|
+
"Harborlight",
|
|
259
|
+
"Loom",
|
|
260
|
+
"Maple",
|
|
261
|
+
"Marsh",
|
|
262
|
+
"North",
|
|
263
|
+
"Pebble",
|
|
264
|
+
"Quartz",
|
|
265
|
+
"Rain",
|
|
266
|
+
"Range",
|
|
267
|
+
"Terrace",
|
|
268
|
+
"Thicket",
|
|
269
|
+
"Wren",
|
|
81
270
|
];
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
271
|
+
export const SPACE_TITLE_COMBINATION_COUNT = ADJECTIVES.length * NOUNS.length;
|
|
272
|
+
export function generateSpaceTitle(random = Math.random) {
|
|
273
|
+
const index = Math.floor(random() * SPACE_TITLE_COMBINATION_COUNT);
|
|
274
|
+
const adjective = ADJECTIVES[Math.floor(index / NOUNS.length)];
|
|
275
|
+
const noun = NOUNS[index % NOUNS.length];
|
|
276
|
+
if (!adjective || !noun) {
|
|
277
|
+
throw new Error("generateSpaceName: random source must return a value from 0 up to 1.");
|
|
85
278
|
}
|
|
86
|
-
|
|
87
|
-
const value = list[index];
|
|
88
|
-
if (value === undefined) {
|
|
89
|
-
throw new Error("generateSpaceName: word list contained a hole.");
|
|
90
|
-
}
|
|
91
|
-
return value;
|
|
92
|
-
}
|
|
93
|
-
export function generateSpaceTitle() {
|
|
94
|
-
return `${pickRandom(ADJECTIVES)} ${pickRandom(NOUNS)}`;
|
|
279
|
+
return `${adjective} ${noun}`;
|
|
95
280
|
}
|