superslate 0.4.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/cli.js +113 -38
  2. package/package.json +2 -2
package/dist/cli.js CHANGED
@@ -1681,7 +1681,7 @@ import { existsSync, readdirSync, statSync } from "fs";
1681
1681
  import { mkdir as mkdir5, mkdtemp as mkdtemp2, readFile as readFile6, readdir as readdir2, rename as rename2, rm as rm5, rmdir, stat as stat5 } from "fs/promises";
1682
1682
  import { createConnection, createServer } from "net";
1683
1683
  import { fileURLToPath as fileURLToPath2 } from "url";
1684
- import { dirname as dirname2, join as join8, relative as relative2, resolve as resolve4, sep } from "path";
1684
+ import { dirname as dirname3, join as join8, relative as relative2, resolve as resolve4, sep } from "path";
1685
1685
 
1686
1686
  // src/constants.ts
1687
1687
  var CLI_NAME = "superslate";
@@ -1694,6 +1694,7 @@ var BUYER_CLI_NAME = "create-app";
1694
1694
  var BUYER_CLI_PACKAGE_NAME = "create-app";
1695
1695
  var DEFAULT_SCOPE = "@app";
1696
1696
  var SOURCE_BRAND_NAME = "superslate";
1697
+ var DOCS_BASE_URL = "https://docs.superslate.dev";
1697
1698
  var DELIVERY_BASE_URL = "https://dl.superslate.dev";
1698
1699
  var DELIVERY_URL_VARIABLE = "SUPERSLATE_DELIVERY_URL";
1699
1700
  var LICENSE_KEY_VARIABLE2 = "SUPERSLATE_LICENSE_KEY";
@@ -2319,9 +2320,17 @@ function isExecutable(path) {
2319
2320
 
2320
2321
  // src/agent-setup.ts
2321
2322
  var CLIENTS = ["codex", "claude", "cursor"];
2322
- var SERVER_NAME = "superslate-docs";
2323
- var CODEX_START = "# superslate-agent-context:start";
2324
- var CODEX_END = "# superslate-agent-context:end";
2323
+ var SERVER_NAME = "agent-docs";
2324
+ var CODEX_START = "# agent-context:start";
2325
+ var CODEX_END = "# agent-context:end";
2326
+ var AGENT_CONTEXT_TOOLS = [
2327
+ "search_docs",
2328
+ "search_implementation",
2329
+ "get_repository_map",
2330
+ "plan_change",
2331
+ "get_invariants",
2332
+ "get_verification"
2333
+ ];
2325
2334
  function takeValue(args, index, flag) {
2326
2335
  const value = args[index + 1];
2327
2336
  if (!value || value.startsWith("-"))
@@ -2352,7 +2361,7 @@ function parseAgentSetupArguments(argv) {
2352
2361
  function agentSetupUsage(cliName) {
2353
2362
  return `Usage: ${cliName} agent setup [options]
2354
2363
 
2355
- Connect local coding clients to this checkout's read-only superslate documentation server.
2364
+ Connect local coding clients to this checkout's read-only project context server.
2356
2365
 
2357
2366
  Options:
2358
2367
  --clients <list> Comma-separated clients: codex,claude,cursor
@@ -2373,12 +2382,12 @@ async function findAgentRepositoryRoot(start = process.cwd()) {
2373
2382
  }
2374
2383
  const parent = dirname(current);
2375
2384
  if (parent === current)
2376
- throw new Error("Run agent setup inside a superslate repository.");
2385
+ throw new Error("Run agent setup inside a project repository.");
2377
2386
  current = parent;
2378
2387
  }
2379
2388
  }
2380
2389
  function serverCommand(root) {
2381
- return { command: "pnpm", args: ["--dir", resolve(root), "superslate:mcp"] };
2390
+ return { command: "pnpm", args: ["--dir", resolve(root), "agent:mcp"] };
2382
2391
  }
2383
2392
  function codexManagedBlock(root) {
2384
2393
  const server = serverCommand(root);
@@ -2388,7 +2397,7 @@ function codexManagedBlock(root) {
2388
2397
  command = ${JSON.stringify(server.command)}
2389
2398
  args = [${args}]
2390
2399
  required = false
2391
- enabled_tools = ["search_docs", "get_repository_map", "plan_change", "get_invariants", "get_verification"]
2400
+ enabled_tools = ${JSON.stringify(AGENT_CONTEXT_TOOLS)}
2392
2401
  ${CODEX_END}`;
2393
2402
  }
2394
2403
  function mergeCodexConfig(existing, root) {
@@ -2397,14 +2406,14 @@ function mergeCodexConfig(existing, root) {
2397
2406
  const end = existing.indexOf(CODEX_END);
2398
2407
  if (start >= 0 || end >= 0) {
2399
2408
  if (start < 0 || end < start)
2400
- throw new Error("Codex config has an incomplete superslate block.");
2409
+ throw new Error("Codex config has an incomplete agent-context block.");
2401
2410
  const after = end + CODEX_END.length;
2402
2411
  return `${existing.slice(0, start).trimEnd()}
2403
2412
 
2404
2413
  ${managed}${existing.slice(after)}`.trimStart();
2405
2414
  }
2406
- if (/^\[mcp_servers\.(?:superslate-docs|superslate_docs|"superslate-docs")\]$/m.test(existing)) {
2407
- throw new Error("Codex already has an unmanaged superslate-docs server; remove or rename it first.");
2415
+ if (/^\[mcp_servers\.(?:agent-docs|agent_docs|"agent-docs")\]$/m.test(existing)) {
2416
+ throw new Error("Codex already has an unmanaged agent-docs server; remove or rename it first.");
2408
2417
  }
2409
2418
  return `${existing.trimEnd()}${existing.trim() ? `
2410
2419
 
@@ -2430,7 +2439,7 @@ function mergeCursorConfig(existing, root) {
2430
2439
  const current = servers[SERVER_NAME];
2431
2440
  const desired = serverCommand(root);
2432
2441
  if (current !== undefined && JSON.stringify(current) !== JSON.stringify(desired)) {
2433
- throw new Error("Cursor already has a different superslate-docs server; remove or rename it first.");
2442
+ throw new Error("Cursor already has a different agent-docs server; remove or rename it first.");
2434
2443
  }
2435
2444
  config.mcpServers = { ...servers, [SERVER_NAME]: desired };
2436
2445
  return `${JSON.stringify(config, null, 2)}
@@ -2460,7 +2469,7 @@ async function addGitInfoExcludes(root, paths) {
2460
2469
  const prefix = existing && !existing.endsWith(`
2461
2470
  `) ? `
2462
2471
  ` : "";
2463
- const marker = "# superslate local agent configuration";
2472
+ const marker = "# Local agent configuration";
2464
2473
  const heading = existing.split(/\r?\n/).includes(marker) ? "" : `${marker}
2465
2474
  `;
2466
2475
  await atomicWrite(excludePath, `${existing}${prefix}${heading}${missing.join(`
@@ -2491,10 +2500,10 @@ async function configureClaude(root) {
2491
2500
  if (existing.exitCode === 0) {
2492
2501
  const combined = `${existing.stdout}
2493
2502
  ${existing.stderr}`;
2494
- if (combined.includes("superslate:mcp") && combined.includes(root)) {
2503
+ if (combined.includes("agent:mcp") && combined.includes(root)) {
2495
2504
  return "Claude Code already has the matching local server.";
2496
2505
  }
2497
- throw new Error("Claude Code already has a different superslate-docs server; remove it first.");
2506
+ throw new Error("Claude Code already has a different agent-docs server; remove it first.");
2498
2507
  }
2499
2508
  const server = serverCommand(root);
2500
2509
  const result = await capture(["claude", "mcp", "add", SERVER_NAME, "--scope", "local", "--", server.command, ...server.args], root);
@@ -2505,14 +2514,15 @@ ${existing.stderr}`;
2505
2514
  return "Configured Claude Code local project scope.";
2506
2515
  }
2507
2516
  async function smokeServer(root) {
2508
- const result = await capture(["pnpm", "--dir", root, "superslate:mcp", "--check", "--root", root], root);
2517
+ const result = await capture(["pnpm", "--dir", root, "agent:mcp", "--check", "--root", root], root);
2509
2518
  if (result.exitCode !== 0) {
2510
2519
  const output = result.stderr.trim() || result.stdout.trim();
2511
- throw new Error(`superslate MCP self-check failed${output ? `: ${output}` : "."}`);
2520
+ throw new Error(`Agent context MCP self-check failed${output ? `: ${output}` : "."}`);
2512
2521
  }
2513
2522
  const report = JSON.parse(result.stdout);
2514
- if (!report.ok || report.tools !== 5)
2515
- throw new Error("superslate MCP self-check was incomplete.");
2523
+ if (!report.ok || report.tools !== AGENT_CONTEXT_TOOLS.length) {
2524
+ throw new Error("Agent context MCP self-check was incomplete.");
2525
+ }
2516
2526
  }
2517
2527
  function detectedClients() {
2518
2528
  return CLIENTS.filter((client) => {
@@ -2582,7 +2592,7 @@ async function runAgentSetup(argv, cliName) {
2582
2592
  const clients = await chooseClients(parsed);
2583
2593
  if (!clients)
2584
2594
  return;
2585
- intro2("superslate local agent context");
2595
+ intro2("Local agent context");
2586
2596
  if (parsed.dryRun) {
2587
2597
  for (const client of clients) {
2588
2598
  log2.info(`${client}
@@ -2600,7 +2610,7 @@ ${dryRunDescription(client, root)}`);
2600
2610
  log2.success(`${client}: ${result}`);
2601
2611
  }
2602
2612
  log2.info("Restart configured clients, then ask: “Use plan_change for my next feature.”");
2603
- outro2("superslate agent context is ready.");
2613
+ outro2("Agent context is ready.");
2604
2614
  }
2605
2615
 
2606
2616
  // src/deployment-cli.ts
@@ -2735,7 +2745,8 @@ Create a GitHub environment named \`${config.environment}\` and configure:
2735
2745
  - a \`BACKEND_HCL\` secret containing the selected remote-state backend configuration;
2736
2746
  - a \`TFVARS_JSON\` secret containing only:
2737
2747
  - ${providerInputs};
2738
- - \`VITE_TERMS_URL\` and \`VITE_PRIVACY_URL\`.
2748
+ - \`VITE_TERMS_URL\` and \`VITE_PRIVACY_URL\`, plus \`VITE_MARKETING_URL\` when the product has a
2749
+ public marketing site.
2739
2750
 
2740
2751
  ## Cloud preparation
2741
2752
 
@@ -3244,7 +3255,8 @@ Create a GitHub environment named \`${config.environment}\` and configure:
3244
3255
  - a \`BACKEND_HCL\` secret containing the selected remote-state backend configuration;
3245
3256
  - a \`TFVARS_JSON\` secret containing only:
3246
3257
  - ${providerInputs};
3247
- - \`VITE_TERMS_URL\` and \`VITE_PRIVACY_URL\`.
3258
+ - \`VITE_TERMS_URL\` and \`VITE_PRIVACY_URL\`, plus \`VITE_MARKETING_URL\` when the product has a
3259
+ public marketing site.
3248
3260
 
3249
3261
  ## Cloud preparation
3250
3262
 
@@ -3331,7 +3343,7 @@ import { execFile } from "node:child_process";
3331
3343
  import { createHash } from "node:crypto";
3332
3344
  import { cp, lstat, mkdir as mkdir4, mkdtemp, readFile as readFile5, readdir, rm as rm4, stat as stat4, writeFile as writeFile4 } from "node:fs/promises";
3333
3345
  import { tmpdir } from "node:os";
3334
- import { basename, join as join7, relative, resolve as resolve3 } from "node:path";
3346
+ import { basename, dirname as dirname2, join as join7, relative, resolve as resolve3 } from "node:path";
3335
3347
  import { promisify } from "node:util";
3336
3348
 
3337
3349
  // src/delivery.ts
@@ -3446,6 +3458,9 @@ var BRAND_MANIFEST = [
3446
3458
  { path: "apps/web/public/favicon/site.webmanifest", occurrences: 2 },
3447
3459
  { path: "apps/web/public/offline.html", occurrences: 6 },
3448
3460
  { path: "apps/docs/lib/shared.ts", occurrences: 1 },
3461
+ { path: "apps/docs/README.md", occurrences: 1 },
3462
+ { path: "README.md", occurrences: 1 },
3463
+ { path: "docs/meta.json", occurrences: 1 },
3449
3464
  { path: "apps/server/.env.example", occurrences: 1 },
3450
3465
  { path: "apps/server/src/config/env.ts", occurrences: 2 },
3451
3466
  { path: "apps/server/src/config/env.test.ts", occurrences: 1 },
@@ -3469,6 +3484,7 @@ var BRAND_MANIFEST = [
3469
3484
  { path: "apps/server/email-templates/security-alert.html", occurrences: 4 },
3470
3485
  { path: "apps/server/email-templates/verify-email.html", occurrences: 5 },
3471
3486
  { path: "apps/server/email-templates/reset-password.html", occurrences: 5 },
3487
+ { path: "apps/server/email-templates/organization-invitation.html", occurrences: 3 },
3472
3488
  { path: "apps/server/email-templates/welcome-email.html", occurrences: 8 }
3473
3489
  ];
3474
3490
  function validateAppName2(value) {
@@ -3517,7 +3533,7 @@ function rewriteBrandContent(content, brandName) {
3517
3533
  if (error)
3518
3534
  throw new Error(error);
3519
3535
  const escapedSourceBrand = SOURCE_BRAND_NAME.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
3520
- const sourceBrandPattern = new RegExp(`\\b${escapedSourceBrand}\\b`, "g");
3536
+ const sourceBrandPattern = new RegExp(`\\b${escapedSourceBrand}\\b`, "gi");
3521
3537
  const matches = content.match(sourceBrandPattern);
3522
3538
  if (brandName === SOURCE_BRAND_NAME || !matches)
3523
3539
  return { content, replacements: 0 };
@@ -3615,6 +3631,20 @@ function rewriteRootPackageName(content, appName) {
3615
3631
  return { content: `${JSON.stringify(parsed, null, 2)}
3616
3632
  `, replacements: 1 };
3617
3633
  }
3634
+ var WORKER_NAME_DECLARATION = /^name = "[^"]*"$/m;
3635
+ function rewriteWorkerName(content, appName) {
3636
+ const error = validateAppName2(appName);
3637
+ if (error)
3638
+ throw new Error(error);
3639
+ const declaration = content.match(WORKER_NAME_DECLARATION)?.[0];
3640
+ if (!declaration) {
3641
+ throw new Error("Cloudflare Worker configuration is missing a name declaration.");
3642
+ }
3643
+ const replacement = `name = "${appName}"`;
3644
+ if (declaration === replacement)
3645
+ return { content, replacements: 0 };
3646
+ return { content: content.replace(WORKER_NAME_DECLARATION, replacement), replacements: 1 };
3647
+ }
3618
3648
  function replaceMarkdownSection(content, heading, replacement) {
3619
3649
  const marker = `## ${heading}
3620
3650
  `;
@@ -3667,6 +3697,12 @@ into this repository.
3667
3697
  }
3668
3698
  return rewritten;
3669
3699
  }
3700
+ var BUYER_README_HEADING = "## Create your product";
3701
+ function stripDistributionReadmeBootstrap(content) {
3702
+ if (!content.includes(BUYER_README_HEADING))
3703
+ return content;
3704
+ return replaceMarkdownSection(content, "Create your product", "");
3705
+ }
3670
3706
  var REQUIRED_BUYER_CLI_CONSTANTS = ["CLI_NAME", "CLI_PACKAGE_NAME", "DEFAULT_SCOPE"];
3671
3707
  function rewriteBuyerCliConstants(content, scope, brandName) {
3672
3708
  const buyerVariablePrefix = BUYER_CLI_NAME.toUpperCase().replaceAll("-", "_");
@@ -3677,6 +3713,7 @@ function rewriteBuyerCliConstants(content, scope, brandName) {
3677
3713
  ["SOURCE_BRAND_NAME", brandName],
3678
3714
  ["TEMPLATE_REPOSITORY", "OWNER/REPOSITORY"],
3679
3715
  ["DELIVERY_BASE_URL", "https://releases.example.com"],
3716
+ ["DOCS_BASE_URL", "https://docs.example.com"],
3680
3717
  ["DELIVERY_URL_VARIABLE", `${buyerVariablePrefix}_DELIVERY_URL`],
3681
3718
  ["LICENSE_KEY_VARIABLE", `${buyerVariablePrefix}_LICENSE_KEY`],
3682
3719
  ["LICENSE_KEY_PREFIX", "LICENSE-"]
@@ -3696,6 +3733,7 @@ function rewriteBuyerCliConstants(content, scope, brandName) {
3696
3733
  CLI_PACKAGE_NAME,
3697
3734
  SOURCE_BRAND_NAME,
3698
3735
  DELIVERY_BASE_URL,
3736
+ DOCS_BASE_URL,
3699
3737
  DELIVERY_URL_VARIABLE,
3700
3738
  LICENSE_KEY_VARIABLE2,
3701
3739
  LICENSE_KEY_PREFIX
@@ -3779,6 +3817,8 @@ function isTemplatePathExcluded(relativePath) {
3779
3817
  return true;
3780
3818
  if (normalized === "internal" || normalized.startsWith("internal/"))
3781
3819
  return true;
3820
+ if (normalized === "marketing" || normalized.startsWith("marketing/"))
3821
+ return true;
3782
3822
  if (normalized === ".github/workflows/internal-commercial.yml")
3783
3823
  return true;
3784
3824
  if (normalized === "apps/worker" || normalized.startsWith("apps/worker/"))
@@ -3799,6 +3839,8 @@ function isTemplatePathExcluded(relativePath) {
3799
3839
  return true;
3800
3840
  if (normalized === "packages/create-app/src/cli-brand-contract.test.ts")
3801
3841
  return true;
3842
+ if (normalized === "packages/create-app/src/commercial-contract.test.ts")
3843
+ return true;
3802
3844
  if (normalized === "packages/create-app/LICENSE")
3803
3845
  return true;
3804
3846
  if (normalized === "packages/create-app/README.md")
@@ -3827,6 +3869,29 @@ async function assertEmptyTarget(targetDirectory) {
3827
3869
  throw error;
3828
3870
  }
3829
3871
  }
3872
+ async function trackedTemplatePaths(sourceDirectory) {
3873
+ const topLevel = await execFileAsync("git", ["rev-parse", "--show-toplevel"], {
3874
+ cwd: sourceDirectory
3875
+ }).then((result) => resolve3(result.stdout.trim())).catch(() => {
3876
+ return;
3877
+ });
3878
+ if (topLevel !== sourceDirectory)
3879
+ return;
3880
+ const { stdout: stdout2 } = await execFileAsync("git", ["ls-files", "-z"], {
3881
+ cwd: sourceDirectory,
3882
+ maxBuffer: 64 * 1024 * 1024
3883
+ });
3884
+ const tracked = new Set;
3885
+ for (const path of stdout2.split("\x00")) {
3886
+ if (!path)
3887
+ continue;
3888
+ tracked.add(path);
3889
+ for (let parent = dirname2(path);parent !== "."; parent = dirname2(parent)) {
3890
+ tracked.add(parent);
3891
+ }
3892
+ }
3893
+ return tracked;
3894
+ }
3830
3895
  async function copyLocalTemplate(source, target) {
3831
3896
  const sourceDirectory = resolve3(source);
3832
3897
  const sourceStat = await lstat(sourceDirectory).catch(() => {
@@ -3834,29 +3899,28 @@ async function copyLocalTemplate(source, target) {
3834
3899
  });
3835
3900
  if (!sourceStat?.isDirectory())
3836
3901
  throw new Error(`Template path is not a directory: ${sourceDirectory}`);
3837
- await assertNoSymbolicLinks(sourceDirectory, sourceDirectory, true);
3902
+ const tracked = await trackedTemplatePaths(sourceDirectory);
3903
+ const isTemplatePathIncluded = (relativePath) => relativePath === "" || !isTemplatePathExcluded(relativePath) && (!tracked || tracked.has(relativePath));
3904
+ await assertNoSymbolicLinks(sourceDirectory, sourceDirectory, isTemplatePathIncluded);
3838
3905
  await mkdir4(target, { recursive: true });
3839
3906
  await cp(sourceDirectory, target, {
3840
3907
  recursive: true,
3841
- filter: (path) => {
3842
- const relativePath = relative(sourceDirectory, path);
3843
- return relativePath === "" || !isTemplatePathExcluded(relativePath);
3844
- }
3908
+ filter: (path) => isTemplatePathIncluded(relative(sourceDirectory, path).replaceAll("\\", "/"))
3845
3909
  });
3846
3910
  await assertNoSymbolicLinks(target);
3847
3911
  }
3848
- async function assertNoSymbolicLinks(directory, root = directory, skipExcludedPaths = false) {
3912
+ async function assertNoSymbolicLinks(directory, root = directory, isIncluded) {
3849
3913
  const entries = await readdir(directory, { withFileTypes: true });
3850
3914
  for (const entry of entries) {
3851
3915
  const path = join7(directory, entry.name);
3852
- const relativePath = relative(root, path);
3853
- if (skipExcludedPaths && isTemplatePathExcluded(relativePath))
3916
+ const relativePath = relative(root, path).replaceAll("\\", "/");
3917
+ if (isIncluded && !isIncluded(relativePath))
3854
3918
  continue;
3855
3919
  if (entry.isSymbolicLink()) {
3856
3920
  throw new Error(`Template contains a symbolic link, which is not supported: ${path}`);
3857
3921
  }
3858
3922
  if (entry.isDirectory())
3859
- await assertNoSymbolicLinks(path, root, skipExcludedPaths);
3923
+ await assertNoSymbolicLinks(path, root, isIncluded);
3860
3924
  }
3861
3925
  }
3862
3926
  function verifyReleaseMetadata(checksum, manifest, artifactName, digest, templateRef) {
@@ -3953,6 +4017,14 @@ async function applyBrandRewrite(target, brandName) {
3953
4017
  }
3954
4018
  return report;
3955
4019
  }
4020
+ async function renameFrontendWorker(target, appName) {
4021
+ const workerPath = join7(target, "apps/web/wrangler.toml");
4022
+ if (!await stat4(workerPath).catch(() => {
4023
+ return;
4024
+ }))
4025
+ return;
4026
+ await rewriteFile(workerPath, (content) => rewriteWorkerName(content, appName));
4027
+ }
3956
4028
  async function generateEnvironmentFiles(target, databasePort = 5432) {
3957
4029
  const serverExample = await readFile5(join7(target, "apps/server/.env.example"), "utf8");
3958
4030
  await writeFile4(join7(target, "apps/server/.env"), generateServerEnv(serverExample, undefined, databasePort));
@@ -3966,8 +4038,10 @@ async function generateEnvironmentFiles(target, databasePort = 5432) {
3966
4038
  async function neutralizeAgentInstructions(target) {
3967
4039
  const agentPath = join7(target, "AGENTS.md");
3968
4040
  const claudePath = join7(target, "CLAUDE.md");
4041
+ const readmePath = join7(target, "README.md");
3969
4042
  await writeFile4(agentPath, rewriteBuyerAgentInstructions(await readFile5(agentPath, "utf8")));
3970
4043
  await writeFile4(claudePath, rewriteBuyerClaudeInstructions(await readFile5(claudePath, "utf8")));
4044
+ await writeFile4(readmePath, stripDistributionReadmeBootstrap(await readFile5(readmePath, "utf8")));
3971
4045
  const rootPackagePath = join7(target, "package.json");
3972
4046
  await writeFile4(rootPackagePath, stripSellerOnlyRootScripts(await readFile5(rootPackagePath, "utf8")));
3973
4047
  }
@@ -4036,6 +4110,7 @@ async function scaffold(options) {
4036
4110
  }
4037
4111
  const packagePath = join7(target, "package.json");
4038
4112
  const packageReplacements = await rewriteFile(packagePath, (content) => rewriteRootPackageName(content, options.appName));
4113
+ await renameFrontendWorker(target, options.appName);
4039
4114
  const scope = await applyScopeRewrite(target, options.scope);
4040
4115
  await neutralizeAgentInstructions(target);
4041
4116
  await neutralizeSourceCli(target, options.scope, options.brandName);
@@ -4074,7 +4149,7 @@ Create a buyer-owned SaaS application from your licensed ${suggestBrandName(CLI_
4074
4149
  Options:
4075
4150
  --license-key <key> Licence key from your purchase (or set ${LICENSE_KEY_VARIABLE})
4076
4151
  --source-version <version> Pin an immutable release (default: the latest you are entitled to)
4077
- --from <path> Use a local source checkout (maintainer/testing)
4152
+ --from <path> Use a local Git checkout, tracked files only (maintainer/testing)
4078
4153
  --scope <namespace> Advanced workspace namespace override (default: derived from brand)
4079
4154
  --brand <name> Display name (default: derived from app name)
4080
4155
  --yes Accept recommended defaults for omitted options
@@ -4287,7 +4362,7 @@ async function collectOptions(parsed) {
4287
4362
  };
4288
4363
  }
4289
4364
  async function readCliVersion() {
4290
- const packageJson = JSON.parse(await readFile6(resolve4(dirname2(fileURLToPath2(import.meta.url)), "../package.json"), "utf8"));
4365
+ const packageJson = JSON.parse(await readFile6(resolve4(dirname3(fileURLToPath2(import.meta.url)), "../package.json"), "utf8"));
4291
4366
  if (!packageJson.version)
4292
4367
  throw new Error(`${CLI_NAME} package version is missing.`);
4293
4368
  return packageJson.version;
@@ -4443,8 +4518,8 @@ async function createApplication(options) {
4443
4518
  await assertTargetAvailable(target);
4444
4519
  assertSiblingTarget(options.from, target);
4445
4520
  const databasePort = await findAvailablePort();
4446
- await mkdir5(dirname2(target), { recursive: true });
4447
- const staging = await mkdtemp2(join8(dirname2(target), `.${options.appName}-${CLI_NAME}-`));
4521
+ await mkdir5(dirname3(target), { recursive: true });
4522
+ const staging = await mkdtemp2(join8(dirname3(target), `.${options.appName}-${CLI_NAME}-`));
4448
4523
  const preparing = "Preparing your application";
4449
4524
  const reporter = createScaffoldReporter(preparing, Boolean(options.licenseKey));
4450
4525
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "superslate",
3
- "version": "0.4.0",
3
+ "version": "0.8.0",
4
4
  "description": "Create a production-oriented SaaS application from superslate.",
5
5
  "keywords": [
6
6
  "bun",
@@ -39,7 +39,7 @@
39
39
  },
40
40
  "devDependencies": {
41
41
  "@clack/prompts": "^1.7.0",
42
- "@types/node": "^26.1.2",
42
+ "@types/node": "^26.2.0",
43
43
  "typescript": "^7.0.2",
44
44
  "vitest": "^4.1.10"
45
45
  },