create-specra 0.1.7 → 0.2.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.
- package/LICENSE.MD +16 -4
- package/README.md +53 -17
- package/dist/chunk-3DKWECRK.js +45 -0
- package/dist/chunk-3DKWECRK.js.map +1 -0
- package/dist/chunk-MA7QG54W.js +74 -0
- package/dist/chunk-MA7QG54W.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +33 -0
- package/dist/cli.js.map +1 -0
- package/dist/deploy-SCEMUQNS.js +141 -0
- package/dist/deploy-SCEMUQNS.js.map +1 -0
- package/dist/index.js +11 -11
- package/dist/index.js.map +1 -1
- package/dist/login-NKDRQXRE.js +71 -0
- package/dist/login-NKDRQXRE.js.map +1 -0
- package/dist/logout-H543QEKU.js +20 -0
- package/dist/logout-H543QEKU.js.map +1 -0
- package/dist/logs-YDAUCMAV.js +71 -0
- package/dist/logs-YDAUCMAV.js.map +1 -0
- package/dist/projects-3TAY7EDJ.js +42 -0
- package/dist/projects-3TAY7EDJ.js.map +1 -0
- package/package.json +7 -3
- package/templates/book-docs/docs/v1.0.0/concepts.mdx +89 -0
- package/templates/book-docs/docs/v1.0.0/content/_category_.json +7 -0
- package/templates/book-docs/docs/v1.0.0/content/formatting.mdx +128 -0
- package/templates/book-docs/docs/v1.0.0/content/reusable-content.mdx +116 -0
- package/templates/book-docs/docs/v1.0.0/content/structure.mdx +92 -0
- package/templates/book-docs/docs/v1.0.0/customization/_category_.json +7 -0
- package/templates/book-docs/docs/v1.0.0/customization/branding.mdx +115 -0
- package/templates/book-docs/docs/v1.0.0/customization/themes.mdx +81 -0
- package/templates/book-docs/docs/v1.0.0/introduction.mdx +38 -0
- package/templates/book-docs/docs/v1.0.0/quickstart.mdx +112 -0
- package/templates/book-docs/docs/v2.0.0/concepts.mdx +89 -0
- package/templates/book-docs/docs/v2.0.0/content/_category_.json +7 -0
- package/templates/book-docs/docs/v2.0.0/content/formatting.mdx +128 -0
- package/templates/book-docs/docs/v2.0.0/content/reusable-content.mdx +116 -0
- package/templates/book-docs/docs/v2.0.0/content/structure.mdx +92 -0
- package/templates/book-docs/docs/v2.0.0/customization/_category_.json +7 -0
- package/templates/book-docs/docs/v2.0.0/customization/branding.mdx +115 -0
- package/templates/book-docs/docs/v2.0.0/customization/themes.mdx +81 -0
- package/templates/book-docs/docs/v2.0.0/introduction.mdx +39 -0
- package/templates/book-docs/docs/v2.0.0/quickstart.mdx +112 -0
- package/templates/book-docs/gitignore +7 -0
- package/templates/book-docs/package.json +28 -0
- package/templates/book-docs/postcss.config.mjs +8 -0
- package/templates/book-docs/public/api-specs/openapi-example.json +259 -0
- package/templates/book-docs/public/api-specs/postman-example.json +205 -0
- package/templates/book-docs/public/api-specs/test-api.json +256 -0
- package/templates/book-docs/public/api-specs/users-api.json +264 -0
- package/templates/book-docs/specra.config.json +77 -0
- package/templates/book-docs/src/app.css +2 -0
- package/templates/book-docs/src/app.html +12 -0
- package/templates/book-docs/src/routes/+layout.server.ts +11 -0
- package/templates/book-docs/src/routes/+layout.svelte +21 -0
- package/templates/book-docs/src/routes/+page.server.ts +9 -0
- package/templates/book-docs/src/routes/docs/[version]/[...slug]/+page.server.ts +119 -0
- package/templates/book-docs/src/routes/docs/[version]/[...slug]/+page.svelte +129 -0
- package/templates/book-docs/svelte.config.js +8 -0
- package/templates/book-docs/tsconfig.json +12 -0
- package/templates/book-docs/vite.config.ts +6 -0
- package/templates/jbrains-docs/docs/v1.0.0/advanced/_category_.json +8 -0
- package/templates/jbrains-docs/docs/v1.0.0/advanced/async.mdx +95 -0
- package/templates/jbrains-docs/docs/v1.0.0/advanced/generics.mdx +126 -0
- package/templates/jbrains-docs/docs/v1.0.0/basics/_category_.json +8 -0
- package/templates/jbrains-docs/docs/v1.0.0/basics/control-flow.mdx +106 -0
- package/templates/jbrains-docs/docs/v1.0.0/basics/syntax.mdx +129 -0
- package/templates/jbrains-docs/docs/v1.0.0/basics/types.mdx +135 -0
- package/templates/jbrains-docs/docs/v1.0.0/getting-started.mdx +111 -0
- package/templates/jbrains-docs/docs/v1.0.0/home.mdx +37 -0
- package/templates/jbrains-docs/docs/v1.0.0/tools/_category_.json +8 -0
- package/templates/jbrains-docs/docs/v1.0.0/tools/build-tools.mdx +165 -0
- package/templates/jbrains-docs/docs/v1.0.0/tools/testing.mdx +112 -0
- package/templates/jbrains-docs/docs/v2.0.0/advanced/_category_.json +8 -0
- package/templates/jbrains-docs/docs/v2.0.0/advanced/async.mdx +95 -0
- package/templates/jbrains-docs/docs/v2.0.0/advanced/generics.mdx +126 -0
- package/templates/jbrains-docs/docs/v2.0.0/basics/_category_.json +8 -0
- package/templates/jbrains-docs/docs/v2.0.0/basics/control-flow.mdx +106 -0
- package/templates/jbrains-docs/docs/v2.0.0/basics/syntax.mdx +129 -0
- package/templates/jbrains-docs/docs/v2.0.0/basics/types.mdx +135 -0
- package/templates/jbrains-docs/docs/v2.0.0/getting-started.mdx +111 -0
- package/templates/jbrains-docs/docs/v2.0.0/home.mdx +37 -0
- package/templates/jbrains-docs/docs/v2.0.0/tools/_category_.json +8 -0
- package/templates/jbrains-docs/docs/v2.0.0/tools/build-tools.mdx +165 -0
- package/templates/jbrains-docs/docs/v2.0.0/tools/testing.mdx +112 -0
- package/templates/jbrains-docs/gitignore +7 -0
- package/templates/jbrains-docs/package.json +28 -0
- package/templates/jbrains-docs/postcss.config.mjs +8 -0
- package/templates/jbrains-docs/public/api-specs/openapi-example.json +259 -0
- package/templates/jbrains-docs/public/api-specs/postman-example.json +205 -0
- package/templates/jbrains-docs/public/api-specs/test-api.json +256 -0
- package/templates/jbrains-docs/public/api-specs/users-api.json +264 -0
- package/templates/jbrains-docs/specra.config.json +80 -0
- package/templates/jbrains-docs/src/app.css +2 -0
- package/templates/jbrains-docs/src/app.html +12 -0
- package/templates/jbrains-docs/src/routes/+layout.server.ts +11 -0
- package/templates/jbrains-docs/src/routes/+layout.svelte +21 -0
- package/templates/jbrains-docs/src/routes/+page.server.ts +9 -0
- package/templates/jbrains-docs/src/routes/docs/[version]/[...slug]/+page.server.ts +119 -0
- package/templates/jbrains-docs/src/routes/docs/[version]/[...slug]/+page.svelte +129 -0
- package/templates/jbrains-docs/svelte.config.js +8 -0
- package/templates/jbrains-docs/tsconfig.json +12 -0
- package/templates/jbrains-docs/vite.config.ts +6 -0
- package/templates/minimal/docs/v1.0.0/about.mdx +3 -3
- package/templates/minimal/docs/v2.0.0/about.mdx +3 -3
- package/templates/minimal/gitignore +7 -0
- package/templates/minimal/package.json +18 -24
- package/templates/minimal/specra.config.json +12 -63
- package/templates/minimal/src/app.css +2 -0
- package/templates/minimal/src/app.html +12 -0
- package/templates/minimal/src/routes/+layout.server.ts +11 -0
- package/templates/minimal/src/routes/+layout.svelte +21 -0
- package/templates/minimal/src/routes/+page.server.ts +9 -0
- package/templates/minimal/src/routes/docs/[version]/[...slug]/+page.server.ts +119 -0
- package/templates/minimal/src/routes/docs/[version]/[...slug]/+page.svelte +129 -0
- package/templates/minimal/svelte.config.js +8 -0
- package/templates/minimal/tsconfig.json +7 -36
- package/templates/minimal/vite.config.ts +6 -0
- package/templates/minimal/README.md +0 -132
- package/templates/minimal/app/api/mdx-watch/route.ts +0 -6
- package/templates/minimal/app/api/search/route.ts +0 -75
- package/templates/minimal/app/docs/[version]/[...slug]/loading.tsx +0 -7
- package/templates/minimal/app/docs/[version]/[...slug]/page.tsx +0 -205
- package/templates/minimal/app/docs/[version]/[...slug]/page.tsx.bak +0 -203
- package/templates/minimal/app/docs/[version]/not-found.tsx +0 -10
- package/templates/minimal/app/docs/[version]/page.tsx +0 -27
- package/templates/minimal/app/globals.css +0 -9
- package/templates/minimal/app/layout.tsx +0 -62
- package/templates/minimal/app/not-found.tsx +0 -10
- package/templates/minimal/app/page.tsx +0 -179
- package/templates/minimal/next.config.mjs +0 -1
- package/templates/minimal/package-lock.json +0 -7881
- package/templates/minimal/proxy_.ts +0 -22
- package/templates/minimal/scripts/generate-redirects.mjs +0 -128
- package/templates/minimal/scripts/generate-static-redirects.mjs +0 -115
- package/templates/minimal/scripts/index-search.ts +0 -182
- package/templates/minimal/scripts/test-search.ts +0 -83
package/LICENSE.MD
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
MIT License
|
|
1
|
+
MIT License with Branding Requirement
|
|
2
2
|
|
|
3
|
-
Copyright (c) 2025 dalmasonto, arthur-kamau
|
|
3
|
+
Copyright (c) 2025-2026 dalmasonto, arthur-kamau
|
|
4
4
|
|
|
5
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
6
|
of this software and associated documentation files (the "Software"), to deal
|
|
@@ -9,8 +9,20 @@ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
9
9
|
copies of the Software, and to permit persons to whom the Software is
|
|
10
10
|
furnished to do so, subject to the following conditions:
|
|
11
11
|
|
|
12
|
-
The above copyright notice and this permission notice shall be included in
|
|
13
|
-
copies or substantial portions of the Software.
|
|
12
|
+
1. The above copyright notice and this permission notice shall be included in
|
|
13
|
+
all copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
2. BRANDING / WATERMARK REQUIREMENT: All documentation sites generated using
|
|
16
|
+
this Software or the associated Specra SDK MUST display the "Powered by
|
|
17
|
+
Specra" watermark in a visible location (footer or equivalent) on every
|
|
18
|
+
public-facing page.
|
|
19
|
+
|
|
20
|
+
The watermark MUST NOT be removed, hidden, obscured, or made invisible
|
|
21
|
+
unless the user holds an active paid subscription (Starter tier or above)
|
|
22
|
+
on the Specra platform (https://specra-docs.com).
|
|
23
|
+
|
|
24
|
+
Removal, hiding, or circumvention of the watermark without a valid paid
|
|
25
|
+
subscription constitutes a COPYRIGHT VIOLATION and a breach of this license.
|
|
14
26
|
|
|
15
27
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
28
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
package/README.md
CHANGED
|
@@ -40,7 +40,7 @@ npx create-specra [project-directory] [options]
|
|
|
40
40
|
|
|
41
41
|
### Options
|
|
42
42
|
|
|
43
|
-
- `--template <template>` - Template to use: `minimal` (will prompt if not provided)
|
|
43
|
+
- `--template <template>` - Template to use: `minimal`, `book-docs`, `jbrains-docs` (will prompt if not provided)
|
|
44
44
|
- `--use-npm` - Use npm as the package manager
|
|
45
45
|
- `--use-pnpm` - Use pnpm as the package manager
|
|
46
46
|
- `--use-yarn` - Use yarn as the package manager
|
|
@@ -56,6 +56,25 @@ Minimal setup to get started quickly:
|
|
|
56
56
|
- Clean starting point
|
|
57
57
|
- Ready to customize
|
|
58
58
|
|
|
59
|
+
### Book Docs
|
|
60
|
+
|
|
61
|
+
Knowledge base style inspired by popular docs platforms:
|
|
62
|
+
- Dark theme by default
|
|
63
|
+
- Categorized sidebar with section headers (Content, Customization)
|
|
64
|
+
- Site-wide banner
|
|
65
|
+
- Flush sidebar layout (attached to screen edge)
|
|
66
|
+
- Version badge in sidebar
|
|
67
|
+
|
|
68
|
+
### JBrains Docs
|
|
69
|
+
|
|
70
|
+
Reference documentation style with tabbed navigation:
|
|
71
|
+
- Light theme by default
|
|
72
|
+
- Tab groups for organizing content (Language, Multiplatform)
|
|
73
|
+
- Collapsible tree-style sidebar
|
|
74
|
+
- No table of contents (right panel)
|
|
75
|
+
- Flush sidebar layout
|
|
76
|
+
- Version badge in sidebar
|
|
77
|
+
|
|
59
78
|
## Examples
|
|
60
79
|
|
|
61
80
|
Create a new project with interactive prompts:
|
|
@@ -70,6 +89,12 @@ Create a project with the minimal template using npm:
|
|
|
70
89
|
npx create-specra my-docs --template minimal --use-npm
|
|
71
90
|
```
|
|
72
91
|
|
|
92
|
+
Create a project with the book-docs template:
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
npx create-specra my-docs --template book-docs
|
|
96
|
+
```
|
|
97
|
+
|
|
73
98
|
Create a project and skip installation:
|
|
74
99
|
|
|
75
100
|
```bash
|
|
@@ -78,22 +103,29 @@ npx create-specra my-docs --skip-install
|
|
|
78
103
|
|
|
79
104
|
## What's Created
|
|
80
105
|
|
|
81
|
-
The CLI creates a new
|
|
106
|
+
The CLI creates a new SvelteKit project with Specra pre-configured:
|
|
82
107
|
|
|
83
108
|
```
|
|
84
109
|
my-docs/
|
|
85
|
-
├──
|
|
86
|
-
│ ├──
|
|
87
|
-
│ ├──
|
|
88
|
-
│ └──
|
|
89
|
-
│
|
|
110
|
+
├── src/
|
|
111
|
+
│ ├── app.css
|
|
112
|
+
│ ├── app.html
|
|
113
|
+
│ └── routes/
|
|
114
|
+
│ ├── +layout.server.ts
|
|
115
|
+
│ ├── +layout.svelte
|
|
116
|
+
│ ├── +page.server.ts
|
|
117
|
+
│ └── docs/
|
|
118
|
+
│ └── [version]/
|
|
119
|
+
│ └── [...slug]/
|
|
120
|
+
│ ├── +page.server.ts
|
|
121
|
+
│ └── +page.svelte
|
|
90
122
|
├── docs/
|
|
91
|
-
│
|
|
92
|
-
│
|
|
123
|
+
│ ├── v1.0.0/
|
|
124
|
+
│ └── v2.0.0/
|
|
93
125
|
├── public/
|
|
94
|
-
├── specra.config.
|
|
95
|
-
├──
|
|
96
|
-
├──
|
|
126
|
+
├── specra.config.json
|
|
127
|
+
├── svelte.config.js
|
|
128
|
+
├── vite.config.ts
|
|
97
129
|
└── package.json
|
|
98
130
|
```
|
|
99
131
|
|
|
@@ -107,30 +139,34 @@ Once your project is created, you can:
|
|
|
107
139
|
npm run dev
|
|
108
140
|
```
|
|
109
141
|
|
|
110
|
-
2. Open [http://localhost:
|
|
142
|
+
2. Open [http://localhost:5173](http://localhost:5173) in your browser
|
|
111
143
|
|
|
112
144
|
3. Edit your documentation in the `docs/` directory
|
|
113
145
|
|
|
114
|
-
4. Customize your site in `specra.config.
|
|
146
|
+
4. Customize your site in `specra.config.json`
|
|
115
147
|
|
|
116
148
|
## What is Specra?
|
|
117
149
|
|
|
118
|
-
Specra is a modern documentation library for
|
|
150
|
+
Specra is a modern documentation library for SvelteKit that provides:
|
|
119
151
|
- Multi-version documentation support
|
|
120
152
|
- API reference generation
|
|
121
153
|
- Full-text search
|
|
122
154
|
- MDX-powered content
|
|
123
155
|
- Beautiful UI components
|
|
124
156
|
|
|
157
|
+
The official Specra site ([specra-docs](https://specra-docs.com)) also offers a SaaS platform with paid tiers (Starter, Pro, Enterprise) including authentication, Stripe/M-Pesa billing, and a user dashboard. The CLI scaffolds free, self-hosted documentation sites — no billing features are included in generated projects.
|
|
158
|
+
|
|
125
159
|
## Learn More
|
|
126
160
|
|
|
127
161
|
- [Specra on npm](https://www.npmjs.com/package/specra)
|
|
128
|
-
- [
|
|
162
|
+
- [SvelteKit Documentation](https://svelte.dev/docs/kit)
|
|
129
163
|
- [MDX Documentation](https://mdxjs.com)
|
|
130
164
|
|
|
131
165
|
## License
|
|
132
166
|
|
|
133
|
-
MIT
|
|
167
|
+
MIT with Branding Requirement — see [LICENSE.MD](LICENSE.MD).
|
|
168
|
+
|
|
169
|
+
All documentation sites generated with create-specra display a "Powered by Specra" watermark by default. Removing the watermark requires an active paid subscription (Starter tier or above) at [specra-docs.com](https://specra-docs.com). Unauthorized removal is a copyright violation.
|
|
134
170
|
|
|
135
171
|
## Authors
|
|
136
172
|
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/config.ts
|
|
4
|
+
import { readFileSync, writeFileSync, mkdirSync, existsSync, unlinkSync } from "fs";
|
|
5
|
+
import { join } from "path";
|
|
6
|
+
import { homedir } from "os";
|
|
7
|
+
var CONFIG_DIR = join(homedir(), ".specra");
|
|
8
|
+
var CONFIG_FILE = join(CONFIG_DIR, "config.json");
|
|
9
|
+
var DEFAULT_CONFIG = {
|
|
10
|
+
apiUrl: "https://specra.dev"
|
|
11
|
+
};
|
|
12
|
+
function getConfig() {
|
|
13
|
+
try {
|
|
14
|
+
const raw = readFileSync(CONFIG_FILE, "utf-8");
|
|
15
|
+
return { ...DEFAULT_CONFIG, ...JSON.parse(raw) };
|
|
16
|
+
} catch {
|
|
17
|
+
return DEFAULT_CONFIG;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
function saveConfig(config) {
|
|
21
|
+
mkdirSync(CONFIG_DIR, { recursive: true });
|
|
22
|
+
const current = getConfig();
|
|
23
|
+
const merged = { ...current, ...config };
|
|
24
|
+
writeFileSync(CONFIG_FILE, JSON.stringify(merged, null, 2));
|
|
25
|
+
}
|
|
26
|
+
function clearConfig() {
|
|
27
|
+
if (existsSync(CONFIG_FILE)) {
|
|
28
|
+
unlinkSync(CONFIG_FILE);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
function getToken() {
|
|
32
|
+
return getConfig().token;
|
|
33
|
+
}
|
|
34
|
+
function isAuthenticated() {
|
|
35
|
+
return !!getToken();
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export {
|
|
39
|
+
getConfig,
|
|
40
|
+
saveConfig,
|
|
41
|
+
clearConfig,
|
|
42
|
+
getToken,
|
|
43
|
+
isAuthenticated
|
|
44
|
+
};
|
|
45
|
+
//# sourceMappingURL=chunk-3DKWECRK.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/config.ts"],"sourcesContent":["import { readFileSync, writeFileSync, mkdirSync, existsSync, unlinkSync } from 'fs'\nimport { join } from 'path'\nimport { homedir } from 'os'\n\nconst CONFIG_DIR = join(homedir(), '.specra')\nconst CONFIG_FILE = join(CONFIG_DIR, 'config.json')\n\ninterface SpecraConfig {\n apiUrl: string\n token?: string\n defaultProject?: string\n}\n\nconst DEFAULT_CONFIG: SpecraConfig = {\n apiUrl: 'https://specra.dev',\n}\n\nexport function getConfig(): SpecraConfig {\n try {\n const raw = readFileSync(CONFIG_FILE, 'utf-8')\n return { ...DEFAULT_CONFIG, ...JSON.parse(raw) }\n } catch {\n return DEFAULT_CONFIG\n }\n}\n\nexport function saveConfig(config: Partial<SpecraConfig>) {\n mkdirSync(CONFIG_DIR, { recursive: true })\n const current = getConfig()\n const merged = { ...current, ...config }\n writeFileSync(CONFIG_FILE, JSON.stringify(merged, null, 2))\n}\n\nexport function clearConfig() {\n if (existsSync(CONFIG_FILE)) {\n unlinkSync(CONFIG_FILE)\n }\n}\n\nexport function getToken(): string | undefined {\n return getConfig().token\n}\n\nexport function isAuthenticated(): boolean {\n return !!getToken()\n}\n"],"mappings":";;;AAAA,SAAS,cAAc,eAAe,WAAW,YAAY,kBAAkB;AAC/E,SAAS,YAAY;AACrB,SAAS,eAAe;AAExB,IAAM,aAAa,KAAK,QAAQ,GAAG,SAAS;AAC5C,IAAM,cAAc,KAAK,YAAY,aAAa;AAQlD,IAAM,iBAA+B;AAAA,EACnC,QAAQ;AACV;AAEO,SAAS,YAA0B;AACxC,MAAI;AACF,UAAM,MAAM,aAAa,aAAa,OAAO;AAC7C,WAAO,EAAE,GAAG,gBAAgB,GAAG,KAAK,MAAM,GAAG,EAAE;AAAA,EACjD,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEO,SAAS,WAAW,QAA+B;AACxD,YAAU,YAAY,EAAE,WAAW,KAAK,CAAC;AACzC,QAAM,UAAU,UAAU;AAC1B,QAAM,SAAS,EAAE,GAAG,SAAS,GAAG,OAAO;AACvC,gBAAc,aAAa,KAAK,UAAU,QAAQ,MAAM,CAAC,CAAC;AAC5D;AAEO,SAAS,cAAc;AAC5B,MAAI,WAAW,WAAW,GAAG;AAC3B,eAAW,WAAW;AAAA,EACxB;AACF;AAEO,SAAS,WAA+B;AAC7C,SAAO,UAAU,EAAE;AACrB;AAEO,SAAS,kBAA2B;AACzC,SAAO,CAAC,CAAC,SAAS;AACpB;","names":[]}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
getConfig,
|
|
4
|
+
getToken
|
|
5
|
+
} from "./chunk-3DKWECRK.js";
|
|
6
|
+
|
|
7
|
+
// src/api-client.ts
|
|
8
|
+
var ApiError = class extends Error {
|
|
9
|
+
constructor(status, message) {
|
|
10
|
+
super(message);
|
|
11
|
+
this.status = status;
|
|
12
|
+
this.name = "ApiError";
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
async function apiRequest(path, options = {}) {
|
|
16
|
+
const config = getConfig();
|
|
17
|
+
const token = getToken();
|
|
18
|
+
if (!token) {
|
|
19
|
+
throw new Error("Not authenticated. Run `specra login` first.");
|
|
20
|
+
}
|
|
21
|
+
const url = `${config.apiUrl}${path}`;
|
|
22
|
+
const res = await fetch(url, {
|
|
23
|
+
...options,
|
|
24
|
+
headers: {
|
|
25
|
+
Authorization: `Bearer ${token}`,
|
|
26
|
+
...options.headers
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
if (!res.ok) {
|
|
30
|
+
let message;
|
|
31
|
+
try {
|
|
32
|
+
const data = await res.json();
|
|
33
|
+
message = data.error || res.statusText;
|
|
34
|
+
} catch {
|
|
35
|
+
message = res.statusText;
|
|
36
|
+
}
|
|
37
|
+
throw new ApiError(res.status, message);
|
|
38
|
+
}
|
|
39
|
+
return res.json();
|
|
40
|
+
}
|
|
41
|
+
async function apiUpload(path, body, headers = {}) {
|
|
42
|
+
const config = getConfig();
|
|
43
|
+
const token = getToken();
|
|
44
|
+
if (!token) {
|
|
45
|
+
throw new Error("Not authenticated. Run `specra login` first.");
|
|
46
|
+
}
|
|
47
|
+
const url = `${config.apiUrl}${path}`;
|
|
48
|
+
const res = await fetch(url, {
|
|
49
|
+
method: "POST",
|
|
50
|
+
headers: {
|
|
51
|
+
Authorization: `Bearer ${token}`,
|
|
52
|
+
"Content-Type": "application/octet-stream",
|
|
53
|
+
...headers
|
|
54
|
+
},
|
|
55
|
+
body
|
|
56
|
+
});
|
|
57
|
+
if (!res.ok) {
|
|
58
|
+
let message;
|
|
59
|
+
try {
|
|
60
|
+
const data = await res.json();
|
|
61
|
+
message = data.error || res.statusText;
|
|
62
|
+
} catch {
|
|
63
|
+
message = res.statusText;
|
|
64
|
+
}
|
|
65
|
+
throw new ApiError(res.status, message);
|
|
66
|
+
}
|
|
67
|
+
return res.json();
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export {
|
|
71
|
+
apiRequest,
|
|
72
|
+
apiUpload
|
|
73
|
+
};
|
|
74
|
+
//# sourceMappingURL=chunk-MA7QG54W.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/api-client.ts"],"sourcesContent":["import { getConfig, getToken } from './config.js'\n\nclass ApiError extends Error {\n constructor(public status: number, message: string) {\n super(message)\n this.name = 'ApiError'\n }\n}\n\nexport async function apiRequest<T = unknown>(\n path: string,\n options: RequestInit = {}\n): Promise<T> {\n const config = getConfig()\n const token = getToken()\n\n if (!token) {\n throw new Error('Not authenticated. Run `specra login` first.')\n }\n\n const url = `${config.apiUrl}${path}`\n const res = await fetch(url, {\n ...options,\n headers: {\n Authorization: `Bearer ${token}`,\n ...options.headers,\n },\n })\n\n if (!res.ok) {\n let message: string\n try {\n const data = (await res.json()) as Record<string, string>\n message = data.error || res.statusText\n } catch {\n message = res.statusText\n }\n throw new ApiError(res.status, message)\n }\n\n return res.json() as Promise<T>\n}\n\nexport async function apiUpload(\n path: string,\n body: Buffer | ReadableStream,\n headers: Record<string, string> = {}\n): Promise<unknown> {\n const config = getConfig()\n const token = getToken()\n\n if (!token) {\n throw new Error('Not authenticated. Run `specra login` first.')\n }\n\n const url = `${config.apiUrl}${path}`\n const res = await fetch(url, {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${token}`,\n 'Content-Type': 'application/octet-stream',\n ...headers,\n },\n body,\n })\n\n if (!res.ok) {\n let message: string\n try {\n const data = (await res.json()) as Record<string, string>\n message = data.error || res.statusText\n } catch {\n message = res.statusText\n }\n throw new ApiError(res.status, message)\n }\n\n return res.json()\n}\n"],"mappings":";;;;;;;AAEA,IAAM,WAAN,cAAuB,MAAM;AAAA,EAC3B,YAAmB,QAAgB,SAAiB;AAClD,UAAM,OAAO;AADI;AAEjB,SAAK,OAAO;AAAA,EACd;AACF;AAEA,eAAsB,WACpB,MACA,UAAuB,CAAC,GACZ;AACZ,QAAM,SAAS,UAAU;AACzB,QAAM,QAAQ,SAAS;AAEvB,MAAI,CAAC,OAAO;AACV,UAAM,IAAI,MAAM,8CAA8C;AAAA,EAChE;AAEA,QAAM,MAAM,GAAG,OAAO,MAAM,GAAG,IAAI;AACnC,QAAM,MAAM,MAAM,MAAM,KAAK;AAAA,IAC3B,GAAG;AAAA,IACH,SAAS;AAAA,MACP,eAAe,UAAU,KAAK;AAAA,MAC9B,GAAG,QAAQ;AAAA,IACb;AAAA,EACF,CAAC;AAED,MAAI,CAAC,IAAI,IAAI;AACX,QAAI;AACJ,QAAI;AACF,YAAM,OAAQ,MAAM,IAAI,KAAK;AAC7B,gBAAU,KAAK,SAAS,IAAI;AAAA,IAC9B,QAAQ;AACN,gBAAU,IAAI;AAAA,IAChB;AACA,UAAM,IAAI,SAAS,IAAI,QAAQ,OAAO;AAAA,EACxC;AAEA,SAAO,IAAI,KAAK;AAClB;AAEA,eAAsB,UACpB,MACA,MACA,UAAkC,CAAC,GACjB;AAClB,QAAM,SAAS,UAAU;AACzB,QAAM,QAAQ,SAAS;AAEvB,MAAI,CAAC,OAAO;AACV,UAAM,IAAI,MAAM,8CAA8C;AAAA,EAChE;AAEA,QAAM,MAAM,GAAG,OAAO,MAAM,GAAG,IAAI;AACnC,QAAM,MAAM,MAAM,MAAM,KAAK;AAAA,IAC3B,QAAQ;AAAA,IACR,SAAS;AAAA,MACP,eAAe,UAAU,KAAK;AAAA,MAC9B,gBAAgB;AAAA,MAChB,GAAG;AAAA,IACL;AAAA,IACA;AAAA,EACF,CAAC;AAED,MAAI,CAAC,IAAI,IAAI;AACX,QAAI;AACJ,QAAI;AACF,YAAM,OAAQ,MAAM,IAAI,KAAK;AAC7B,gBAAU,KAAK,SAAS,IAAI;AAAA,IAC9B,QAAQ;AACN,gBAAU,IAAI;AAAA,IAChB;AACA,UAAM,IAAI,SAAS,IAAI,QAAQ,OAAO;AAAA,EACxC;AAEA,SAAO,IAAI,KAAK;AAClB;","names":[]}
|
package/dist/cli.d.ts
ADDED
package/dist/cli.js
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/cli.ts
|
|
4
|
+
import { Command } from "commander";
|
|
5
|
+
import pc from "picocolors";
|
|
6
|
+
var program = new Command();
|
|
7
|
+
program.name("specra").description("Specra CLI - Deploy and manage your documentation sites").version("0.1.0");
|
|
8
|
+
program.command("login").description("Authenticate with your Specra account").action(async () => {
|
|
9
|
+
const { login } = await import("./login-NKDRQXRE.js");
|
|
10
|
+
await login();
|
|
11
|
+
});
|
|
12
|
+
program.command("logout").description("Clear stored credentials").action(async () => {
|
|
13
|
+
const { logout } = await import("./logout-H543QEKU.js");
|
|
14
|
+
await logout();
|
|
15
|
+
});
|
|
16
|
+
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) => {
|
|
17
|
+
const { deploy } = await import("./deploy-SCEMUQNS.js");
|
|
18
|
+
await deploy(options);
|
|
19
|
+
});
|
|
20
|
+
program.command("projects").description("List your projects").action(async () => {
|
|
21
|
+
const { projects } = await import("./projects-3TAY7EDJ.js");
|
|
22
|
+
await projects();
|
|
23
|
+
});
|
|
24
|
+
program.command("logs").description("View deployment logs").argument("<projectId>", "Project ID").option("--deployment <id>", "Specific deployment ID").action(async (projectId, options) => {
|
|
25
|
+
const { logs } = await import("./logs-YDAUCMAV.js");
|
|
26
|
+
await logs(projectId, options);
|
|
27
|
+
});
|
|
28
|
+
program.parse();
|
|
29
|
+
process.on("unhandledRejection", (err) => {
|
|
30
|
+
console.error(pc.red("Error:"), err);
|
|
31
|
+
process.exit(1);
|
|
32
|
+
});
|
|
33
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts"],"sourcesContent":["import { Command } from 'commander'\nimport pc from 'picocolors'\n\nconst program = new Command()\n\nprogram\n .name('specra')\n .description('Specra CLI - Deploy and manage your documentation sites')\n .version('0.1.0')\n\nprogram\n .command('login')\n .description('Authenticate with your Specra account')\n .action(async () => {\n const { login } = await import('./commands/login.js')\n await login()\n })\n\nprogram\n .command('logout')\n .description('Clear stored credentials')\n .action(async () => {\n const { logout } = await import('./commands/logout.js')\n await logout()\n })\n\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\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\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\nprogram.parse()\n\n// Handle unhandled rejections\nprocess.on('unhandledRejection', (err) => {\n console.error(pc.red('Error:'), err)\n process.exit(1)\n})\n"],"mappings":";;;AAAA,SAAS,eAAe;AACxB,OAAO,QAAQ;AAEf,IAAM,UAAU,IAAI,QAAQ;AAE5B,QACG,KAAK,QAAQ,EACb,YAAY,yDAAyD,EACrE,QAAQ,OAAO;AAElB,QACG,QAAQ,OAAO,EACf,YAAY,uCAAuC,EACnD,OAAO,YAAY;AAClB,QAAM,EAAE,MAAM,IAAI,MAAM,OAAO,qBAAqB;AACpD,QAAM,MAAM;AACd,CAAC;AAEH,QACG,QAAQ,QAAQ,EAChB,YAAY,0BAA0B,EACtC,OAAO,YAAY;AAClB,QAAM,EAAE,OAAO,IAAI,MAAM,OAAO,sBAAsB;AACtD,QAAM,OAAO;AACf,CAAC;AAEH,QACG,QAAQ,QAAQ,EAChB,YAAY,0BAA0B,EACtC,OAAO,sBAAsB,yBAAyB,EACtD,OAAO,yBAAyB,4BAA4B,GAAG,EAC/D,OAAO,OAAO,YAAY;AACzB,QAAM,EAAE,OAAO,IAAI,MAAM,OAAO,sBAAsB;AACtD,QAAM,OAAO,OAAO;AACtB,CAAC;AAEH,QACG,QAAQ,UAAU,EAClB,YAAY,oBAAoB,EAChC,OAAO,YAAY;AAClB,QAAM,EAAE,SAAS,IAAI,MAAM,OAAO,wBAAwB;AAC1D,QAAM,SAAS;AACjB,CAAC;AAEH,QACG,QAAQ,MAAM,EACd,YAAY,sBAAsB,EAClC,SAAS,eAAe,YAAY,EACpC,OAAO,qBAAqB,wBAAwB,EACpD,OAAO,OAAO,WAAmB,YAAY;AAC5C,QAAM,EAAE,KAAK,IAAI,MAAM,OAAO,oBAAoB;AAClD,QAAM,KAAK,WAAW,OAAO;AAC/B,CAAC;AAEH,QAAQ,MAAM;AAGd,QAAQ,GAAG,sBAAsB,CAAC,QAAQ;AACxC,UAAQ,MAAM,GAAG,IAAI,QAAQ,GAAG,GAAG;AACnC,UAAQ,KAAK,CAAC;AAChB,CAAC;","names":[]}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
apiRequest,
|
|
4
|
+
apiUpload
|
|
5
|
+
} from "./chunk-MA7QG54W.js";
|
|
6
|
+
import {
|
|
7
|
+
getConfig,
|
|
8
|
+
isAuthenticated
|
|
9
|
+
} from "./chunk-3DKWECRK.js";
|
|
10
|
+
|
|
11
|
+
// src/commands/deploy.ts
|
|
12
|
+
import pc from "picocolors";
|
|
13
|
+
import ora from "ora";
|
|
14
|
+
|
|
15
|
+
// src/archive.ts
|
|
16
|
+
import * as tar from "tar";
|
|
17
|
+
import { existsSync, statSync } from "fs";
|
|
18
|
+
import { join, resolve } from "path";
|
|
19
|
+
async function createArchive(dir) {
|
|
20
|
+
const absDir = resolve(dir);
|
|
21
|
+
if (!existsSync(absDir)) {
|
|
22
|
+
throw new Error(`Directory not found: ${absDir}`);
|
|
23
|
+
}
|
|
24
|
+
if (!statSync(absDir).isDirectory()) {
|
|
25
|
+
throw new Error(`Not a directory: ${absDir}`);
|
|
26
|
+
}
|
|
27
|
+
const hasPackageJson = existsSync(join(absDir, "package.json"));
|
|
28
|
+
const hasDocsDir = existsSync(join(absDir, "docs"));
|
|
29
|
+
const hasSpecraConfig = existsSync(join(absDir, "specra.config.json"));
|
|
30
|
+
if (!hasPackageJson && !hasDocsDir && !hasSpecraConfig) {
|
|
31
|
+
throw new Error(
|
|
32
|
+
"No Specra project found. Ensure the directory contains package.json, docs/, or specra.config.json"
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
const chunks = [];
|
|
36
|
+
await tar.create(
|
|
37
|
+
{
|
|
38
|
+
gzip: true,
|
|
39
|
+
cwd: absDir,
|
|
40
|
+
filter: (path) => {
|
|
41
|
+
if (path.includes("node_modules/")) return false;
|
|
42
|
+
if (path.includes(".next/")) return false;
|
|
43
|
+
if (path.includes(".git/")) return false;
|
|
44
|
+
if (path.includes(".env")) return false;
|
|
45
|
+
return true;
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
["."]
|
|
49
|
+
).on("data", (chunk) => {
|
|
50
|
+
chunks.push(chunk);
|
|
51
|
+
});
|
|
52
|
+
return Buffer.concat(chunks);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// src/commands/deploy.ts
|
|
56
|
+
import { existsSync as existsSync2, readFileSync } from "fs";
|
|
57
|
+
import { join as join2, resolve as resolve2 } from "path";
|
|
58
|
+
async function deploy(options) {
|
|
59
|
+
if (!isAuthenticated()) {
|
|
60
|
+
console.error(pc.red("Not authenticated. Run `specra login` first."));
|
|
61
|
+
process.exit(1);
|
|
62
|
+
}
|
|
63
|
+
const dir = resolve2(options.dir);
|
|
64
|
+
let projectId = options.project;
|
|
65
|
+
if (!projectId) {
|
|
66
|
+
const configPath = join2(dir, "specra.config.json");
|
|
67
|
+
if (existsSync2(configPath)) {
|
|
68
|
+
try {
|
|
69
|
+
const config = JSON.parse(readFileSync(configPath, "utf-8"));
|
|
70
|
+
projectId = config.projectId;
|
|
71
|
+
} catch {
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
if (!projectId) {
|
|
76
|
+
const projects = await apiRequest(
|
|
77
|
+
"/api/projects"
|
|
78
|
+
);
|
|
79
|
+
if (projects.length === 0) {
|
|
80
|
+
console.error(
|
|
81
|
+
pc.red("No projects found. Create one at https://specra.dev/dashboard/projects/new")
|
|
82
|
+
);
|
|
83
|
+
process.exit(1);
|
|
84
|
+
}
|
|
85
|
+
console.log(pc.bold("Select a project to deploy to:"));
|
|
86
|
+
projects.forEach((p, i) => {
|
|
87
|
+
console.log(` ${pc.dim(`${i + 1}.`)} ${p.name} ${pc.dim(`(${p.subdomain}.docs.specra.dev)`)}`);
|
|
88
|
+
});
|
|
89
|
+
const prompts = await import("prompts");
|
|
90
|
+
const response = await prompts.default({
|
|
91
|
+
type: "select",
|
|
92
|
+
name: "project",
|
|
93
|
+
message: "Project",
|
|
94
|
+
choices: projects.map((p) => ({
|
|
95
|
+
title: p.name,
|
|
96
|
+
value: p.id,
|
|
97
|
+
description: `${p.subdomain}.docs.specra.dev`
|
|
98
|
+
}))
|
|
99
|
+
});
|
|
100
|
+
if (!response.project) {
|
|
101
|
+
console.log("Aborted.");
|
|
102
|
+
process.exit(1);
|
|
103
|
+
}
|
|
104
|
+
projectId = response.project;
|
|
105
|
+
}
|
|
106
|
+
const spinner = ora("Packaging docs...").start();
|
|
107
|
+
try {
|
|
108
|
+
const archive = await createArchive(dir);
|
|
109
|
+
spinner.text = `Uploading (${(archive.length / 1024).toFixed(0)}KB)...`;
|
|
110
|
+
let commitSha;
|
|
111
|
+
try {
|
|
112
|
+
const { execSync } = await import("child_process");
|
|
113
|
+
commitSha = execSync("git rev-parse HEAD", { cwd: dir }).toString().trim();
|
|
114
|
+
} catch {
|
|
115
|
+
}
|
|
116
|
+
const result = await apiUpload(
|
|
117
|
+
`/api/projects/${projectId}/deploy`,
|
|
118
|
+
archive,
|
|
119
|
+
{
|
|
120
|
+
"X-Deploy-Trigger": "CLI",
|
|
121
|
+
...commitSha ? { "X-Commit-Sha": commitSha } : {}
|
|
122
|
+
}
|
|
123
|
+
);
|
|
124
|
+
spinner.succeed(pc.green("Deployment triggered!"));
|
|
125
|
+
console.log();
|
|
126
|
+
console.log(` Deployment ID: ${pc.cyan(result.deploymentId)}`);
|
|
127
|
+
const config = getConfig();
|
|
128
|
+
console.log(
|
|
129
|
+
` View status: ${pc.dim(`${config.apiUrl}/dashboard/projects/${projectId}/deployments`)}`
|
|
130
|
+
);
|
|
131
|
+
console.log();
|
|
132
|
+
} catch (err) {
|
|
133
|
+
spinner.fail(pc.red("Deploy failed"));
|
|
134
|
+
console.error(err instanceof Error ? err.message : err);
|
|
135
|
+
process.exit(1);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
export {
|
|
139
|
+
deploy
|
|
140
|
+
};
|
|
141
|
+
//# sourceMappingURL=deploy-SCEMUQNS.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/deploy.ts","../src/archive.ts"],"sourcesContent":["import pc from 'picocolors'\nimport ora from 'ora'\nimport { createArchive } from '../archive.js'\nimport { apiUpload, apiRequest } from '../api-client.js'\nimport { isAuthenticated, getConfig } from '../config.js'\nimport { existsSync, readFileSync } from 'fs'\nimport { join, resolve } from 'path'\n\ninterface DeployOptions {\n project?: string\n dir: string\n}\n\nexport async function deploy(options: DeployOptions) {\n if (!isAuthenticated()) {\n console.error(pc.red('Not authenticated. Run `specra login` first.'))\n process.exit(1)\n }\n\n const dir = resolve(options.dir)\n let projectId = options.project\n\n // If no project specified, try to read from specra.config.json\n if (!projectId) {\n const configPath = join(dir, 'specra.config.json')\n if (existsSync(configPath)) {\n try {\n const config = JSON.parse(readFileSync(configPath, 'utf-8'))\n projectId = config.projectId\n } catch {\n // ignore\n }\n }\n }\n\n if (!projectId) {\n // List projects and ask user to pick\n const projects = await apiRequest<Array<{ id: string; name: string; subdomain: string }>>(\n '/api/projects'\n )\n\n if (projects.length === 0) {\n console.error(\n pc.red('No projects found. Create one at https://specra.dev/dashboard/projects/new')\n )\n process.exit(1)\n }\n\n console.log(pc.bold('Select a project to deploy to:'))\n projects.forEach((p, i) => {\n console.log(` ${pc.dim(`${i + 1}.`)} ${p.name} ${pc.dim(`(${p.subdomain}.docs.specra.dev)`)}`)\n })\n\n const prompts = await import('prompts')\n const response = await prompts.default({\n type: 'select',\n name: 'project',\n message: 'Project',\n choices: projects.map((p) => ({\n title: p.name,\n value: p.id,\n description: `${p.subdomain}.docs.specra.dev`,\n })),\n })\n\n if (!response.project) {\n console.log('Aborted.')\n process.exit(1)\n }\n\n projectId = response.project\n }\n\n // Create archive\n const spinner = ora('Packaging docs...').start()\n\n try {\n const archive = await createArchive(dir)\n spinner.text = `Uploading (${(archive.length / 1024).toFixed(0)}KB)...`\n\n // Get git commit SHA if available\n let commitSha: string | undefined\n try {\n const { execSync } = await import('child_process')\n commitSha = execSync('git rev-parse HEAD', { cwd: dir })\n .toString()\n .trim()\n } catch {\n // not a git repo\n }\n\n const result = await apiUpload(\n `/api/projects/${projectId}/deploy`,\n archive,\n {\n 'X-Deploy-Trigger': 'CLI',\n ...(commitSha ? { 'X-Commit-Sha': commitSha } : {}),\n }\n ) as { deploymentId: string }\n\n spinner.succeed(pc.green('Deployment triggered!'))\n console.log()\n console.log(` Deployment ID: ${pc.cyan(result.deploymentId)}`)\n\n const config = getConfig()\n console.log(\n ` View status: ${pc.dim(`${config.apiUrl}/dashboard/projects/${projectId}/deployments`)}`\n )\n console.log()\n } catch (err) {\n spinner.fail(pc.red('Deploy failed'))\n console.error(err instanceof Error ? err.message : err)\n process.exit(1)\n }\n}\n","import * as tar from 'tar'\nimport { existsSync, statSync } from 'fs'\nimport { join, resolve } from 'path'\n\nexport async function createArchive(dir: string): Promise<Buffer> {\n const absDir = resolve(dir)\n\n if (!existsSync(absDir)) {\n throw new Error(`Directory not found: ${absDir}`)\n }\n\n if (!statSync(absDir).isDirectory()) {\n throw new Error(`Not a directory: ${absDir}`)\n }\n\n // Check for docs content - look for common indicators\n const hasPackageJson = existsSync(join(absDir, 'package.json'))\n const hasDocsDir = existsSync(join(absDir, 'docs'))\n const hasSpecraConfig = existsSync(join(absDir, 'specra.config.json'))\n\n if (!hasPackageJson && !hasDocsDir && !hasSpecraConfig) {\n throw new Error(\n 'No Specra project found. Ensure the directory contains package.json, docs/, or specra.config.json'\n )\n }\n\n // Build the file list — include relevant files, exclude node_modules/.next/.git\n const chunks: Buffer[] = []\n\n await tar.create(\n {\n gzip: true,\n cwd: absDir,\n filter: (path: string) => {\n if (path.includes('node_modules/')) return false\n if (path.includes('.next/')) return false\n if (path.includes('.git/')) return false\n if (path.includes('.env')) return false\n return true\n },\n },\n ['.']\n ).on('data', (chunk: Buffer) => {\n chunks.push(chunk)\n })\n\n // Wait for stream to finish\n return Buffer.concat(chunks)\n}\n"],"mappings":"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","names":["existsSync","join","resolve"]}
|
package/dist/index.js
CHANGED
|
@@ -179,7 +179,7 @@ async function createProject({
|
|
|
179
179
|
// src/index.ts
|
|
180
180
|
import pc2 from "picocolors";
|
|
181
181
|
var program = new Command();
|
|
182
|
-
program.name("create-specra").description("Create a new Specra documentation site").argument("[project-directory]", "Directory to create the project in").option("--template <template>", "Template to use (
|
|
182
|
+
program.name("create-specra").description("Create a new Specra documentation site").argument("[project-directory]", "Directory to create the project in").option("--template <template>", "Template to use (minimal, book-docs, jbrains-docs)").option("--use-npm", "Use npm as the package manager").option("--use-pnpm", "Use pnpm as the package manager").option("--use-yarn", "Use yarn as the package manager").option("--skip-install", "Skip package installation").action(async (projectDirectory, options) => {
|
|
183
183
|
console.log();
|
|
184
184
|
console.log(pc2.bold(pc2.cyan("Create Specra Documentation Site")));
|
|
185
185
|
console.log();
|
|
@@ -227,21 +227,21 @@ program.name("create-specra").description("Create a new Specra documentation sit
|
|
|
227
227
|
name: "template",
|
|
228
228
|
message: "Which template would you like to use?",
|
|
229
229
|
choices: [
|
|
230
|
-
// {
|
|
231
|
-
// title: 'Default',
|
|
232
|
-
// value: 'default',
|
|
233
|
-
// description: 'Full-featured documentation site with examples',
|
|
234
|
-
// },
|
|
235
230
|
{
|
|
236
231
|
title: "Minimal",
|
|
237
232
|
value: "minimal",
|
|
238
233
|
description: "Minimal setup to get started quickly"
|
|
234
|
+
},
|
|
235
|
+
{
|
|
236
|
+
title: "Book Docs",
|
|
237
|
+
value: "book-docs",
|
|
238
|
+
description: "Knowledge base style with dark theme and categorized sidebar"
|
|
239
|
+
},
|
|
240
|
+
{
|
|
241
|
+
title: "JBrains Docs",
|
|
242
|
+
value: "jbrains-docs",
|
|
243
|
+
description: "Reference docs style with light theme and tab groups"
|
|
239
244
|
}
|
|
240
|
-
// {
|
|
241
|
-
// title: 'API-Focused',
|
|
242
|
-
// value: 'api-focused',
|
|
243
|
-
// description: 'Optimized for API documentation',
|
|
244
|
-
// },
|
|
245
245
|
],
|
|
246
246
|
initial: 0
|
|
247
247
|
});
|
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 { createProject } from './create-project.js'\nimport { validateProjectName } from './utils.js'\nimport pc from 'picocolors'\n\nconst program = new Command()\n\nprogram\n .name('create-specra')\n .description('Create a new Specra documentation site')\n .argument('[project-directory]', 'Directory to create the project in')\n .option('--template <template>', 'Template to use (default, minimal, api-focused)')\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 project name\n const validation = validateProjectName(projectName!)\n if (!validation.valid) {\n console.error(\n pc.red(\n `Cannot create a project named ${pc.cyan(\n `\"${projectName}\"`\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: 'Default',\n // value: 'default',\n // description: 'Full-featured documentation site with examples',\n // },\n {\n title: 'Minimal',\n value: 'minimal',\n description: 'Minimal setup to get started quickly',\n },\n // {\n // title: 'API-Focused',\n // value: 'api-focused',\n // description: 'Optimized for API documentation',\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 || 'default',\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\nprogram.parse()\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 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('start')}`))\n console.log(' Runs the built app in production mode.')\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":["fs","path","execSync","path","path","fs","__filename","__dirname","command","execSync","pc","validation"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/create-project.ts","../src/utils.ts"],"sourcesContent":["import { Command } from 'commander'\nimport prompts from 'prompts'\nimport { createProject } from './create-project.js'\nimport { validateProjectName } from './utils.js'\nimport pc from 'picocolors'\n\nconst program = new Command()\n\nprogram\n .name('create-specra')\n .description('Create a new Specra documentation site')\n .argument('[project-directory]', 'Directory to create the project in')\n .option('--template <template>', 'Template to use (minimal, book-docs, jbrains-docs)')\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 project name\n const validation = validateProjectName(projectName!)\n if (!validation.valid) {\n console.error(\n pc.red(\n `Cannot create a project named ${pc.cyan(\n `\"${projectName}\"`\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 || 'default',\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\nprogram.parse()\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 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('start')}`))\n console.log(' Runs the built app in production mode.')\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":["fs","path","execSync","path","path","fs","__filename","__dirname","command","execSync","pc","validation"]}
|