smoodly 0.0.51 → 0.0.52
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-config.d.ts +6 -5
- package/dist/admin/auth.d.ts +3 -11
- package/dist/admin/auth.js +1 -30
- package/dist/admin/browser/fetch-op.js +3 -2
- package/dist/admin/browser/main.js +6 -2
- package/dist/admin/client-ops.d.ts +5 -4
- package/dist/admin/client-ops.js +14 -11
- 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 +5 -8
- package/dist/admin/index.js +3 -6
- package/dist/admin/ops.d.ts +36 -22
- package/dist/admin/page-data.d.ts +14 -6
- package/dist/admin/page-data.js +1 -1
- package/dist/admin/session-flow.d.ts +43 -0
- package/dist/admin/session-flow.js +94 -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 +5 -4
- 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 +20 -12
- package/dist/admin/shell/session.js +113 -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 +5 -8
- 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 +4 -302
- package/dist/asset-store.d.ts +28 -30
- package/dist/asset-store.js +26 -121
- 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 +54 -25
- 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 +2 -1
- package/dist/astro/runtime.js +4 -3
- package/dist/astro/server.d.ts +7 -11
- package/dist/astro/server.js +22 -28
- package/dist/astro/shell.d.ts +2 -2
- 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 +22 -23
- package/dist/content/content-api.js +46 -56
- package/dist/content/mime.d.ts +1 -0
- package/dist/content/mime.js +6 -0
- package/dist/deploy-store.d.ts +19 -0
- package/dist/deploy-store.js +1 -0
- package/dist/entry-store.d.ts +3 -89
- package/dist/entry-store.js +2 -550
- 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 +12 -22
- 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 +57 -3
- package/dist/media.js +125 -15
- package/dist/member-store.d.ts +3 -22
- package/dist/member-store.js +1 -53
- 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/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 +5 -2
- package/dist/space-transfer.js +17 -5
- 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/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/cli/migrate.js
DELETED
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
// packages/smoodly/src/cli/migrate.ts
|
|
2
|
-
// The filesystem half of `smoodly migrate` (spec 2026-09-26 §2): reads
|
|
3
|
-
// the package's migrations/ and the app's supabase/migrations/, loads the
|
|
4
|
-
// app's collections, asks the pure planner (../migrations.ts) what to
|
|
5
|
-
// write, writes it. The message strings are what the docs quote.
|
|
6
|
-
import { existsSync } from "node:fs";
|
|
7
|
-
import { readdir, readFile, writeFile } from "node:fs/promises";
|
|
8
|
-
import { join, resolve } from "node:path";
|
|
9
|
-
import { fileURLToPath } from "node:url";
|
|
10
|
-
import { collectionSQL } from "../sql.js";
|
|
11
|
-
import { coreFileVersion, SCHEMA_VERSION, secretKeyRefusedMessage } from "../schema-version.js";
|
|
12
|
-
import { readSchemaVersion } from "../schema-read.js";
|
|
13
|
-
import { createSmoodlyClient } from "../client.js";
|
|
14
|
-
import { resolveSmoodlyEnv } from "../env.js";
|
|
15
|
-
import { loadAppEnv } from "./space-io.js";
|
|
16
|
-
import { planIsEmpty, planMigrate } from "../migrations.js";
|
|
17
|
-
import { loadCollections } from "./load-collections.js";
|
|
18
|
-
import { loadConfig } from "./load-config.js";
|
|
19
|
-
import { siteOptions } from "../bind.js";
|
|
20
|
-
import { documentStamp } from "../document-stamp.js";
|
|
21
|
-
import { SupabasePublishedStore } from "../supabase-published-store.js";
|
|
22
|
-
export const DEFAULT_COLLECTIONS = "smoodly/collections.ts";
|
|
23
|
-
/** The Astro starter keeps the setup under src/ (plan 2026-10-06 astro adapter 3); the default follows it when the Next path is absent. */
|
|
24
|
-
export function collectionsFile(cwd, given, exists = existsSync) {
|
|
25
|
-
if (given !== DEFAULT_COLLECTIONS || exists(resolve(cwd, given)))
|
|
26
|
-
return given;
|
|
27
|
-
return exists(resolve(cwd, "src/smoodly/collections.ts")) ? "src/smoodly/collections.ts" : given;
|
|
28
|
-
}
|
|
29
|
-
/** The folder shipped in the package: `../../migrations/` from dist/cli/ and from src/cli/ alike. */
|
|
30
|
-
export const PACKAGE_MIGRATIONS_DIR = fileURLToPath(new URL("../../migrations/", import.meta.url));
|
|
31
|
-
export const NO_FOLDER = (dir) => `No supabase/migrations folder here (${dir}) — nothing to do. Run it in your app's folder, or pass --migrations. (Smoodly Cloud keeps the schema current; a self-host app gets the folder from \`supabase init\`.)`;
|
|
32
|
-
export const NEXT_STEP = "Next: apply it — `supabase db push` (hosted) or `supabase migration up` (local).";
|
|
33
|
-
export const upToDate = (version, n) => `Up to date: core schema v${version}, every collection's view is current (${n} ${n === 1 ? "collection" : "collections"}).`;
|
|
34
|
-
export const KEY_NOT_CHECKED = "Key not checked: SMOODLY_URL and SMOODLY_SECRET_KEY are not both set here.";
|
|
35
|
-
export const keyChecked = (version) => `SMOODLY_SECRET_KEY reads the database (schema v${version}).`;
|
|
36
|
-
export const modifiedMessage = (name) => `Refusing: ${name} differs from the package's copy. A published migration is never edited — restore it from the package, or move your change to a new file.`;
|
|
37
|
-
export async function readSqlFiles(dir) {
|
|
38
|
-
const names = (await readdir(dir)).filter((n) => n.endsWith(".sql")).sort();
|
|
39
|
-
return Promise.all(names.map(async (name) => ({ name, text: await readFile(join(dir, name), "utf8") })));
|
|
40
|
-
}
|
|
41
|
-
/** One line per thing the plan does; "Pending" wording under --check. */
|
|
42
|
-
export function describePlan(plan, check) {
|
|
43
|
-
const lines = [];
|
|
44
|
-
for (const name of plan.modified)
|
|
45
|
-
lines.push(modifiedMessage(name));
|
|
46
|
-
for (const f of plan.copy)
|
|
47
|
-
lines.push(`${check ? "Pending" : "Copied"} ${f.name} (core schema v${coreFileVersion(f.name)}).`);
|
|
48
|
-
if (plan.views) {
|
|
49
|
-
const names = [...plan.views.text.matchAll(/^-- smoodly:collection (\S+)/gm)].map((m) => m[1]);
|
|
50
|
-
lines.push(`${check ? "Pending" : "Wrote"} ${plan.views.name} (views: ${names.join(", ")}).`);
|
|
51
|
-
}
|
|
52
|
-
return lines;
|
|
53
|
-
}
|
|
54
|
-
/** The delivery line of `--check` (DESIGN §3, the document stamp): a count with the one command to run, never a verdict. */
|
|
55
|
-
export const deliveryLine = (d) => d.behind === 0
|
|
56
|
-
? `Delivery: every published document is current (${d.total}).`
|
|
57
|
-
: `Delivery: ${d.behind} of ${d.total} documents are behind the current stamp — run npx smoodly rebuild.`;
|
|
58
|
-
async function countDelivery(env, cwd) {
|
|
59
|
-
const config = await loadConfig(cwd);
|
|
60
|
-
const stamp = documentStamp(siteOptions(config, () => { throw new Error("smoodly: the stamp reads no store"); }));
|
|
61
|
-
const db = createSmoodlyClient(resolveSmoodlyEnv(env));
|
|
62
|
-
return new SupabasePublishedStore(db, config.registry.collections ?? []).countBehind(stamp);
|
|
63
|
-
}
|
|
64
|
-
/** Errors that are a verdict on the env itself, not on the network: they fail the build. */
|
|
65
|
-
const ENV_VERDICT = /SMOODLY_(SECRET|PUBLISHABLE)_KEY|SMOODLY_URL "/;
|
|
66
|
-
/** The build's key check (decided 2026-10-02): a key the site would be refused with fails the
|
|
67
|
-
* deploy, so the running deployment keeps serving. No key here, or no route to the database
|
|
68
|
-
* (a CI build), passes without a verdict. */
|
|
69
|
-
async function checkKey(out, cwd, deps) {
|
|
70
|
-
const env = deps.env ?? process.env;
|
|
71
|
-
loadAppEnv(cwd, env);
|
|
72
|
-
if (!env.SMOODLY_URL || !env.SMOODLY_SECRET_KEY) {
|
|
73
|
-
out(KEY_NOT_CHECKED);
|
|
74
|
-
return 0;
|
|
75
|
-
}
|
|
76
|
-
let read;
|
|
77
|
-
try {
|
|
78
|
-
read = await (deps.readKey ?? ((e) => readSchemaVersion(createSmoodlyClient(resolveSmoodlyEnv(e)))))(env);
|
|
79
|
-
}
|
|
80
|
-
catch (e) {
|
|
81
|
-
const message = e instanceof Error ? e.message : String(e);
|
|
82
|
-
if (ENV_VERDICT.test(message)) {
|
|
83
|
-
out(message);
|
|
84
|
-
return 1;
|
|
85
|
-
}
|
|
86
|
-
out(`Key not checked: ${message}`);
|
|
87
|
-
return 0;
|
|
88
|
-
}
|
|
89
|
-
if ("version" in read) {
|
|
90
|
-
out(keyChecked(read.version));
|
|
91
|
-
try {
|
|
92
|
-
out(deliveryLine(await (deps.delivery ?? countDelivery)(env, cwd)));
|
|
93
|
-
}
|
|
94
|
-
catch (e) {
|
|
95
|
-
out(`Delivery: not checked: ${e instanceof Error ? e.message : String(e)}`);
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
else if (read.missing === "key") {
|
|
99
|
-
out(secretKeyRefusedMessage);
|
|
100
|
-
return 1;
|
|
101
|
-
}
|
|
102
|
-
else
|
|
103
|
-
out("Key not checked: the database has no Smoodly schema yet — apply the migrations before the site goes live.");
|
|
104
|
-
return 0;
|
|
105
|
-
}
|
|
106
|
-
export async function runMigrate(args, out, deps = {}) {
|
|
107
|
-
const cwd = deps.cwd ?? process.cwd();
|
|
108
|
-
const appDir = resolve(cwd, args.migrations);
|
|
109
|
-
if (!existsSync(appDir)) {
|
|
110
|
-
// A build that runs the check must not pass one it never made (spec 2026-09-30 tester findings §5).
|
|
111
|
-
if (args.check) {
|
|
112
|
-
out(`smoodly: no supabase/migrations here (${appDir}) — run the check in the app's folder, or pass --migrations.`);
|
|
113
|
-
return 1;
|
|
114
|
-
}
|
|
115
|
-
out(NO_FOLDER(appDir));
|
|
116
|
-
return 0;
|
|
117
|
-
}
|
|
118
|
-
const collections = await (deps.load ?? loadCollections)(resolve(cwd, collectionsFile(cwd, args.collections)), cwd);
|
|
119
|
-
const plan = planMigrate({
|
|
120
|
-
packageFiles: await readSqlFiles(PACKAGE_MIGRATIONS_DIR),
|
|
121
|
-
appFiles: await readSqlFiles(appDir),
|
|
122
|
-
collections: collections.map((c) => ({ name: c.name, sql: collectionSQL(c) })),
|
|
123
|
-
}, (deps.now ?? (() => new Date()))());
|
|
124
|
-
for (const line of describePlan(plan, args.check))
|
|
125
|
-
out(line);
|
|
126
|
-
if (plan.modified.length > 0)
|
|
127
|
-
return 1;
|
|
128
|
-
if (planIsEmpty(plan)) {
|
|
129
|
-
out(upToDate(SCHEMA_VERSION, collections.length));
|
|
130
|
-
return args.check ? checkKey(out, cwd, deps) : 0;
|
|
131
|
-
}
|
|
132
|
-
if (args.check)
|
|
133
|
-
return 1;
|
|
134
|
-
for (const f of [...plan.copy, ...(plan.views ? [plan.views] : [])])
|
|
135
|
-
await writeFile(join(appDir, f.name), f.text, "utf8");
|
|
136
|
-
out(NEXT_STEP);
|
|
137
|
-
return 0;
|
|
138
|
-
}
|
package/dist/cli/rebuild.d.ts
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import type { SupabaseClient } from "@supabase/supabase-js";
|
|
2
|
-
import type { ResolvedConfig } from "../config.ts";
|
|
3
|
-
import { type SpaceConnection } from "./space-io.ts";
|
|
4
|
-
export type RebuildArgs = Record<string, never>;
|
|
5
|
-
export type RebuildDeps = {
|
|
6
|
-
cwd?: string;
|
|
7
|
-
connection?: SpaceConnection;
|
|
8
|
-
/** The app's config; default: loaded from the folder (load-config.ts). */
|
|
9
|
-
config?: ResolvedConfig;
|
|
10
|
-
/** Test seam: the projection; default rebuildSpace. */
|
|
11
|
-
rebuild?: (db: SupabaseClient, config: ResolvedConfig) => Promise<{
|
|
12
|
-
pages: number;
|
|
13
|
-
entries: number;
|
|
14
|
-
model: string;
|
|
15
|
-
}>;
|
|
16
|
-
};
|
|
17
|
-
/** The line a rebuild ends with: import's counts, and the model the rows now carry. */
|
|
18
|
-
export declare const rebuildMessage: (r: {
|
|
19
|
-
pages: number;
|
|
20
|
-
entries: number;
|
|
21
|
-
model: string;
|
|
22
|
-
}) => string;
|
|
23
|
-
export declare function runRebuild(_args: RebuildArgs, out: (line: string) => void, deps?: RebuildDeps): Promise<number>;
|
package/dist/cli/rebuild.js
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { schemaBehind, schemaBehindMessage } from "../schema-version.js";
|
|
2
|
-
import { loadConfig } from "./load-config.js";
|
|
3
|
-
import { connectFromEnv, readSchemaVersion, rebuildSpace, rebuiltMessage, schemaRefusal } from "./space-io.js";
|
|
4
|
-
/** The line a rebuild ends with: import's counts, and the model the rows now carry. */
|
|
5
|
-
export const rebuildMessage = (r) => `${rebuiltMessage(r).replace(/\.$/, "")} (model ${r.model}).`;
|
|
6
|
-
export async function runRebuild(_args, out, deps = {}) {
|
|
7
|
-
const cwd = deps.cwd ?? process.cwd();
|
|
8
|
-
const { db } = deps.connection ?? connectFromEnv(cwd);
|
|
9
|
-
const schema = await readSchemaVersion(db);
|
|
10
|
-
if ("missing" in schema) {
|
|
11
|
-
out(schemaRefusal(schema.missing, "Rebuild"));
|
|
12
|
-
return 1;
|
|
13
|
-
}
|
|
14
|
-
// A behind schema has no delivery tables (version 8) or reads columns it lacks: refused before any write.
|
|
15
|
-
if (schemaBehind(schema.version)) {
|
|
16
|
-
out(schemaBehindMessage(schema.version));
|
|
17
|
-
return 1;
|
|
18
|
-
}
|
|
19
|
-
const config = deps.config ?? (await loadConfig(cwd));
|
|
20
|
-
out(rebuildMessage(await (deps.rebuild ?? rebuildSpace)(db, config)));
|
|
21
|
-
return 0;
|
|
22
|
-
}
|
package/dist/cli/space-io.d.ts
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import type { SupabaseClient } from "@supabase/supabase-js";
|
|
2
|
-
import type { ResolvedConfig } from "../config.ts";
|
|
3
|
-
import type { ContentTable } from "../sql-space.ts";
|
|
4
|
-
import { type Row } from "../space-transfer.ts";
|
|
5
|
-
export type SpaceConnection = {
|
|
6
|
-
db: SupabaseClient;
|
|
7
|
-
};
|
|
8
|
-
export declare const MEDIA_BUCKET = "media";
|
|
9
|
-
/** Rows per request. A host may cap below it, so a read stops at the first empty page, not the first short one. */
|
|
10
|
-
export declare const PAGE_ROWS = 1000;
|
|
11
|
-
/** `.env.local`, then `.env`, as Next reads them; a variable already set wins (spec §5). Returns the files it read. */
|
|
12
|
-
export declare function loadAppEnv(cwd: string, env?: Record<string, string | undefined>): string[];
|
|
13
|
-
/** The app's content client, from its env. Run outside the app, the missing keys are a missing
|
|
14
|
-
* folder, so the error names the folder it looked in. */
|
|
15
|
-
export declare function connectFromEnv(cwd: string, env?: Record<string, string | undefined>): SpaceConnection;
|
|
16
|
-
export { readSchemaVersion } from "../schema-read.ts";
|
|
17
|
-
/** The key's space projected whole into the delivery tables (spec 2026-10-07 delivery model §2): the stores and
|
|
18
|
-
* the site built from the config as the app's glue builds them, then every page and entry. */
|
|
19
|
-
export declare function rebuildSpace(db: SupabaseClient, config: ResolvedConfig): Promise<{
|
|
20
|
-
model: string;
|
|
21
|
-
pages: number;
|
|
22
|
-
entries: number;
|
|
23
|
-
stale: number;
|
|
24
|
-
}>;
|
|
25
|
-
/** The line a rebuild ends with. */
|
|
26
|
-
export declare const rebuiltMessage: (counts: {
|
|
27
|
-
pages: number;
|
|
28
|
-
entries: number;
|
|
29
|
-
}) => string;
|
|
30
|
-
export declare function schemaRefusal(missing: "key" | "schema", command: "Export" | "Import" | "Rebuild"): string;
|
|
31
|
-
/** Every row of one table in one space, paged in primary-key order. The space filter is explicit: a service-role key sees every space. */
|
|
32
|
-
export declare function readSpaceRows(db: SupabaseClient, table: ContentTable, space: string, where?: Record<string, string>, columns?: string): Promise<Row[]>;
|
|
33
|
-
type StorageErrorLike = {
|
|
34
|
-
message: string;
|
|
35
|
-
statusCode?: string | number;
|
|
36
|
-
status?: number;
|
|
37
|
-
};
|
|
38
|
-
export declare const isNotFound: (e: StorageErrorLike) => boolean;
|
|
39
|
-
export declare const isAlreadyExists: (e: StorageErrorLike) => boolean;
|
|
40
|
-
/** The installed package's version for the manifest: `../../package.json` from src/cli/ and dist/cli/ alike. */
|
|
41
|
-
export declare function packageVersion(): string;
|
package/dist/cli/space-io.js
DELETED
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
// packages/smoodly/src/cli/space-io.ts
|
|
2
|
-
// What export and import share (spec 2026-09-28 export/import §5, §8):
|
|
3
|
-
// the app's env and client (the space is the database's answer, read
|
|
4
|
-
// after the schema check so a missing schema is refused first), the schema-
|
|
5
|
-
// version read that doubles as the secret-key check, paged reads of one
|
|
6
|
-
// space's rows, and the two storage error tests.
|
|
7
|
-
import { existsSync, readFileSync } from "node:fs";
|
|
8
|
-
import { join } from "node:path";
|
|
9
|
-
import { parseEnv } from "node:util";
|
|
10
|
-
import { createSupabaseStores, siteOptions } from "../bind.js";
|
|
11
|
-
import { createSmoodlyClient } from "../client.js";
|
|
12
|
-
import { projectAll } from "../project.js";
|
|
13
|
-
import { createSmoodlySite } from "../site.js";
|
|
14
|
-
import { resolveSmoodlyEnv } from "../env.js";
|
|
15
|
-
import { ROW_KEY } from "../space-transfer.js";
|
|
16
|
-
export const MEDIA_BUCKET = "media";
|
|
17
|
-
/** Rows per request. A host may cap below it, so a read stops at the first empty page, not the first short one. */
|
|
18
|
-
export const PAGE_ROWS = 1000;
|
|
19
|
-
/** `.env.local`, then `.env`, as Next reads them; a variable already set wins (spec §5). Returns the files it read. */
|
|
20
|
-
export function loadAppEnv(cwd, env = process.env) {
|
|
21
|
-
const read = [];
|
|
22
|
-
for (const name of [".env.local", ".env"]) {
|
|
23
|
-
const file = join(cwd, name);
|
|
24
|
-
if (!existsSync(file))
|
|
25
|
-
continue;
|
|
26
|
-
read.push(name);
|
|
27
|
-
for (const [key, value] of Object.entries(parseEnv(readFileSync(file, "utf8")))) {
|
|
28
|
-
if (env[key] === undefined)
|
|
29
|
-
env[key] = value;
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
return read;
|
|
33
|
-
}
|
|
34
|
-
/** The app's content client, from its env. Run outside the app, the missing keys are a missing
|
|
35
|
-
* folder, so the error names the folder it looked in. */
|
|
36
|
-
export function connectFromEnv(cwd, env = process.env) {
|
|
37
|
-
const read = loadAppEnv(cwd, env);
|
|
38
|
-
if (read.length === 0 && (!env.SMOODLY_URL || !env.SMOODLY_SECRET_KEY)) {
|
|
39
|
-
throw new Error(`smoodly: no .env.local or .env in ${cwd} — run this in your app's folder.`);
|
|
40
|
-
}
|
|
41
|
-
return { db: createSmoodlyClient(resolveSmoodlyEnv(env)) };
|
|
42
|
-
}
|
|
43
|
-
export { readSchemaVersion } from "../schema-read.js";
|
|
44
|
-
/** The key's space projected whole into the delivery tables (spec 2026-10-07 delivery model §2): the stores and
|
|
45
|
-
* the site built from the config as the app's glue builds them, then every page and entry. */
|
|
46
|
-
export async function rebuildSpace(db, config) {
|
|
47
|
-
const { pages, entries, assets, published } = createSupabaseStores(db, config);
|
|
48
|
-
const { projector, stamp } = createSmoodlySite(siteOptions(config, () => ({ pages, entries, assets, published })));
|
|
49
|
-
const names = [...(config.registry.collections ?? []), ...(config.registry.globals ?? [])].map((c) => c.name);
|
|
50
|
-
// The document stamp every row now carries, recorded as the space's current one (DESIGN §3).
|
|
51
|
-
return { ...(await projectAll({ stores: { pages, entries }, projector, names })), model: stamp };
|
|
52
|
-
}
|
|
53
|
-
/** The line a rebuild ends with. */
|
|
54
|
-
export const rebuiltMessage = (counts) => `Rebuilt the delivery tables: ${counts.pages} ${counts.pages === 1 ? "page" : "pages"}, ${counts.entries} ${counts.entries === 1 ? "entry" : "entries"}.`;
|
|
55
|
-
export function schemaRefusal(missing, command) {
|
|
56
|
-
return missing === "key"
|
|
57
|
-
? `${command} needs SMOODLY_SECRET_KEY — the service-role key, or the cloud's write key. The publishable key reads no content.`
|
|
58
|
-
: "This database has no Smoodly schema. Run `npx smoodly migrate`, then `supabase db push` (hosted) or `supabase migration up` (local).";
|
|
59
|
-
}
|
|
60
|
-
/** Every row of one table in one space, paged in primary-key order. The space filter is explicit: a service-role key sees every space. */
|
|
61
|
-
export async function readSpaceRows(db, table, space, where = {}, columns = "*") {
|
|
62
|
-
const rows = [];
|
|
63
|
-
for (let from = 0;;) {
|
|
64
|
-
let q = db.from(table).select(columns).eq("space_id", space);
|
|
65
|
-
for (const [column, value] of Object.entries(where))
|
|
66
|
-
q = q.eq(column, value);
|
|
67
|
-
for (const column of ROW_KEY[table])
|
|
68
|
-
q = q.order(column);
|
|
69
|
-
const res = await q.range(from, from + PAGE_ROWS - 1);
|
|
70
|
-
if (res.error)
|
|
71
|
-
throw new Error(`smoodly: reading ${table}: ${res.error.message}`);
|
|
72
|
-
const page = (res.data ?? []);
|
|
73
|
-
if (page.length === 0)
|
|
74
|
-
return rows;
|
|
75
|
-
rows.push(...page);
|
|
76
|
-
from += page.length;
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
export const isNotFound = (e) => String(e.statusCode) === "404" || e.status === 404 || /not.?found/i.test(e.message);
|
|
80
|
-
export const isAlreadyExists = (e) => String(e.statusCode) === "409" || e.status === 409 || /already exists/i.test(e.message);
|
|
81
|
-
/** The installed package's version for the manifest: `../../package.json` from src/cli/ and dist/cli/ alike. */
|
|
82
|
-
export function packageVersion() {
|
|
83
|
-
return JSON.parse(readFileSync(new URL("../../package.json", import.meta.url), "utf8")).version;
|
|
84
|
-
}
|
package/dist/client.d.ts
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { type SupabaseClient } from "@supabase/supabase-js";
|
|
2
|
-
import type { SmoodlyEnv } from "./env.ts";
|
|
3
|
-
type ContentEnv = Pick<SmoodlyEnv, "url" | "secretKey" | "publishableKey">;
|
|
4
|
-
export declare function clientOptions(env: ContentEnv): {
|
|
5
|
-
url: string;
|
|
6
|
-
key: string;
|
|
7
|
-
headers: Record<string, string>;
|
|
8
|
-
};
|
|
9
|
-
/** The server-side client the stores are built on. */
|
|
10
|
-
export declare function createSmoodlyClient(env: ContentEnv): SupabaseClient;
|
|
11
|
-
export {};
|
package/dist/client.js
DELETED
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
// How the secret reaches PostgREST. A JWT (the self-host service role, or
|
|
2
|
-
// a cloud space key) rides as the bearer PostgREST derives the role from,
|
|
3
|
-
// with the publishable key satisfying the API gateway's apikey check. A
|
|
4
|
-
// Supabase `sb_secret_…` key is itself an apikey. Key *format*, not mode.
|
|
5
|
-
import { createClient } from "@supabase/supabase-js";
|
|
6
|
-
export function clientOptions(env) {
|
|
7
|
-
if (env.secretKey.startsWith("sb_secret_")) {
|
|
8
|
-
return { url: env.url, key: env.secretKey, headers: {} };
|
|
9
|
-
}
|
|
10
|
-
// The gateway's apikey is the publishable key, or the secret itself when the site runs
|
|
11
|
-
// without one (spec 2026-09-30 tester findings §4): a self-host service role is a valid apikey.
|
|
12
|
-
return { url: env.url, key: env.publishableKey || env.secretKey, headers: { Authorization: `Bearer ${env.secretKey}` } };
|
|
13
|
-
}
|
|
14
|
-
/** Where a framework adapter hears each database call (spec 2026-10-07 delivery model): the Astro request
|
|
15
|
-
* scope installs it and counts, so a test can hold a live page to one lookup. A global, not an import:
|
|
16
|
-
* the client stays free of any adapter. */
|
|
17
|
-
const READ_COUNTER = Symbol.for("smoodly:read-counter");
|
|
18
|
-
/** fetch that names the variable behind two failures supabase-js reports bare: the network
|
|
19
|
-
* ("TypeError: fetch failed") and PostgREST refusing the key. */
|
|
20
|
-
function namedFetch(url) {
|
|
21
|
-
return async (input, init) => {
|
|
22
|
-
globalThis[READ_COUNTER]?.();
|
|
23
|
-
let res;
|
|
24
|
-
try {
|
|
25
|
-
res = await fetch(input, init);
|
|
26
|
-
}
|
|
27
|
-
catch (e) {
|
|
28
|
-
if (e instanceof Error && e.name === "AbortError")
|
|
29
|
-
throw e;
|
|
30
|
-
throw new TypeError(`can't reach SMOODLY_URL (${url}): ${e instanceof Error ? e.message : String(e)}`);
|
|
31
|
-
}
|
|
32
|
-
if (res.status !== 401)
|
|
33
|
-
return res;
|
|
34
|
-
// PostgREST's key errors are PGRST300–303; their message varies by version ("JWT cryptographic
|
|
35
|
-
// operation failed", "No suitable key or wrong key type").
|
|
36
|
-
const body = (await res.clone().json().catch(() => null));
|
|
37
|
-
if (typeof body?.message !== "string")
|
|
38
|
-
return res;
|
|
39
|
-
if (!(typeof body.code === "string" && /^PGRST30\d$/.test(body.code)) && !/JWT/i.test(body.message))
|
|
40
|
-
return res;
|
|
41
|
-
const headers = new Headers(res.headers);
|
|
42
|
-
headers.delete("content-length");
|
|
43
|
-
const message = `SMOODLY_SECRET_KEY is not a valid key for SMOODLY_URL (${url}): ${body.message}`;
|
|
44
|
-
return new Response(JSON.stringify({ ...body, message }), { status: 401, statusText: res.statusText, headers });
|
|
45
|
-
};
|
|
46
|
-
}
|
|
47
|
-
/** The server-side client the stores are built on. */
|
|
48
|
-
export function createSmoodlyClient(env) {
|
|
49
|
-
const options = clientOptions(env);
|
|
50
|
-
return createClient(options.url, options.key, {
|
|
51
|
-
global: { headers: options.headers, fetch: namedFetch(options.url) },
|
|
52
|
-
auth: { persistSession: false, autoRefreshToken: false },
|
|
53
|
-
});
|
|
54
|
-
}
|
package/dist/current-space.d.ts
DELETED
package/dist/current-space.js
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
export async function readCurrentSpace(db) {
|
|
2
|
-
const res = await db.rpc("smoodly_current_space");
|
|
3
|
-
if (res.error)
|
|
4
|
-
throw new Error(`smoodly: reading the space: ${res.error.message}`);
|
|
5
|
-
if (typeof res.data !== "string" || !res.data) {
|
|
6
|
-
throw new Error("smoodly: smoodly_current_space() returned no space — is the schema up to date?");
|
|
7
|
-
}
|
|
8
|
-
return res.data;
|
|
9
|
-
}
|
package/dist/document-stamp.d.ts
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import type { SiteOptions } from "./site.ts";
|
|
2
|
-
/** Bumped by hand when the assembler's output changes shape; the upgrading guide names each bump. */
|
|
3
|
-
export declare const DOCUMENT_FORMAT = 1;
|
|
4
|
-
/** The parts of the registry that reach a document: what `cacheKey` hashes, minus the presentation. */
|
|
5
|
-
export declare function documentModel(options: SiteOptions): unknown;
|
|
6
|
-
/** `<format>:<model hash>` — what a delivery row's `model` column holds. */
|
|
7
|
-
export declare function documentStamp(options: SiteOptions): string;
|
package/dist/document-stamp.js
DELETED
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
// The stamp a delivery row carries (DESIGN §3, the document stamp, 2026-10-08): which document format and
|
|
2
|
-
// which content model built it. Not the cache key: the package version is in that one, not here, because a
|
|
3
|
-
// release that leaves documents alone must leave them alone.
|
|
4
|
-
import { modelKey } from "./model-key.js";
|
|
5
|
-
import { schemaOf } from "./registration.js";
|
|
6
|
-
/** Bumped by hand when the assembler's output changes shape; the upgrading guide names each bump. */
|
|
7
|
-
export const DOCUMENT_FORMAT = 1;
|
|
8
|
-
/** Schema keys that reach the admin only: a change to one leaves every document as it was. */
|
|
9
|
-
const PRESENTATION = new Set(["title", "description", "sample", "icon", "preview", "group", "admin"]);
|
|
10
|
-
/** A field descriptor without the parts that reach the admin only (a hidden condition decides what the editor shows). */
|
|
11
|
-
function fieldModel(field) {
|
|
12
|
-
if (!field || typeof field !== "object")
|
|
13
|
-
return field;
|
|
14
|
-
const { hidden: _hidden, ...rest } = field;
|
|
15
|
-
return Object.fromEntries(Object.entries(rest).map(([k, v]) => [k, k === "fields" ? fieldsModel(v) : k === "of" ? fieldModel(v) : v]));
|
|
16
|
-
}
|
|
17
|
-
function fieldsModel(fields) {
|
|
18
|
-
if (!fields || typeof fields !== "object")
|
|
19
|
-
return fields;
|
|
20
|
-
return Object.fromEntries(Object.entries(fields).map(([k, v]) => [k, fieldModel(v)]));
|
|
21
|
-
}
|
|
22
|
-
/** A schema without its presentation. */
|
|
23
|
-
function schemaModel(schema) {
|
|
24
|
-
if (!schema || typeof schema !== "object")
|
|
25
|
-
return schema;
|
|
26
|
-
return Object.fromEntries(Object.entries(schema)
|
|
27
|
-
.filter(([k]) => !PRESENTATION.has(k))
|
|
28
|
-
.map(([k, v]) => [k, k === "fields" || k === "settings" ? fieldsModel(v) : v]));
|
|
29
|
-
}
|
|
30
|
-
/** The parts of the registry that reach a document: what `cacheKey` hashes, minus the presentation. */
|
|
31
|
-
export function documentModel(options) {
|
|
32
|
-
return {
|
|
33
|
-
collections: options.collections.map(schemaModel),
|
|
34
|
-
// A global whole, its presentation dropped: its settings' defaults reach a visual item's document.
|
|
35
|
-
globals: (options.globals ?? []).map(schemaModel),
|
|
36
|
-
sections: options.sections.map((x) => schemaModel(schemaOf(x))),
|
|
37
|
-
elements: (options.elements ?? []).map((x) => schemaModel(schemaOf(x))),
|
|
38
|
-
pages: options.pages.map((x) => schemaModel(schemaOf(x))),
|
|
39
|
-
locales: options.locales,
|
|
40
|
-
homePageSlug: options.homePageSlug,
|
|
41
|
-
styles: options.styles,
|
|
42
|
-
custom: options.custom,
|
|
43
|
-
};
|
|
44
|
-
}
|
|
45
|
-
/** `<format>:<model hash>` — what a delivery row's `model` column holds. */
|
|
46
|
-
export function documentStamp(options) {
|
|
47
|
-
return `${DOCUMENT_FORMAT}:${modelKey(documentModel(options))}`;
|
|
48
|
-
}
|
package/dist/image/loaders.d.ts
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import type { ResolvedImage } from "../media.ts";
|
|
2
|
-
export type ImageUrlOptions = {
|
|
3
|
-
width?: number;
|
|
4
|
-
quality?: number;
|
|
5
|
-
format?: string;
|
|
6
|
-
};
|
|
7
|
-
export type ImageLoader = {
|
|
8
|
-
name: string;
|
|
9
|
-
/** True when the URL already applies crop and hotspot. */
|
|
10
|
-
handlesCrop: boolean;
|
|
11
|
-
url(image: ResolvedImage, opts: ImageUrlOptions): string;
|
|
12
|
-
};
|
|
13
|
-
export declare const nextLoader: ImageLoader;
|
|
14
|
-
/** The escape hatch: a URL for a width, through the loader. */
|
|
15
|
-
export declare function imageUrl(image: ResolvedImage, opts?: ImageUrlOptions, loader?: ImageLoader): string;
|
package/dist/image/loaders.js
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
export type RemotePattern = {
|
|
2
|
-
protocol: "http" | "https";
|
|
3
|
-
hostname: string;
|
|
4
|
-
port?: string;
|
|
5
|
-
pathname: string;
|
|
6
|
-
};
|
|
7
|
-
export type SmoodlyImagesConfig = {
|
|
8
|
-
remotePatterns: RemotePattern[];
|
|
9
|
-
dangerouslyAllowLocalIP?: true;
|
|
10
|
-
};
|
|
11
|
-
/** `localhost`, loopback and the RFC 1918 ranges — the hosts a local
|
|
12
|
-
* Supabase stack answers on. A public hostname that happens to resolve
|
|
13
|
-
* privately (a Docker alias) is not detected; set the flag by hand then. */
|
|
14
|
-
export declare function isPrivateHost(hostname: string): boolean;
|
|
15
|
-
/** The Supabase host's public media path as a remote pattern. Defined here, not in remote-pattern.ts: this
|
|
16
|
-
* entry loads in plain Node and imports nothing; remote-pattern.ts re-exports it for the Astro side. */
|
|
17
|
-
export declare function mediaRemotePattern(url: string): RemotePattern;
|
|
18
|
-
export declare function smoodlyImages(url?: string | undefined): SmoodlyImagesConfig;
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
/** `localhost`, loopback and the RFC 1918 ranges — the hosts a local
|
|
2
|
-
* Supabase stack answers on. A public hostname that happens to resolve
|
|
3
|
-
* privately (a Docker alias) is not detected; set the flag by hand then. */
|
|
4
|
-
export function isPrivateHost(hostname) {
|
|
5
|
-
const h = hostname.replace(/^\[|\]$/g, "");
|
|
6
|
-
if (h === "localhost" || h.endsWith(".localhost") || h === "::1")
|
|
7
|
-
return true;
|
|
8
|
-
const m = /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/.exec(h);
|
|
9
|
-
if (!m)
|
|
10
|
-
return false;
|
|
11
|
-
const [a, b] = [Number(m[1]), Number(m[2])];
|
|
12
|
-
return a === 127 || a === 10 || (a === 192 && b === 168) || (a === 172 && b >= 16 && b <= 31);
|
|
13
|
-
}
|
|
14
|
-
/** The Supabase host's public media path as a remote pattern. Defined here, not in remote-pattern.ts: this
|
|
15
|
-
* entry loads in plain Node and imports nothing; remote-pattern.ts re-exports it for the Astro side. */
|
|
16
|
-
export function mediaRemotePattern(url) {
|
|
17
|
-
const u = new URL(url);
|
|
18
|
-
return {
|
|
19
|
-
protocol: u.protocol === "http:" ? "http" : "https",
|
|
20
|
-
hostname: u.hostname,
|
|
21
|
-
...(u.port ? { port: u.port } : {}),
|
|
22
|
-
pathname: "/storage/v1/object/public/media/**",
|
|
23
|
-
};
|
|
24
|
-
}
|
|
25
|
-
export function smoodlyImages(url = process.env.SMOODLY_URL) {
|
|
26
|
-
if (!url) {
|
|
27
|
-
console.warn("smoodly: SMOODLY_URL is not set — next/image will refuse Supabase media URLs until it is.");
|
|
28
|
-
return { remotePatterns: [] };
|
|
29
|
-
}
|
|
30
|
-
const pattern = mediaRemotePattern(url);
|
|
31
|
-
return { remotePatterns: [pattern], ...(isPrivateHost(new URL(url).hostname) ? { dangerouslyAllowLocalIP: true } : {}) };
|
|
32
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { mediaRemotePattern, type RemotePattern } from "./next-config.ts";
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
// The Supabase host's public media path as a remote pattern (spec 2026-09-08 media §9): what next/image
|
|
2
|
-
// (next-config.ts) and Astro's image service (astro/index.ts) are both told they may resize from.
|
|
3
|
-
// The function lives in next-config.ts, which must import nothing (it loads in plain Node from
|
|
4
|
-
// next.config.ts); this module is the import path the Astro side uses.
|
|
5
|
-
export { mediaRemotePattern } from "./next-config.js";
|
package/dist/migrations.d.ts
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
export type MigrationFile = {
|
|
2
|
-
name: string;
|
|
3
|
-
text: string;
|
|
4
|
-
};
|
|
5
|
-
export type CollectionSQL = {
|
|
6
|
-
name: string;
|
|
7
|
-
sql: string;
|
|
8
|
-
};
|
|
9
|
-
export declare const MARKER_PREFIX = "-- smoodly:collection ";
|
|
10
|
-
/** The first 16 hex chars of sha256 over the exact emitted SQL. */
|
|
11
|
-
export declare const collectionHash: (sql: string) => string;
|
|
12
|
-
export declare const collectionMarker: (c: CollectionSQL) => string;
|
|
13
|
-
/** name → hash, the LAST marker per collection across the files in name order. */
|
|
14
|
-
export declare function parseMarkers(files: MigrationFile[]): Map<string, string>;
|
|
15
|
-
/** UTC yyyyMMddHHmmss — the Supabase CLI's file-name prefix. */
|
|
16
|
-
export declare const stamp: (at: Date) => string;
|
|
17
|
-
/** A views file must sort after every core file it may depend on and
|
|
18
|
-
* after any earlier views file it supersedes: the later of `now` and the
|
|
19
|
-
* newest own stamp plus a minute. */
|
|
20
|
-
export declare function viewsStamp(names: string[], now: Date): Date;
|
|
21
|
-
/** One file with a block per new or changed collection; null when none changed. */
|
|
22
|
-
export declare function viewsFile(collections: CollectionSQL[], existing: Map<string, string>, at: Date): MigrationFile | null;
|
|
23
|
-
export type CorePending = {
|
|
24
|
-
copy: MigrationFile[];
|
|
25
|
-
modified: string[];
|
|
26
|
-
};
|
|
27
|
-
/** Package files the app lacks (copy) and same-named files whose text differs (modified — never overwritten). */
|
|
28
|
-
export declare function pendingCoreFiles(packageFiles: MigrationFile[], appFiles: MigrationFile[]): CorePending;
|
|
29
|
-
export type MigratePlan = CorePending & {
|
|
30
|
-
views: MigrationFile | null;
|
|
31
|
-
};
|
|
32
|
-
export declare function planMigrate(input: {
|
|
33
|
-
packageFiles: MigrationFile[];
|
|
34
|
-
appFiles: MigrationFile[];
|
|
35
|
-
collections: CollectionSQL[];
|
|
36
|
-
}, now: Date): MigratePlan;
|
|
37
|
-
export declare const planIsEmpty: (plan: MigratePlan) => boolean;
|