create-specra 0.2.2 → 0.2.3

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 (42) hide show
  1. package/dist/{api-client-4XZPF7GL.js → api-client-VHQARPDT.js} +3 -3
  2. package/dist/chunk-5765WX4D.js +192 -0
  3. package/dist/chunk-5765WX4D.js.map +1 -0
  4. package/dist/{chunk-CIM73PDF.js → chunk-72RDEJR2.js} +2 -2
  5. package/dist/chunk-SQ2MMFUZ.js +102 -0
  6. package/dist/chunk-SQ2MMFUZ.js.map +1 -0
  7. package/dist/cli.js +7 -7
  8. package/dist/cli.js.map +1 -1
  9. package/dist/{deploy-ETWFNB4Z.js → deploy-V4JO2D6B.js} +32 -6
  10. package/dist/deploy-V4JO2D6B.js.map +1 -0
  11. package/dist/{doctor-IFELWGQB.js → doctor-ICALAJ4N.js} +41 -2
  12. package/dist/doctor-ICALAJ4N.js.map +1 -0
  13. package/dist/index.js +40 -107
  14. package/dist/index.js.map +1 -1
  15. package/dist/{login-DRPP77G4.js → login-UG3WU7DY.js} +17 -11
  16. package/dist/login-UG3WU7DY.js.map +1 -0
  17. package/dist/{logout-UJFYUAQC.js → logout-WJKHJZT6.js} +2 -2
  18. package/dist/{logs-K2CSCKOE.js → logs-BLUJPWNO.js} +3 -3
  19. package/dist/{projects-NORBBC4D.js → projects-LJ57GK3D.js} +3 -3
  20. package/package.json +1 -1
  21. package/templates/book-docs/.env.sample +1 -0
  22. package/templates/book-docs/package.json +1 -1
  23. package/templates/book-docs/src/routes/+layout.server.ts +3 -0
  24. package/templates/book-docs/src/routes/docs/[version]/[...slug]/+page.server.ts +1 -1
  25. package/templates/book-docs/svelte.config.js +6 -1
  26. package/templates/jbrains-docs/.env.sample +1 -0
  27. package/templates/jbrains-docs/package.json +1 -1
  28. package/templates/jbrains-docs/src/routes/+layout.server.ts +3 -0
  29. package/templates/jbrains-docs/src/routes/docs/[version]/[...slug]/+page.server.ts +1 -1
  30. package/templates/jbrains-docs/svelte.config.js +6 -1
  31. package/templates/minimal/.env.sample +1 -0
  32. package/templates/minimal/svelte.config.js +1 -1
  33. package/dist/chunk-ATRUBLRX.js +0 -102
  34. package/dist/chunk-ATRUBLRX.js.map +0 -1
  35. package/dist/deploy-ETWFNB4Z.js.map +0 -1
  36. package/dist/doctor-IFELWGQB.js.map +0 -1
  37. package/dist/login-DRPP77G4.js.map +0 -1
  38. /package/dist/{api-client-4XZPF7GL.js.map → api-client-VHQARPDT.js.map} +0 -0
  39. /package/dist/{chunk-CIM73PDF.js.map → chunk-72RDEJR2.js.map} +0 -0
  40. /package/dist/{logout-UJFYUAQC.js.map → logout-WJKHJZT6.js.map} +0 -0
  41. /package/dist/{logs-K2CSCKOE.js.map → logs-BLUJPWNO.js.map} +0 -0
  42. /package/dist/{projects-NORBBC4D.js.map → projects-LJ57GK3D.js.map} +0 -0
package/dist/index.js CHANGED
@@ -1,106 +1,33 @@
1
1
  #!/usr/bin/env node
2
+ import {
3
+ copyRecursive,
4
+ getPackageManagerCommand,
5
+ isFolderEmpty,
6
+ isWriteable,
7
+ tryGitInit,
8
+ validateProjectName
9
+ } from "./chunk-SQ2MMFUZ.js";
2
10
 
3
11
  // src/index.ts
4
12
  import { Command } from "commander";
5
13
  import prompts from "prompts";
6
- import path3 from "path";
7
-
8
- // src/create-project.ts
9
- import fs2 from "fs";
10
14
  import path2 from "path";
11
- import { fileURLToPath } from "url";
12
- import { execSync as execSync2 } from "child_process";
13
- import pc from "picocolors";
14
15
 
15
- // src/utils.ts
16
- import validateNpmPackageName from "validate-npm-package-name";
17
- import { execSync } from "child_process";
16
+ // src/create-project.ts
18
17
  import fs from "fs";
19
18
  import path from "path";
20
- function validateProjectName(name) {
21
- const validation = validateNpmPackageName(name);
22
- if (validation.validForNewPackages) {
23
- return { valid: true };
24
- }
25
- return {
26
- valid: false,
27
- problems: [
28
- ...validation.errors || [],
29
- ...validation.warnings || []
30
- ]
31
- };
32
- }
33
- function isWriteable(directory) {
34
- try {
35
- fs.accessSync(directory, fs.constants.W_OK);
36
- return true;
37
- } catch {
38
- return false;
39
- }
40
- }
41
- function isFolderEmpty(path4) {
42
- const files = fs.readdirSync(path4);
43
- return files.length === 0 || files.length === 1 && files[0] === ".git";
44
- }
45
- function getPackageManagerCommand(packageManager) {
46
- switch (packageManager) {
47
- case "yarn":
48
- return {
49
- install: "yarn install",
50
- run: (script) => `yarn ${script}`
51
- };
52
- case "pnpm":
53
- return {
54
- install: "pnpm install",
55
- run: (script) => `pnpm ${script}`
56
- };
57
- case "npm":
58
- default:
59
- return {
60
- install: "npm install",
61
- run: (script) => `npm run ${script}`
62
- };
63
- }
64
- }
65
- function tryGitInit(root) {
66
- try {
67
- execSync("git --version", { stdio: "ignore" });
68
- execSync("git init", { cwd: root, stdio: "ignore" });
69
- execSync("git add -A", { cwd: root, stdio: "ignore" });
70
- execSync('git commit -m "Initial commit from create-specra"', {
71
- cwd: root,
72
- stdio: "ignore"
73
- });
74
- return true;
75
- } catch {
76
- return false;
77
- }
78
- }
79
- function copyRecursive(src, dest) {
80
- const stat = fs.statSync(src);
81
- if (stat.isDirectory()) {
82
- fs.mkdirSync(dest, { recursive: true });
83
- const entries = fs.readdirSync(src);
84
- for (const entry of entries) {
85
- const srcPath = path.join(src, entry);
86
- const destPath = path.join(dest, entry);
87
- copyRecursive(srcPath, destPath);
88
- }
89
- } else {
90
- fs.copyFileSync(src, dest);
91
- }
92
- }
93
-
94
- // src/create-project.ts
19
+ import { fileURLToPath } from "url";
20
+ import { execSync } from "child_process";
21
+ import pc from "picocolors";
95
22
  async function createProject({
96
23
  projectName,
97
24
  template,
98
25
  packageManager,
99
26
  skipInstall
100
27
  }) {
101
- const root = path2.resolve(projectName);
102
- const appName = path2.basename(root);
103
- if (fs2.existsSync(root)) {
28
+ const root = path.resolve(projectName);
29
+ const appName = path.basename(root);
30
+ if (fs.existsSync(root)) {
104
31
  if (!isWriteable(root)) {
105
32
  console.error(
106
33
  pc.red(`The directory ${pc.cyan(projectName)} is not writable.`)
@@ -118,34 +45,40 @@ async function createProject({
118
45
  process.exit(1);
119
46
  }
120
47
  } else {
121
- fs2.mkdirSync(root, { recursive: true });
48
+ fs.mkdirSync(root, { recursive: true });
122
49
  }
123
50
  console.log(`Creating a new Specra documentation site (SvelteKit) in ${pc.cyan(root)}`);
124
51
  console.log();
125
52
  const __filename2 = fileURLToPath(import.meta.url);
126
- const __dirname2 = path2.dirname(__filename2);
127
- const templateDir = path2.join(__dirname2, "..", "templates", template);
128
- if (!fs2.existsSync(templateDir)) {
53
+ const __dirname2 = path.dirname(__filename2);
54
+ const templateDir = path.join(__dirname2, "..", "templates", template);
55
+ if (!fs.existsSync(templateDir)) {
129
56
  console.error(pc.red(`Template ${pc.cyan(template)} not found.`));
130
57
  process.exit(1);
131
58
  }
132
59
  console.log(`Using template: ${pc.cyan(template)}`);
133
60
  console.log();
134
61
  copyRecursive(templateDir, root);
135
- const packageJsonPath = path2.join(root, "package.json");
136
- const packageJson = JSON.parse(fs2.readFileSync(packageJsonPath, "utf8"));
62
+ const packageJsonPath = path.join(root, "package.json");
63
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf8"));
137
64
  packageJson.name = appName;
138
- fs2.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2) + "\n");
139
- const gitignorePath = path2.join(root, "gitignore");
140
- if (fs2.existsSync(gitignorePath)) {
141
- fs2.renameSync(gitignorePath, path2.join(root, ".gitignore"));
65
+ fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2) + "\n");
66
+ const specraConfigPath = path.join(root, "specra.config.json");
67
+ if (fs.existsSync(specraConfigPath)) {
68
+ const specraConfig = JSON.parse(fs.readFileSync(specraConfigPath, "utf8"));
69
+ specraConfig.packageManager = packageManager;
70
+ fs.writeFileSync(specraConfigPath, JSON.stringify(specraConfig, null, 2) + "\n");
71
+ }
72
+ const gitignorePath = path.join(root, "gitignore");
73
+ if (fs.existsSync(gitignorePath)) {
74
+ fs.renameSync(gitignorePath, path.join(root, ".gitignore"));
142
75
  }
143
76
  if (!skipInstall) {
144
77
  console.log("Installing dependencies...");
145
78
  console.log();
146
79
  const command2 = getPackageManagerCommand(packageManager);
147
80
  try {
148
- execSync2(command2.install, { cwd: root, stdio: "inherit" });
81
+ execSync(command2.install, { cwd: root, stdio: "inherit" });
149
82
  } catch (error) {
150
83
  console.error(pc.red("Failed to install dependencies."));
151
84
  process.exit(1);
@@ -210,7 +143,7 @@ var initCmd = program.command("init [project-directory]", { isDefault: true }).d
210
143
  }
211
144
  projectName = response.projectName;
212
145
  }
213
- const projectBaseName = path3.basename(path3.resolve(projectName));
146
+ const projectBaseName = path2.basename(path2.resolve(projectName));
214
147
  const validation = validateProjectName(projectBaseName);
215
148
  if (!validation.valid) {
216
149
  console.error(
@@ -292,27 +225,27 @@ var initCmd = program.command("init [project-directory]", { isDefault: true }).d
292
225
  }
293
226
  });
294
227
  program.command("login").description("Authenticate with your Specra account").option("-g, --global", "Store credentials in ~/.specra/ instead of local specra.config.json").action(async (options) => {
295
- const { login } = await import("./login-DRPP77G4.js");
228
+ const { login } = await import("./login-UG3WU7DY.js");
296
229
  await login(options);
297
230
  });
298
231
  program.command("logout").description("Clear stored credentials").option("-g, --global", "Clear credentials from ~/.specra/ instead of local specra.config.json").action(async (options) => {
299
- const { logout } = await import("./logout-UJFYUAQC.js");
232
+ const { logout } = await import("./logout-WJKHJZT6.js");
300
233
  await logout(options);
301
234
  });
302
- program.command("deploy").description("Deploy your docs project").option("-p, --project <id>", "Project ID to deploy to").option("-d, --dir <directory>", "Docs directory to deploy", ".").action(async (options) => {
303
- const { deploy } = await import("./deploy-ETWFNB4Z.js");
235
+ program.command("deploy").description("Deploy your docs project").option("-p, --project <id>", "Project ID to deploy to").option("-d, --dir <directory>", "Docs directory to deploy", ".").option("-v, --verbose", "Show detailed build output and logs").action(async (options) => {
236
+ const { deploy } = await import("./deploy-V4JO2D6B.js");
304
237
  await deploy(options);
305
238
  });
306
239
  program.command("projects").description("List your projects").action(async () => {
307
- const { projects } = await import("./projects-NORBBC4D.js");
240
+ const { projects } = await import("./projects-LJ57GK3D.js");
308
241
  await projects();
309
242
  });
310
243
  program.command("logs").description("View deployment logs").argument("<projectId>", "Project ID").option("--deployment <id>", "Specific deployment ID").action(async (projectId, options) => {
311
- const { logs } = await import("./logs-K2CSCKOE.js");
244
+ const { logs } = await import("./logs-BLUJPWNO.js");
312
245
  await logs(projectId, options);
313
246
  });
314
247
  program.command("doctor").description("Check specra.config.json for issues").option("-d, --dir <directory>", "Project directory to check", ".").action(async (options) => {
315
- const { doctor } = await import("./doctor-IFELWGQB.js");
248
+ const { doctor } = await import("./doctor-ICALAJ4N.js");
316
249
  await doctor(options);
317
250
  });
318
251
  program.parse();
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/create-project.ts","../src/utils.ts"],"sourcesContent":["import { Command } from 'commander'\nimport prompts from 'prompts'\nimport path from 'path'\nimport { createProject } from './create-project.js'\nimport { validateProjectName } from './utils.js'\nimport pc from 'picocolors'\nimport { createRequire } from 'module'\n\nconst require = createRequire(import.meta.url)\nconst { version } = require('../package.json')\n\nconst program = new Command()\n\nprogram\n .name('create-specra')\n .description('Specra CLI - Create, deploy, and manage your documentation sites')\n .version(version)\n\n// init command - create a new project (default when no subcommand given)\nconst initCmd = program\n .command('init [project-directory]', { isDefault: true })\n .description('Create a new Specra documentation site')\n .option('--template <template>', 'Template to use (minimal)')\n .option('--use-npm', 'Use npm as the package manager')\n .option('--use-pnpm', 'Use pnpm as the package manager')\n .option('--use-yarn', 'Use yarn as the package manager')\n .option('--skip-install', 'Skip package installation')\n .action(async (projectDirectory: string | undefined, options) => {\n console.log()\n console.log(pc.bold(pc.cyan('Create Specra Documentation Site')))\n console.log()\n\n let projectName = projectDirectory\n\n // Prompt for project name if not provided\n if (!projectName) {\n const response = await prompts({\n type: 'text',\n name: 'projectName',\n message: 'What is your project named?',\n initial: 'my-docs',\n validate: (name) => {\n const validation = validateProjectName(name)\n if (validation.valid) {\n return true\n }\n return validation.problems![0]\n },\n })\n\n if (!response.projectName) {\n console.log()\n console.log('Aborting.')\n process.exit(1)\n }\n\n projectName = response.projectName\n }\n\n // Validate the basename as a package name (allow full paths like /tmp/my-docs)\n const projectBaseName = path.basename(path.resolve(projectName!))\n const validation = validateProjectName(projectBaseName)\n if (!validation.valid) {\n console.error(\n pc.red(\n `Cannot create a project named ${pc.cyan(\n `\"${projectBaseName}\"`\n )} because of npm naming restrictions:\\n`\n )\n )\n validation.problems!.forEach((p) =>\n console.error(` ${pc.red('•')} ${p}`)\n )\n process.exit(1)\n }\n\n // Prompt for template if not provided\n let template = options.template\n\n if (!template) {\n const response = await prompts({\n type: 'select',\n name: 'template',\n message: 'Which template would you like to use?',\n choices: [\n {\n title: 'Minimal',\n value: 'minimal',\n description: 'Minimal setup to get started quickly',\n },\n {\n title: 'Book Docs',\n value: 'book-docs',\n description: 'Knowledge base style with dark theme and categorized sidebar',\n },\n {\n title: 'JBrains Docs',\n value: 'jbrains-docs',\n description: 'Reference docs style with light theme and tab groups',\n },\n ],\n initial: 0,\n })\n\n if (!response.template) {\n console.log()\n console.log('Aborting.')\n process.exit(1)\n }\n\n template = response.template\n }\n\n // Detect or prompt for package manager\n let packageManager = options.useNpm\n ? 'npm'\n : options.usePnpm\n ? 'pnpm'\n : options.useYarn\n ? 'yarn'\n : undefined\n\n if (!packageManager && !options.skipInstall) {\n const response = await prompts({\n type: 'select',\n name: 'packageManager',\n message: 'Which package manager do you want to use?',\n choices: [\n { title: 'npm', value: 'npm' },\n { title: 'yarn', value: 'yarn' },\n { title: 'pnpm', value: 'pnpm' },\n ],\n initial: 0,\n })\n\n if (!response.packageManager) {\n console.log()\n console.log('Aborting.')\n process.exit(1)\n }\n\n packageManager = response.packageManager\n }\n\n // Create the project\n try {\n await createProject({\n projectName: projectName!,\n template: template || 'minimal',\n packageManager: packageManager || 'npm',\n skipInstall: options.skipInstall,\n })\n } catch (error) {\n console.error(pc.red('\\nError creating project:'))\n console.error(error)\n process.exit(1)\n }\n })\n\n// login\nprogram\n .command('login')\n .description('Authenticate with your Specra account')\n .option('-g, --global', 'Store credentials in ~/.specra/ instead of local specra.config.json')\n .action(async (options) => {\n const { login } = await import('./commands/login.js')\n await login(options)\n })\n\n// logout\nprogram\n .command('logout')\n .description('Clear stored credentials')\n .option('-g, --global', 'Clear credentials from ~/.specra/ instead of local specra.config.json')\n .action(async (options) => {\n const { logout } = await import('./commands/logout.js')\n await logout(options)\n })\n\n// deploy\nprogram\n .command('deploy')\n .description('Deploy your docs project')\n .option('-p, --project <id>', 'Project ID to deploy to')\n .option('-d, --dir <directory>', 'Docs directory to deploy', '.')\n .action(async (options) => {\n const { deploy } = await import('./commands/deploy.js')\n await deploy(options)\n })\n\n// projects\nprogram\n .command('projects')\n .description('List your projects')\n .action(async () => {\n const { projects } = await import('./commands/projects.js')\n await projects()\n })\n\n// logs\nprogram\n .command('logs')\n .description('View deployment logs')\n .argument('<projectId>', 'Project ID')\n .option('--deployment <id>', 'Specific deployment ID')\n .action(async (projectId: string, options) => {\n const { logs } = await import('./commands/logs.js')\n await logs(projectId, options)\n })\n\n// doctor\nprogram\n .command('doctor')\n .description('Check specra.config.json for issues')\n .option('-d, --dir <directory>', 'Project directory to check', '.')\n .action(async (options) => {\n const { doctor } = await import('./commands/doctor.js')\n await doctor(options)\n })\n\nprogram.parse()\n\n// Handle unhandled rejections\nprocess.on('unhandledRejection', (err) => {\n console.error(pc.red('Error:'), err)\n process.exit(1)\n})\n","import fs from 'fs'\nimport path from 'path'\nimport { fileURLToPath } from 'url'\nimport { execSync } from 'child_process'\nimport pc from 'picocolors'\nimport {\n isWriteable,\n isFolderEmpty,\n getPackageManagerCommand,\n tryGitInit,\n copyRecursive,\n} from './utils.js'\n\ninterface CreateProjectOptions {\n projectName: string\n template: string\n packageManager: string\n skipInstall: boolean\n}\n\nexport async function createProject({\n projectName,\n template,\n packageManager,\n skipInstall,\n}: CreateProjectOptions) {\n const root = path.resolve(projectName)\n const appName = path.basename(root)\n\n // Check if directory exists\n if (fs.existsSync(root)) {\n if (!isWriteable(root)) {\n console.error(\n pc.red(`The directory ${pc.cyan(projectName)} is not writable.`)\n )\n process.exit(1)\n }\n\n if (!isFolderEmpty(root)) {\n console.error(\n pc.red(\n `The directory ${pc.cyan(\n projectName\n )} contains files that could conflict. Please use a new directory.`\n )\n )\n process.exit(1)\n }\n } else {\n fs.mkdirSync(root, { recursive: true })\n }\n\n console.log(`Creating a new Specra documentation site (SvelteKit) in ${pc.cyan(root)}`)\n console.log()\n\n // Create project structure based on template\n const __filename = fileURLToPath(import.meta.url)\n const __dirname = path.dirname(__filename)\n const templateDir = path.join(__dirname, '..', 'templates', template)\n\n if (!fs.existsSync(templateDir)) {\n console.error(pc.red(`Template ${pc.cyan(template)} not found.`))\n process.exit(1)\n }\n\n console.log(`Using template: ${pc.cyan(template)}`)\n console.log()\n\n // Copy template files\n copyRecursive(templateDir, root)\n\n // Update package.json with project name\n const packageJsonPath = path.join(root, 'package.json')\n const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'))\n packageJson.name = appName\n fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2) + '\\n')\n\n // Rename gitignore\n const gitignorePath = path.join(root, 'gitignore')\n if (fs.existsSync(gitignorePath)) {\n fs.renameSync(gitignorePath, path.join(root, '.gitignore'))\n }\n\n // Install dependencies\n if (!skipInstall) {\n console.log('Installing dependencies...')\n console.log()\n\n const command = getPackageManagerCommand(packageManager)\n\n try {\n execSync(command.install, { cwd: root, stdio: 'inherit' })\n } catch (error) {\n console.error(pc.red('Failed to install dependencies.'))\n process.exit(1)\n }\n\n console.log()\n }\n\n // Initialize git\n if (tryGitInit(root)) {\n console.log('Initialized a git repository.')\n console.log()\n }\n\n // Success message\n console.log(pc.green('Success!') + ` Created ${appName} at ${root}`)\n console.log()\n console.log('Inside that directory, you can run several commands:')\n console.log()\n\n const command = getPackageManagerCommand(packageManager)\n\n console.log(pc.cyan(` ${command.run('dev')}`))\n console.log(' Starts the development server.')\n console.log()\n console.log(pc.cyan(` ${command.run('build')}`))\n console.log(' Builds the app for production.')\n console.log()\n console.log(pc.cyan(` ${command.run('preview')}`))\n console.log(' Previews the built app locally.')\n console.log()\n console.log('We suggest that you begin by typing:')\n console.log()\n console.log(pc.cyan(' cd'), projectName)\n console.log(` ${pc.cyan(command.run('dev'))}`)\n console.log()\n}\n","import validateNpmPackageName from 'validate-npm-package-name'\nimport { execSync } from 'child_process'\nimport fs from 'fs'\nimport path from 'path'\n\nexport function validateProjectName(name: string) {\n const validation = validateNpmPackageName(name)\n\n if (validation.validForNewPackages) {\n return { valid: true }\n }\n\n return {\n valid: false,\n problems: [\n ...(validation.errors || []),\n ...(validation.warnings || []),\n ],\n }\n}\n\nexport function isWriteable(directory: string): boolean {\n try {\n fs.accessSync(directory, fs.constants.W_OK)\n return true\n } catch {\n return false\n }\n}\n\nexport function isFolderEmpty(path: string): boolean {\n const files = fs.readdirSync(path)\n return files.length === 0 || (files.length === 1 && files[0] === '.git')\n}\n\nexport function getPackageManagerCommand(packageManager: string): {\n install: string\n run: (script: string) => string\n} {\n switch (packageManager) {\n case 'yarn':\n return {\n install: 'yarn install',\n run: (script) => `yarn ${script}`,\n }\n case 'pnpm':\n return {\n install: 'pnpm install',\n run: (script) => `pnpm ${script}`,\n }\n case 'npm':\n default:\n return {\n install: 'npm install',\n run: (script) => `npm run ${script}`,\n }\n }\n}\n\nexport function tryGitInit(root: string): boolean {\n try {\n execSync('git --version', { stdio: 'ignore' })\n execSync('git init', { cwd: root, stdio: 'ignore' })\n execSync('git add -A', { cwd: root, stdio: 'ignore' })\n execSync('git commit -m \"Initial commit from create-specra\"', {\n cwd: root,\n stdio: 'ignore',\n })\n return true\n } catch {\n return false\n }\n}\n\nexport function copyRecursive(src: string, dest: string) {\n const stat = fs.statSync(src)\n\n if (stat.isDirectory()) {\n fs.mkdirSync(dest, { recursive: true })\n const entries = fs.readdirSync(src)\n\n for (const entry of entries) {\n const srcPath = path.join(src, entry)\n const destPath = path.join(dest, entry)\n copyRecursive(srcPath, destPath)\n }\n } else {\n fs.copyFileSync(src, dest)\n }\n}\n"],"mappings":"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","names":["path","fs","path","execSync","path","path","fs","__filename","__dirname","command","execSync","pc","require","validation","path"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/create-project.ts"],"sourcesContent":["import { Command } from 'commander'\nimport prompts from 'prompts'\nimport path from 'path'\nimport { createProject } from './create-project.js'\nimport { validateProjectName } from './utils.js'\nimport pc from 'picocolors'\nimport { createRequire } from 'module'\n\nconst require = createRequire(import.meta.url)\nconst { version } = require('../package.json')\n\nconst program = new Command()\n\nprogram\n .name('create-specra')\n .description('Specra CLI - Create, deploy, and manage your documentation sites')\n .version(version)\n\n// init command - create a new project (default when no subcommand given)\nconst initCmd = program\n .command('init [project-directory]', { isDefault: true })\n .description('Create a new Specra documentation site')\n .option('--template <template>', 'Template to use (minimal)')\n .option('--use-npm', 'Use npm as the package manager')\n .option('--use-pnpm', 'Use pnpm as the package manager')\n .option('--use-yarn', 'Use yarn as the package manager')\n .option('--skip-install', 'Skip package installation')\n .action(async (projectDirectory: string | undefined, options) => {\n console.log()\n console.log(pc.bold(pc.cyan('Create Specra Documentation Site')))\n console.log()\n\n let projectName = projectDirectory\n\n // Prompt for project name if not provided\n if (!projectName) {\n const response = await prompts({\n type: 'text',\n name: 'projectName',\n message: 'What is your project named?',\n initial: 'my-docs',\n validate: (name) => {\n const validation = validateProjectName(name)\n if (validation.valid) {\n return true\n }\n return validation.problems![0]\n },\n })\n\n if (!response.projectName) {\n console.log()\n console.log('Aborting.')\n process.exit(1)\n }\n\n projectName = response.projectName\n }\n\n // Validate the basename as a package name (allow full paths like /tmp/my-docs)\n const projectBaseName = path.basename(path.resolve(projectName!))\n const validation = validateProjectName(projectBaseName)\n if (!validation.valid) {\n console.error(\n pc.red(\n `Cannot create a project named ${pc.cyan(\n `\"${projectBaseName}\"`\n )} because of npm naming restrictions:\\n`\n )\n )\n validation.problems!.forEach((p) =>\n console.error(` ${pc.red('•')} ${p}`)\n )\n process.exit(1)\n }\n\n // Prompt for template if not provided\n let template = options.template\n\n if (!template) {\n const response = await prompts({\n type: 'select',\n name: 'template',\n message: 'Which template would you like to use?',\n choices: [\n {\n title: 'Minimal',\n value: 'minimal',\n description: 'Minimal setup to get started quickly',\n },\n {\n title: 'Book Docs',\n value: 'book-docs',\n description: 'Knowledge base style with dark theme and categorized sidebar',\n },\n {\n title: 'JBrains Docs',\n value: 'jbrains-docs',\n description: 'Reference docs style with light theme and tab groups',\n },\n ],\n initial: 0,\n })\n\n if (!response.template) {\n console.log()\n console.log('Aborting.')\n process.exit(1)\n }\n\n template = response.template\n }\n\n // Detect or prompt for package manager\n let packageManager = options.useNpm\n ? 'npm'\n : options.usePnpm\n ? 'pnpm'\n : options.useYarn\n ? 'yarn'\n : undefined\n\n if (!packageManager && !options.skipInstall) {\n const response = await prompts({\n type: 'select',\n name: 'packageManager',\n message: 'Which package manager do you want to use?',\n choices: [\n { title: 'npm', value: 'npm' },\n { title: 'yarn', value: 'yarn' },\n { title: 'pnpm', value: 'pnpm' },\n ],\n initial: 0,\n })\n\n if (!response.packageManager) {\n console.log()\n console.log('Aborting.')\n process.exit(1)\n }\n\n packageManager = response.packageManager\n }\n\n // Create the project\n try {\n await createProject({\n projectName: projectName!,\n template: template || 'minimal',\n packageManager: packageManager || 'npm',\n skipInstall: options.skipInstall,\n })\n } catch (error) {\n console.error(pc.red('\\nError creating project:'))\n console.error(error)\n process.exit(1)\n }\n })\n\n// login\nprogram\n .command('login')\n .description('Authenticate with your Specra account')\n .option('-g, --global', 'Store credentials in ~/.specra/ instead of local specra.config.json')\n .action(async (options) => {\n const { login } = await import('./commands/login.js')\n await login(options)\n })\n\n// logout\nprogram\n .command('logout')\n .description('Clear stored credentials')\n .option('-g, --global', 'Clear credentials from ~/.specra/ instead of local specra.config.json')\n .action(async (options) => {\n const { logout } = await import('./commands/logout.js')\n await logout(options)\n })\n\n// deploy\nprogram\n .command('deploy')\n .description('Deploy your docs project')\n .option('-p, --project <id>', 'Project ID to deploy to')\n .option('-d, --dir <directory>', 'Docs directory to deploy', '.')\n .option('-v, --verbose', 'Show detailed build output and logs')\n .action(async (options) => {\n const { deploy } = await import('./commands/deploy.js')\n await deploy(options)\n })\n\n// projects\nprogram\n .command('projects')\n .description('List your projects')\n .action(async () => {\n const { projects } = await import('./commands/projects.js')\n await projects()\n })\n\n// logs\nprogram\n .command('logs')\n .description('View deployment logs')\n .argument('<projectId>', 'Project ID')\n .option('--deployment <id>', 'Specific deployment ID')\n .action(async (projectId: string, options) => {\n const { logs } = await import('./commands/logs.js')\n await logs(projectId, options)\n })\n\n// doctor\nprogram\n .command('doctor')\n .description('Check specra.config.json for issues')\n .option('-d, --dir <directory>', 'Project directory to check', '.')\n .action(async (options) => {\n const { doctor } = await import('./commands/doctor.js')\n await doctor(options)\n })\n\nprogram.parse()\n\n// Handle unhandled rejections\nprocess.on('unhandledRejection', (err) => {\n console.error(pc.red('Error:'), err)\n process.exit(1)\n})\n","import fs from 'fs'\nimport path from 'path'\nimport { fileURLToPath } from 'url'\nimport { execSync } from 'child_process'\nimport pc from 'picocolors'\nimport {\n isWriteable,\n isFolderEmpty,\n getPackageManagerCommand,\n tryGitInit,\n copyRecursive,\n} from './utils.js'\n\ninterface CreateProjectOptions {\n projectName: string\n template: string\n packageManager: string\n skipInstall: boolean\n}\n\nexport async function createProject({\n projectName,\n template,\n packageManager,\n skipInstall,\n}: CreateProjectOptions) {\n const root = path.resolve(projectName)\n const appName = path.basename(root)\n\n // Check if directory exists\n if (fs.existsSync(root)) {\n if (!isWriteable(root)) {\n console.error(\n pc.red(`The directory ${pc.cyan(projectName)} is not writable.`)\n )\n process.exit(1)\n }\n\n if (!isFolderEmpty(root)) {\n console.error(\n pc.red(\n `The directory ${pc.cyan(\n projectName\n )} contains files that could conflict. Please use a new directory.`\n )\n )\n process.exit(1)\n }\n } else {\n fs.mkdirSync(root, { recursive: true })\n }\n\n console.log(`Creating a new Specra documentation site (SvelteKit) in ${pc.cyan(root)}`)\n console.log()\n\n // Create project structure based on template\n const __filename = fileURLToPath(import.meta.url)\n const __dirname = path.dirname(__filename)\n const templateDir = path.join(__dirname, '..', 'templates', template)\n\n if (!fs.existsSync(templateDir)) {\n console.error(pc.red(`Template ${pc.cyan(template)} not found.`))\n process.exit(1)\n }\n\n console.log(`Using template: ${pc.cyan(template)}`)\n console.log()\n\n // Copy template files\n copyRecursive(templateDir, root)\n\n // Update package.json with project name\n const packageJsonPath = path.join(root, 'package.json')\n const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'))\n packageJson.name = appName\n fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2) + '\\n')\n\n // Save package manager choice to specra.config.json\n const specraConfigPath = path.join(root, 'specra.config.json')\n if (fs.existsSync(specraConfigPath)) {\n const specraConfig = JSON.parse(fs.readFileSync(specraConfigPath, 'utf8'))\n specraConfig.packageManager = packageManager\n fs.writeFileSync(specraConfigPath, JSON.stringify(specraConfig, null, 2) + '\\n')\n }\n\n // Rename gitignore\n const gitignorePath = path.join(root, 'gitignore')\n if (fs.existsSync(gitignorePath)) {\n fs.renameSync(gitignorePath, path.join(root, '.gitignore'))\n }\n\n // Install dependencies\n if (!skipInstall) {\n console.log('Installing dependencies...')\n console.log()\n\n const command = getPackageManagerCommand(packageManager)\n\n try {\n execSync(command.install, { cwd: root, stdio: 'inherit' })\n } catch (error) {\n console.error(pc.red('Failed to install dependencies.'))\n process.exit(1)\n }\n\n console.log()\n }\n\n // Initialize git\n if (tryGitInit(root)) {\n console.log('Initialized a git repository.')\n console.log()\n }\n\n // Success message\n console.log(pc.green('Success!') + ` Created ${appName} at ${root}`)\n console.log()\n console.log('Inside that directory, you can run several commands:')\n console.log()\n\n const command = getPackageManagerCommand(packageManager)\n\n console.log(pc.cyan(` ${command.run('dev')}`))\n console.log(' Starts the development server.')\n console.log()\n console.log(pc.cyan(` ${command.run('build')}`))\n console.log(' Builds the app for production.')\n console.log()\n console.log(pc.cyan(` ${command.run('preview')}`))\n console.log(' Previews the built app locally.')\n console.log()\n console.log('We suggest that you begin by typing:')\n console.log()\n console.log(pc.cyan(' cd'), projectName)\n console.log(` ${pc.cyan(command.run('dev'))}`)\n console.log()\n}\n"],"mappings":"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","names":["path","__filename","__dirname","command","pc","require","validation","path"]}
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  getConfig,
4
4
  saveToken
5
- } from "./chunk-ATRUBLRX.js";
5
+ } from "./chunk-5765WX4D.js";
6
6
 
7
7
  // src/commands/login.ts
8
8
  import pc from "picocolors";
@@ -13,9 +13,9 @@ async function login(options = {}) {
13
13
  console.log(pc.bold("Specra Login"));
14
14
  console.log();
15
15
  if (options.global) {
16
- console.log(pc.dim("Storing credentials globally in ~/.specra/"));
16
+ console.log(pc.dim("Storing credentials globally in ~/.specra/config.json"));
17
17
  } else {
18
- console.log(pc.dim("Storing credentials in local specra.config.json"));
18
+ console.log(pc.dim("Storing credentials in local .env (referenced by specra.config.json)"));
19
19
  }
20
20
  console.log();
21
21
  const state = randomBytes(16).toString("hex");
@@ -30,8 +30,10 @@ async function login(options = {}) {
30
30
  if (returnedState !== state) {
31
31
  res.writeHead(400, { "Content-Type": "text/html" });
32
32
  res.end("<html><body><h1>State mismatch. Please try again.</h1></body></html>");
33
- server.close();
34
- resolve();
33
+ server.close(() => {
34
+ resolve();
35
+ process.exit(1);
36
+ });
35
37
  return;
36
38
  }
37
39
  if (token) {
@@ -49,7 +51,7 @@ async function login(options = {}) {
49
51
  }
50
52
  }
51
53
  try {
52
- const { apiRequest } = await import("./api-client-4XZPF7GL.js");
54
+ const { apiRequest } = await import("./api-client-VHQARPDT.js");
53
55
  const user = await apiRequest("/api/auth/verify");
54
56
  console.log(pc.green(`Authenticated as ${user.email}`));
55
57
  } catch {
@@ -62,8 +64,10 @@ async function login(options = {}) {
62
64
  res.writeHead(400, { "Content-Type": "text/html" });
63
65
  res.end("<html><body><h1>Authentication failed.</h1></body></html>");
64
66
  }
65
- server.close();
66
- resolve();
67
+ server.close(() => {
68
+ resolve();
69
+ process.exit(0);
70
+ });
67
71
  }
68
72
  });
69
73
  server.listen(port, () => {
@@ -75,12 +79,14 @@ async function login(options = {}) {
75
79
  });
76
80
  setTimeout(() => {
77
81
  console.log(pc.yellow("Login timed out."));
78
- server.close();
79
- resolve();
82
+ server.close(() => {
83
+ resolve();
84
+ process.exit(1);
85
+ });
80
86
  }, 3e5);
81
87
  });
82
88
  }
83
89
  export {
84
90
  login
85
91
  };
86
- //# sourceMappingURL=login-DRPP77G4.js.map
92
+ //# sourceMappingURL=login-UG3WU7DY.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/login.ts"],"sourcesContent":["import pc from 'picocolors'\nimport open from 'open'\nimport { createServer } from 'http'\nimport { saveToken, getGlobalConfig } from '../config.js'\nimport { getConfig, saveConfig } from '../config.js'\nimport { apiRequest } from '../api-client.js'\nimport { randomBytes } from 'crypto'\n\ninterface LoginOptions {\n global?: boolean\n}\n\nexport async function login(options: LoginOptions = {}) {\n console.log(pc.bold('Specra Login'))\n console.log()\n\n if (options.global) {\n console.log(pc.dim('Storing credentials globally in ~/.specra/config.json'))\n } else {\n console.log(pc.dim('Storing credentials in local .env (referenced by specra.config.json)'))\n }\n console.log()\n\n const state = randomBytes(16).toString('hex')\n const port = 9876\n // const apiUrl = getGlobalConfig().apiUrl\n const { apiUrl } = getConfig()\n\n return new Promise<void>((resolve) => {\n const server = createServer(async (req, res) => {\n const url = new URL(req.url!, `http://localhost:${port}`)\n\n // Backend redirects to root path with token as query param\n const token = url.searchParams.get('token')\n const returnedState = url.searchParams.get('state')\n\n if (token || returnedState) {\n if (returnedState !== state) {\n res.writeHead(400, { 'Content-Type': 'text/html' })\n res.end('<html><body><h1>State mismatch. Please try again.</h1></body></html>')\n server.close(() => {\n resolve()\n process.exit(1)\n })\n return\n }\n\n if (token) {\n try {\n saveToken(token, { global: options.global })\n console.log(pc.green('Token saved.'))\n } catch (err) {\n if (!options.global) {\n console.log(pc.yellow(`Could not save to local config: ${err instanceof Error ? err.message : err}`))\n console.log(pc.yellow('Falling back to global ~/.specra/ config'))\n saveToken(token, { global: true })\n console.log(pc.green('Token saved globally.'))\n } else {\n throw err\n }\n }\n\n // Verify the token works\n try {\n const { apiRequest } = await import('../api-client.js')\n const user = await apiRequest<{ email: string }>('/api/auth/verify')\n console.log(pc.green(`Authenticated as ${user.email}`))\n } catch {\n // verification is optional\n }\n\n res.writeHead(200, { 'Content-Type': 'text/html' })\n res.end(\n '<html><body><h1>Authenticated!</h1><p>You can close this window and return to the terminal.</p></body></html>'\n )\n } else {\n res.writeHead(400, { 'Content-Type': 'text/html' })\n res.end('<html><body><h1>Authentication failed.</h1></body></html>')\n }\n\n server.close(() => {\n resolve()\n process.exit(0)\n })\n }\n })\n\n server.listen(port, () => {\n const loginUrl = `${apiUrl}/auth/cli?port=${port}&state=${state}`\n console.log(`Opening browser to authenticate...`)\n console.log(pc.dim(`If the browser doesn't open, visit: ${loginUrl}`))\n console.log()\n open(loginUrl)\n })\n\n // Timeout after 5 minutes\n setTimeout(() => {\n console.log(pc.yellow('Login timed out.'))\n server.close(() => {\n resolve()\n process.exit(1)\n })\n }, 300000)\n })\n}\n"],"mappings":";;;;;;;AAAA,OAAO,QAAQ;AACf,OAAO,UAAU;AACjB,SAAS,oBAAoB;AAI7B,SAAS,mBAAmB;AAM5B,eAAsB,MAAM,UAAwB,CAAC,GAAG;AACtD,UAAQ,IAAI,GAAG,KAAK,cAAc,CAAC;AACnC,UAAQ,IAAI;AAEZ,MAAI,QAAQ,QAAQ;AAClB,YAAQ,IAAI,GAAG,IAAI,uDAAuD,CAAC;AAAA,EAC7E,OAAO;AACL,YAAQ,IAAI,GAAG,IAAI,sEAAsE,CAAC;AAAA,EAC5F;AACA,UAAQ,IAAI;AAEZ,QAAM,QAAQ,YAAY,EAAE,EAAE,SAAS,KAAK;AAC5C,QAAM,OAAO;AAEb,QAAM,EAAE,OAAO,IAAI,UAAU;AAE7B,SAAO,IAAI,QAAc,CAAC,YAAY;AACpC,UAAM,SAAS,aAAa,OAAO,KAAK,QAAQ;AAC9C,YAAM,MAAM,IAAI,IAAI,IAAI,KAAM,oBAAoB,IAAI,EAAE;AAGxD,YAAM,QAAQ,IAAI,aAAa,IAAI,OAAO;AAC1C,YAAM,gBAAgB,IAAI,aAAa,IAAI,OAAO;AAElD,UAAI,SAAS,eAAe;AAC1B,YAAI,kBAAkB,OAAO;AAC3B,cAAI,UAAU,KAAK,EAAE,gBAAgB,YAAY,CAAC;AAClD,cAAI,IAAI,sEAAsE;AAC9E,iBAAO,MAAM,MAAM;AACjB,oBAAQ;AACR,oBAAQ,KAAK,CAAC;AAAA,UAChB,CAAC;AACD;AAAA,QACF;AAEA,YAAI,OAAO;AACT,cAAI;AACF,sBAAU,OAAO,EAAE,QAAQ,QAAQ,OAAO,CAAC;AAC3C,oBAAQ,IAAI,GAAG,MAAM,cAAc,CAAC;AAAA,UACtC,SAAS,KAAK;AACZ,gBAAI,CAAC,QAAQ,QAAQ;AACnB,sBAAQ,IAAI,GAAG,OAAO,mCAAmC,eAAe,QAAQ,IAAI,UAAU,GAAG,EAAE,CAAC;AACpG,sBAAQ,IAAI,GAAG,OAAO,0CAA0C,CAAC;AACjE,wBAAU,OAAO,EAAE,QAAQ,KAAK,CAAC;AACjC,sBAAQ,IAAI,GAAG,MAAM,uBAAuB,CAAC;AAAA,YAC/C,OAAO;AACL,oBAAM;AAAA,YACR;AAAA,UACF;AAGA,cAAI;AACF,kBAAM,EAAE,WAAW,IAAI,MAAM,OAAO,0BAAkB;AACtD,kBAAM,OAAO,MAAM,WAA8B,kBAAkB;AACnE,oBAAQ,IAAI,GAAG,MAAM,oBAAoB,KAAK,KAAK,EAAE,CAAC;AAAA,UACxD,QAAQ;AAAA,UAER;AAEA,cAAI,UAAU,KAAK,EAAE,gBAAgB,YAAY,CAAC;AAClD,cAAI;AAAA,YACF;AAAA,UACF;AAAA,QACF,OAAO;AACL,cAAI,UAAU,KAAK,EAAE,gBAAgB,YAAY,CAAC;AAClD,cAAI,IAAI,2DAA2D;AAAA,QACrE;AAEA,eAAO,MAAM,MAAM;AACjB,kBAAQ;AACR,kBAAQ,KAAK,CAAC;AAAA,QAChB,CAAC;AAAA,MACH;AAAA,IACF,CAAC;AAED,WAAO,OAAO,MAAM,MAAM;AACxB,YAAM,WAAW,GAAG,MAAM,kBAAkB,IAAI,UAAU,KAAK;AAC/D,cAAQ,IAAI,oCAAoC;AAChD,cAAQ,IAAI,GAAG,IAAI,uCAAuC,QAAQ,EAAE,CAAC;AACrE,cAAQ,IAAI;AACZ,WAAK,QAAQ;AAAA,IACf,CAAC;AAGD,eAAW,MAAM;AACf,cAAQ,IAAI,GAAG,OAAO,kBAAkB,CAAC;AACzC,aAAO,MAAM,MAAM;AACjB,gBAAQ;AACR,gBAAQ,KAAK,CAAC;AAAA,MAChB,CAAC;AAAA,IACH,GAAG,GAAM;AAAA,EACX,CAAC;AACH;","names":[]}
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  clearToken,
4
4
  isAuthenticated
5
- } from "./chunk-ATRUBLRX.js";
5
+ } from "./chunk-5765WX4D.js";
6
6
 
7
7
  // src/commands/logout.ts
8
8
  import pc from "picocolors";
@@ -21,4 +21,4 @@ async function logout(options = {}) {
21
21
  export {
22
22
  logout
23
23
  };
24
- //# sourceMappingURL=logout-UJFYUAQC.js.map
24
+ //# sourceMappingURL=logout-WJKHJZT6.js.map
@@ -2,10 +2,10 @@
2
2
  import {
3
3
  apiRequest,
4
4
  formatError
5
- } from "./chunk-CIM73PDF.js";
5
+ } from "./chunk-72RDEJR2.js";
6
6
  import {
7
7
  isAuthenticated
8
- } from "./chunk-ATRUBLRX.js";
8
+ } from "./chunk-5765WX4D.js";
9
9
 
10
10
  // src/commands/logs.ts
11
11
  import pc from "picocolors";
@@ -74,4 +74,4 @@ function colorStatus(status) {
74
74
  export {
75
75
  logs
76
76
  };
77
- //# sourceMappingURL=logs-K2CSCKOE.js.map
77
+ //# sourceMappingURL=logs-BLUJPWNO.js.map
@@ -2,10 +2,10 @@
2
2
  import {
3
3
  apiRequest,
4
4
  formatError
5
- } from "./chunk-CIM73PDF.js";
5
+ } from "./chunk-72RDEJR2.js";
6
6
  import {
7
7
  isAuthenticated
8
- } from "./chunk-ATRUBLRX.js";
8
+ } from "./chunk-5765WX4D.js";
9
9
 
10
10
  // src/commands/projects.ts
11
11
  import pc from "picocolors";
@@ -46,4 +46,4 @@ async function projects() {
46
46
  export {
47
47
  projects
48
48
  };
49
- //# sourceMappingURL=projects-NORBBC4D.js.map
49
+ //# sourceMappingURL=projects-LJ57GK3D.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-specra",
3
- "version": "0.2.2",
3
+ "version": "0.2.3",
4
4
  "description": "CLI tool to scaffold a new Specra documentation site with Next.js",
5
5
  "type": "module",
6
6
  "bin": {
@@ -0,0 +1 @@
1
+ SPECTRA_TOKEN=sk_xxx...
@@ -13,7 +13,7 @@
13
13
  "specra": "^0.2.1"
14
14
  },
15
15
  "devDependencies": {
16
- "@sveltejs/adapter-auto": "^3.0.0",
16
+ "@sveltejs/adapter-static": "^3.0.0",
17
17
  "@sveltejs/kit": "^2.0.0",
18
18
  "@sveltejs/vite-plugin-svelte": "^6.0.0",
19
19
  "@tailwindcss/postcss": "^4.1.9",
@@ -5,6 +5,9 @@ import type { SpecraConfig } from 'specra';
5
5
 
6
6
  initConfig(specraConfig as unknown as Partial<SpecraConfig>);
7
7
 
8
+ export const prerender = true;
9
+ export const trailingSlash = 'always';
10
+
8
11
  export const load: LayoutServerLoad = async () => {
9
12
  const config = getConfig();
10
13
  return { config };
@@ -12,7 +12,7 @@ import type { PageServerLoad } from './$types';
12
12
 
13
13
  export const load: PageServerLoad = async ({ params }) => {
14
14
  const { version, slug: slugArray } = params;
15
- const slug = slugArray;
15
+ const slug = slugArray.replace(/\/$/, '');
16
16
 
17
17
  const i18nConfig = getI18nConfig();
18
18
  const slugParts = slug.split('/');
@@ -1,8 +1,13 @@
1
+ import adapter from '@sveltejs/adapter-static';
1
2
  import { specraConfig } from 'specra/svelte-config';
2
3
  import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
3
4
 
4
5
  const config = specraConfig({
5
- vitePreprocess: { vitePreprocess }
6
+ vitePreprocess: { vitePreprocess },
7
+ kit: {
8
+ adapter: adapter(),
9
+ prerender: { handleHttpError: 'warn', handleMissingId: 'warn' }
10
+ }
6
11
  });
7
12
 
8
13
  export default config;
@@ -0,0 +1 @@
1
+ SPECTRA_TOKEN=sk_xxx...
@@ -13,7 +13,7 @@
13
13
  "specra": "^0.2.1"
14
14
  },
15
15
  "devDependencies": {
16
- "@sveltejs/adapter-auto": "^3.0.0",
16
+ "@sveltejs/adapter-static": "^3.0.0",
17
17
  "@sveltejs/kit": "^2.0.0",
18
18
  "@sveltejs/vite-plugin-svelte": "^6.0.0",
19
19
  "@tailwindcss/postcss": "^4.1.9",
@@ -5,6 +5,9 @@ import type { SpecraConfig } from 'specra';
5
5
 
6
6
  initConfig(specraConfig as unknown as Partial<SpecraConfig>);
7
7
 
8
+ export const prerender = true;
9
+ export const trailingSlash = 'always';
10
+
8
11
  export const load: LayoutServerLoad = async () => {
9
12
  const config = getConfig();
10
13
  return { config };
@@ -12,7 +12,7 @@ import type { PageServerLoad } from './$types';
12
12
 
13
13
  export const load: PageServerLoad = async ({ params }) => {
14
14
  const { version, slug: slugArray } = params;
15
- const slug = slugArray;
15
+ const slug = slugArray.replace(/\/$/, '');
16
16
 
17
17
  const i18nConfig = getI18nConfig();
18
18
  const slugParts = slug.split('/');
@@ -1,8 +1,13 @@
1
+ import adapter from '@sveltejs/adapter-static';
1
2
  import { specraConfig } from 'specra/svelte-config';
2
3
  import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
3
4
 
4
5
  const config = specraConfig({
5
- vitePreprocess: { vitePreprocess }
6
+ vitePreprocess: { vitePreprocess },
7
+ kit: {
8
+ adapter: adapter(),
9
+ prerender: { handleHttpError: 'warn', handleMissingId: 'warn' }
10
+ }
6
11
  });
7
12
 
8
13
  export default config;
@@ -0,0 +1 @@
1
+ SPECTRA_TOKEN=sk_xxx...
@@ -5,7 +5,7 @@ import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
5
5
  const config = specraConfig({
6
6
  vitePreprocess: { vitePreprocess },
7
7
  kit: {
8
- adapter: adapter({ fallback: '404.html' }),
8
+ adapter: adapter(),
9
9
  prerender: { handleHttpError: 'warn', handleMissingId: 'warn' }
10
10
  }
11
11
  });