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.
Files changed (136) hide show
  1. package/LICENSE.MD +16 -4
  2. package/README.md +53 -17
  3. package/dist/chunk-3DKWECRK.js +45 -0
  4. package/dist/chunk-3DKWECRK.js.map +1 -0
  5. package/dist/chunk-MA7QG54W.js +74 -0
  6. package/dist/chunk-MA7QG54W.js.map +1 -0
  7. package/dist/cli.d.ts +2 -0
  8. package/dist/cli.js +33 -0
  9. package/dist/cli.js.map +1 -0
  10. package/dist/deploy-SCEMUQNS.js +141 -0
  11. package/dist/deploy-SCEMUQNS.js.map +1 -0
  12. package/dist/index.js +11 -11
  13. package/dist/index.js.map +1 -1
  14. package/dist/login-NKDRQXRE.js +71 -0
  15. package/dist/login-NKDRQXRE.js.map +1 -0
  16. package/dist/logout-H543QEKU.js +20 -0
  17. package/dist/logout-H543QEKU.js.map +1 -0
  18. package/dist/logs-YDAUCMAV.js +71 -0
  19. package/dist/logs-YDAUCMAV.js.map +1 -0
  20. package/dist/projects-3TAY7EDJ.js +42 -0
  21. package/dist/projects-3TAY7EDJ.js.map +1 -0
  22. package/package.json +7 -3
  23. package/templates/book-docs/docs/v1.0.0/concepts.mdx +89 -0
  24. package/templates/book-docs/docs/v1.0.0/content/_category_.json +7 -0
  25. package/templates/book-docs/docs/v1.0.0/content/formatting.mdx +128 -0
  26. package/templates/book-docs/docs/v1.0.0/content/reusable-content.mdx +116 -0
  27. package/templates/book-docs/docs/v1.0.0/content/structure.mdx +92 -0
  28. package/templates/book-docs/docs/v1.0.0/customization/_category_.json +7 -0
  29. package/templates/book-docs/docs/v1.0.0/customization/branding.mdx +115 -0
  30. package/templates/book-docs/docs/v1.0.0/customization/themes.mdx +81 -0
  31. package/templates/book-docs/docs/v1.0.0/introduction.mdx +38 -0
  32. package/templates/book-docs/docs/v1.0.0/quickstart.mdx +112 -0
  33. package/templates/book-docs/docs/v2.0.0/concepts.mdx +89 -0
  34. package/templates/book-docs/docs/v2.0.0/content/_category_.json +7 -0
  35. package/templates/book-docs/docs/v2.0.0/content/formatting.mdx +128 -0
  36. package/templates/book-docs/docs/v2.0.0/content/reusable-content.mdx +116 -0
  37. package/templates/book-docs/docs/v2.0.0/content/structure.mdx +92 -0
  38. package/templates/book-docs/docs/v2.0.0/customization/_category_.json +7 -0
  39. package/templates/book-docs/docs/v2.0.0/customization/branding.mdx +115 -0
  40. package/templates/book-docs/docs/v2.0.0/customization/themes.mdx +81 -0
  41. package/templates/book-docs/docs/v2.0.0/introduction.mdx +39 -0
  42. package/templates/book-docs/docs/v2.0.0/quickstart.mdx +112 -0
  43. package/templates/book-docs/gitignore +7 -0
  44. package/templates/book-docs/package.json +28 -0
  45. package/templates/book-docs/postcss.config.mjs +8 -0
  46. package/templates/book-docs/public/api-specs/openapi-example.json +259 -0
  47. package/templates/book-docs/public/api-specs/postman-example.json +205 -0
  48. package/templates/book-docs/public/api-specs/test-api.json +256 -0
  49. package/templates/book-docs/public/api-specs/users-api.json +264 -0
  50. package/templates/book-docs/specra.config.json +77 -0
  51. package/templates/book-docs/src/app.css +2 -0
  52. package/templates/book-docs/src/app.html +12 -0
  53. package/templates/book-docs/src/routes/+layout.server.ts +11 -0
  54. package/templates/book-docs/src/routes/+layout.svelte +21 -0
  55. package/templates/book-docs/src/routes/+page.server.ts +9 -0
  56. package/templates/book-docs/src/routes/docs/[version]/[...slug]/+page.server.ts +119 -0
  57. package/templates/book-docs/src/routes/docs/[version]/[...slug]/+page.svelte +129 -0
  58. package/templates/book-docs/svelte.config.js +8 -0
  59. package/templates/book-docs/tsconfig.json +12 -0
  60. package/templates/book-docs/vite.config.ts +6 -0
  61. package/templates/jbrains-docs/docs/v1.0.0/advanced/_category_.json +8 -0
  62. package/templates/jbrains-docs/docs/v1.0.0/advanced/async.mdx +95 -0
  63. package/templates/jbrains-docs/docs/v1.0.0/advanced/generics.mdx +126 -0
  64. package/templates/jbrains-docs/docs/v1.0.0/basics/_category_.json +8 -0
  65. package/templates/jbrains-docs/docs/v1.0.0/basics/control-flow.mdx +106 -0
  66. package/templates/jbrains-docs/docs/v1.0.0/basics/syntax.mdx +129 -0
  67. package/templates/jbrains-docs/docs/v1.0.0/basics/types.mdx +135 -0
  68. package/templates/jbrains-docs/docs/v1.0.0/getting-started.mdx +111 -0
  69. package/templates/jbrains-docs/docs/v1.0.0/home.mdx +37 -0
  70. package/templates/jbrains-docs/docs/v1.0.0/tools/_category_.json +8 -0
  71. package/templates/jbrains-docs/docs/v1.0.0/tools/build-tools.mdx +165 -0
  72. package/templates/jbrains-docs/docs/v1.0.0/tools/testing.mdx +112 -0
  73. package/templates/jbrains-docs/docs/v2.0.0/advanced/_category_.json +8 -0
  74. package/templates/jbrains-docs/docs/v2.0.0/advanced/async.mdx +95 -0
  75. package/templates/jbrains-docs/docs/v2.0.0/advanced/generics.mdx +126 -0
  76. package/templates/jbrains-docs/docs/v2.0.0/basics/_category_.json +8 -0
  77. package/templates/jbrains-docs/docs/v2.0.0/basics/control-flow.mdx +106 -0
  78. package/templates/jbrains-docs/docs/v2.0.0/basics/syntax.mdx +129 -0
  79. package/templates/jbrains-docs/docs/v2.0.0/basics/types.mdx +135 -0
  80. package/templates/jbrains-docs/docs/v2.0.0/getting-started.mdx +111 -0
  81. package/templates/jbrains-docs/docs/v2.0.0/home.mdx +37 -0
  82. package/templates/jbrains-docs/docs/v2.0.0/tools/_category_.json +8 -0
  83. package/templates/jbrains-docs/docs/v2.0.0/tools/build-tools.mdx +165 -0
  84. package/templates/jbrains-docs/docs/v2.0.0/tools/testing.mdx +112 -0
  85. package/templates/jbrains-docs/gitignore +7 -0
  86. package/templates/jbrains-docs/package.json +28 -0
  87. package/templates/jbrains-docs/postcss.config.mjs +8 -0
  88. package/templates/jbrains-docs/public/api-specs/openapi-example.json +259 -0
  89. package/templates/jbrains-docs/public/api-specs/postman-example.json +205 -0
  90. package/templates/jbrains-docs/public/api-specs/test-api.json +256 -0
  91. package/templates/jbrains-docs/public/api-specs/users-api.json +264 -0
  92. package/templates/jbrains-docs/specra.config.json +80 -0
  93. package/templates/jbrains-docs/src/app.css +2 -0
  94. package/templates/jbrains-docs/src/app.html +12 -0
  95. package/templates/jbrains-docs/src/routes/+layout.server.ts +11 -0
  96. package/templates/jbrains-docs/src/routes/+layout.svelte +21 -0
  97. package/templates/jbrains-docs/src/routes/+page.server.ts +9 -0
  98. package/templates/jbrains-docs/src/routes/docs/[version]/[...slug]/+page.server.ts +119 -0
  99. package/templates/jbrains-docs/src/routes/docs/[version]/[...slug]/+page.svelte +129 -0
  100. package/templates/jbrains-docs/svelte.config.js +8 -0
  101. package/templates/jbrains-docs/tsconfig.json +12 -0
  102. package/templates/jbrains-docs/vite.config.ts +6 -0
  103. package/templates/minimal/docs/v1.0.0/about.mdx +3 -3
  104. package/templates/minimal/docs/v2.0.0/about.mdx +3 -3
  105. package/templates/minimal/gitignore +7 -0
  106. package/templates/minimal/package.json +18 -24
  107. package/templates/minimal/specra.config.json +12 -63
  108. package/templates/minimal/src/app.css +2 -0
  109. package/templates/minimal/src/app.html +12 -0
  110. package/templates/minimal/src/routes/+layout.server.ts +11 -0
  111. package/templates/minimal/src/routes/+layout.svelte +21 -0
  112. package/templates/minimal/src/routes/+page.server.ts +9 -0
  113. package/templates/minimal/src/routes/docs/[version]/[...slug]/+page.server.ts +119 -0
  114. package/templates/minimal/src/routes/docs/[version]/[...slug]/+page.svelte +129 -0
  115. package/templates/minimal/svelte.config.js +8 -0
  116. package/templates/minimal/tsconfig.json +7 -36
  117. package/templates/minimal/vite.config.ts +6 -0
  118. package/templates/minimal/README.md +0 -132
  119. package/templates/minimal/app/api/mdx-watch/route.ts +0 -6
  120. package/templates/minimal/app/api/search/route.ts +0 -75
  121. package/templates/minimal/app/docs/[version]/[...slug]/loading.tsx +0 -7
  122. package/templates/minimal/app/docs/[version]/[...slug]/page.tsx +0 -205
  123. package/templates/minimal/app/docs/[version]/[...slug]/page.tsx.bak +0 -203
  124. package/templates/minimal/app/docs/[version]/not-found.tsx +0 -10
  125. package/templates/minimal/app/docs/[version]/page.tsx +0 -27
  126. package/templates/minimal/app/globals.css +0 -9
  127. package/templates/minimal/app/layout.tsx +0 -62
  128. package/templates/minimal/app/not-found.tsx +0 -10
  129. package/templates/minimal/app/page.tsx +0 -179
  130. package/templates/minimal/next.config.mjs +0 -1
  131. package/templates/minimal/package-lock.json +0 -7881
  132. package/templates/minimal/proxy_.ts +0 -22
  133. package/templates/minimal/scripts/generate-redirects.mjs +0 -128
  134. package/templates/minimal/scripts/generate-static-redirects.mjs +0 -115
  135. package/templates/minimal/scripts/index-search.ts +0 -182
  136. 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 all
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 Next.js project with Specra pre-configured:
106
+ The CLI creates a new SvelteKit project with Specra pre-configured:
82
107
 
83
108
  ```
84
109
  my-docs/
85
- ├── app/
86
- │ ├── layout.tsx
87
- │ ├── page.tsx
88
- │ └── [...slug]/
89
- └── page.tsx
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
- └── v1.0.0/
92
- └── index.mdx
123
+ ├── v1.0.0/
124
+ └── v2.0.0/
93
125
  ├── public/
94
- ├── specra.config.ts
95
- ├── next.config.js
96
- ├── tailwind.config.ts
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:3000](http://localhost:3000) in your browser
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.ts`
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 Next.js that provides:
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
- - [Next.js Documentation](https://nextjs.org/docs)
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
@@ -0,0 +1,2 @@
1
+
2
+ export { }
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
@@ -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":";;;;;;;;;;;AAAA,OAAO,QAAQ;AACf,OAAO,SAAS;;;ACDhB,YAAY,SAAS;AACrB,SAAS,YAAY,gBAAgB;AACrC,SAAS,MAAM,eAAe;AAE9B,eAAsB,cAAc,KAA8B;AAChE,QAAM,SAAS,QAAQ,GAAG;AAE1B,MAAI,CAAC,WAAW,MAAM,GAAG;AACvB,UAAM,IAAI,MAAM,wBAAwB,MAAM,EAAE;AAAA,EAClD;AAEA,MAAI,CAAC,SAAS,MAAM,EAAE,YAAY,GAAG;AACnC,UAAM,IAAI,MAAM,oBAAoB,MAAM,EAAE;AAAA,EAC9C;AAGA,QAAM,iBAAiB,WAAW,KAAK,QAAQ,cAAc,CAAC;AAC9D,QAAM,aAAa,WAAW,KAAK,QAAQ,MAAM,CAAC;AAClD,QAAM,kBAAkB,WAAW,KAAK,QAAQ,oBAAoB,CAAC;AAErE,MAAI,CAAC,kBAAkB,CAAC,cAAc,CAAC,iBAAiB;AACtD,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAGA,QAAM,SAAmB,CAAC;AAE1B,QAAU;AAAA,IACR;AAAA,MACE,MAAM;AAAA,MACN,KAAK;AAAA,MACL,QAAQ,CAAC,SAAiB;AACxB,YAAI,KAAK,SAAS,eAAe,EAAG,QAAO;AAC3C,YAAI,KAAK,SAAS,QAAQ,EAAG,QAAO;AACpC,YAAI,KAAK,SAAS,OAAO,EAAG,QAAO;AACnC,YAAI,KAAK,SAAS,MAAM,EAAG,QAAO;AAClC,eAAO;AAAA,MACT;AAAA,IACF;AAAA,IACA,CAAC,GAAG;AAAA,EACN,EAAE,GAAG,QAAQ,CAAC,UAAkB;AAC9B,WAAO,KAAK,KAAK;AAAA,EACnB,CAAC;AAGD,SAAO,OAAO,OAAO,MAAM;AAC7B;;;AD3CA,SAAS,cAAAA,aAAY,oBAAoB;AACzC,SAAS,QAAAC,OAAM,WAAAC,gBAAe;AAO9B,eAAsB,OAAO,SAAwB;AACnD,MAAI,CAAC,gBAAgB,GAAG;AACtB,YAAQ,MAAM,GAAG,IAAI,8CAA8C,CAAC;AACpE,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,MAAMA,SAAQ,QAAQ,GAAG;AAC/B,MAAI,YAAY,QAAQ;AAGxB,MAAI,CAAC,WAAW;AACd,UAAM,aAAaD,MAAK,KAAK,oBAAoB;AACjD,QAAID,YAAW,UAAU,GAAG;AAC1B,UAAI;AACF,cAAM,SAAS,KAAK,MAAM,aAAa,YAAY,OAAO,CAAC;AAC3D,oBAAY,OAAO;AAAA,MACrB,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF;AAEA,MAAI,CAAC,WAAW;AAEd,UAAM,WAAW,MAAM;AAAA,MACrB;AAAA,IACF;AAEA,QAAI,SAAS,WAAW,GAAG;AACzB,cAAQ;AAAA,QACN,GAAG,IAAI,4EAA4E;AAAA,MACrF;AACA,cAAQ,KAAK,CAAC;AAAA,IAChB;AAEA,YAAQ,IAAI,GAAG,KAAK,gCAAgC,CAAC;AACrD,aAAS,QAAQ,CAAC,GAAG,MAAM;AACzB,cAAQ,IAAI,KAAK,GAAG,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,IAAI,GAAG,IAAI,IAAI,EAAE,SAAS,mBAAmB,CAAC,EAAE;AAAA,IAChG,CAAC;AAED,UAAM,UAAU,MAAM,OAAO,SAAS;AACtC,UAAM,WAAW,MAAM,QAAQ,QAAQ;AAAA,MACrC,MAAM;AAAA,MACN,MAAM;AAAA,MACN,SAAS;AAAA,MACT,SAAS,SAAS,IAAI,CAAC,OAAO;AAAA,QAC5B,OAAO,EAAE;AAAA,QACT,OAAO,EAAE;AAAA,QACT,aAAa,GAAG,EAAE,SAAS;AAAA,MAC7B,EAAE;AAAA,IACJ,CAAC;AAED,QAAI,CAAC,SAAS,SAAS;AACrB,cAAQ,IAAI,UAAU;AACtB,cAAQ,KAAK,CAAC;AAAA,IAChB;AAEA,gBAAY,SAAS;AAAA,EACvB;AAGA,QAAM,UAAU,IAAI,mBAAmB,EAAE,MAAM;AAE/C,MAAI;AACF,UAAM,UAAU,MAAM,cAAc,GAAG;AACvC,YAAQ,OAAO,eAAe,QAAQ,SAAS,MAAM,QAAQ,CAAC,CAAC;AAG/D,QAAI;AACJ,QAAI;AACF,YAAM,EAAE,SAAS,IAAI,MAAM,OAAO,eAAe;AACjD,kBAAY,SAAS,sBAAsB,EAAE,KAAK,IAAI,CAAC,EACpD,SAAS,EACT,KAAK;AAAA,IACV,QAAQ;AAAA,IAER;AAEA,UAAM,SAAS,MAAM;AAAA,MACnB,iBAAiB,SAAS;AAAA,MAC1B;AAAA,MACA;AAAA,QACE,oBAAoB;AAAA,QACpB,GAAI,YAAY,EAAE,gBAAgB,UAAU,IAAI,CAAC;AAAA,MACnD;AAAA,IACF;AAEA,YAAQ,QAAQ,GAAG,MAAM,uBAAuB,CAAC;AACjD,YAAQ,IAAI;AACZ,YAAQ,IAAI,oBAAoB,GAAG,KAAK,OAAO,YAAY,CAAC,EAAE;AAE9D,UAAM,SAAS,UAAU;AACzB,YAAQ;AAAA,MACN,oBAAoB,GAAG,IAAI,GAAG,OAAO,MAAM,uBAAuB,SAAS,cAAc,CAAC;AAAA,IAC5F;AACA,YAAQ,IAAI;AAAA,EACd,SAAS,KAAK;AACZ,YAAQ,KAAK,GAAG,IAAI,eAAe,CAAC;AACpC,YAAQ,MAAM,eAAe,QAAQ,IAAI,UAAU,GAAG;AACtD,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF;","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 (default, minimal, api-focused)").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) => {
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"]}