@coherent.js/cli 1.0.0-beta.3 → 1.0.0-beta.5

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 (3) hide show
  1. package/README.md +4 -12
  2. package/dist/index.js +481 -201
  3. package/package.json +3 -2
package/README.md CHANGED
@@ -6,7 +6,7 @@ Command-line interface for Coherent.js projects. Scaffold new applications, gene
6
6
 
7
7
  ```bash
8
8
  # Install globally
9
- npm install -g @coherent.js/cli
9
+ pnpm add -g @coherent.js/cli
10
10
 
11
11
  # Create a new project
12
12
  coherent create my-app
@@ -23,24 +23,16 @@ coherent dev
23
23
  ### Global Installation (Recommended)
24
24
 
25
25
  ```bash
26
- npm install -g @coherent.js/cli
27
- # or
28
- yarn global add @coherent.js/cli
29
- # or
30
26
  pnpm add -g @coherent.js/cli
31
27
  ```
32
28
 
33
29
  ### Local Installation
34
30
 
35
31
  ```bash
36
- npm install --save-dev @coherent.js/cli
37
- # or
38
- yarn add --dev @coherent.js/cli
39
- # or
40
32
  pnpm add -D @coherent.js/cli
41
33
 
42
- # Use with npx
43
- npx coherent create my-app
34
+ # Use with pnpm
35
+ pnpm exec coherent create my-app
44
36
  ```
45
37
 
46
38
  ## 🛠️ Commands
@@ -381,7 +373,7 @@ test('Button renders correctly', () => {
381
373
 
382
374
  Run tests with:
383
375
  ```bash
384
- npm test
376
+ pnpm test
385
377
  # or if using the CLI
386
378
  coherent test
387
379
  ```
package/dist/index.js CHANGED
@@ -43,13 +43,14 @@ function getCLIVersion() {
43
43
  // src/generators/runtime-scaffold.js
44
44
  var cliVersion = getCLIVersion();
45
45
  function generateBuiltInServer(options = {}) {
46
- const { port = 3e3, hasApi = false, hasDatabase = false } = options;
46
+ const { port = 3e3, hasApi = false, hasDatabase = false, hasAuth = false } = options;
47
47
  const imports = [
48
48
  `import http from 'http';`,
49
49
  `import { render } from '@coherent.js/core';`
50
50
  ];
51
51
  if (hasApi) imports.push(`import { setupRoutes } from './api/routes.js';`);
52
52
  if (hasDatabase) imports.push(`import { initDatabase } from './db/index.js';`);
53
+ if (hasAuth) imports.push(`import { setupAuthRoutes } from './api/auth.js';`);
53
54
  const server = `
54
55
  ${imports.join("\n")}
55
56
  import { HomePage } from './components/HomePage.js';
@@ -60,15 +61,21 @@ ${hasDatabase ? `// Initialize database
60
61
  await initDatabase();
61
62
  ` : ""}${hasApi ? `// Setup API routes
62
63
  const apiRoutes = setupRoutes();
64
+ ` : ""}${hasAuth ? `// Setup auth routes
65
+ const authRoutes = setupAuthRoutes();
63
66
  ` : ""}
64
67
  const server = http.createServer(async (req, res) => {
65
68
  const url = new URL(req.url, \`http://\${req.headers.host}\`);
66
69
 
67
- ${hasApi ? ` // Handle API routes
70
+ ${hasApi || hasAuth ? ` // Handle API routes
68
71
  if (url.pathname.startsWith('/api')) {
69
- const route = apiRoutes.find(r => r.path === url.pathname && r.method === req.method);
70
- if (route) {
71
- return route.handler(req, res);
72
+ const allRoutes = [...${hasApi ? "apiRoutes" : "[]"}, ...${hasAuth ? "authRoutes" : "[]"}];
73
+ for (const route of allRoutes) {
74
+ const match = matchRoute(route.path, url.pathname, req.method, route.method);
75
+ if (match) {
76
+ req.params = match.params;
77
+ return route.handler(req, res);
78
+ }
72
79
  }
73
80
  }
74
81
 
@@ -101,6 +108,42 @@ ${hasApi ? ` // Handle API routes
101
108
  }
102
109
  });
103
110
 
111
+ // Route matching helper
112
+ function matchRoute(routePattern, urlPath, requestMethod, routeMethod) {
113
+ // Check HTTP method
114
+ if (requestMethod !== routeMethod) {
115
+ return null;
116
+ }
117
+
118
+ // Split paths into segments
119
+ const routeSegments = routePattern.split('/').filter(Boolean);
120
+ const urlSegments = urlPath.split('/').filter(Boolean);
121
+
122
+ // Check if lengths match
123
+ if (routeSegments.length !== urlSegments.length) {
124
+ return null;
125
+ }
126
+
127
+ const params = {};
128
+
129
+ // Match each segment
130
+ for (let i = 0; i < routeSegments.length; i++) {
131
+ const routeSegment = routeSegments[i];
132
+ const urlSegment = urlSegments[i];
133
+
134
+ // Check for parameter (e.g., :id)
135
+ if (routeSegment.startsWith(':')) {
136
+ const paramName = routeSegment.substring(1);
137
+ params[paramName] = urlSegment;
138
+ } else if (routeSegment !== urlSegment) {
139
+ // Literal segment doesn't match
140
+ return null;
141
+ }
142
+ }
143
+
144
+ return { params };
145
+ }
146
+
104
147
  server.listen(PORT, () => {
105
148
  console.log(\`Server running at http://localhost:\${PORT}\`);
106
149
  });
@@ -517,7 +560,7 @@ process.on('SIGINT', async () => {
517
560
  function generateExampleModel(dbType) {
518
561
  const models = {
519
562
  postgres: `
520
- import { getDatabase } from './index.js';
563
+ import { getDatabase } from '../index.js';
521
564
 
522
565
  export class UserModel {
523
566
  static async createTable() {
@@ -570,7 +613,7 @@ export class UserModel {
570
613
  }
571
614
  `,
572
615
  mysql: `
573
- import { getDatabase } from './index.js';
616
+ import { getDatabase } from '../index.js';
574
617
 
575
618
  export class UserModel {
576
619
  static async createTable() {
@@ -623,7 +666,7 @@ export class UserModel {
623
666
  }
624
667
  `,
625
668
  sqlite: `
626
- import { getDatabase } from './index.js';
669
+ import { getDatabase } from '../index.js';
627
670
 
628
671
  export class UserModel {
629
672
  static createTable() {
@@ -673,7 +716,7 @@ export class UserModel {
673
716
  }
674
717
  `,
675
718
  mongodb: `
676
- import { getDatabase } from './index.js';
719
+ import { getDatabase } from '../index.js';
677
720
 
678
721
  export class UserModel {
679
722
  static collectionName = 'users';
@@ -1156,6 +1199,158 @@ router.get('/me', authMiddleware, async (req, res) => {
1156
1199
  });
1157
1200
 
1158
1201
  export default router;
1202
+ `,
1203
+ "built-in": `
1204
+ // Auth routes for built-in HTTP server
1205
+ import { generateToken, verifyToken } from '../middleware/auth.js';
1206
+ import { UserModel } from '../db/models/User.js';
1207
+
1208
+ // Register handler
1209
+ export async function registerHandler(req, res) {
1210
+ try {
1211
+ // Parse JSON body
1212
+ let body = '';
1213
+ req.on('data', chunk => {
1214
+ body += chunk.toString();
1215
+ });
1216
+
1217
+ req.on('end', async () => {
1218
+ try {
1219
+ const { email, name, password } = JSON.parse(body);
1220
+
1221
+ // Validate input
1222
+ if (!email || !name || !password) {
1223
+ res.writeHead(400, { 'Content-Type': 'application/json' });
1224
+ return res.end(JSON.stringify({ error: 'Missing required fields' }));
1225
+ }
1226
+
1227
+ // Check if user exists
1228
+ const existingUser = await UserModel.findByEmail(email);
1229
+ if (existingUser) {
1230
+ res.writeHead(400, { 'Content-Type': 'application/json' });
1231
+ return res.end(JSON.stringify({ error: 'User already exists' }));
1232
+ }
1233
+
1234
+ // Create user (you should hash the password!)
1235
+ const user = await UserModel.create({ email, name });
1236
+
1237
+ // Generate token
1238
+ const token = generateToken({ id: user.id, email: user.email });
1239
+
1240
+ res.writeHead(200, { 'Content-Type': 'application/json' });
1241
+ res.end(JSON.stringify({ user: { id: user.id, email: user.email, name: user.name }, token }));
1242
+ } catch (error) {
1243
+ console.error('Register error:', error);
1244
+ res.writeHead(500, { 'Content-Type': 'application/json' });
1245
+ res.end(JSON.stringify({ error: 'Registration failed' }));
1246
+ }
1247
+ });
1248
+ } catch (error) {
1249
+ console.error('Register error:', error);
1250
+ res.writeHead(500, { 'Content-Type': 'application/json' });
1251
+ res.end(JSON.stringify({ error: 'Registration failed' }));
1252
+ }
1253
+ }
1254
+
1255
+ // Login handler
1256
+ export async function loginHandler(req, res) {
1257
+ try {
1258
+ // Parse JSON body
1259
+ let body = '';
1260
+ req.on('data', chunk => {
1261
+ body += chunk.toString();
1262
+ });
1263
+
1264
+ req.on('end', async () => {
1265
+ try {
1266
+ const { email, password } = JSON.parse(body);
1267
+
1268
+ // Validate input
1269
+ if (!email || !password) {
1270
+ res.writeHead(400, { 'Content-Type': 'application/json' });
1271
+ return res.end(JSON.stringify({ error: 'Missing required fields' }));
1272
+ }
1273
+
1274
+ // Find user
1275
+ const user = await UserModel.findByEmail(email);
1276
+ if (!user) {
1277
+ res.writeHead(401, { 'Content-Type': 'application/json' });
1278
+ return res.end(JSON.stringify({ error: 'Invalid credentials' }));
1279
+ }
1280
+
1281
+ // Verify password (you should implement proper password checking!)
1282
+
1283
+ // Generate token
1284
+ const token = generateToken({ id: user.id, email: user.email });
1285
+
1286
+ res.writeHead(200, { 'Content-Type': 'application/json' });
1287
+ res.end(JSON.stringify({ user: { id: user.id, email: user.email, name: user.name }, token }));
1288
+ } catch (error) {
1289
+ console.error('Login error:', error);
1290
+ res.writeHead(500, { 'Content-Type': 'application/json' });
1291
+ res.end(JSON.stringify({ error: 'Login failed' }));
1292
+ }
1293
+ });
1294
+ } catch (error) {
1295
+ console.error('Login error:', error);
1296
+ res.writeHead(500, { 'Content-Type': 'application/json' });
1297
+ res.end(JSON.stringify({ error: 'Login failed' }));
1298
+ }
1299
+ }
1300
+
1301
+ // Get current user handler
1302
+ export async function meHandler(req, res) {
1303
+ try {
1304
+ // Verify token from Authorization header
1305
+ const authHeader = req.headers.authorization;
1306
+ if (!authHeader || !authHeader.startsWith('Bearer ')) {
1307
+ res.writeHead(401, { 'Content-Type': 'application/json' });
1308
+ return res.end(JSON.stringify({ error: 'No token provided' }));
1309
+ }
1310
+
1311
+ const token = authHeader.substring(7);
1312
+ const decoded = verifyToken(token);
1313
+
1314
+ if (!decoded) {
1315
+ res.writeHead(401, { 'Content-Type': 'application/json' });
1316
+ return res.end(JSON.stringify({ error: 'Invalid or expired token' }));
1317
+ }
1318
+
1319
+ const user = await UserModel.findById(decoded.id);
1320
+ if (!user) {
1321
+ res.writeHead(404, { 'Content-Type': 'application/json' });
1322
+ return res.end(JSON.stringify({ error: 'User not found' }));
1323
+ }
1324
+
1325
+ res.writeHead(200, { 'Content-Type': 'application/json' });
1326
+ res.end(JSON.stringify({ user: { id: user.id, email: user.email, name: user.name } }));
1327
+ } catch (error) {
1328
+ console.error('Get user error:', error);
1329
+ res.writeHead(500, { 'Content-Type': 'application/json' });
1330
+ res.end(JSON.stringify({ error: 'Failed to get user' }));
1331
+ }
1332
+ }
1333
+
1334
+ // For built-in HTTP server compatibility
1335
+ export function setupAuthRoutes() {
1336
+ return [
1337
+ {
1338
+ path: '/api/auth/register',
1339
+ method: 'POST',
1340
+ handler: registerHandler
1341
+ },
1342
+ {
1343
+ path: '/api/auth/login',
1344
+ method: 'POST',
1345
+ handler: loginHandler
1346
+ },
1347
+ {
1348
+ path: '/api/auth/me',
1349
+ method: 'GET',
1350
+ handler: meHandler
1351
+ }
1352
+ ];
1353
+ }
1159
1354
  `,
1160
1355
  fastify: `
1161
1356
  import { generateToken } from '../plugins/auth.js';
@@ -1504,6 +1699,73 @@ router.post('/users', {
1504
1699
  }
1505
1700
  });
1506
1701
 
1702
+ // Handler for GET /api/users/:id
1703
+ export async function getUsersByIdHandler(req, res) {
1704
+ try {
1705
+ // Extract ID from URL parameters
1706
+ const { id } = req.params;
1707
+
1708
+ // Call the original handler
1709
+ const result = await router.handle('GET', '/users/:id', { params: { id } }, {});
1710
+
1711
+ // Send JSON response
1712
+ res.writeHead(200, { 'Content-Type': 'application/json' });
1713
+ res.end(JSON.stringify(result));
1714
+ } catch (error) {
1715
+ console.error('API Error:', error);
1716
+ res.writeHead(500, { 'Content-Type': 'application/json' });
1717
+ res.end(JSON.stringify({ error: 'Internal server error' }));
1718
+ }
1719
+ }
1720
+
1721
+ // Handler for POST /api/users
1722
+ export async function postUsersHandler(req, res) {
1723
+ try {
1724
+ // Parse JSON body
1725
+ let body = '';
1726
+ req.on('data', chunk => {
1727
+ body += chunk.toString();
1728
+ });
1729
+
1730
+ req.on('end', async () => {
1731
+ try {
1732
+ const parsedBody = JSON.parse(body);
1733
+
1734
+ // Call the original handler
1735
+ const result = await router.handle('POST', '/users', { body: parsedBody }, {});
1736
+
1737
+ // Send JSON response
1738
+ res.writeHead(200, { 'Content-Type': 'application/json' });
1739
+ res.end(JSON.stringify(result));
1740
+ } catch (error) {
1741
+ console.error('API Error:', error);
1742
+ res.writeHead(500, { 'Content-Type': 'application/json' });
1743
+ res.end(JSON.stringify({ error: 'Internal server error' }));
1744
+ }
1745
+ });
1746
+ } catch (error) {
1747
+ console.error('API Error:', error);
1748
+ res.writeHead(500, { 'Content-Type': 'application/json' });
1749
+ res.end(JSON.stringify({ error: 'Internal server error' }));
1750
+ }
1751
+ }
1752
+
1753
+ // For built-in HTTP server compatibility
1754
+ export function setupRoutes() {
1755
+ return [
1756
+ {
1757
+ path: '/api/users/:id',
1758
+ method: 'GET',
1759
+ handler: getUsersByIdHandler
1760
+ },
1761
+ {
1762
+ path: '/api/users',
1763
+ method: 'POST',
1764
+ handler: postUsersHandler
1765
+ }
1766
+ ];
1767
+ }
1768
+
1507
1769
  export default router;
1508
1770
  `;
1509
1771
  return {
@@ -2295,16 +2557,16 @@ A Coherent.js application built with pure JavaScript objects.
2295
2557
 
2296
2558
  \`\`\`bash
2297
2559
  # Install dependencies
2298
- npm install
2560
+ pnpm install
2299
2561
 
2300
2562
  # Start development server
2301
- npm run dev
2563
+ pnpm run dev
2302
2564
 
2303
2565
  # Build for production
2304
- npm run build
2566
+ pnpm run build
2305
2567
 
2306
2568
  # Run tests
2307
- npm test
2569
+ pnpm test
2308
2570
  \`\`\`
2309
2571
 
2310
2572
  ## Project Structure
@@ -2323,7 +2585,7 @@ tests/ # Test files
2323
2585
  ## Learn More
2324
2586
 
2325
2587
  - [Coherent.js Documentation](https://github.com/Tomdrouv1/coherent.js)
2326
- - [API Reference](https://github.com/Tomdrouv1/coherent.js/docs/api-reference.md)
2588
+ - [API Reference](https://github.com/Tomdrouv1/coherent.js/tree/main/docs/api-reference.md)
2327
2589
 
2328
2590
  ## License
2329
2591
 
@@ -2387,21 +2649,21 @@ logs
2387
2649
  .node_repl_history
2388
2650
  `;
2389
2651
  writeFileSync(join2(projectPath, ".gitignore"), gitignore);
2390
- const testFile = `import { test } from 'node:test';
2391
- import assert from 'node:assert';
2652
+ const testFile = `import { describe, it, expect } from 'vitest';
2392
2653
  import { render } from '@coherent.js/core';
2393
2654
 
2394
- test('renders basic component', () => {
2395
- const component = {
2396
- div: {
2397
- text: 'Hello, World!'
2398
- }
2399
- };
2655
+ describe('Basic Component Rendering', () => {
2656
+ it('renders basic component', () => {
2657
+ const component = {
2658
+ div: {
2659
+ text: 'Hello, World!'
2660
+ }
2661
+ };
2400
2662
 
2401
- const html = render(component);
2402
- assert(html.includes('Hello, World!'));
2403
- });
2404
- `;
2663
+ const html = render(component);
2664
+ expect(html).toContain('Hello, World!');
2665
+ });
2666
+ });`;
2405
2667
  writeFileSync(join2(projectPath, "tests/basic.test.js"), testFile);
2406
2668
  }
2407
2669
 
@@ -2776,7 +3038,7 @@ function generateBasicComponent(name) {
2776
3038
 
2777
3039
  /**
2778
3040
  * ${name} component
2779
- *
3041
+ *
2780
3042
  * @param {Object} props - Component properties
2781
3043
  * @param {string} props.className - CSS class name
2782
3044
  * @param {Array|Object} props.children - Child elements
@@ -2803,7 +3065,7 @@ function generateFunctionalComponent(name) {
2803
3065
 
2804
3066
  /**
2805
3067
  * ${name} - Functional component with business logic
2806
- *
3068
+ *
2807
3069
  * @param {Object} props - Component properties
2808
3070
  * @param {Array} props.items - Items to display
2809
3071
  * @param {Function} props.onItemClick - Callback for item clicks
@@ -2821,11 +3083,11 @@ export const ${name} = createComponent(({ items = [], onItemClick, className = '
2821
3083
  div: {
2822
3084
  className: \`${name.toLowerCase()} \${className}\`.trim(),
2823
3085
  children: [
2824
- {
2825
- h3: {
3086
+ {
3087
+ h3: {
2826
3088
  className: '${name.toLowerCase()}__title',
2827
- text: '${name}'
2828
- }
3089
+ text: '${name}'
3090
+ }
2829
3091
  },
2830
3092
  {
2831
3093
  ul: {
@@ -2868,17 +3130,17 @@ function generateInteractiveComponent(name) {
2868
3130
 
2869
3131
  /**
2870
3132
  * ${name} - Interactive component with state management
2871
- *
3133
+ *
2872
3134
  * @param {Object} props - Component properties
2873
3135
  * @param {*} props.initialValue - Initial value
2874
3136
  * @param {Function} props.onChange - Change callback
2875
3137
  * @param {string} props.className - CSS class name
2876
3138
  */
2877
- export const ${name} = createComponent(({
2878
- initialValue = '',
3139
+ export const ${name} = createComponent(({
3140
+ initialValue = '',
2879
3141
  onChange,
2880
3142
  className = '',
2881
- ...props
3143
+ ...props
2882
3144
  }) => {
2883
3145
  // Component state (handled by Coherent.js hydration)
2884
3146
  const state = {
@@ -2955,7 +3217,7 @@ function generateLayoutComponent(name) {
2955
3217
 
2956
3218
  /**
2957
3219
  * ${name} - Layout component for page structure
2958
- *
3220
+ *
2959
3221
  * @param {Object} props - Component properties
2960
3222
  * @param {string} props.title - Page title
2961
3223
  * @param {Array|Object} props.children - Child content
@@ -2963,7 +3225,7 @@ function generateLayoutComponent(name) {
2963
3225
  * @param {Object} props.footer - Footer content
2964
3226
  * @param {string} props.className - CSS class name
2965
3227
  */
2966
- export const ${name} = createComponent(({
3228
+ export const ${name} = createComponent(({
2967
3229
  title = 'Page Title',
2968
3230
  children = [],
2969
3231
  header = null,
@@ -3037,38 +3299,39 @@ export const ${name} = createComponent(({
3037
3299
  `;
3038
3300
  }
3039
3301
  function generateTestContent(name) {
3040
- return `import { test } from 'node:test';
3041
- import assert from 'node:assert';
3302
+ return `import { describe, it, expect } from 'vitest';
3042
3303
  import { render } from '@coherent.js/core';
3043
3304
  import { ${name} } from './${name}.js';
3044
3305
 
3045
- test('${name} renders correctly', () => {
3046
- const component = ${name}({});
3047
- const html = render(component);
3048
-
3049
- assert(typeof html === 'string');
3050
- assert(html.length > 0);
3051
- assert(html.includes('${name.toLowerCase()}'));
3052
- });
3306
+ describe('${name}', () => {
3307
+ it('renders correctly', () => {
3308
+ const component = ${name}({});
3309
+ const html = render(component);
3053
3310
 
3054
- test('${name} accepts className prop', () => {
3055
- const component = ${name}({ className: 'test-class' });
3056
- const html = render(component);
3057
-
3058
- assert(html.includes('test-class'));
3059
- });
3311
+ expect(typeof html).toBe('string');
3312
+ expect(html.length).toBeGreaterThan(0);
3313
+ expect(html).toContain('${name.toLowerCase()}');
3314
+ });
3060
3315
 
3061
- test('${name} renders children correctly', () => {
3062
- const children = [
3063
- { p: { text: 'Test child content' } }
3064
- ];
3065
-
3066
- const component = ${name}({ children });
3067
- const html = render(component);
3068
-
3069
- assert(html.includes('Test child content'));
3316
+ it('accepts className prop', () => {
3317
+ const component = ${name}({ className: 'test-class' });
3318
+ const html = render(component);
3319
+
3320
+ expect(html).toContain('test-class');
3321
+ });
3070
3322
  });
3071
- `;
3323
+
3324
+ it('renders children correctly', () => {
3325
+ const children = [
3326
+ { p: { text: 'Test child content' } }
3327
+ ];
3328
+
3329
+ const component = ${name}({ children });
3330
+ const html = render(component);
3331
+
3332
+ expect(html).toContain('Test child content');
3333
+ });
3334
+ });`;
3072
3335
  }
3073
3336
  function generateStoryContent(name) {
3074
3337
  return `import { ${name} } from './${name}.js';
@@ -3161,7 +3424,7 @@ function generateBasicPage(name) {
3161
3424
  /**
3162
3425
  * ${name} Page Component
3163
3426
  * Route: /${routeName}
3164
- *
3427
+ *
3165
3428
  * @param {Object} props - Page properties
3166
3429
  * @param {Object} props.params - Route parameters
3167
3430
  * @param {Object} props.query - Query parameters
@@ -3179,17 +3442,17 @@ export const ${name} = createComponent(({ params = {}, query = {}, request, ...p
3179
3442
  head: {
3180
3443
  children: [
3181
3444
  { title: { text: pageTitle } },
3182
- {
3183
- meta: {
3445
+ {
3446
+ meta: {
3184
3447
  name: 'description',
3185
3448
  content: pageDescription
3186
- }
3449
+ }
3187
3450
  },
3188
- {
3189
- meta: {
3190
- name: 'viewport',
3191
- content: 'width=device-width, initial-scale=1.0'
3192
- }
3451
+ {
3452
+ meta: {
3453
+ name: 'viewport',
3454
+ content: 'width=device-width, initial-scale=1.0'
3455
+ }
3193
3456
  }
3194
3457
  ]
3195
3458
  }
@@ -3300,10 +3563,10 @@ ${name}.description = '${name} page description';
3300
3563
 
3301
3564
  // Usage in router:
3302
3565
  // app.get('/${routeName}', (req, res) => {
3303
- // const html = render(${name}({
3304
- // params: req.params,
3566
+ // const html = render(${name}({
3567
+ // params: req.params,
3305
3568
  // query: req.query,
3306
- // request: req
3569
+ // request: req
3307
3570
  // }));
3308
3571
  // res.send(html);
3309
3572
  // });
@@ -3331,11 +3594,11 @@ export const ${name} = createComponent(({ stats = {}, user = null }) => {
3331
3594
  head: {
3332
3595
  children: [
3333
3596
  { title: { text: '${name} Dashboard' } },
3334
- {
3335
- meta: {
3336
- name: 'viewport',
3337
- content: 'width=device-width, initial-scale=1.0'
3338
- }
3597
+ {
3598
+ meta: {
3599
+ name: 'viewport',
3600
+ content: 'width=device-width, initial-scale=1.0'
3601
+ }
3339
3602
  }
3340
3603
  ]
3341
3604
  }
@@ -3486,11 +3749,11 @@ export const ${name} = createComponent(({ initialData = {}, errors = {} }) => {
3486
3749
  head: {
3487
3750
  children: [
3488
3751
  { title: { text: '${name} Form' } },
3489
- {
3490
- meta: {
3491
- name: 'viewport',
3492
- content: 'width=device-width, initial-scale=1.0'
3493
- }
3752
+ {
3753
+ meta: {
3754
+ name: 'viewport',
3755
+ content: 'width=device-width, initial-scale=1.0'
3756
+ }
3494
3757
  }
3495
3758
  ]
3496
3759
  }
@@ -3630,42 +3893,42 @@ export const ${name} = createComponent(({ initialData = {}, errors = {} }) => {
3630
3893
  `;
3631
3894
  }
3632
3895
  function generateTestContent2(name) {
3633
- return `import { test } from 'node:test';
3634
- import assert from 'node:assert';
3896
+ return `import { describe, it, expect } from 'vitest';
3635
3897
  import { render } from '@coherent.js/core';
3636
3898
  import { ${name} } from './${name}.js';
3637
3899
 
3638
- test('${name} page renders correctly', () => {
3639
- const page = ${name}({});
3640
- const html = render(page);
3641
-
3642
- assert(typeof html === 'string');
3643
- assert(html.length > 0);
3644
- assert(html.includes('<html>'));
3645
- assert(html.includes('${name}'));
3646
- });
3900
+ describe('${name} Page', () => {
3901
+ it('renders correctly', () => {
3902
+ const page = ${name}({});
3903
+ const html = render(page);
3647
3904
 
3648
- test('${name} page includes proper head elements', () => {
3905
+ expect(typeof html).toBe('string');
3906
+ expect(html.length).toBeGreaterThan(0);
3907
+ expect(html).toContain('<html>');
3908
+ expect(html).toContain('${name}');
3909
+ });
3910
+
3911
+ it('includes proper head elements', () => {
3649
3912
  const page = ${name}({});
3650
- const html = render(page);
3651
-
3652
- assert(html.includes('<title>'));
3653
- assert(html.includes('<meta'));
3654
- assert(html.includes('viewport'));
3655
- });
3913
+ const html = render(page);
3914
+
3915
+ expect(html).toContain('<title>');
3916
+ expect(html).toContain('<meta');
3917
+ expect(html).toContain('viewport');
3918
+ });
3919
+
3920
+ it('renders with custom props', () => {
3921
+ const props = {
3922
+ params: { id: '123' },
3923
+ query: { search: 'test' }
3924
+ };
3656
3925
 
3657
- test('${name} page renders with custom props', () => {
3658
- const props = {
3659
- params: { id: '123' },
3660
- query: { search: 'test' }
3661
- };
3662
-
3663
3926
  const page = ${name}(props);
3664
- const html = render(page);
3665
-
3666
- assert(html.includes('${name}'));
3667
- });
3668
- `;
3927
+ const html = render(page);
3928
+
3929
+ expect(html).toContain('${name}');
3930
+ });
3931
+ });`;
3669
3932
  }
3670
3933
  function toPascalCase2(str) {
3671
3934
  return str.replace(/[-_\s]+(.)?/g, (_, c) => c ? c.toUpperCase() : "").replace(/^(.)/, (_, c) => c.toUpperCase());
@@ -3722,7 +3985,7 @@ function generateRESTAPI(apiName, originalName) {
3722
3985
  /**
3723
3986
  * ${className} API Routes
3724
3987
  * REST API for ${apiName} resources
3725
- *
3988
+ *
3726
3989
  * Base URL: /api/${apiName}
3727
3990
  */
3728
3991
 
@@ -3742,14 +4005,14 @@ const sampleData = [
3742
4005
  const ${apiName}Schema = {
3743
4006
  type: 'object',
3744
4007
  properties: {
3745
- name: {
3746
- type: 'string',
4008
+ name: {
4009
+ type: 'string',
3747
4010
  minLength: 1,
3748
- maxLength: 100
4011
+ maxLength: 100
3749
4012
  },
3750
- description: {
4013
+ description: {
3751
4014
  type: 'string',
3752
- maxLength: 500
4015
+ maxLength: 500
3753
4016
  }
3754
4017
  },
3755
4018
  required: ['name'],
@@ -3759,14 +4022,14 @@ const ${apiName}Schema = {
3759
4022
  const ${apiName}UpdateSchema = {
3760
4023
  type: 'object',
3761
4024
  properties: {
3762
- name: {
3763
- type: 'string',
4025
+ name: {
4026
+ type: 'string',
3764
4027
  minLength: 1,
3765
- maxLength: 100
4028
+ maxLength: 100
3766
4029
  },
3767
- description: {
4030
+ description: {
3768
4031
  type: 'string',
3769
- maxLength: 500
4032
+ maxLength: 500
3770
4033
  }
3771
4034
  },
3772
4035
  additionalProperties: false,
@@ -3781,21 +4044,21 @@ const ${apiName}UpdateSchema = {
3781
4044
  */
3782
4045
  ${camelCaseApiName}API.get('/', (req, res) => {
3783
4046
  const { page = 1, limit = 10, search } = req.query;
3784
-
4047
+
3785
4048
  let data = [...sampleData];
3786
-
4049
+
3787
4050
  // Apply search filter
3788
4051
  if (search) {
3789
- data = data.filter(item =>
4052
+ data = data.filter(item =>
3790
4053
  item.name.toLowerCase().includes(search.toLowerCase())
3791
4054
  );
3792
4055
  }
3793
-
4056
+
3794
4057
  // Apply pagination
3795
4058
  const startIndex = (page - 1) * limit;
3796
4059
  const endIndex = startIndex + parseInt(limit);
3797
4060
  const paginatedData = data.slice(startIndex, endIndex);
3798
-
4061
+
3799
4062
  return {
3800
4063
  data: paginatedData,
3801
4064
  pagination: {
@@ -3814,14 +4077,14 @@ ${camelCaseApiName}API.get('/', (req, res) => {
3814
4077
  ${camelCaseApiName}API.get('/:id', (req, res) => {
3815
4078
  const { id } = req.params;
3816
4079
  const item = sampleData.find(item => item.id === id);
3817
-
4080
+
3818
4081
  if (!item) {
3819
4082
  return res.status(404).json({
3820
4083
  _error: '${className} not found',
3821
4084
  code: 'NOT_FOUND'
3822
4085
  });
3823
4086
  }
3824
-
4087
+
3825
4088
  return { data: item };
3826
4089
  });
3827
4090
 
@@ -3829,11 +4092,11 @@ ${camelCaseApiName}API.get('/:id', (req, res) => {
3829
4092
  * POST /${apiName}
3830
4093
  * Create a new ${apiName} item
3831
4094
  */
3832
- ${camelCaseApiName}API.post('/',
4095
+ ${camelCaseApiName}API.post('/',
3833
4096
  withValidation(${apiName}Schema),
3834
4097
  (req, res) => {
3835
4098
  const { name, description } = req.body;
3836
-
4099
+
3837
4100
  const newItem = {
3838
4101
  id: String(Date.now()),
3839
4102
  name,
@@ -3841,9 +4104,9 @@ ${camelCaseApiName}API.post('/',
3841
4104
  createdAt: new Date().toISOString(),
3842
4105
  updatedAt: new Date().toISOString()
3843
4106
  };
3844
-
4107
+
3845
4108
  sampleData.push(newItem);
3846
-
4109
+
3847
4110
  return res.status(201).json({
3848
4111
  data: newItem,
3849
4112
  message: '${className} created successfully'
@@ -3860,22 +4123,22 @@ ${camelCaseApiName}API.put('/:id',
3860
4123
  (req, res) => {
3861
4124
  const { id } = req.params;
3862
4125
  const itemIndex = sampleData.findIndex(item => item.id === id);
3863
-
4126
+
3864
4127
  if (itemIndex === -1) {
3865
4128
  return res.status(404).json({
3866
4129
  _error: '${className} not found',
3867
4130
  code: 'NOT_FOUND'
3868
4131
  });
3869
4132
  }
3870
-
4133
+
3871
4134
  const updatedItem = {
3872
4135
  ...sampleData[itemIndex],
3873
4136
  ...req.body,
3874
4137
  updatedAt: new Date().toISOString()
3875
4138
  };
3876
-
4139
+
3877
4140
  sampleData[itemIndex] = updatedItem;
3878
-
4141
+
3879
4142
  return {
3880
4143
  data: updatedItem,
3881
4144
  message: '${className} updated successfully'
@@ -3890,16 +4153,16 @@ ${camelCaseApiName}API.put('/:id',
3890
4153
  ${camelCaseApiName}API.delete('/:id', (req, res) => {
3891
4154
  const { id } = req.params;
3892
4155
  const itemIndex = sampleData.findIndex(item => item.id === id);
3893
-
4156
+
3894
4157
  if (itemIndex === -1) {
3895
4158
  return res.status(404).json({
3896
4159
  _error: '${className} not found',
3897
4160
  code: 'NOT_FOUND'
3898
4161
  });
3899
4162
  }
3900
-
4163
+
3901
4164
  const deletedItem = sampleData.splice(itemIndex, 1)[0];
3902
-
4165
+
3903
4166
  return {
3904
4167
  data: deletedItem,
3905
4168
  message: '${className} deleted successfully'
@@ -3920,7 +4183,7 @@ export default ${camelCaseApiName}API;
3920
4183
  // Usage example:
3921
4184
  // import express from 'express';
3922
4185
  // import ${camelCaseApiName}API from './api/${apiName}.js';
3923
- //
4186
+ //
3924
4187
  // const app = express();
3925
4188
  // app.use(express.json());
3926
4189
  // app.use('/api', ${camelCaseApiName}API.toExpress());
@@ -3941,7 +4204,7 @@ function generateRPCAPI(apiName, originalName) {
3941
4204
  /**
3942
4205
  * ${className} RPC API
3943
4206
  * Remote Procedure Call API for ${apiName}
3944
- *
4207
+ *
3945
4208
  * Base URL: /rpc/${apiName}
3946
4209
  */
3947
4210
 
@@ -3964,10 +4227,10 @@ sampleData.set('2', { id: '2', name: 'Sample ${className} 2', createdAt: new Dat
3964
4227
  ${camelCaseApiName}RPC.post('/list', (req, res) => {
3965
4228
  const { params = {} } = req.body;
3966
4229
  const { limit = 10, offset = 0 } = params;
3967
-
4230
+
3968
4231
  const items = Array.from(sampleData.values())
3969
4232
  .slice(offset, offset + limit);
3970
-
4233
+
3971
4234
  return {
3972
4235
  jsonrpc: '2.0',
3973
4236
  result: {
@@ -3982,7 +4245,7 @@ ${camelCaseApiName}RPC.post('/list', (req, res) => {
3982
4245
  * RPC Method: ${apiName}.get
3983
4246
  * Get a specific ${apiName} item
3984
4247
  */
3985
- ${camelCaseApiName}RPC.post('/get',
4248
+ ${camelCaseApiName}RPC.post('/get',
3986
4249
  withValidation({
3987
4250
  type: 'object',
3988
4251
  properties: {
@@ -3999,7 +4262,7 @@ ${camelCaseApiName}RPC.post('/get',
3999
4262
  (req, res) => {
4000
4263
  const { params } = req.body;
4001
4264
  const item = sampleData.get(params.id);
4002
-
4265
+
4003
4266
  if (!item) {
4004
4267
  return {
4005
4268
  jsonrpc: '2.0',
@@ -4010,7 +4273,7 @@ ${camelCaseApiName}RPC.post('/get',
4010
4273
  id: req.body.id
4011
4274
  };
4012
4275
  }
4013
-
4276
+
4014
4277
  return {
4015
4278
  jsonrpc: '2.0',
4016
4279
  result: item,
@@ -4041,16 +4304,16 @@ ${camelCaseApiName}RPC.post('/create',
4041
4304
  (req, res) => {
4042
4305
  const { params } = req.body;
4043
4306
  const id = String(Date.now());
4044
-
4307
+
4045
4308
  const newItem = {
4046
4309
  id,
4047
4310
  ...params,
4048
4311
  createdAt: new Date(),
4049
4312
  updatedAt: new Date()
4050
4313
  };
4051
-
4314
+
4052
4315
  sampleData.set(id, newItem);
4053
-
4316
+
4054
4317
  return {
4055
4318
  jsonrpc: '2.0',
4056
4319
  result: newItem,
@@ -4082,7 +4345,7 @@ ${camelCaseApiName}RPC.post('/update',
4082
4345
  (req, res) => {
4083
4346
  const { params } = req.body;
4084
4347
  const existing = sampleData.get(params.id);
4085
-
4348
+
4086
4349
  if (!existing) {
4087
4350
  return {
4088
4351
  jsonrpc: '2.0',
@@ -4093,15 +4356,15 @@ ${camelCaseApiName}RPC.post('/update',
4093
4356
  id: req.body.id
4094
4357
  };
4095
4358
  }
4096
-
4359
+
4097
4360
  const updated = {
4098
4361
  ...existing,
4099
4362
  ...params,
4100
4363
  updatedAt: new Date()
4101
4364
  };
4102
-
4365
+
4103
4366
  sampleData.set(params.id, updated);
4104
-
4367
+
4105
4368
  return {
4106
4369
  jsonrpc: '2.0',
4107
4370
  result: updated,
@@ -4131,7 +4394,7 @@ ${camelCaseApiName}RPC.post('/delete',
4131
4394
  (req, res) => {
4132
4395
  const { params } = req.body;
4133
4396
  const item = sampleData.get(params.id);
4134
-
4397
+
4135
4398
  if (!item) {
4136
4399
  return {
4137
4400
  jsonrpc: '2.0',
@@ -4142,9 +4405,9 @@ ${camelCaseApiName}RPC.post('/delete',
4142
4405
  id: req.body.id
4143
4406
  };
4144
4407
  }
4145
-
4408
+
4146
4409
  sampleData.delete(params.id);
4147
-
4410
+
4148
4411
  return {
4149
4412
  jsonrpc: '2.0',
4150
4413
  result: { success: true, deleted: item },
@@ -4158,17 +4421,17 @@ export default ${camelCaseApiName}RPC;
4158
4421
  }
4159
4422
  function generateTestContent3(apiName, originalName) {
4160
4423
  const className = toPascalCase3(originalName);
4161
- return `import { test } from 'node:test';
4162
- import assert from 'node:assert';
4424
+ return `import { describe, it, expect } from 'vitest';
4163
4425
  import ${apiName}API from './${apiName}.js';
4164
4426
 
4165
- test('${className} API should be defined', () => {
4166
- assert(typeof ${apiName}API === 'object');
4167
- assert(typeof ${apiName}API.get === 'function');
4168
- assert(typeof ${apiName}API.post === 'function');
4427
+ describe('${className} API', () => {
4428
+ it('should be defined', () => {
4429
+ expect(typeof ${apiName}API).toBe('object');
4430
+ expect(typeof ${apiName}API.get).toBe('function');
4431
+ expect(typeof ${apiName}API.post).toBe('function');
4169
4432
  });
4170
4433
 
4171
- test('${className} API should handle GET requests', async () => {
4434
+ it('should handle GET requests', async () => {
4172
4435
  const mockReq = {
4173
4436
  query: {}
4174
4437
  };
@@ -4176,15 +4439,15 @@ test('${className} API should handle GET requests', async () => {
4176
4439
  status: (code) => mockRes,
4177
4440
  json: (data) => data
4178
4441
  };
4179
-
4442
+
4180
4443
  // This is a basic test structure
4181
4444
  // In a real test, you'd use a testing framework like supertest
4182
- assert(true); // Placeholder
4445
+ expect(true).toBe(true); // Placeholder
4183
4446
  });
4184
4447
 
4185
4448
  // Add more specific tests for your API endpoints
4186
4449
  // Example:
4187
- // test('POST /${apiName} should create new item', async () => {
4450
+ // it('POST /${apiName} should create new item', async () => {
4188
4451
  // // Test implementation
4189
4452
  // });
4190
4453
  //
@@ -4753,7 +5016,7 @@ function expand_(str, isTop) {
4753
5016
  return expansions;
4754
5017
  }
4755
5018
 
4756
- // ../../node_modules/.pnpm/minimatch@10.0.3/node_modules/minimatch/dist/esm/assert-valid-pattern.js
5019
+ // ../../node_modules/.pnpm/minimatch@10.1.1/node_modules/minimatch/dist/esm/assert-valid-pattern.js
4757
5020
  var MAX_PATTERN_LENGTH = 1024 * 64;
4758
5021
  var assertValidPattern = (pattern) => {
4759
5022
  if (typeof pattern !== "string") {
@@ -4764,7 +5027,7 @@ var assertValidPattern = (pattern) => {
4764
5027
  }
4765
5028
  };
4766
5029
 
4767
- // ../../node_modules/.pnpm/minimatch@10.0.3/node_modules/minimatch/dist/esm/brace-expressions.js
5030
+ // ../../node_modules/.pnpm/minimatch@10.1.1/node_modules/minimatch/dist/esm/brace-expressions.js
4768
5031
  var posixClasses = {
4769
5032
  "[:alnum:]": ["\\p{L}\\p{Nl}\\p{Nd}", true],
4770
5033
  "[:alpha:]": ["\\p{L}\\p{Nl}", true],
@@ -4873,12 +5136,15 @@ var parseClass = (glob2, position) => {
4873
5136
  return [comb, uflag, endPos - pos, true];
4874
5137
  };
4875
5138
 
4876
- // ../../node_modules/.pnpm/minimatch@10.0.3/node_modules/minimatch/dist/esm/unescape.js
4877
- var unescape = (s, { windowsPathsNoEscape = false } = {}) => {
4878
- return windowsPathsNoEscape ? s.replace(/\[([^\/\\])\]/g, "$1") : s.replace(/((?!\\).|^)\[([^\/\\])\]/g, "$1$2").replace(/\\([^\/])/g, "$1");
5139
+ // ../../node_modules/.pnpm/minimatch@10.1.1/node_modules/minimatch/dist/esm/unescape.js
5140
+ var unescape = (s, { windowsPathsNoEscape = false, magicalBraces = true } = {}) => {
5141
+ if (magicalBraces) {
5142
+ return windowsPathsNoEscape ? s.replace(/\[([^\/\\])\]/g, "$1") : s.replace(/((?!\\).|^)\[([^\/\\])\]/g, "$1$2").replace(/\\([^\/])/g, "$1");
5143
+ }
5144
+ return windowsPathsNoEscape ? s.replace(/\[([^\/\\{}])\]/g, "$1") : s.replace(/((?!\\).|^)\[([^\/\\{}])\]/g, "$1$2").replace(/\\([^\/{}])/g, "$1");
4879
5145
  };
4880
5146
 
4881
- // ../../node_modules/.pnpm/minimatch@10.0.3/node_modules/minimatch/dist/esm/ast.js
5147
+ // ../../node_modules/.pnpm/minimatch@10.1.1/node_modules/minimatch/dist/esm/ast.js
4882
5148
  var types = /* @__PURE__ */ new Set(["!", "?", "+", "*", "@"]);
4883
5149
  var isExtglobType = (c) => types.has(c);
4884
5150
  var startNoTraversal = "(?!(?:^|/)\\.\\.?(?:$|/))";
@@ -5229,7 +5495,7 @@ var AST = class _AST {
5229
5495
  if (this.#root === this)
5230
5496
  this.#fillNegs();
5231
5497
  if (!this.type) {
5232
- const noEmpty = this.isStart() && this.isEnd();
5498
+ const noEmpty = this.isStart() && this.isEnd() && !this.#parts.some((s) => typeof s !== "string");
5233
5499
  const src = this.#parts.map((p) => {
5234
5500
  const [re, _, hasMagic2, uflag] = typeof p === "string" ? _AST.#parseGlob(p, this.#hasMagic, noEmpty) : p.toRegExpSource(allowDot);
5235
5501
  this.#hasMagic = this.#hasMagic || hasMagic2;
@@ -5339,10 +5605,7 @@ var AST = class _AST {
5339
5605
  }
5340
5606
  }
5341
5607
  if (c === "*") {
5342
- if (noEmpty && glob2 === "*")
5343
- re += starNoEmpty;
5344
- else
5345
- re += star;
5608
+ re += noEmpty && glob2 === "*" ? starNoEmpty : star;
5346
5609
  hasMagic2 = true;
5347
5610
  continue;
5348
5611
  }
@@ -5357,12 +5620,15 @@ var AST = class _AST {
5357
5620
  }
5358
5621
  };
5359
5622
 
5360
- // ../../node_modules/.pnpm/minimatch@10.0.3/node_modules/minimatch/dist/esm/escape.js
5361
- var escape = (s, { windowsPathsNoEscape = false } = {}) => {
5623
+ // ../../node_modules/.pnpm/minimatch@10.1.1/node_modules/minimatch/dist/esm/escape.js
5624
+ var escape = (s, { windowsPathsNoEscape = false, magicalBraces = false } = {}) => {
5625
+ if (magicalBraces) {
5626
+ return windowsPathsNoEscape ? s.replace(/[?*()[\]{}]/g, "[$&]") : s.replace(/[?*()[\]\\{}]/g, "\\$&");
5627
+ }
5362
5628
  return windowsPathsNoEscape ? s.replace(/[?*()[\]]/g, "[$&]") : s.replace(/[?*()[\]\\]/g, "\\$&");
5363
5629
  };
5364
5630
 
5365
- // ../../node_modules/.pnpm/minimatch@10.0.3/node_modules/minimatch/dist/esm/index.js
5631
+ // ../../node_modules/.pnpm/minimatch@10.1.1/node_modules/minimatch/dist/esm/index.js
5366
5632
  var minimatch = (p, pattern, options = {}) => {
5367
5633
  assertValidPattern(pattern);
5368
5634
  if (!options.nocomment && pattern.charAt(0) === "#") {
@@ -5999,16 +6265,27 @@ var Minimatch = class {
5999
6265
  pp[i] = twoStar;
6000
6266
  }
6001
6267
  } else if (next === void 0) {
6002
- pp[i - 1] = prev + "(?:\\/|" + twoStar + ")?";
6268
+ pp[i - 1] = prev + "(?:\\/|\\/" + twoStar + ")?";
6003
6269
  } else if (next !== GLOBSTAR) {
6004
6270
  pp[i - 1] = prev + "(?:\\/|\\/" + twoStar + "\\/)" + next;
6005
6271
  pp[i + 1] = GLOBSTAR;
6006
6272
  }
6007
6273
  });
6008
- return pp.filter((p) => p !== GLOBSTAR).join("/");
6274
+ const filtered = pp.filter((p) => p !== GLOBSTAR);
6275
+ if (this.partial && filtered.length >= 1) {
6276
+ const prefixes = [];
6277
+ for (let i = 1; i <= filtered.length; i++) {
6278
+ prefixes.push(filtered.slice(0, i).join("/"));
6279
+ }
6280
+ return "(?:" + prefixes.join("|") + ")";
6281
+ }
6282
+ return filtered.join("/");
6009
6283
  }).join("|");
6010
6284
  const [open, close] = set.length > 1 ? ["(?:", ")"] : ["", ""];
6011
6285
  re = "^" + open + re + close + "$";
6286
+ if (this.partial) {
6287
+ re = "^(?:\\/|" + open + re.slice(1, -1) + close + ")$";
6288
+ }
6012
6289
  if (this.negate)
6013
6290
  re = "^(?!" + re + ").+$";
6014
6291
  try {
@@ -6080,10 +6357,10 @@ minimatch.Minimatch = Minimatch;
6080
6357
  minimatch.escape = escape;
6081
6358
  minimatch.unescape = unescape;
6082
6359
 
6083
- // ../../node_modules/.pnpm/glob@11.0.3/node_modules/glob/dist/esm/glob.js
6360
+ // ../../node_modules/.pnpm/glob@11.1.0/node_modules/glob/dist/esm/glob.js
6084
6361
  import { fileURLToPath as fileURLToPath3 } from "node:url";
6085
6362
 
6086
- // ../../node_modules/.pnpm/lru-cache@11.2.1/node_modules/lru-cache/dist/esm/index.js
6363
+ // ../../node_modules/.pnpm/lru-cache@11.2.2/node_modules/lru-cache/dist/esm/index.js
6087
6364
  var defaultPerf = typeof performance === "object" && performance && typeof performance.now === "function" ? performance : Date;
6088
6365
  var warned = /* @__PURE__ */ new Set();
6089
6366
  var PROCESS = typeof process === "object" && !!process ? process : {};
@@ -7129,7 +7406,8 @@ var LRUCache = class _LRUCache {
7129
7406
  return fetchFail(ac.signal.reason);
7130
7407
  }
7131
7408
  const bf2 = p;
7132
- if (this.#valList[index] === p) {
7409
+ const vl = this.#valList[index];
7410
+ if (vl === p || ignoreAbort && updateCache && vl === void 0) {
7133
7411
  if (v2 === void 0) {
7134
7412
  if (bf2.__staleWhileFetching !== void 0) {
7135
7413
  this.#valList[index] = bf2.__staleWhileFetching;
@@ -7483,7 +7761,7 @@ var LRUCache = class _LRUCache {
7483
7761
  }
7484
7762
  };
7485
7763
 
7486
- // ../../node_modules/.pnpm/path-scurry@2.0.0/node_modules/path-scurry/dist/esm/index.js
7764
+ // ../../node_modules/.pnpm/path-scurry@2.0.1/node_modules/path-scurry/dist/esm/index.js
7487
7765
  import { posix, win32 } from "node:path";
7488
7766
  import { fileURLToPath as fileURLToPath2 } from "node:url";
7489
7767
  import { lstatSync, readdir as readdirCB, readdirSync, readlinkSync, realpathSync as rps } from "fs";
@@ -8368,7 +8646,7 @@ var Minipass = class extends EventEmitter {
8368
8646
  }
8369
8647
  };
8370
8648
 
8371
- // ../../node_modules/.pnpm/path-scurry@2.0.0/node_modules/path-scurry/dist/esm/index.js
8649
+ // ../../node_modules/.pnpm/path-scurry@2.0.1/node_modules/path-scurry/dist/esm/index.js
8372
8650
  var realpathSync = rps.native;
8373
8651
  var defaultFS = {
8374
8652
  lstatSync,
@@ -8413,7 +8691,7 @@ var ENOREALPATH = 512;
8413
8691
  var ENOCHILD = ENOTDIR | ENOENT | ENOREALPATH;
8414
8692
  var TYPEMASK = 1023;
8415
8693
  var entToType = (s) => s.isFile() ? IFREG : s.isDirectory() ? IFDIR : s.isSymbolicLink() ? IFLNK : s.isCharacterDevice() ? IFCHR : s.isBlockDevice() ? IFBLK : s.isSocket() ? IFSOCK : s.isFIFO() ? IFIFO : UNKNOWN;
8416
- var normalizeCache = /* @__PURE__ */ new Map();
8694
+ var normalizeCache = new LRUCache({ max: 2 ** 12 });
8417
8695
  var normalize = (s) => {
8418
8696
  const c = normalizeCache.get(s);
8419
8697
  if (c)
@@ -8422,7 +8700,7 @@ var normalize = (s) => {
8422
8700
  normalizeCache.set(s, n);
8423
8701
  return n;
8424
8702
  };
8425
- var normalizeNocaseCache = /* @__PURE__ */ new Map();
8703
+ var normalizeNocaseCache = new LRUCache({ max: 2 ** 12 });
8426
8704
  var normalizeNocase = (s) => {
8427
8705
  const c = normalizeNocaseCache.get(s);
8428
8706
  if (c)
@@ -8579,6 +8857,7 @@ var PathBase = class {
8579
8857
  get parentPath() {
8580
8858
  return (this.parent || this).fullpath();
8581
8859
  }
8860
+ /* c8 ignore start */
8582
8861
  /**
8583
8862
  * Deprecated alias for Dirent['parentPath'] Somewhat counterintuitively,
8584
8863
  * this property refers to the *parent* path, not the path object itself.
@@ -8588,6 +8867,7 @@ var PathBase = class {
8588
8867
  get path() {
8589
8868
  return this.parentPath;
8590
8869
  }
8870
+ /* c8 ignore stop */
8591
8871
  /**
8592
8872
  * Do not create new Path objects directly. They should always be accessed
8593
8873
  * via the PathScurry class or other methods on the Path class.
@@ -10094,7 +10374,7 @@ var PathScurryDarwin = class extends PathScurryPosix {
10094
10374
  var Path = process.platform === "win32" ? PathWin32 : PathPosix;
10095
10375
  var PathScurry = process.platform === "win32" ? PathScurryWin32 : process.platform === "darwin" ? PathScurryDarwin : PathScurryPosix;
10096
10376
 
10097
- // ../../node_modules/.pnpm/glob@11.0.3/node_modules/glob/dist/esm/pattern.js
10377
+ // ../../node_modules/.pnpm/glob@11.1.0/node_modules/glob/dist/esm/pattern.js
10098
10378
  var isPatternList = (pl) => pl.length >= 1;
10099
10379
  var isGlobList = (gl) => gl.length >= 1;
10100
10380
  var Pattern = class _Pattern {
@@ -10259,7 +10539,7 @@ var Pattern = class _Pattern {
10259
10539
  }
10260
10540
  };
10261
10541
 
10262
- // ../../node_modules/.pnpm/glob@11.0.3/node_modules/glob/dist/esm/ignore.js
10542
+ // ../../node_modules/.pnpm/glob@11.1.0/node_modules/glob/dist/esm/ignore.js
10263
10543
  var defaultPlatform2 = typeof process === "object" && process && typeof process.platform === "string" ? process.platform : "linux";
10264
10544
  var Ignore = class {
10265
10545
  relative;
@@ -10346,7 +10626,7 @@ var Ignore = class {
10346
10626
  }
10347
10627
  };
10348
10628
 
10349
- // ../../node_modules/.pnpm/glob@11.0.3/node_modules/glob/dist/esm/processor.js
10629
+ // ../../node_modules/.pnpm/glob@11.1.0/node_modules/glob/dist/esm/processor.js
10350
10630
  var HasWalkedCache = class _HasWalkedCache {
10351
10631
  store;
10352
10632
  constructor(store = /* @__PURE__ */ new Map()) {
@@ -10567,7 +10847,7 @@ var Processor = class _Processor {
10567
10847
  }
10568
10848
  };
10569
10849
 
10570
- // ../../node_modules/.pnpm/glob@11.0.3/node_modules/glob/dist/esm/walker.js
10850
+ // ../../node_modules/.pnpm/glob@11.1.0/node_modules/glob/dist/esm/walker.js
10571
10851
  var makeIgnore = (ignore, opts) => typeof ignore === "string" ? new Ignore([ignore], opts) : Array.isArray(ignore) ? new Ignore(ignore, opts) : ignore;
10572
10852
  var GlobUtil = class {
10573
10853
  path;
@@ -10894,7 +11174,7 @@ var GlobStream = class extends GlobUtil {
10894
11174
  }
10895
11175
  };
10896
11176
 
10897
- // ../../node_modules/.pnpm/glob@11.0.3/node_modules/glob/dist/esm/glob.js
11177
+ // ../../node_modules/.pnpm/glob@11.1.0/node_modules/glob/dist/esm/glob.js
10898
11178
  var defaultPlatform3 = typeof process === "object" && process && typeof process.platform === "string" ? process.platform : "linux";
10899
11179
  var Glob = class {
10900
11180
  absolute;
@@ -11094,7 +11374,7 @@ var Glob = class {
11094
11374
  }
11095
11375
  };
11096
11376
 
11097
- // ../../node_modules/.pnpm/glob@11.0.3/node_modules/glob/dist/esm/has-magic.js
11377
+ // ../../node_modules/.pnpm/glob@11.1.0/node_modules/glob/dist/esm/has-magic.js
11098
11378
  var hasMagic = (pattern, options = {}) => {
11099
11379
  if (!Array.isArray(pattern)) {
11100
11380
  pattern = [pattern];
@@ -11106,7 +11386,7 @@ var hasMagic = (pattern, options = {}) => {
11106
11386
  return false;
11107
11387
  };
11108
11388
 
11109
- // ../../node_modules/.pnpm/glob@11.0.3/node_modules/glob/dist/esm/index.js
11389
+ // ../../node_modules/.pnpm/glob@11.1.0/node_modules/glob/dist/esm/index.js
11110
11390
  function globStreamSync(pattern, options = {}) {
11111
11391
  return new Glob(pattern, options).streamSync();
11112
11392
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coherent.js/cli",
3
- "version": "1.0.0-beta.3",
3
+ "version": "1.0.0-beta.5",
4
4
  "description": "Command-line interface for Coherent.js projects",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -29,7 +29,7 @@
29
29
  },
30
30
  "dependencies": {
31
31
  "commander": "^12.1.0",
32
- "glob": "11.0.3",
32
+ "glob": "11.1.0",
33
33
  "ora": "^8.1.0",
34
34
  "picocolors": "^1.1.1",
35
35
  "prompts": "^2.4.2"
@@ -43,6 +43,7 @@
43
43
  "access": "public",
44
44
  "registry": "https://registry.npmjs.org/"
45
45
  },
46
+ "sideEffects": false,
46
47
  "scripts": {
47
48
  "build": "node build.mjs",
48
49
  "clean": "rm -rf dist/",