zyket 1.2.18 → 1.2.20
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/.claude-plugin/marketplace.json +2 -2
- package/AGENTS.md +407 -0
- package/README.md +175 -279
- package/SECURITY.md +40 -0
- package/bin/cli.js +310 -202
- package/index.js +4 -3
- package/package.json +7 -1
- package/plugin/.claude-plugin/plugin.json +2 -2
- package/plugin/skills/build/SKILL.md +88 -0
- package/src/extensions/bullboard/index.js +14 -3
- package/src/extensions/interactive-storage/index.js +25 -9
- package/src/extensions/interactive-storage/routes/delete-folder.js +13 -1
- package/src/extensions/interactive-storage/routes/delete.js +14 -3
- package/src/extensions/interactive-storage/routes/download.js +22 -3
- package/src/extensions/interactive-storage/routes/info.js +13 -0
- package/src/services/auth/index.js +46 -28
- package/src/services/express/Express.js +32 -15
- package/src/services/express/RequireAdminMiddleware.js +14 -0
- package/src/services/express/RequireAuthMiddleware.js +46 -0
- package/src/services/express/index.js +7 -5
- package/src/services/socketio/AuthGuard.js +33 -0
- package/src/services/socketio/SocketIO.js +3 -1
- package/src/services/socketio/index.js +2 -1
- package/src/services/template-manager/index.js +1 -0
- package/src/templates/api-rest/.env.example +24 -0
- package/src/templates/api-rest/README.md +50 -0
- package/src/templates/api-rest/index.js +18 -0
- package/src/templates/api-rest/src/models/Task.js +18 -0
- package/src/templates/api-rest/src/routes/tasks/[id].js +42 -0
- package/src/templates/api-rest/src/routes/tasks/index.js +26 -0
- package/src/templates/api-rest/src/services/auth/auth.js +9 -0
- package/src/templates/api-rest/src/services/auth/index.js +23 -0
- package/src/templates/realtime-chat/.env.example +26 -0
- package/src/templates/realtime-chat/README.md +38 -0
- package/src/templates/realtime-chat/frontend/.env.example +3 -0
- package/src/templates/realtime-chat/frontend/index.html +12 -0
- package/src/templates/realtime-chat/frontend/main.jsx +18 -0
- package/src/templates/realtime-chat/frontend/src/hooks/useAuth.jsx +27 -0
- package/src/templates/realtime-chat/frontend/src/hooks/useChatSocket.jsx +29 -0
- package/src/templates/realtime-chat/frontend/src/middlewares/LoggedMiddleware.jsx +12 -0
- package/src/templates/realtime-chat/frontend/src/middlewares/NotLoggedMiddleware.jsx +12 -0
- package/src/templates/realtime-chat/frontend/src/store/storeAuth.jsx +11 -0
- package/src/templates/realtime-chat/frontend/src/views/AuthView.jsx +70 -0
- package/src/templates/realtime-chat/frontend/src/views/ChatView.jsx +69 -0
- package/src/templates/realtime-chat/frontend/styles.css +1 -0
- package/src/templates/realtime-chat/frontend/vite.config.js +7 -0
- package/src/templates/realtime-chat/index.js +14 -0
- package/src/templates/realtime-chat/src/guards/auth.js +3 -0
- package/src/templates/realtime-chat/src/handlers/connection.js +23 -0
- package/src/templates/realtime-chat/src/handlers/message.js +29 -0
- package/src/templates/realtime-chat/src/services/auth/auth.js +8 -0
- package/src/templates/realtime-chat/src/services/auth/index.js +19 -0
- package/src/templates/saas-multitenant/.env.example +22 -0
- package/src/templates/saas-multitenant/README.md +71 -0
- package/src/templates/saas-multitenant/frontend/.env.example +3 -0
- package/src/templates/saas-multitenant/frontend/index.html +12 -0
- package/src/templates/saas-multitenant/frontend/main.jsx +18 -0
- package/src/templates/saas-multitenant/frontend/src/hooks/useAuth.jsx +27 -0
- package/src/templates/saas-multitenant/frontend/src/hooks/useProjects.jsx +41 -0
- package/src/templates/saas-multitenant/frontend/src/middlewares/LoggedMiddleware.jsx +12 -0
- package/src/templates/saas-multitenant/frontend/src/middlewares/NotLoggedMiddleware.jsx +12 -0
- package/src/templates/saas-multitenant/frontend/src/store/storeAuth.jsx +13 -0
- package/src/templates/saas-multitenant/frontend/src/views/AuthView.jsx +70 -0
- package/src/templates/saas-multitenant/frontend/src/views/DashboardView.jsx +131 -0
- package/src/templates/saas-multitenant/frontend/styles.css +1 -0
- package/src/templates/saas-multitenant/frontend/vite.config.js +7 -0
- package/src/templates/saas-multitenant/index.js +14 -0
- package/src/templates/saas-multitenant/src/middlewares/RequireOrganization.js +22 -0
- package/src/templates/saas-multitenant/src/models/Project.js +17 -0
- package/src/templates/saas-multitenant/src/routes/admin/stats.js +15 -0
- package/src/templates/saas-multitenant/src/routes/projects/index.js +34 -0
- package/src/templates/saas-multitenant/src/services/auth/auth.js +8 -0
- package/src/templates/saas-multitenant/src/services/auth/index.js +43 -0
- package/src/utils/EnvManager.js +23 -0
package/bin/cli.js
CHANGED
|
@@ -1,202 +1,310 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
const prompts = require('prompts');
|
|
3
|
-
const fs = require('fs');
|
|
4
|
-
const path = require('path');
|
|
5
|
-
const { spawn } = require('child_process');
|
|
6
|
-
const TemplateManager = require('../src/services/template-manager');
|
|
7
|
-
const EnvManager = require('../src/utils/EnvManager');
|
|
8
|
-
const templateManager = new TemplateManager();
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
})
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
const prompts = require('prompts');
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const { spawn } = require('child_process');
|
|
6
|
+
const TemplateManager = require('../src/services/template-manager');
|
|
7
|
+
const EnvManager = require('../src/utils/EnvManager');
|
|
8
|
+
const templateManager = new TemplateManager();
|
|
9
|
+
|
|
10
|
+
const ZYKET_PKG = (() => {
|
|
11
|
+
try { return require('../package.json'); } catch { return { version: '1.0.0', dependencies: {} }; }
|
|
12
|
+
})();
|
|
13
|
+
const ZYKET_VERSION = ZYKET_PKG.version || '1.0.0';
|
|
14
|
+
|
|
15
|
+
const TEMPLATE_DESCRIPTIONS = {
|
|
16
|
+
default: 'Full-stack starter (React frontend + auth)',
|
|
17
|
+
'api-rest': 'Backend-only REST API (auth + CRUD)',
|
|
18
|
+
'saas-multitenant': 'Multi-tenant SaaS (orgs, roles) + dashboard',
|
|
19
|
+
'realtime-chat': 'Authenticated real-time chat (Socket.IO) + UI',
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
// ---- helpers ----------------------------------------------------------------
|
|
23
|
+
|
|
24
|
+
function templateChoices() {
|
|
25
|
+
const all = templateManager.getTemplates();
|
|
26
|
+
// Show "default" first, then the rest.
|
|
27
|
+
const ordered = ['default', ...all.filter((t) => t !== 'default')];
|
|
28
|
+
return ordered
|
|
29
|
+
.filter((t) => templateManager.exists(t))
|
|
30
|
+
.map((t) => ({ title: t, value: t, description: TEMPLATE_DESCRIPTIONS[t] || '' }));
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Write every file of a template into the project, stripping the template-name
|
|
34
|
+
// prefix. Existing files are left untouched. Returns whether the template ships
|
|
35
|
+
// its own index.js. `exclude(rel)` can skip specific files.
|
|
36
|
+
function writeTemplateFiles(templateName, { exclude = () => false } = {}) {
|
|
37
|
+
const files = templateManager.getTemplate(templateName);
|
|
38
|
+
let hasIndex = false;
|
|
39
|
+
for (const file of files) {
|
|
40
|
+
const rel = file.route.split('/').slice(1).join('/');
|
|
41
|
+
if (!rel || exclude(rel)) continue;
|
|
42
|
+
if (rel === 'index.js') hasIndex = true;
|
|
43
|
+
const dest = path.join(process.cwd(), rel);
|
|
44
|
+
fs.mkdirSync(path.dirname(dest), { recursive: true });
|
|
45
|
+
if (!fs.existsSync(dest)) fs.writeFileSync(dest, file.content);
|
|
46
|
+
}
|
|
47
|
+
return { hasIndex };
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Merge KEY=VALUE pairs from a copied .env.example onto the generated .env so a
|
|
51
|
+
// template can override defaults (e.g. DISABLE_VITE=false).
|
|
52
|
+
function applyEnvOverridesFromExample(envPath) {
|
|
53
|
+
const examplePath = path.join(process.cwd(), '.env.example');
|
|
54
|
+
if (!fs.existsSync(examplePath)) return;
|
|
55
|
+
for (const line of fs.readFileSync(examplePath, 'utf-8').split(/\r?\n/)) {
|
|
56
|
+
const trimmed = line.trim();
|
|
57
|
+
if (!trimmed || trimmed.startsWith('#')) continue;
|
|
58
|
+
const eq = trimmed.indexOf('=');
|
|
59
|
+
if (eq === -1) continue;
|
|
60
|
+
const key = trimmed.slice(0, eq).trim();
|
|
61
|
+
const value = trimmed.slice(eq + 1).trim();
|
|
62
|
+
if (key) EnvManager.setEnvVariable(envPath, key, value);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function writeDefaultIndex() {
|
|
67
|
+
const indexContent = `const { Kernel } = require('zyket');
|
|
68
|
+
|
|
69
|
+
const kernel = new Kernel({
|
|
70
|
+
services: [
|
|
71
|
+
['auth', require('./src/services/auth'), ["@service_container"]],
|
|
72
|
+
]
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
kernel.boot().then(() => {
|
|
76
|
+
console.log('Kernel booted successfully!');
|
|
77
|
+
}).catch((error) => {
|
|
78
|
+
console.error('Error booting kernel:', error);
|
|
79
|
+
});
|
|
80
|
+
`;
|
|
81
|
+
fs.writeFileSync(path.join(process.cwd(), 'index.js'), indexContent);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function templateRoutes(name) {
|
|
85
|
+
return templateManager.getTemplate(name).map((f) => f.route);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function templateHasFrontend(name) {
|
|
89
|
+
return templateRoutes(name).some((r) => r.startsWith(`${name}/frontend/`));
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function templateUsesAuth(name) {
|
|
93
|
+
return templateRoutes(name).some((r) => r.startsWith(`${name}/src/services/auth/`));
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Build the dependency set a generated project needs. The user's own code
|
|
97
|
+
// (frontend configs, handlers, stores) imports these DIRECTLY, so they must be
|
|
98
|
+
// real project dependencies — not just transitive deps of zyket. Versions are
|
|
99
|
+
// pinned to whatever this zyket release uses.
|
|
100
|
+
function depsForTemplate(template) {
|
|
101
|
+
const deps = { zyket: `^${ZYKET_VERSION}` };
|
|
102
|
+
if (template === 'default') return deps; // default init is backend-only
|
|
103
|
+
|
|
104
|
+
const copy = (names) => names.forEach((n) => {
|
|
105
|
+
const v = ZYKET_PKG.dependencies?.[n];
|
|
106
|
+
if (v) deps[n] = v;
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
if (templateUsesAuth(template)) copy(['better-auth']);
|
|
110
|
+
if (templateHasFrontend(template)) {
|
|
111
|
+
copy([
|
|
112
|
+
'react', 'react-dom', 'react-router-dom', 'zustand', 'prop-types',
|
|
113
|
+
'vite', '@vitejs/plugin-react', '@tailwindcss/vite', 'tailwindcss',
|
|
114
|
+
]);
|
|
115
|
+
}
|
|
116
|
+
if (template === 'realtime-chat') copy(['socket.io-client']);
|
|
117
|
+
|
|
118
|
+
return deps;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// `node-dependency-injection` loads @typescript-eslint/typescript-estree@5 at
|
|
122
|
+
// require time, which reads `ts.SyntaxKind` off whatever `typescript` npm
|
|
123
|
+
// hoisted. TypeScript 7 dropped that CJS shape, so an unpinned tree dies on
|
|
124
|
+
// boot with "Cannot read properties of undefined (reading 'BarBarToken')".
|
|
125
|
+
// zyket depends on typescript ^5 for this reason; the override is what keeps an
|
|
126
|
+
// already-resolved lockfile from pulling 7.x back in.
|
|
127
|
+
const TYPESCRIPT_PIN = ZYKET_PKG.dependencies?.typescript || '^5.9.3';
|
|
128
|
+
|
|
129
|
+
function projectName() {
|
|
130
|
+
const raw = path.basename(process.cwd()).toLowerCase().replace(/[^a-z0-9._-]+/g, '-').replace(/^[._-]+/, '');
|
|
131
|
+
return raw || 'zyket-app';
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// `npm install zyket` already leaves a package.json behind, so merging into an
|
|
135
|
+
// existing file is the normal path, not the exception. Only fill in what's
|
|
136
|
+
// missing — never clobber versions or scripts the user already chose.
|
|
137
|
+
function ensurePackageJson(template) {
|
|
138
|
+
const packageJsonPath = path.join(process.cwd(), 'package.json');
|
|
139
|
+
let packageJson = {};
|
|
140
|
+
if (fs.existsSync(packageJsonPath)) {
|
|
141
|
+
try {
|
|
142
|
+
packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8')) || {};
|
|
143
|
+
} catch {
|
|
144
|
+
console.log('[ZYKET] package.json is not valid JSON — leaving it untouched.');
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
const defaults = {
|
|
149
|
+
name: projectName(),
|
|
150
|
+
version: '1.0.0',
|
|
151
|
+
description: 'Zyket application',
|
|
152
|
+
main: 'index.js',
|
|
153
|
+
keywords: [],
|
|
154
|
+
author: '',
|
|
155
|
+
license: 'ISC',
|
|
156
|
+
};
|
|
157
|
+
for (const [key, value] of Object.entries(defaults)) {
|
|
158
|
+
if (packageJson[key] === undefined) packageJson[key] = value;
|
|
159
|
+
}
|
|
160
|
+
packageJson.scripts = { dev: 'node index.js', ...packageJson.scripts };
|
|
161
|
+
packageJson.dependencies = { ...depsForTemplate(template), ...packageJson.dependencies };
|
|
162
|
+
packageJson.overrides = { typescript: TYPESCRIPT_PIN, ...packageJson.overrides };
|
|
163
|
+
fs.writeFileSync(packageJsonPath, `${JSON.stringify(packageJson, null, 2)}\n`);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
function npmInstall() {
|
|
167
|
+
return new Promise((resolve, reject) => {
|
|
168
|
+
const npmInstallProcess = spawn('npm', ['install'], { cwd: process.cwd(), stdio: 'inherit', shell: true });
|
|
169
|
+
npmInstallProcess.on('close', (code) => {
|
|
170
|
+
if (code === 0) resolve();
|
|
171
|
+
else reject(new Error(`npm install exited with code ${code}`));
|
|
172
|
+
});
|
|
173
|
+
npmInstallProcess.on('error', reject);
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// ---- main -------------------------------------------------------------------
|
|
178
|
+
|
|
179
|
+
(async () => {
|
|
180
|
+
process.stdout.write("[2J[0;0H");
|
|
181
|
+
await templateManager.boot();
|
|
182
|
+
|
|
183
|
+
const args = process.argv.slice(2);
|
|
184
|
+
const directCommand = args[0];
|
|
185
|
+
|
|
186
|
+
let actionToRun = null;
|
|
187
|
+
let templateArg = null;
|
|
188
|
+
|
|
189
|
+
if (directCommand === 'init') {
|
|
190
|
+
actionToRun = 'init-project';
|
|
191
|
+
templateArg = args[1] || null; // e.g. `npx zyket init api-rest`
|
|
192
|
+
} else {
|
|
193
|
+
const response = await prompts({
|
|
194
|
+
type: 'select',
|
|
195
|
+
name: 'value',
|
|
196
|
+
message: '[ZYKET] What do you want to do?',
|
|
197
|
+
choices: [
|
|
198
|
+
{ title: 'Initialize Project', value: 'init-project', description: 'Scaffold a new Zyket project from a template', disabled: false },
|
|
199
|
+
{ title: 'Install Template', value: 'install-template', description: 'Add a template into the current project', disabled: false },
|
|
200
|
+
],
|
|
201
|
+
initial: 0,
|
|
202
|
+
});
|
|
203
|
+
actionToRun = response.value;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
if (!actionToRun) {
|
|
207
|
+
console.log('[ZYKET] No action selected. Exiting.');
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
const actions = {
|
|
212
|
+
'init-project': async (preselectedTemplate) => {
|
|
213
|
+
// Resolve which template to scaffold.
|
|
214
|
+
let template = preselectedTemplate && templateManager.exists(preselectedTemplate) ? preselectedTemplate : null;
|
|
215
|
+
if (preselectedTemplate && !template) {
|
|
216
|
+
console.log(`[ZYKET] Template '${preselectedTemplate}' not found. Pick one:`);
|
|
217
|
+
}
|
|
218
|
+
if (!template) {
|
|
219
|
+
const response = await prompts({
|
|
220
|
+
type: 'select',
|
|
221
|
+
name: 'value',
|
|
222
|
+
message: '[ZYKET] Choose a template to initialize',
|
|
223
|
+
choices: templateChoices(),
|
|
224
|
+
initial: 0,
|
|
225
|
+
});
|
|
226
|
+
template = response.value;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
if (!template) {
|
|
230
|
+
console.log('[ZYKET] No template selected. Exiting.');
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
const indexPath = path.join(process.cwd(), 'index.js');
|
|
235
|
+
const envPath = path.join(process.cwd(), '.env');
|
|
236
|
+
|
|
237
|
+
if (fs.existsSync(indexPath)) {
|
|
238
|
+
const overwrite = await prompts({
|
|
239
|
+
type: 'confirm',
|
|
240
|
+
name: 'value',
|
|
241
|
+
message: '[ZYKET] index.js already exists. Continue scaffolding (existing files are kept)?',
|
|
242
|
+
initial: false,
|
|
243
|
+
});
|
|
244
|
+
if (!overwrite.value) {
|
|
245
|
+
console.log('[ZYKET] Initialization cancelled.');
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
console.log(`[ZYKET] Initializing with template '${template}'...`);
|
|
251
|
+
EnvManager.createEnvFile(envPath);
|
|
252
|
+
|
|
253
|
+
if (template === 'default') {
|
|
254
|
+
// Curated default: backend files only (no frontend, no socket guards/handlers).
|
|
255
|
+
writeTemplateFiles('default', {
|
|
256
|
+
exclude: (rel) => !(
|
|
257
|
+
(rel.startsWith('src/') || rel.startsWith('config/')) &&
|
|
258
|
+
!rel.startsWith('src/guards/') &&
|
|
259
|
+
!rel.startsWith('src/handlers/')
|
|
260
|
+
),
|
|
261
|
+
});
|
|
262
|
+
writeDefaultIndex();
|
|
263
|
+
} else {
|
|
264
|
+
// Self-contained template: copy everything (incl. its index.js and frontend).
|
|
265
|
+
const { hasIndex } = writeTemplateFiles(template);
|
|
266
|
+
applyEnvOverridesFromExample(envPath);
|
|
267
|
+
if (!hasIndex) writeDefaultIndex();
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
ensurePackageJson(template);
|
|
271
|
+
|
|
272
|
+
console.log('\n[ZYKET] Installing dependencies...');
|
|
273
|
+
await npmInstall();
|
|
274
|
+
|
|
275
|
+
console.log(`\n[ZYKET] ✅ Project initialized with template '${template}'!`);
|
|
276
|
+
|
|
277
|
+
if (template === 'default') {
|
|
278
|
+
// Preserve previous behavior: start immediately.
|
|
279
|
+
console.log('\n[ZYKET] Starting project...\n');
|
|
280
|
+
spawn('node', ['index.js'], { cwd: process.cwd(), stdio: 'inherit', shell: true })
|
|
281
|
+
.on('error', (error) => console.error('[ZYKET] Error starting project:', error));
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// Templates that ship auth need their tables created first.
|
|
286
|
+
const usesAuth = fs.existsSync(path.join(process.cwd(), 'src', 'services', 'auth'));
|
|
287
|
+
console.log('\nNext steps:');
|
|
288
|
+
if (usesAuth) console.log(' npx @better-auth/cli migrate # create the auth tables');
|
|
289
|
+
console.log(' node index.js\n');
|
|
290
|
+
if (fs.existsSync(path.join(process.cwd(), 'README.md'))) {
|
|
291
|
+
console.log('See README.md for template-specific details.\n');
|
|
292
|
+
}
|
|
293
|
+
},
|
|
294
|
+
|
|
295
|
+
'install-template': async () => {
|
|
296
|
+
const templates = templateManager.getTemplates();
|
|
297
|
+
const response = await prompts({
|
|
298
|
+
type: 'select',
|
|
299
|
+
name: 'templateToInstall',
|
|
300
|
+
message: '[ZYKET] What template would you like to install?',
|
|
301
|
+
choices: templates.map((template) => ({ title: template.toUpperCase(), value: template, description: TEMPLATE_DESCRIPTIONS[template] || '', disabled: false })),
|
|
302
|
+
initial: 0,
|
|
303
|
+
});
|
|
304
|
+
if (!templateManager.exists(response.templateToInstall)) throw new Error(`Template ${response.templateToInstall} not found`);
|
|
305
|
+
templateManager.installTemplate(response.templateToInstall);
|
|
306
|
+
},
|
|
307
|
+
};
|
|
308
|
+
|
|
309
|
+
await actions[actionToRun](templateArg);
|
|
310
|
+
})();
|
package/index.js
CHANGED
|
@@ -2,8 +2,8 @@ const Kernel = require("./src/kernel");
|
|
|
2
2
|
const Service = require("./src/services/Service");
|
|
3
3
|
const EnvManager = require("./src/utils/EnvManager");
|
|
4
4
|
|
|
5
|
-
const {Route, Middleware, Express} = require("./src/services/express");
|
|
6
|
-
const { Handler, Guard } = require("./src/services/socketio");
|
|
5
|
+
const {Route, Middleware, Express, RequireAuthMiddleware, RequireAdminMiddleware} = require("./src/services/express");
|
|
6
|
+
const { Handler, Guard, AuthGuard } = require("./src/services/socketio");
|
|
7
7
|
const Schedule = require("./src/services/scheduler/Schedule");
|
|
8
8
|
const Event = require("./src/services/events/Event");
|
|
9
9
|
const Worker = require("./src/services/bullmq/Worker");
|
|
@@ -20,7 +20,8 @@ module.exports = {
|
|
|
20
20
|
Express,
|
|
21
21
|
Kernel, Service,
|
|
22
22
|
Route, Middleware,
|
|
23
|
-
|
|
23
|
+
RequireAuthMiddleware, RequireAdminMiddleware,
|
|
24
|
+
Handler, Guard, AuthGuard,
|
|
24
25
|
Schedule, Event,
|
|
25
26
|
Worker,
|
|
26
27
|
EnvManager,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "zyket",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.20",
|
|
4
4
|
"main": "index.js",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"test": "echo \"Error: no test specified\" && exit 1"
|
|
@@ -39,10 +39,12 @@
|
|
|
39
39
|
"redis": "^5.11.0",
|
|
40
40
|
"sequelize": "^6.37.8",
|
|
41
41
|
"socket.io": "^4.8.3",
|
|
42
|
+
"socket.io-client": "^4.8.3",
|
|
42
43
|
"sqlite3": "^6.0.1",
|
|
43
44
|
"swagger-jsdoc": "^6.2.8",
|
|
44
45
|
"swagger-ui-express": "^5.0.1",
|
|
45
46
|
"tailwindcss": "^4.2.2",
|
|
47
|
+
"typescript": "^5.9.3",
|
|
46
48
|
"umzug": "^3.8.2",
|
|
47
49
|
"vite": "^8.0.2",
|
|
48
50
|
"zustand": "^5.0.12"
|
|
@@ -50,5 +52,9 @@
|
|
|
50
52
|
"optionalDependencies": {
|
|
51
53
|
"@socket.io/redis-adapter": "^8.3.0",
|
|
52
54
|
"ioredis": "^5.6.1"
|
|
55
|
+
},
|
|
56
|
+
"overrides": {
|
|
57
|
+
"ajv": "^8.17.1",
|
|
58
|
+
"typescript": "^5.9.3"
|
|
53
59
|
}
|
|
54
60
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "zyket",
|
|
3
|
-
"description": "Claude Code plugin for the Zyket framework
|
|
4
|
-
"version": "1.
|
|
3
|
+
"description": "Claude Code plugin for the Zyket framework. `build`: start, configure, and run a Zyket app (templates, services, auth, security). `generate`: scaffold handlers, guards, routes, middlewares, services, events, schedulers, workers, and extensions.",
|
|
4
|
+
"version": "1.1.0",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "OnchainTech"
|
|
7
7
|
}
|