create-smoodly-app 0.0.42 → 0.0.44

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/index.js CHANGED
@@ -489,12 +489,23 @@ async function run(answers2, deps) {
489
489
  await sh("supabase", ["init"], { stdin: "ignore" });
490
490
  const configPath = join2(cwd, "supabase/config.toml");
491
491
  const toml = withoutSeedSql(await deps.fs.readFile(configPath));
492
- const base = await findFreeBlock(blockPorts(toml), deps.isPortFree);
492
+ const ports = blockPorts(toml);
493
+ const base = await findFreeBlock(ports, deps.isPortFree);
493
494
  await deps.fs.writeFile(configPath, base !== DEFAULT_BASE ? shiftBlock(toml, base) : toml);
494
495
  if (base !== DEFAULT_BASE) {
495
496
  deps.log(`Ports ${DEFAULT_BASE / 100}xx are busy (another Supabase project running?), using ${base / 100}xx.`);
496
497
  }
497
- await sh("supabase", LOCAL_START_ARGS);
498
+ try {
499
+ await sh("supabase", LOCAL_START_ARGS);
500
+ } catch (e) {
501
+ const shifted = ports.map((p3) => base + (p3 - DEFAULT_BASE));
502
+ const taken = (await Promise.all(shifted.map(deps.isPortFree))).some((free) => !free);
503
+ if (!taken) throw e;
504
+ const next = await findFreeBlock(ports, deps.isPortFree);
505
+ await deps.fs.writeFile(configPath, shiftBlock(toml, next));
506
+ deps.log(`Ports ${base / 100}xx were taken while starting (another Supabase project?), retrying on ${next / 100}xx.`);
507
+ await sh("supabase", LOCAL_START_ARGS);
508
+ }
498
509
  ctx.keys = parseStatusEnv((await sh("supabase", ["status", "-o", "env"], { capture: true })).stdout);
499
510
  break;
500
511
  }
@@ -540,7 +551,7 @@ var withoutSeedSql = (toml) => toml.replace(/(\[db\.seed\]\n(?:#.*\n)*enabled =
540
551
  function fallbackFor(step, answers2, keys) {
541
552
  const envLines = keys ? `Write ${answers2.dir}/.env.local:
542
553
 
543
- ${renderEnv(keys).split("\n").filter((l) => !l.startsWith("#")).join("\n").trimEnd()}` : `Write ${answers2.dir}/.env.local with SMOODLY_URL, SMOODLY_SECRET_KEY and SMOODLY_PUBLISHABLE_KEY (from \`supabase status\`).`;
554
+ ${renderEnv(keys).split("\n").filter((l) => !l.startsWith("#")).join("\n").trimEnd()}` : `Write ${answers2.dir}/.env.local with SMOODLY_URL, SMOODLY_SECRET_KEY and SMOODLY_PUBLISHABLE_KEY (from \`supabase status\`), and SITE_URL=http://localhost:3000.`;
544
555
  const editorLines = [
545
556
  "Create the first editor, then the starter content:",
546
557
  "",
@@ -549,7 +560,7 @@ ${renderEnv(keys).split("\n").filter((l) => !l.startsWith("#")).join("\n").trimE
549
560
  ].join("\n");
550
561
  switch (step) {
551
562
  case "supabaseLocal":
552
- return [`cd ${answers2.dir} && supabase init && supabase ${LOCAL_START_ARGS.join(" ")}`, "", envLines, "", editorLines].join("\n");
563
+ return [`cd ${answers2.dir} && supabase ${LOCAL_START_ARGS.join(" ")}`, "", envLines, "", editorLines].join("\n");
553
564
  case "supabaseInit": {
554
565
  const commands = answers2.hosted?.linkAndPush ? [`cd ${answers2.dir} && supabase init && ${linkCommand(answers2)} && supabase db push`] : [`cd ${answers2.dir} && supabase init`, "", `When you are ready: ${linkCommand(answers2)} && supabase db push`];
555
566
  return [...commands, "", envLines, "", editorLines].join("\n");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-smoodly-app",
3
- "version": "0.0.42",
3
+ "version": "0.0.44",
4
4
  "description": "Create a Smoodly site: a fresh Next.js app with the admin mounted, a Supabase schema, an env file and a first editor.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -14,7 +14,7 @@
14
14
  "next": "^16.3.4",
15
15
  "react": "^19",
16
16
  "react-dom": "^19",
17
- "smoodly": "0.0.42"
17
+ "smoodly": "0.0.44"
18
18
  },
19
19
  "devDependencies": {
20
20
  "@next/env": "^16.3.4",
@@ -18,6 +18,7 @@ import {
18
18
  // shell in every live page's JavaScript.
19
19
  import { createSmoodlyContent, supabaseAdminAuth, type AdminAuth, type AuthConfig, type SmoodlyContent } from "smoodly/admin";
20
20
  import { createPageRenderer, createSmoodlyQueries, type PageRegistration } from "smoodly/next";
21
+ import { connection } from "next/server";
21
22
  import type { SupabaseClient } from "@supabase/supabase-js";
22
23
  import { collections, config, elements, sections, globals } from "./config";
23
24
 
@@ -115,10 +116,19 @@ export const href = (path: string, _locale: string) => path;
115
116
  * { locale })`, `q().getPageTree({ locale })`. Typed by the registry, the
116
117
  * live draft in the editor preview, cached under tags the admin expires.
117
118
  * Rename it if `q` is not to your taste — this file is yours. */
118
- export const q = (): Queries => bound().q;
119
+ export const q = (): Queries =>
120
+ new Proxy({} as Queries, {
121
+ get: (_, name) => async (...args: unknown[]) => {
122
+ await connection();
123
+ return (bound().q as unknown as Record<string | symbol, (...a: unknown[]) => unknown>)[name](...args);
124
+ },
125
+ });
119
126
 
127
+ // A request first, then the env: `await connection()` makes the route dynamic before bound()
128
+ // reads SMOODLY_*, so `next build` prerenders nothing here and needs no keys — a layout
129
+ // reading a global through q() included (2026-10-02, tester round 6).
120
130
  /** The two route files call these. */
121
- export const renderSmoodlyPath: Renderer["renderSmoodlyPath"] = (...args) => bound().renderer.renderSmoodlyPath(...args);
122
- export const smoodlyMetadata: Renderer["smoodlyMetadata"] = (...args) => bound().renderer.smoodlyMetadata(...args);
123
- export const renderSmoodlyPage: Renderer["renderSmoodlyPage"] = (...args) => bound().renderer.renderSmoodlyPage(...args);
124
- export const smoodlyPageMetadata: Renderer["smoodlyPageMetadata"] = (...args) => bound().renderer.smoodlyPageMetadata(...args);
131
+ export const renderSmoodlyPath: Renderer["renderSmoodlyPath"] = async (...args) => { await connection(); return bound().renderer.renderSmoodlyPath(...args); };
132
+ export const smoodlyMetadata: Renderer["smoodlyMetadata"] = async (...args) => { await connection(); return bound().renderer.smoodlyMetadata(...args); };
133
+ export const renderSmoodlyPage: Renderer["renderSmoodlyPage"] = async (...args) => { await connection(); return bound().renderer.renderSmoodlyPage(...args); };
134
+ export const smoodlyPageMetadata: Renderer["smoodlyPageMetadata"] = async (...args) => { await connection(); return bound().renderer.smoodlyPageMetadata(...args); };
@@ -14,7 +14,7 @@
14
14
  "next": "^16.3.4",
15
15
  "react": "^19",
16
16
  "react-dom": "^19",
17
- "smoodly": "0.0.42",
17
+ "smoodly": "0.0.44",
18
18
  "next-intl": "^4.14.2"
19
19
  },
20
20
  "devDependencies": {
@@ -18,6 +18,7 @@ import {
18
18
  // shell in every live page's JavaScript.
19
19
  import { createSmoodlyContent, supabaseAdminAuth, type AdminAuth, type AuthConfig, type SmoodlyContent } from "smoodly/admin";
20
20
  import { createPageRenderer, createSmoodlyQueries, type PageRegistration } from "smoodly/next";
21
+ import { connection } from "next/server";
21
22
  import type { SupabaseClient } from "@supabase/supabase-js";
22
23
  import { getPathname } from "@/i18n/navigation";
23
24
  import { collections, config, elements, sections, globals } from "./config";
@@ -116,10 +117,19 @@ export const href = (path: string, locale: string) => getPathname({ locale, href
116
117
  * { locale })`, `q().getPageTree({ locale })`. Typed by the registry, the
117
118
  * live draft in the editor preview, cached under tags the admin expires.
118
119
  * Rename it if `q` is not to your taste — this file is yours. */
119
- export const q = (): Queries => bound().q;
120
+ export const q = (): Queries =>
121
+ new Proxy({} as Queries, {
122
+ get: (_, name) => async (...args: unknown[]) => {
123
+ await connection();
124
+ return (bound().q as unknown as Record<string | symbol, (...a: unknown[]) => unknown>)[name](...args);
125
+ },
126
+ });
120
127
 
128
+ // A request first, then the env: `await connection()` makes the route dynamic before bound()
129
+ // reads SMOODLY_*, so `next build` prerenders nothing here and needs no keys — a layout
130
+ // reading a global through q() included (2026-10-02, tester round 6).
121
131
  /** The two route files call these. */
122
- export const renderSmoodlyPath: Renderer["renderSmoodlyPath"] = (...args) => bound().renderer.renderSmoodlyPath(...args);
123
- export const smoodlyMetadata: Renderer["smoodlyMetadata"] = (...args) => bound().renderer.smoodlyMetadata(...args);
124
- export const renderSmoodlyPage: Renderer["renderSmoodlyPage"] = (...args) => bound().renderer.renderSmoodlyPage(...args);
125
- export const smoodlyPageMetadata: Renderer["smoodlyPageMetadata"] = (...args) => bound().renderer.smoodlyPageMetadata(...args);
132
+ export const renderSmoodlyPath: Renderer["renderSmoodlyPath"] = async (...args) => { await connection(); return bound().renderer.renderSmoodlyPath(...args); };
133
+ export const smoodlyMetadata: Renderer["smoodlyMetadata"] = async (...args) => { await connection(); return bound().renderer.smoodlyMetadata(...args); };
134
+ export const renderSmoodlyPage: Renderer["renderSmoodlyPage"] = async (...args) => { await connection(); return bound().renderer.renderSmoodlyPage(...args); };
135
+ export const smoodlyPageMetadata: Renderer["smoodlyPageMetadata"] = async (...args) => { await connection(); return bound().renderer.smoodlyPageMetadata(...args); };
@@ -14,7 +14,7 @@
14
14
  "next": "^16.3.4",
15
15
  "react": "^19",
16
16
  "react-dom": "^19",
17
- "smoodly": "0.0.42"
17
+ "smoodly": "0.0.44"
18
18
  },
19
19
  "devDependencies": {
20
20
  "@next/env": "^16.3.4",
@@ -18,6 +18,7 @@ import {
18
18
  // shell in every live page's JavaScript.
19
19
  import { createSmoodlyContent, supabaseAdminAuth, type AdminAuth, type AuthConfig, type SmoodlyContent } from "smoodly/admin";
20
20
  import { createPageRenderer, createSmoodlyQueries, type PageRegistration } from "smoodly/next";
21
+ import { connection } from "next/server";
21
22
  import type { SupabaseClient } from "@supabase/supabase-js";
22
23
  import { collections, config, elements, sections, globals } from "./config";
23
24
 
@@ -115,10 +116,19 @@ export const href = (path: string, _locale: string) => path;
115
116
  * { locale })`, `q().getPageTree({ locale })`. Typed by the registry, the
116
117
  * live draft in the editor preview, cached under tags the admin expires.
117
118
  * Rename it if `q` is not to your taste — this file is yours. */
118
- export const q = (): Queries => bound().q;
119
+ export const q = (): Queries =>
120
+ new Proxy({} as Queries, {
121
+ get: (_, name) => async (...args: unknown[]) => {
122
+ await connection();
123
+ return (bound().q as unknown as Record<string | symbol, (...a: unknown[]) => unknown>)[name](...args);
124
+ },
125
+ });
119
126
 
127
+ // A request first, then the env: `await connection()` makes the route dynamic before bound()
128
+ // reads SMOODLY_*, so `next build` prerenders nothing here and needs no keys — a layout
129
+ // reading a global through q() included (2026-10-02, tester round 6).
120
130
  /** The two route files call these. */
121
- export const renderSmoodlyPath: Renderer["renderSmoodlyPath"] = (...args) => bound().renderer.renderSmoodlyPath(...args);
122
- export const smoodlyMetadata: Renderer["smoodlyMetadata"] = (...args) => bound().renderer.smoodlyMetadata(...args);
123
- export const renderSmoodlyPage: Renderer["renderSmoodlyPage"] = (...args) => bound().renderer.renderSmoodlyPage(...args);
124
- export const smoodlyPageMetadata: Renderer["smoodlyPageMetadata"] = (...args) => bound().renderer.smoodlyPageMetadata(...args);
131
+ export const renderSmoodlyPath: Renderer["renderSmoodlyPath"] = async (...args) => { await connection(); return bound().renderer.renderSmoodlyPath(...args); };
132
+ export const smoodlyMetadata: Renderer["smoodlyMetadata"] = async (...args) => { await connection(); return bound().renderer.smoodlyMetadata(...args); };
133
+ export const renderSmoodlyPage: Renderer["renderSmoodlyPage"] = async (...args) => { await connection(); return bound().renderer.renderSmoodlyPage(...args); };
134
+ export const smoodlyPageMetadata: Renderer["smoodlyPageMetadata"] = async (...args) => { await connection(); return bound().renderer.smoodlyPageMetadata(...args); };
@@ -14,7 +14,7 @@
14
14
  "next": "^16.3.4",
15
15
  "react": "^19",
16
16
  "react-dom": "^19",
17
- "smoodly": "0.0.42",
17
+ "smoodly": "0.0.44",
18
18
  "next-intl": "^4.14.2"
19
19
  },
20
20
  "devDependencies": {
@@ -18,6 +18,7 @@ import {
18
18
  // shell in every live page's JavaScript.
19
19
  import { createSmoodlyContent, supabaseAdminAuth, type AdminAuth, type AuthConfig, type SmoodlyContent } from "smoodly/admin";
20
20
  import { createPageRenderer, createSmoodlyQueries, type PageRegistration } from "smoodly/next";
21
+ import { connection } from "next/server";
21
22
  import type { SupabaseClient } from "@supabase/supabase-js";
22
23
  import { getPathname } from "@/i18n/navigation";
23
24
  import { collections, config, elements, sections, globals } from "./config";
@@ -116,10 +117,19 @@ export const href = (path: string, locale: string) => getPathname({ locale, href
116
117
  * { locale })`, `q().getPageTree({ locale })`. Typed by the registry, the
117
118
  * live draft in the editor preview, cached under tags the admin expires.
118
119
  * Rename it if `q` is not to your taste — this file is yours. */
119
- export const q = (): Queries => bound().q;
120
+ export const q = (): Queries =>
121
+ new Proxy({} as Queries, {
122
+ get: (_, name) => async (...args: unknown[]) => {
123
+ await connection();
124
+ return (bound().q as unknown as Record<string | symbol, (...a: unknown[]) => unknown>)[name](...args);
125
+ },
126
+ });
120
127
 
128
+ // A request first, then the env: `await connection()` makes the route dynamic before bound()
129
+ // reads SMOODLY_*, so `next build` prerenders nothing here and needs no keys — a layout
130
+ // reading a global through q() included (2026-10-02, tester round 6).
121
131
  /** The two route files call these. */
122
- export const renderSmoodlyPath: Renderer["renderSmoodlyPath"] = (...args) => bound().renderer.renderSmoodlyPath(...args);
123
- export const smoodlyMetadata: Renderer["smoodlyMetadata"] = (...args) => bound().renderer.smoodlyMetadata(...args);
124
- export const renderSmoodlyPage: Renderer["renderSmoodlyPage"] = (...args) => bound().renderer.renderSmoodlyPage(...args);
125
- export const smoodlyPageMetadata: Renderer["smoodlyPageMetadata"] = (...args) => bound().renderer.smoodlyPageMetadata(...args);
132
+ export const renderSmoodlyPath: Renderer["renderSmoodlyPath"] = async (...args) => { await connection(); return bound().renderer.renderSmoodlyPath(...args); };
133
+ export const smoodlyMetadata: Renderer["smoodlyMetadata"] = async (...args) => { await connection(); return bound().renderer.smoodlyMetadata(...args); };
134
+ export const renderSmoodlyPage: Renderer["renderSmoodlyPage"] = async (...args) => { await connection(); return bound().renderer.renderSmoodlyPage(...args); };
135
+ export const smoodlyPageMetadata: Renderer["smoodlyPageMetadata"] = async (...args) => { await connection(); return bound().renderer.smoodlyPageMetadata(...args); };