smoodly 0.0.51 → 0.0.53
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -13
- package/dist/admin/auth.d.ts +3 -11
- package/dist/admin/auth.js +1 -30
- package/dist/admin/client-ops.d.ts +5 -4
- package/dist/admin/client-ops.js +15 -12
- package/dist/admin/delivery-mode.d.ts +1 -1
- package/dist/admin/delivery-mode.js +2 -2
- package/dist/admin/drift.d.ts +0 -2
- package/dist/admin/drift.js +1 -1
- package/dist/admin/editor/EditorView.d.ts +0 -3
- package/dist/admin/editor/EditorView.js +11 -16
- package/dist/admin/editor/FloatingToolbar.d.ts +0 -1
- package/dist/admin/editor/FloatingToolbar.js +1 -1
- package/dist/admin/editor/SeoSettings.d.ts +0 -2
- package/dist/admin/editor/SeoSettings.js +2 -2
- package/dist/admin/editor/canvas-address.d.ts +8 -0
- package/dist/admin/editor/canvas-address.js +18 -2
- package/dist/admin/editor/canvas-diagnosis.d.ts +2 -0
- package/dist/admin/editor/canvas-diagnosis.js +3 -0
- package/dist/admin/editor/inline-dom.d.ts +0 -4
- package/dist/admin/editor/inline-dom.js +1 -1
- package/dist/admin/editor/preview-grant.d.ts +6 -0
- package/dist/admin/editor/preview-grant.js +25 -0
- package/dist/admin/editor/useCanvasDiagnosis.js +2 -2
- package/dist/admin/files.generated.js +1 -1
- package/dist/admin/fixed-nodes.d.ts +0 -6
- package/dist/admin/fixed-nodes.js +1 -81
- package/dist/admin/forms/CropEditor.d.ts +4 -2
- package/dist/admin/forms/CropEditor.js +58 -5
- package/dist/admin/forms/ImagePreview.d.ts +3 -1
- package/dist/admin/forms/ImagePreview.js +9 -3
- package/dist/admin/forms/MediaGrid.js +2 -1
- package/dist/admin/forms/MediaPicker.js +9 -6
- package/dist/admin/forms/MediaWidget.js +11 -9
- package/dist/admin/forms/assets-context.d.ts +7 -3
- package/dist/admin/forms/assets-context.js +5 -3
- package/dist/admin/forms/crop-editor.d.ts +24 -2
- package/dist/admin/forms/crop-editor.js +36 -2
- package/dist/admin/forms/date-picker.d.ts +0 -1
- package/dist/admin/forms/date-picker.js +1 -1
- package/dist/admin/forms/tabs.d.ts +0 -1
- package/dist/admin/forms/tabs.js +1 -1
- package/dist/admin/forms/upload.d.ts +18 -11
- package/dist/admin/forms/upload.js +62 -24
- package/dist/admin/global-items.d.ts +0 -3
- package/dist/admin/global-items.js +0 -54
- package/dist/admin/handler.d.ts +22 -28
- package/dist/admin/handler.js +146 -47
- package/dist/admin/health.d.ts +0 -4
- package/dist/admin/index.d.ts +6 -9
- package/dist/admin/index.js +3 -6
- package/dist/admin/ops.d.ts +40 -32
- package/dist/admin/page-data.d.ts +14 -6
- package/dist/admin/page-data.js +1 -1
- package/dist/admin/session-flow.d.ts +65 -0
- package/dist/admin/session-flow.js +121 -0
- package/dist/admin/shell/AdminApp.d.ts +8 -3
- package/dist/admin/shell/AdminApp.js +37 -58
- package/dist/admin/shell/ContentHealthPage.js +1 -3
- package/dist/admin/shell/GlobalFields.d.ts +0 -3
- package/dist/admin/shell/GlobalFields.js +1 -1
- package/dist/admin/shell/IconRail.js +10 -8
- package/dist/admin/shell/MediaScreen.js +9 -6
- package/dist/admin/shell/MembersPage.d.ts +1 -2
- package/dist/admin/shell/MembersPage.js +19 -90
- package/dist/admin/shell/SettingsView.d.ts +1 -2
- package/dist/admin/shell/SettingsView.js +2 -2
- package/dist/admin/shell/SignedOutView.d.ts +5 -0
- package/dist/admin/shell/SignedOutView.js +9 -0
- package/dist/admin/shell/console-links.d.ts +5 -0
- package/dist/admin/shell/console-links.js +11 -0
- package/dist/admin/shell/members-list.d.ts +1 -14
- package/dist/admin/shell/members-list.js +2 -23
- package/dist/admin/shell/pages-tree.d.ts +0 -2
- package/dist/admin/shell/pages-tree.js +1 -1
- package/dist/admin/shell/presence-socket.d.ts +10 -0
- package/dist/admin/shell/presence-socket.js +191 -0
- package/dist/admin/shell/presence.d.ts +6 -18
- package/dist/admin/shell/presence.js +4 -11
- package/dist/admin/shell/session.d.ts +19 -12
- package/dist/admin/shell/session.js +114 -47
- package/dist/admin/ui/LocaleSwitcher.d.ts +0 -4
- package/dist/admin/ui/LocaleSwitcher.js +2 -2
- package/dist/admin/ui/primitives.d.ts +4 -14
- package/dist/admin/ui/primitives.js +7 -9
- package/dist/admin/ui/theme.js +13 -2
- package/dist/admin/validate.js +10 -1
- package/dist/api-client.d.ts +26 -0
- package/dist/api-client.js +107 -0
- package/dist/assemble.d.ts +4 -41
- package/dist/assemble.js +5 -303
- package/dist/asset-store.d.ts +28 -30
- package/dist/asset-store.js +26 -121
- package/dist/astro/cache.d.ts +1 -1
- package/dist/astro/components/Head.astro +4 -1
- package/dist/astro/components/Image.astro +12 -17
- package/dist/astro/components/Video.astro +5 -2
- package/dist/astro/head.d.ts +3 -0
- package/dist/astro/head.js +24 -0
- package/dist/astro/index.js +61 -27
- package/dist/astro/locale-paths.d.ts +5 -2
- package/dist/astro/locale-paths.js +10 -2
- package/dist/astro/routes/admin.js +9 -7
- package/dist/astro/runtime.d.ts +3 -2
- package/dist/astro/runtime.js +5 -4
- package/dist/astro/server.d.ts +7 -11
- package/dist/astro/server.js +22 -28
- package/dist/astro/shell.d.ts +3 -3
- package/dist/astro/shell.js +1 -1
- package/dist/astro/static-media-node.d.ts +4 -0
- package/dist/astro/static-media-node.js +25 -0
- package/dist/astro/static-media.d.ts +17 -0
- package/dist/astro/static-media.js +55 -0
- package/dist/astro/static.d.ts +5 -10
- package/dist/astro/static.js +13 -29
- package/dist/canvas-marker.d.ts +14 -0
- package/dist/canvas-marker.js +36 -0
- package/dist/cli/api.d.ts +14 -0
- package/dist/cli/api.js +48 -0
- package/dist/cli/app-env.d.ts +2 -0
- package/dist/cli/app-env.js +20 -0
- package/dist/cli/export.d.ts +16 -2
- package/dist/cli/export.js +52 -35
- package/dist/cli/import.d.ts +7 -11
- package/dist/cli/import.js +50 -54
- package/dist/cli/load-config.d.ts +0 -1
- package/dist/cli/load-config.js +1 -1
- package/dist/cli/main.d.ts +4 -12
- package/dist/cli/main.js +26 -72
- package/dist/cli/push.d.ts +6 -0
- package/dist/cli/push.js +31 -0
- package/dist/collections.d.ts +0 -1
- package/dist/collections.js +1 -1
- package/dist/config.d.ts +20 -5
- package/dist/config.js +18 -1
- package/dist/content/content-api.d.ts +23 -23
- package/dist/content/content-api.js +48 -56
- package/dist/content/mime.d.ts +1 -0
- package/dist/content/mime.js +6 -0
- package/dist/css.js +1 -1
- package/dist/deploy-store.d.ts +19 -0
- package/dist/entry-store.d.ts +8 -94
- package/dist/entry-store.js +9 -557
- package/dist/env.d.ts +27 -20
- package/dist/env.js +38 -50
- package/dist/fields.d.ts +11 -3
- package/dist/fields.js +33 -2
- package/dist/global-id.d.ts +2 -0
- package/dist/global-id.js +4 -2
- package/dist/image/SmoodlyImage.d.ts +9 -5
- package/dist/image/SmoodlyImage.js +29 -15
- package/dist/image/SmoodlyVideo.d.ts +1 -1
- package/dist/image/SmoodlyVideo.js +3 -2
- package/dist/image/index.d.ts +2 -3
- package/dist/image/index.js +0 -2
- package/dist/image/markup.d.ts +53 -0
- package/dist/image/markup.js +111 -0
- package/dist/index.d.ts +13 -23
- package/dist/index.js +7 -20
- package/dist/media-cut.d.ts +44 -0
- package/dist/media-cut.js +70 -0
- package/dist/media.d.ts +58 -4
- package/dist/media.js +126 -16
- package/dist/member-store.d.ts +2 -50
- package/dist/member-store.js +0 -56
- package/dist/next/admin-route.d.ts +1 -1
- package/dist/next/admin-route.js +5 -3
- package/dist/next/meta.js +2 -3
- package/dist/next/page-renderer.d.ts +2 -2
- package/dist/next/page-renderer.js +22 -11
- package/dist/next/queries.d.ts +2 -2
- package/dist/path-index.d.ts +0 -24
- package/dist/path-index.js +0 -98
- package/dist/paths.d.ts +1 -1
- package/dist/paths.js +1 -1
- package/dist/push.d.ts +30 -0
- package/dist/push.js +52 -0
- package/dist/read-counter.d.ts +2 -0
- package/dist/read-counter.js +6 -0
- package/dist/reads.d.ts +7 -7
- package/dist/reads.js +3 -0
- package/dist/registry-json.d.ts +11 -0
- package/dist/registry-json.js +81 -0
- package/dist/render.d.ts +0 -1
- package/dist/render.js +1 -1
- package/dist/resolve.d.ts +12 -6
- package/dist/resolve.js +11 -8
- package/dist/revalidate.d.ts +8 -1
- package/dist/revalidate.js +8 -1
- package/dist/richtext/index.d.ts +1 -1
- package/dist/section-wrapper.d.ts +1 -1
- package/dist/section-wrapper.js +0 -9
- package/dist/signed-message.d.ts +26 -0
- package/dist/signed-message.js +103 -0
- package/dist/site.d.ts +59 -18
- package/dist/site.js +21 -252
- package/dist/space-transfer.d.ts +6 -3
- package/dist/space-transfer.js +18 -6
- package/dist/store.d.ts +2 -80
- package/dist/store.js +3 -489
- package/dist/toolset.d.ts +2 -1
- package/dist/toolset.js +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +4 -15
- package/dist/admin/auth-config.d.ts +0 -6
- package/dist/admin/browser/fetch-op.d.ts +0 -10
- package/dist/admin/browser/fetch-op.js +0 -44
- package/dist/admin/browser/main.d.ts +0 -1
- package/dist/admin/browser/main.js +0 -23
- package/dist/admin/ops-impl.d.ts +0 -51
- package/dist/admin/ops-impl.js +0 -1403
- package/dist/admin/shell/InviteModal.d.ts +0 -6
- package/dist/admin/shell/InviteModal.js +0 -28
- package/dist/admin/shell/LoginView.d.ts +0 -5
- package/dist/admin/shell/LoginView.js +0 -80
- package/dist/admin/shell/SchemaNotice.d.ts +0 -4
- package/dist/admin/shell/SchemaNotice.js +0 -4
- package/dist/admin/shell/SetPasswordView.d.ts +0 -7
- package/dist/admin/shell/SetPasswordView.js +0 -41
- package/dist/admin/shell/presence-realtime.d.ts +0 -3
- package/dist/admin/shell/presence-realtime.js +0 -32
- package/dist/admin/supabase-auth.d.ts +0 -7
- package/dist/admin/supabase-auth.js +0 -30
- package/dist/astro/deploy-deps.d.ts +0 -10
- package/dist/astro/deploy-deps.js +0 -8
- package/dist/astro/image.d.ts +0 -27
- package/dist/astro/image.js +0 -29
- package/dist/bind.d.ts +0 -19
- package/dist/bind.js +0 -34
- package/dist/cli/add-admin.d.ts +0 -11
- package/dist/cli/add-admin.js +0 -25
- package/dist/cli/load-collections.d.ts +0 -2
- package/dist/cli/load-collections.js +0 -27
- package/dist/cli/migrate.d.ts +0 -43
- package/dist/cli/migrate.js +0 -138
- package/dist/cli/rebuild.d.ts +0 -23
- package/dist/cli/rebuild.js +0 -22
- package/dist/cli/space-io.d.ts +0 -41
- package/dist/cli/space-io.js +0 -84
- package/dist/client.d.ts +0 -11
- package/dist/client.js +0 -54
- package/dist/current-space.d.ts +0 -4
- package/dist/current-space.js +0 -9
- package/dist/document-stamp.d.ts +0 -7
- package/dist/document-stamp.js +0 -48
- package/dist/image/loaders.d.ts +0 -15
- package/dist/image/loaders.js +0 -5
- package/dist/image/next-config.d.ts +0 -18
- package/dist/image/next-config.js +0 -32
- package/dist/image/remote-pattern.d.ts +0 -1
- package/dist/image/remote-pattern.js +0 -5
- package/dist/migrations.d.ts +0 -37
- package/dist/migrations.js +0 -73
- package/dist/project.d.ts +0 -88
- package/dist/project.js +0 -231
- package/dist/published.d.ts +0 -142
- package/dist/published.js +0 -164
- package/dist/ref-index.d.ts +0 -19
- package/dist/ref-index.js +0 -0
- package/dist/schema-read.d.ts +0 -23
- package/dist/schema-read.js +0 -50
- package/dist/schema-version.d.ts +0 -19
- package/dist/schema-version.js +0 -34
- package/dist/sql-space.d.ts +0 -44
- package/dist/sql-space.js +0 -289
- package/dist/sql.d.ts +0 -15
- package/dist/sql.js +0 -556
- package/dist/supabase-asset-store.d.ts +0 -21
- package/dist/supabase-asset-store.js +0 -170
- package/dist/supabase-entry-store.d.ts +0 -92
- package/dist/supabase-entry-store.js +0 -824
- package/dist/supabase-member-store.d.ts +0 -21
- package/dist/supabase-member-store.js +0 -96
- package/dist/supabase-path-index.d.ts +0 -30
- package/dist/supabase-path-index.js +0 -138
- package/dist/supabase-published-store.d.ts +0 -56
- package/dist/supabase-published-store.js +0 -314
- package/dist/supabase-store.d.ts +0 -103
- package/dist/supabase-store.js +0 -678
- package/migrations/20260926120000_smoodly_v1.sql +0 -535
- package/migrations/20260926130000_smoodly_v2.sql +0 -26
- package/migrations/20260926140000_smoodly_v3.sql +0 -38
- package/migrations/20260926150000_smoodly_v4.sql +0 -41
- package/migrations/20260929120000_smoodly_v5.sql +0 -56
- package/migrations/20260929135523_smoodly_v6.sql +0 -200
- package/migrations/20260930040956_smoodly_v7.sql +0 -84
- package/migrations/20261007120000_smoodly_v8.sql +0 -154
- package/migrations/20261007200000_smoodly_v9.sql +0 -30
- package/migrations/20261008120000_smoodly_v10.sql +0 -47
- package/migrations/20261009120000_smoodly_v11.sql +0 -49
- /package/dist/{admin/auth-config.js → deploy-store.js} +0 -0
|
@@ -2,13 +2,11 @@
|
|
|
2
2
|
// operations with no signed-in editor, as a few verbs that throw. Scripts
|
|
3
3
|
// and route handlers write content through this, never through the stores,
|
|
4
4
|
// so validation, the code-owned address guards and publish checks apply.
|
|
5
|
-
|
|
5
|
+
// One surface over a transport (spec 2026-10-14 §1): the content API with the
|
|
6
|
+
// secret key for a seed or a script, the stores in one process for the service.
|
|
7
|
+
import { makeClientOps } from "../admin/client-ops.js";
|
|
6
8
|
import { imageDimensions } from "../image-dimensions.js";
|
|
7
|
-
|
|
8
|
-
jpg: "image/jpeg", jpeg: "image/jpeg", png: "image/png", webp: "image/webp", gif: "image/gif", avif: "image/avif",
|
|
9
|
-
svg: "image/svg+xml", mp4: "video/mp4", webm: "video/webm", pdf: "application/pdf",
|
|
10
|
-
};
|
|
11
|
-
const EMAIL = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
9
|
+
import { mimeOf } from "./mime.js";
|
|
12
10
|
export class SmoodlyContentError extends Error {
|
|
13
11
|
constructor(error) {
|
|
14
12
|
const list = (error.fields ?? []).map((f) => `\n ${f.field}: ${f.message}`).join("");
|
|
@@ -24,42 +22,57 @@ async function must(result) {
|
|
|
24
22
|
throw new SmoodlyContentError(r);
|
|
25
23
|
return r.data;
|
|
26
24
|
}
|
|
27
|
-
/**
|
|
28
|
-
*
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
}
|
|
38
|
-
try {
|
|
39
|
-
// Where smoodly.io manages the members, nothing here writes them — as the admin's Members page refuses.
|
|
40
|
-
if ((await members.consoleUrl()) !== null) {
|
|
41
|
-
throw new SmoodlyContentError({ code: "blocked", message: "smoodly: this site's members are managed at smoodly.io." });
|
|
25
|
+
/** Over the content API with the secret key (a seed, a script, the installer). A refusal throws SmoodlyContentError
|
|
26
|
+
* with the service's code and message; a network failure names SMOODLY_API_URL. */
|
|
27
|
+
export function apiTransport(options) {
|
|
28
|
+
const apiUrl = options.apiUrl.replace(/\/+$/, "");
|
|
29
|
+
const base = `${apiUrl}/v1/spaces/${encodeURIComponent(options.spaceId)}`;
|
|
30
|
+
const doFetch = options.fetch ?? fetch;
|
|
31
|
+
async function send(path, init = {}) {
|
|
32
|
+
let res;
|
|
33
|
+
try {
|
|
34
|
+
res = await doFetch(`${base}${path}`, { ...init, headers: { ...init.headers, authorization: `Bearer ${options.key}`, accept: "application/json" } });
|
|
42
35
|
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
return { email, invited: false };
|
|
36
|
+
catch (e) {
|
|
37
|
+
throw new SmoodlyContentError({ code: "internal", message: `smoodly: can't reach SMOODLY_API_URL (${apiUrl}): ${e instanceof Error ? e.message : String(e)}` });
|
|
46
38
|
}
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
throw e;
|
|
53
|
-
throw new SmoodlyContentError({ code: "internal", message: e instanceof Error ? e.message : String(e) });
|
|
39
|
+
const body = (await res.json().catch(() => null));
|
|
40
|
+
if (!body || typeof body.ok !== "boolean") {
|
|
41
|
+
return { ok: false, code: "internal", message: `smoodly: SMOODLY_API_URL (${apiUrl}) answered ${res.status} with no message.` };
|
|
42
|
+
}
|
|
43
|
+
return body;
|
|
54
44
|
}
|
|
45
|
+
const json = (body) => ({ method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify(body) });
|
|
46
|
+
return {
|
|
47
|
+
op: (call) => send("/op", json({ path: call.path, args: call.args })),
|
|
48
|
+
// A draft read (DESIGN §1 Content API › Writes): the caller holds the secret key and asks about what it is writing,
|
|
49
|
+
// and a draft read is never stored at the edge, so a script sees its own create at once.
|
|
50
|
+
locate: (locale, path) => must(send(`/locate?${new URLSearchParams({ locale, path, draft: "1" })}`)),
|
|
51
|
+
// The bytes as the body with their length, the rest in the query (spec 2026-10-18 media on R2 and Images §4).
|
|
52
|
+
async upload(bytes, filename, mime, meta) {
|
|
53
|
+
const type = mime ?? mimeOf(filename);
|
|
54
|
+
const params = { name: filename, mime: type };
|
|
55
|
+
const dims = imageDimensions(bytes);
|
|
56
|
+
if (dims) {
|
|
57
|
+
params.width = String(dims.width);
|
|
58
|
+
params.height = String(dims.height);
|
|
59
|
+
}
|
|
60
|
+
for (const key of ["title", "alt", "caption", "credit"])
|
|
61
|
+
if (meta[key] !== undefined)
|
|
62
|
+
params[key] = meta[key];
|
|
63
|
+
const record = await must(send(`/media?${new URLSearchParams(params)}`, { method: "PUT", headers: { "content-type": type }, body: bytes }));
|
|
64
|
+
return { asset: record.id, ...(meta.alt !== undefined ? { alt: meta.alt } : {}) };
|
|
65
|
+
},
|
|
66
|
+
};
|
|
55
67
|
}
|
|
56
68
|
export function createSmoodlyContent(deps) {
|
|
57
|
-
const
|
|
69
|
+
const { transport } = deps;
|
|
70
|
+
const ops = makeClientOps((call) => transport.op(call));
|
|
58
71
|
const def = deps.config.locales.default;
|
|
59
72
|
async function findPage(locale, path) {
|
|
60
|
-
const hit = await
|
|
73
|
+
const hit = await transport.locate(locale, path);
|
|
61
74
|
if (hit?.kind === "page" && !hit.redirect)
|
|
62
|
-
return
|
|
75
|
+
return (await must(ops.pages.get(hit.id, locale))).record;
|
|
63
76
|
return null;
|
|
64
77
|
}
|
|
65
78
|
async function updateEntry(collection, id, locale, fields) {
|
|
@@ -145,32 +158,11 @@ export function createSmoodlyContent(deps) {
|
|
|
145
158
|
media: {
|
|
146
159
|
/** A file path or bytes in, a ready asset and the value an image field stores out. */
|
|
147
160
|
async upload(file, meta = {}) {
|
|
148
|
-
if (!deps.assets)
|
|
149
|
-
throw new SmoodlyContentError({ code: "internal", message: "smoodly: no media store — pass `assets` to createSmoodlyContent." });
|
|
150
161
|
// Loaded here, not at the top: this module is reachable from `smoodly/admin`, which a bundler may walk.
|
|
151
162
|
const bytes = typeof file === "string" ? new Uint8Array(await (await import("node:fs/promises")).readFile(file)) : file;
|
|
152
163
|
const filename = meta.filename ?? (typeof file === "string" ? file.split(/[\\/]/).pop() : "upload");
|
|
153
|
-
|
|
154
|
-
// The media library's own rules, as the admin's upload applies them (config.media).
|
|
155
|
-
const { accept, maxSize } = deps.config.media;
|
|
156
|
-
if (!accept.includes(mime))
|
|
157
|
-
throw new SmoodlyContentError({ code: "validation", message: `smoodly: "${filename}" is ${mime}, not an accepted file type.` });
|
|
158
|
-
if (bytes.byteLength > maxSize) {
|
|
159
|
-
throw new SmoodlyContentError({ code: "validation", message: `smoodly: "${filename}" is larger than ${Math.round(maxSize / 1024 / 1024)} MB.` });
|
|
160
|
-
}
|
|
161
|
-
const { alt, title, caption, credit } = meta;
|
|
162
|
-
let asset;
|
|
163
|
-
try {
|
|
164
|
-
asset = await deps.assets.create({ filename, mime, size: bytes.byteLength, bytes, alt, title, caption, credit, ...(imageDimensions(bytes) ?? {}) });
|
|
165
|
-
}
|
|
166
|
-
catch (e) {
|
|
167
|
-
throw new SmoodlyContentError({ code: "internal", message: e instanceof Error ? e.message : String(e) });
|
|
168
|
-
}
|
|
169
|
-
return { asset: asset.id, ...(alt !== undefined ? { alt } : {}) };
|
|
164
|
+
return transport.upload(bytes, filename, meta.mime, meta);
|
|
170
165
|
},
|
|
171
166
|
},
|
|
172
|
-
members: {
|
|
173
|
-
addAdmin: (email, options = {}) => addAdmin(deps.members, email, options),
|
|
174
|
-
},
|
|
175
167
|
};
|
|
176
168
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const mimeOf: (filename: string) => string;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
// A file's type from its extension, for an upload that names none (a script's file path, bytes with a filename).
|
|
2
|
+
const MIME = {
|
|
3
|
+
jpg: "image/jpeg", jpeg: "image/jpeg", png: "image/png", webp: "image/webp", gif: "image/gif", avif: "image/avif",
|
|
4
|
+
svg: "image/svg+xml", mp4: "video/mp4", webm: "video/webm", pdf: "application/pdf",
|
|
5
|
+
};
|
|
6
|
+
export const mimeOf = (filename) => MIME[filename.split(".").pop().toLowerCase()] ?? "application/octet-stream";
|
package/dist/css.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// The custom-CSS box (spec 2026-09-14 §4): a per-section snippet the
|
|
2
2
|
// wrapper nests under the section's own [data-smd-node] selector. CSS
|
|
3
3
|
// can do two things beyond styling — pull a remote stylesheet and beacon
|
|
4
|
-
// to a host — so those, the two
|
|
4
|
+
// to a host — so those, the two old code hooks (`expression()`, `behavior:`) and the tag-closing
|
|
5
5
|
// sequence are refused at save and stripped at render, in that order.
|
|
6
6
|
// The checks run on the snippet with its CSS escapes decoded, so
|
|
7
7
|
// `\75 rl(` cannot spell `url(` past them; and the braces must balance,
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export interface DeployStore {
|
|
2
|
+
/** The latest published_at over pages and entries (ms); null when nothing is published. The static build's watermark. */
|
|
3
|
+
newestPublishedAt(): Promise<number | null>;
|
|
4
|
+
/** Locale rows published strictly after `since` (ms), pages plus entries: the tile's "changes waiting". */
|
|
5
|
+
countPublishedAfter(since: number): Promise<number>;
|
|
6
|
+
/** The space's last Deploy press; null until the first. */
|
|
7
|
+
deployRequest(): Promise<{
|
|
8
|
+
at: number;
|
|
9
|
+
by: string | null;
|
|
10
|
+
} | null>;
|
|
11
|
+
requestDeploy(by: string | null, at?: number): Promise<void>;
|
|
12
|
+
/** When a published row last went (an unpublish, a delete): a change the count of newer rows cannot see. */
|
|
13
|
+
lastRemovalAt(): Promise<number | null>;
|
|
14
|
+
/** Written by the operations on an unpublish or a delete of a published row. */
|
|
15
|
+
recordRemoval(at?: number): Promise<void>;
|
|
16
|
+
/** Written by the operations on every publish: the SQLite store ignores it (the locale row carries published_at),
|
|
17
|
+
* the memory one counts it. */
|
|
18
|
+
recordPublish(at?: number): Promise<void>;
|
|
19
|
+
}
|
package/dist/entry-store.d.ts
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import type { CollectionSchema, EntryOrder } from "./collections.ts";
|
|
2
2
|
import type { GlobalSchema } from "./global.ts";
|
|
3
3
|
import { type RefEdge, type SectionLike } from "./refs.ts";
|
|
4
|
-
import {
|
|
5
|
-
import
|
|
6
|
-
import { type DraftToken } from "./draft-token.ts";
|
|
4
|
+
import type { PathHit, PathIndex } from "./path-index.ts";
|
|
5
|
+
import type { DraftToken } from "./draft-token.ts";
|
|
7
6
|
import { type LocaleSet } from "./paths.ts";
|
|
8
7
|
export type EntryLocale = {
|
|
9
8
|
/** The entry's segment in this locale; null claims no URL. */
|
|
@@ -59,8 +58,8 @@ export type Where = Record<string, WhereValue | WhereValue[]>;
|
|
|
59
58
|
* adapters read the text form of the whole array, never its elements). */
|
|
60
59
|
export declare const ARRAY_FIELD_TYPES: ReadonlySet<string>;
|
|
61
60
|
/** The memory adapter's and the tests' reading of `where`: a scalar matches an
|
|
62
|
-
* equal value or an array holding it (
|
|
63
|
-
* compared as text
|
|
61
|
+
* equal value or an array holding it (containment); an array is any-of,
|
|
62
|
+
* compared as text (textForm). */
|
|
64
63
|
export declare function matchesWhere(fields: Record<string, unknown>, where: Where): boolean;
|
|
65
64
|
export type ListOptions = {
|
|
66
65
|
/** Equality / any-of on shared fields, executed by the store (spec 2026-09-11 §3). */
|
|
@@ -254,96 +253,11 @@ export declare function entryTitleIn(record: EntryRecord, locale: string, schema
|
|
|
254
253
|
* Sort comparator for one order rule; `seq` breaks ties by creation. A
|
|
255
254
|
* declared order field is SHARED (collection() refuses a localized one),
|
|
256
255
|
* so `e.fields[order.by]` reads the node. Nulls sort last in BOTH
|
|
257
|
-
* directions (the
|
|
256
|
+
* directions (the SQLite list compiler sorts nulls last to match);
|
|
258
257
|
* the creation tiebreak follows `direction` for non-manual orders.
|
|
259
258
|
* Declared fields compare numerically when both values are numbers,
|
|
260
|
-
* otherwise as strings via `localeCompare` — the
|
|
261
|
-
*
|
|
262
|
-
* follow-ups for the mixed-type
|
|
259
|
+
* otherwise as strings via `localeCompare` — the order the SQLite store's
|
|
260
|
+
* `COLLATE NOCASE` gives for one type (ASCII only; see MAINTAINERS.md's
|
|
261
|
+
* follow-ups for the mixed-type, JSON-null and non-ASCII edges).
|
|
263
262
|
*/
|
|
264
263
|
export declare function compareEntries(order: EntryOrder, seq: (e: EntryRecord) => number): (a: EntryRecord, b: EntryRecord) => number;
|
|
265
|
-
/** Comparator for `query`: like compareEntries, but a declared field reads the
|
|
266
|
-
* merged snapshot, `updatedAt` the locale row's, and an absent, null or empty-string value
|
|
267
|
-
* sorts last in both directions; ties break by creation order (ascending). */
|
|
268
|
-
export declare function compareSnapshots(order: EntryOrder, locale: string, seq: (id: string) => number): (a: SnapshotRow, b: SnapshotRow) => number;
|
|
269
|
-
export declare class MemoryEntryStore implements EntryStore {
|
|
270
|
-
private refs;
|
|
271
|
-
private entries;
|
|
272
|
-
private versions;
|
|
273
|
-
/** Insertion order per version — `savedAt` alone can tie within a millisecond. */
|
|
274
|
-
private versionSeq;
|
|
275
|
-
private seq;
|
|
276
|
-
private order;
|
|
277
|
-
private paths;
|
|
278
|
-
private locales;
|
|
279
|
-
private schemas;
|
|
280
|
-
private elements;
|
|
281
|
-
constructor(collections: CollectionSchema<any>[], refs?: MemoryRefIndex, options?: EntryStoreOptions);
|
|
282
|
-
private schema;
|
|
283
|
-
private row;
|
|
284
|
-
private must;
|
|
285
|
-
private byId;
|
|
286
|
-
private snapshot;
|
|
287
|
-
private subtree;
|
|
288
|
-
/** An edit bumps the node and the edited row; `move` and `reorder` never call this. */
|
|
289
|
-
private bump;
|
|
290
|
-
/** The draft rule (spec 2026-09-13 history §1) for every collection (spec 2026-09-14 §1):
|
|
291
|
-
* the unpublished draft row is rewritten in place and a new one starts only when the
|
|
292
|
-
* draft IS the published one. */
|
|
293
|
-
private recordVersion;
|
|
294
|
-
/** A published row from before every collection was versioned has no snapshot; give it
|
|
295
|
-
* one from what is live BEFORE a write changes the fields, so the site keeps serving it
|
|
296
|
-
* and the write lands in a new draft row (spec 2026-09-14 §1). */
|
|
297
|
-
private ensureLiveSnapshot;
|
|
298
|
-
private dropVersions;
|
|
299
|
-
/** Every field set the site can render for this entry: each present
|
|
300
|
-
* locale's live view, plus a published snapshot the draft has moved
|
|
301
|
-
* past (still rendered by the published site). */
|
|
302
|
-
private liveFieldSets;
|
|
303
|
-
private writePaths;
|
|
304
|
-
private writeRefs;
|
|
305
|
-
private siblings;
|
|
306
|
-
/** The friendly pre-check (spec 2026-09-06 §11): a string slug must be
|
|
307
|
-
* unique among the siblings PRESENT in that locale; null never
|
|
308
|
-
* conflicts. The paths primary key remains the invariant. */
|
|
309
|
-
private assertSiblingSlug;
|
|
310
|
-
/** Same collection, within depth. Returns the parent (null at the root). */
|
|
311
|
-
private assertParent;
|
|
312
|
-
/** The parent rule: a locale can only be added where the parent has it. */
|
|
313
|
-
private assertParentHasLocale;
|
|
314
|
-
create(collection: string, fields: Record<string, unknown>, options: CreateEntryOptions, by?: string): Promise<EntryRecord>;
|
|
315
|
-
get(collection: string, id: string): Promise<EntryRecord | null>;
|
|
316
|
-
list(collection: string, options?: ListOptions): Promise<EntryRecord[]>;
|
|
317
|
-
query(collection: string, q: SnapshotQuery): Promise<SnapshotRow[]>;
|
|
318
|
-
getMany(collection: string, ids: string[], locale: string, options?: {
|
|
319
|
-
status?: "published";
|
|
320
|
-
}): Promise<Record<string, Record<string, unknown>>>;
|
|
321
|
-
update(collection: string, id: string, locale: string, fields: Record<string, unknown>, by?: string, expected?: DraftToken | null, options?: {
|
|
322
|
-
redirect?: boolean;
|
|
323
|
-
}): Promise<EntryRecord>;
|
|
324
|
-
setStatus(collection: string, id: string, locale: string, status: "draft" | "published", by?: string, expected?: DraftToken | null): Promise<EntryRecord>;
|
|
325
|
-
discardDraft(collection: string, id: string, locale: string, by?: string, expected?: DraftToken | null): Promise<EntryRecord>;
|
|
326
|
-
addLocale(collection: string, id: string, locale: string, options: AddEntryLocaleOptions, by?: string): Promise<EntryRecord>;
|
|
327
|
-
removeLocale(collection: string, id: string, locale: string): Promise<EntryRecord>;
|
|
328
|
-
scanEntries(): Promise<EntryScan[]>;
|
|
329
|
-
listVersions(collection: string, id: string, locale: string): Promise<EntryVersion[]>;
|
|
330
|
-
restore(collection: string, id: string, locale: string, versionId: string, by?: string, expected?: DraftToken | null): Promise<EntryRecord>;
|
|
331
|
-
getVersion(collection: string, versionId: string): Promise<EntryVersion | null>;
|
|
332
|
-
move(collection: string, id: string, to: {
|
|
333
|
-
parentId: string | null;
|
|
334
|
-
index?: number;
|
|
335
|
-
}, options?: {
|
|
336
|
-
redirect?: boolean;
|
|
337
|
-
}): Promise<EntryRecord>;
|
|
338
|
-
delete(collection: string, id: string): Promise<void>;
|
|
339
|
-
reorder(collection: string, orderedIds: string[]): Promise<void>;
|
|
340
|
-
referencesTo(collection: string, id: string): Promise<EntryUsage[]>;
|
|
341
|
-
incoming(targetId: string): Promise<{
|
|
342
|
-
sourceKind: string;
|
|
343
|
-
sourceId: string;
|
|
344
|
-
}[]>;
|
|
345
|
-
resolvePath(locale: string, path: string): Promise<PathHit | null>;
|
|
346
|
-
pathsIn(collection: string, ids: string[], locale: string): Promise<Record<string, string>>;
|
|
347
|
-
pathsOf(collection: string, id: string): Promise<{}>;
|
|
348
|
-
redirectsOf(collection: string, id: string): Promise<Record<string, string[]>>;
|
|
349
|
-
}
|