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.
Files changed (74) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/AGENTS.md +407 -0
  3. package/README.md +175 -279
  4. package/SECURITY.md +40 -0
  5. package/bin/cli.js +310 -202
  6. package/index.js +4 -3
  7. package/package.json +7 -1
  8. package/plugin/.claude-plugin/plugin.json +2 -2
  9. package/plugin/skills/build/SKILL.md +88 -0
  10. package/src/extensions/bullboard/index.js +14 -3
  11. package/src/extensions/interactive-storage/index.js +25 -9
  12. package/src/extensions/interactive-storage/routes/delete-folder.js +13 -1
  13. package/src/extensions/interactive-storage/routes/delete.js +14 -3
  14. package/src/extensions/interactive-storage/routes/download.js +22 -3
  15. package/src/extensions/interactive-storage/routes/info.js +13 -0
  16. package/src/services/auth/index.js +46 -28
  17. package/src/services/express/Express.js +32 -15
  18. package/src/services/express/RequireAdminMiddleware.js +14 -0
  19. package/src/services/express/RequireAuthMiddleware.js +46 -0
  20. package/src/services/express/index.js +7 -5
  21. package/src/services/socketio/AuthGuard.js +33 -0
  22. package/src/services/socketio/SocketIO.js +3 -1
  23. package/src/services/socketio/index.js +2 -1
  24. package/src/services/template-manager/index.js +1 -0
  25. package/src/templates/api-rest/.env.example +24 -0
  26. package/src/templates/api-rest/README.md +50 -0
  27. package/src/templates/api-rest/index.js +18 -0
  28. package/src/templates/api-rest/src/models/Task.js +18 -0
  29. package/src/templates/api-rest/src/routes/tasks/[id].js +42 -0
  30. package/src/templates/api-rest/src/routes/tasks/index.js +26 -0
  31. package/src/templates/api-rest/src/services/auth/auth.js +9 -0
  32. package/src/templates/api-rest/src/services/auth/index.js +23 -0
  33. package/src/templates/realtime-chat/.env.example +26 -0
  34. package/src/templates/realtime-chat/README.md +38 -0
  35. package/src/templates/realtime-chat/frontend/.env.example +3 -0
  36. package/src/templates/realtime-chat/frontend/index.html +12 -0
  37. package/src/templates/realtime-chat/frontend/main.jsx +18 -0
  38. package/src/templates/realtime-chat/frontend/src/hooks/useAuth.jsx +27 -0
  39. package/src/templates/realtime-chat/frontend/src/hooks/useChatSocket.jsx +29 -0
  40. package/src/templates/realtime-chat/frontend/src/middlewares/LoggedMiddleware.jsx +12 -0
  41. package/src/templates/realtime-chat/frontend/src/middlewares/NotLoggedMiddleware.jsx +12 -0
  42. package/src/templates/realtime-chat/frontend/src/store/storeAuth.jsx +11 -0
  43. package/src/templates/realtime-chat/frontend/src/views/AuthView.jsx +70 -0
  44. package/src/templates/realtime-chat/frontend/src/views/ChatView.jsx +69 -0
  45. package/src/templates/realtime-chat/frontend/styles.css +1 -0
  46. package/src/templates/realtime-chat/frontend/vite.config.js +7 -0
  47. package/src/templates/realtime-chat/index.js +14 -0
  48. package/src/templates/realtime-chat/src/guards/auth.js +3 -0
  49. package/src/templates/realtime-chat/src/handlers/connection.js +23 -0
  50. package/src/templates/realtime-chat/src/handlers/message.js +29 -0
  51. package/src/templates/realtime-chat/src/services/auth/auth.js +8 -0
  52. package/src/templates/realtime-chat/src/services/auth/index.js +19 -0
  53. package/src/templates/saas-multitenant/.env.example +22 -0
  54. package/src/templates/saas-multitenant/README.md +71 -0
  55. package/src/templates/saas-multitenant/frontend/.env.example +3 -0
  56. package/src/templates/saas-multitenant/frontend/index.html +12 -0
  57. package/src/templates/saas-multitenant/frontend/main.jsx +18 -0
  58. package/src/templates/saas-multitenant/frontend/src/hooks/useAuth.jsx +27 -0
  59. package/src/templates/saas-multitenant/frontend/src/hooks/useProjects.jsx +41 -0
  60. package/src/templates/saas-multitenant/frontend/src/middlewares/LoggedMiddleware.jsx +12 -0
  61. package/src/templates/saas-multitenant/frontend/src/middlewares/NotLoggedMiddleware.jsx +12 -0
  62. package/src/templates/saas-multitenant/frontend/src/store/storeAuth.jsx +13 -0
  63. package/src/templates/saas-multitenant/frontend/src/views/AuthView.jsx +70 -0
  64. package/src/templates/saas-multitenant/frontend/src/views/DashboardView.jsx +131 -0
  65. package/src/templates/saas-multitenant/frontend/styles.css +1 -0
  66. package/src/templates/saas-multitenant/frontend/vite.config.js +7 -0
  67. package/src/templates/saas-multitenant/index.js +14 -0
  68. package/src/templates/saas-multitenant/src/middlewares/RequireOrganization.js +22 -0
  69. package/src/templates/saas-multitenant/src/models/Project.js +17 -0
  70. package/src/templates/saas-multitenant/src/routes/admin/stats.js +15 -0
  71. package/src/templates/saas-multitenant/src/routes/projects/index.js +34 -0
  72. package/src/templates/saas-multitenant/src/services/auth/auth.js +8 -0
  73. package/src/templates/saas-multitenant/src/services/auth/index.js +43 -0
  74. 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
- (async () => {
11
- process.stdout.write("\u001b[2J\u001b[0;0H");
12
- await templateManager.boot();
13
-
14
- // Check for direct command (e.g., npx zyket init)
15
- const args = process.argv.slice(2);
16
- const directCommand = args[0];
17
-
18
- let actionToRun = null;
19
-
20
- if (directCommand === 'init') {
21
- actionToRun = 'init-project';
22
- } else {
23
- // Show interactive menu
24
- const response = await prompts({
25
- type: 'select',
26
- name: 'value',
27
- message: '[ZYKET] What do you want to do?',
28
- choices: [
29
- { title: 'Initialize Project', value: 'init-project', description: 'Set up a new Zyket project', disabled: false },
30
- { title: 'Install Template', value: 'install-template', description: 'Install a new template', disabled: false },
31
- /*{ title: 'Remove Template', value: 'remove-template', description: 'Remove an existing template', disabled: false },*/
32
- ],
33
- initial: 0
34
- });
35
- actionToRun = response.value;
36
- }
37
-
38
- if (!actionToRun) {
39
- console.log('[ZYKET] No action selected. Exiting.');
40
- return;
41
- }
42
-
43
- const actions = {
44
- 'init-project': async () => {
45
- const indexPath = path.join(process.cwd(), 'index.js');
46
- const envPath = path.join(process.cwd(), '.env');
47
- const packageJsonPath = path.join(process.cwd(), 'package.json');
48
-
49
- // Check if index.js already exists
50
- if (fs.existsSync(indexPath)) {
51
- const overwrite = await prompts({
52
- type: 'confirm',
53
- name: 'value',
54
- message: '[ZYKET] index.js already exists. Overwrite?',
55
- initial: false
56
- });
57
- if (!overwrite.value) {
58
- console.log('[ZYKET] Initialization cancelled.');
59
- return;
60
- }
61
- }
62
-
63
- // Create .env file
64
- console.log('[ZYKET] Creating .env file...');
65
- EnvManager.createEnvFile(envPath);
66
-
67
- // Install default backend template files (src and config)
68
- console.log('[ZYKET] Installing default backend template files...');
69
- const defaultTemplate = templateManager.getTemplate('default');
70
- const backendFiles = defaultTemplate.filter(file => {
71
- const route = file.route;
72
- // Only install src and config files, not frontend
73
- // Skip guards and handlers folders since socket is disabled by default
74
- return (route.startsWith('default/src/') || route.startsWith('default/config/'))
75
- && !route.startsWith('default/src/guards/')
76
- && !route.startsWith('default/src/handlers/');
77
- });
78
-
79
- for (const file of backendFiles) {
80
- const fileName = file.route.split('/').slice(1).join('/');
81
- const fileLocation = path.join(process.cwd(), fileName);
82
- const folderLocation = path.dirname(fileLocation);
83
-
84
- // Create directory if it doesn't exist
85
- if (!fs.existsSync(folderLocation)) {
86
- fs.mkdirSync(folderLocation, { recursive: true });
87
- }
88
-
89
- // Write file if it doesn't exist
90
- if (!fs.existsSync(fileLocation)) {
91
- fs.writeFileSync(fileLocation, file.content);
92
- }
93
- }
94
- console.log('[ZYKET] ✅ Backend template files installed');
95
-
96
- // Create index.js with boilerplate code
97
- console.log('[ZYKET] Creating index.js...');
98
- const indexContent = `const { Kernel } = require('zyket');
99
-
100
- const kernel = new Kernel({
101
- services: [
102
- ['auth', require('./src/services/auth'), ["@service_container"]],
103
- ]
104
- });
105
-
106
- kernel.boot().then(() => {
107
- console.log('Kernel booted successfully!');
108
- }).catch((error) => {
109
- console.error('Error booting kernel:', error);
110
- });
111
- `;
112
- fs.writeFileSync(indexPath, indexContent);
113
-
114
- // Create package.json if it doesn't exist
115
- if (!fs.existsSync(packageJsonPath)) {
116
- console.log('[ZYKET] Creating package.json...');
117
- const packageJson = {
118
- name: path.basename(process.cwd()),
119
- version: "1.0.0",
120
- description: "Zyket application",
121
- main: "index.js",
122
- scripts: {
123
- dev: "node index.js"
124
- },
125
- keywords: [],
126
- author: "",
127
- license: "ISC",
128
- dependencies: {
129
- zyket: "^1.2.3"
130
- }
131
- };
132
- fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2));
133
- }
134
-
135
- console.log('\n[ZYKET] Project initialized successfully!');
136
-
137
- // Install dependencies automatically
138
- console.log('\n[ZYKET] Installing dependencies...');
139
- await new Promise((resolve, reject) => {
140
- const npmInstall = spawn('npm', ['install'], {
141
- cwd: process.cwd(),
142
- stdio: 'inherit',
143
- shell: true
144
- });
145
-
146
- npmInstall.on('close', (code) => {
147
- if (code === 0) {
148
- console.log('\n[ZYKET] Dependencies installed successfully!');
149
- resolve();
150
- } else {
151
- reject(new Error(`npm install exited with code ${code}`));
152
- }
153
- });
154
-
155
- npmInstall.on('error', (error) => {
156
- reject(error);
157
- });
158
- });
159
-
160
- // Start the project automatically
161
- console.log('\n[ZYKET] Starting project...\n');
162
- const nodeStart = spawn('node', ['index.js'], {
163
- cwd: process.cwd(),
164
- stdio: 'inherit',
165
- shell: true
166
- });
167
-
168
- nodeStart.on('error', (error) => {
169
- console.error('[ZYKET] Error starting project:', error);
170
- });
171
- },
172
- 'install-template': async () => {
173
- const templates = templateManager.getTemplates();
174
- const response = await prompts({
175
- type: 'select',
176
- name: 'templateToInstall',
177
- message: '[ZYKET] What template would you like to install?',
178
- choices: [
179
- ...templates.map((template) => ({ title: template.toUpperCase(), value: template, description: '', disabled: false })),
180
- ],
181
- initial: 0
182
- });
183
- if(!templateManager.exists(response.templateToInstall)) throw new Error(`Template ${response.templateToInstall} not found`);
184
- templateManager.installTemplate(response.templateToInstall);
185
- },
186
- /*'remove-template': async () => {
187
- const response = await prompts({
188
- type: 'select',
189
- name: 'templateToRemove',
190
- message: '[ZYKET] What template would you like to remove?',
191
- choices: [
192
- { title: 'Auth', value: 'auth', description: 'Authentication template', disabled: false },
193
- { title: 'Chat', value: 'chat', description: 'Chat template', disabled: false },
194
- ],
195
- initial: 0
196
- });
197
- console.log(`Removing template: ${response.templateToRemove}`);
198
- }*/
199
- };
200
-
201
- await actions[actionToRun]();
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("");
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
- Handler, Guard,
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.18",
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 scaffold handlers, guards, routes, middlewares, services, events, schedulers, workers, and extensions.",
4
- "version": "1.0.0",
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
  }