@currentjs/gen 0.1.1

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 (55) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/LICENSE +56 -0
  3. package/README.md +686 -0
  4. package/dist/cli.d.ts +2 -0
  5. package/dist/cli.js +143 -0
  6. package/dist/commands/commit.d.ts +1 -0
  7. package/dist/commands/commit.js +153 -0
  8. package/dist/commands/createApp.d.ts +1 -0
  9. package/dist/commands/createApp.js +64 -0
  10. package/dist/commands/createModule.d.ts +1 -0
  11. package/dist/commands/createModule.js +121 -0
  12. package/dist/commands/diff.d.ts +1 -0
  13. package/dist/commands/diff.js +164 -0
  14. package/dist/commands/generateAll.d.ts +4 -0
  15. package/dist/commands/generateAll.js +305 -0
  16. package/dist/commands/infer.d.ts +1 -0
  17. package/dist/commands/infer.js +179 -0
  18. package/dist/generators/controllerGenerator.d.ts +20 -0
  19. package/dist/generators/controllerGenerator.js +280 -0
  20. package/dist/generators/domainModelGenerator.d.ts +33 -0
  21. package/dist/generators/domainModelGenerator.js +175 -0
  22. package/dist/generators/serviceGenerator.d.ts +39 -0
  23. package/dist/generators/serviceGenerator.js +379 -0
  24. package/dist/generators/storeGenerator.d.ts +31 -0
  25. package/dist/generators/storeGenerator.js +191 -0
  26. package/dist/generators/templateGenerator.d.ts +11 -0
  27. package/dist/generators/templateGenerator.js +143 -0
  28. package/dist/generators/templates/appTemplates.d.ts +27 -0
  29. package/dist/generators/templates/appTemplates.js +1621 -0
  30. package/dist/generators/templates/controllerTemplates.d.ts +43 -0
  31. package/dist/generators/templates/controllerTemplates.js +82 -0
  32. package/dist/generators/templates/index.d.ts +5 -0
  33. package/dist/generators/templates/index.js +21 -0
  34. package/dist/generators/templates/serviceTemplates.d.ts +15 -0
  35. package/dist/generators/templates/serviceTemplates.js +54 -0
  36. package/dist/generators/templates/storeTemplates.d.ts +9 -0
  37. package/dist/generators/templates/storeTemplates.js +260 -0
  38. package/dist/generators/templates/validationTemplates.d.ts +25 -0
  39. package/dist/generators/templates/validationTemplates.js +66 -0
  40. package/dist/generators/templates/viewTemplates.d.ts +16 -0
  41. package/dist/generators/templates/viewTemplates.js +359 -0
  42. package/dist/generators/validationGenerator.d.ts +24 -0
  43. package/dist/generators/validationGenerator.js +199 -0
  44. package/dist/utils/cliUtils.d.ts +6 -0
  45. package/dist/utils/cliUtils.js +71 -0
  46. package/dist/utils/colors.d.ts +26 -0
  47. package/dist/utils/colors.js +80 -0
  48. package/dist/utils/commitUtils.d.ts +46 -0
  49. package/dist/utils/commitUtils.js +377 -0
  50. package/dist/utils/constants.d.ts +52 -0
  51. package/dist/utils/constants.js +64 -0
  52. package/dist/utils/generationRegistry.d.ts +25 -0
  53. package/dist/utils/generationRegistry.js +192 -0
  54. package/howto.md +556 -0
  55. package/package.json +44 -0
package/howto.md ADDED
@@ -0,0 +1,556 @@
1
+ # CurrentJS Framework Rules
2
+
3
+ ## Architecture Overview
4
+ This is a CurrentJS framework application using clean architecture principles with the following layers:
5
+ - **Controllers**: Handle HTTP requests/responses and route handling
6
+ - **Services**: Contain business logic and orchestrate operations
7
+ - **Stores**: Provide data access layer and database operations
8
+ - **Domain Entities**: Core business models
9
+ - **Views**: HTML templates for server-side rendering
10
+
11
+ ## Commands
12
+
13
+ ```bash
14
+ current create module Modulename # Creates "Modulename" with default structure and yaml file
15
+ ```
16
+ ```bash
17
+ current generate Modulename # Generates all TypeScript files based on the module's yaml
18
+ current generate # Does the same as above, but for all modules
19
+ ```
20
+ ```bash
21
+ current commit [files...] # Commits all changes in the code, so they won't be overwritten after regeneration
22
+ current diff [module] # Show differences between generated and current code
23
+ ```
24
+
25
+ ## The flow
26
+ 1. Create an empty app (`current create app`)
27
+ 2. Create a new module: `current create module Name`
28
+ 3. In the module's yaml file, define module's:
29
+ - model(s)
30
+ - routes & actions
31
+ - permissions
32
+ 4. Generate TypeScript files: `current generate Name`
33
+ 5. If required, make changes in the:
34
+ - model (i.e. some specific business rules or validations)
35
+ - views
36
+ 6. Commit those changes: `current commit`
37
+
38
+ --- If needed more than CRUD: ---
39
+
40
+ 7. Define action in the service by creating a method
41
+ 8. Describe this action in the module's yaml. Additionaly, you may define routes and permissions.
42
+ 9. `current generate Modulename`
43
+ 10. commit changes: `current commit`
44
+
45
+ ## Configuration Files
46
+
47
+ ### Application Configuration (app.yaml)
48
+
49
+ **Do not modify this file**
50
+
51
+ ### Module Configuration (modulename.yaml)
52
+
53
+ **The most work must be done in these files**
54
+
55
+ **Complete Module Example:**
56
+ ```yaml
57
+ models:
58
+ - name: Post # Entity name (capitalized)
59
+ fields:
60
+ - name: title # Field name
61
+ type: string # Field type: string, number, boolean, datetime
62
+ required: true # Validation requirement
63
+ - name: content
64
+ type: string
65
+ required: true
66
+ - name: authorId
67
+ type: number
68
+ required: true
69
+ - name: publishedAt
70
+ type: datetime
71
+ required: false
72
+ - name: status
73
+ type: string
74
+ required: true
75
+
76
+ api: # REST API configuration
77
+ prefix: /api/posts # Base URL for API endpoints
78
+ endpoints:
79
+ - method: GET # HTTP method
80
+ path: / # Relative path (becomes /api/posts/)
81
+ action: list # Action name (references actions section)
82
+ - method: GET
83
+ path: /:id # Path parameter
84
+ action: get
85
+ - method: POST
86
+ path: /
87
+ action: create
88
+ - method: PUT
89
+ path: /:id
90
+ action: update
91
+ - method: DELETE
92
+ path: /:id
93
+ action: delete
94
+ - method: POST # Custom endpoint
95
+ path: /:id/publish
96
+ action: publish
97
+
98
+ routes: # Web interface configuration
99
+ prefix: /posts # Base URL for web pages
100
+ strategy: [toast, back] # Default success strategies for forms
101
+ endpoints:
102
+ - path: / # List page
103
+ action: list
104
+ view: postList # Template name
105
+ - path: /:id # Detail page
106
+ action: get
107
+ view: postDetail
108
+ - path: /create # Create form page
109
+ action: empty # No data loading action
110
+ view: postCreate
111
+ - path: /:id/edit # Edit form page
112
+ action: get # Load existing data
113
+ view: postUpdate
114
+
115
+ actions: # Business logic mapping
116
+ list:
117
+ handlers: [default:list] # Use built-in list handler
118
+ get:
119
+ handlers: [default:getById] # Use built-in get handler
120
+ create:
121
+ handlers: [default:create] # Built-in create
122
+ update:
123
+ handlers: [default:update]
124
+ delete:
125
+ handlers: [ # Chain multiple handlers
126
+ service:checkCanDelete, # Custom business logic
127
+ default:delete
128
+ ]
129
+ publish: # Custom action
130
+ handlers: [
131
+ default:getById, # Fetch entity
132
+ service:validateForPublish, # Custom validation
133
+ service:updatePublishStatus # Custom update logic
134
+ ]
135
+
136
+ permissions: # Role-based access control
137
+ - action: list
138
+ roles: [all] # Anyone (including anonymous)
139
+ - action: get
140
+ roles: [all] # Anyone can view
141
+ - action: create
142
+ roles: [authenticated] # Must be logged in
143
+ - action: update
144
+ roles: [owner, admin] # Entity owner or admin role
145
+ - action: delete
146
+ roles: [admin] # Only admin role
147
+ - action: publish
148
+ roles: [owner, editor, admin] # Multiple roles allowed
149
+ ```
150
+
151
+ **Make sure no `ID`/`owner id`/`is deleted` fields are present in the model definition, since it's added automatically**
152
+
153
+ **Field Types:**
154
+ - `string` - Text data
155
+ - `number` - Numeric data (integer or float)
156
+ - `boolean` - True/false values
157
+ - `datetime` - Date and time values
158
+
159
+ **Built-in Action Handlers:**
160
+ - `default:list` - Returns paginated list of entities
161
+ - `default:getById` - Fetches single entity by ID
162
+ - `default:create` - Creates new entity with validation
163
+ - `default:update` - Updates existing entity by ID
164
+ - `default:delete` - Soft deletes entity
165
+
166
+ **Custom Action Handlers:**
167
+ - `service:methodName` - Calls custom method on service class
168
+ - Automatically generated with proper type signatures
169
+ - Can be chained with built-in handlers
170
+
171
+ **Strategy Options (for forms):**
172
+ - `toast` - Success toast notification
173
+ - `back` - Navigate back in browser history
174
+ - `message` - Inline success message
175
+ - `modal` - Modal success dialog
176
+ - `redirect` - Redirect to specific URL
177
+ - `refresh` - Reload current page
178
+
179
+ **Permission Roles:**
180
+ - `all` - Anyone (including anonymous users)
181
+ - `authenticated` - Any logged-in user
182
+ - `owner` - User who created the entity
183
+ - `admin`, `editor`, `user` - Custom roles from JWT token
184
+ - Multiple roles can be specified for each action
185
+
186
+ **Generated Files from Configuration:**
187
+ - Domain entity class
188
+ - Service class
189
+ - API controller with REST endpoints
190
+ - Web controller with page rendering
191
+ - Store class with database operations
192
+ - HTML templates for all views
193
+ - TypeScript interfaces and DTOs
194
+
195
+ ## Module Structure
196
+ ```
197
+ src/modules/ModuleName/
198
+ ├── application/
199
+ │ ├── services/ModuleService.ts # Business logic
200
+ │ └── validation/ModuleValidation.ts # DTOs and validation
201
+ ├── domain/
202
+ │ └── entities/Module.ts # Domain model
203
+ ├── infrastructure/
204
+ │ ├── controllers/
205
+ │ │ ├── ModuleApiController.ts # REST API endpoints
206
+ │ │ └── ModuleWebController.ts # Web page controllers
207
+ │ ├── interfaces/StoreInterface.ts # Data access interface
208
+ │ └── stores/ModuleStore.ts # Data access implementation
209
+ ├── views/
210
+ │ ├── modulelist.html # List view template
211
+ │ ├── moduledetail.html # Detail view template
212
+ │ ├── modulecreate.html # Create form template
213
+ │ └── moduleupdate.html # Update form template
214
+ └── module.yaml # Module configuration
215
+ ```
216
+
217
+ ## Best Practices
218
+
219
+ - Use Domain Driven Design and Clean Architecture (kind of).
220
+ - Prefer declarative configuration over imperative programming: when possible, change yamls instead of writing the code. Write the code only when it's really neccessary.
221
+ - CRUD operation are autogenerated (first in module's yaml, then in the generated code).
222
+ - If some custom action is needed, then it has to be defined in the **Service** then just put this action to the module's yaml. You may also define new methods in the *Store* and its interface (if needed).
223
+ - Business rules must be defined only in models. That also applies to business rules validations (in contrast to *just* validations: e.g. if field exists and is of needed type – then validators are in use)
224
+
225
+ ## Core Package APIs (For Generated Code)
226
+
227
+ ### @currentjs/router - Controller Decorators & Context
228
+
229
+ **Decorators (in controllers):**
230
+ ```typescript
231
+ @Controller('/api/posts') // Base path for controller
232
+ @Get('/') // GET endpoint
233
+ @Get('/:id') // GET with path parameter
234
+ @Post('/') // POST endpoint
235
+ @Put('/:id') // PUT endpoint
236
+ @Delete('/:id') // DELETE endpoint
237
+ @Render('template', 'layout') // For web controllers
238
+ ```
239
+
240
+ **Context Object (in route handlers):**
241
+ ```typescript
242
+ interface IContext {
243
+ request: {
244
+ url: string;
245
+ path: string;
246
+ method: string;
247
+ parameters: Record<string, string | number>; // Path params + query params
248
+ body: any; // Parsed JSON or raw string
249
+ headers: Record<string, string | string[]>;
250
+ user?: AuthenticatedUser; // Parsed JWT user if authenticated
251
+ };
252
+ response: Record<string, any>;
253
+ }
254
+
255
+ // Usage examples
256
+ const id = parseInt(ctx.request.parameters.id as string);
257
+ const page = parseInt(ctx.request.parameters.page as string) || 1;
258
+ const payload = ctx.request.body;
259
+ const user = ctx.request.user; // If authenticated
260
+ ```
261
+
262
+ **Authentication Support:**
263
+ - JWT tokens parsed automatically from `Authorization: Bearer <token>` header
264
+ - User object available at `ctx.request.user` with `id`, `email`, `role` fields
265
+ - No manual setup required in generated code
266
+
267
+ ### @currentjs/templating - Template Syntax
268
+
269
+ **Variables & Data Access:**
270
+ ```html
271
+ {{ variableName }}
272
+ {{ object.property }}
273
+ {{ $root.arrayData }} <!-- Access root data -->
274
+ {{ $index }} <!-- Loop index -->
275
+ ```
276
+
277
+ **Control Structures:**
278
+ ```html
279
+ <!-- Loops -->
280
+ <tbody x-for="$root" x-row="item">
281
+ <tr>
282
+ <td>{{ item.name }}</td>
283
+ <td>{{ $index }}</td>
284
+ </tr>
285
+ </tbody>
286
+
287
+ <!-- Conditionals -->
288
+ <div x-if="user.isAdmin">Admin content</div>
289
+ <span x-if="errors.name">{{ errors.name }}</span>
290
+
291
+ <!-- Template includes -->
292
+ <userCard name="{{ user.name }}" role="admin" />
293
+ ```
294
+
295
+ **Layout Integration:**
296
+ - Templates use `<!-- @template name="templateName" -->` header
297
+ - Main layout gets `{{ content }}` variable
298
+ - Forms use `{{ formData.field || '' }}` for default values
299
+
300
+ ### @currentjs/provider-mysql - Database Operations
301
+
302
+ **Query Execution (in stores):**
303
+ ```typescript
304
+ // Named parameters (preferred)
305
+ const result = await this.db.query(
306
+ 'SELECT * FROM users WHERE status = :status AND age > :minAge',
307
+ { status: 'active', minAge: 18 }
308
+ );
309
+
310
+ // Result handling
311
+ if (result.success && result.data.length > 0) {
312
+ return result.data.map(row => this.rowToModel(row));
313
+ }
314
+ ```
315
+
316
+ **Common Query Patterns:**
317
+ ```typescript
318
+ // Insert with auto-generated fields
319
+ const row = { ...data, created_at: new Date(), updated_at: new Date() };
320
+ const result = await this.db.query(
321
+ `INSERT INTO table_name (${fields.join(', ')}) VALUES (${placeholders})`,
322
+ row
323
+ );
324
+ const newId = result.insertId;
325
+
326
+ // Update with validation
327
+ const query = `UPDATE table_name SET ${updateFields.join(', ')}, updated_at = :updated_at WHERE id = :id`;
328
+ await this.db.query(query, { ...updateData, updated_at: new Date(), id });
329
+
330
+ // Soft delete
331
+ await this.db.query(
332
+ 'UPDATE table_name SET deleted_at = :deleted_at WHERE id = :id',
333
+ { deleted_at: new Date(), id }
334
+ );
335
+ ```
336
+
337
+ **Error Handling:**
338
+ ```typescript
339
+ try {
340
+ const result = await this.db.query(query, params);
341
+ } catch (error) {
342
+ if (error instanceof MySQLConnectionError) {
343
+ throw new Error(`Database connection error: ${error.message}`);
344
+ } else if (error instanceof MySQLQueryError) {
345
+ throw new Error(`Query error: ${error.message}`);
346
+ }
347
+ throw error;
348
+ }
349
+ ```
350
+
351
+ ## Frontend System (web/app.js)
352
+
353
+ ### Translation System
354
+
355
+ **Basic Usage:**
356
+ ```javascript
357
+ // Translate strings
358
+ t('Hello World') // Returns translated version or original
359
+ t('Save changes')
360
+
361
+ // Set language
362
+ setLang('pl') // Switch to Polish
363
+ setLang('en') // Switch to English
364
+ getCurrentLanguage() // Get current language code
365
+ ```
366
+
367
+ **Translation File (web/translations.json):**
368
+ ```json
369
+ {
370
+ "pl": {
371
+ "Hello World": "Witaj Świecie",
372
+ "Save changes": "Zapisz zmiany",
373
+ "Delete": "Usuń"
374
+ },
375
+ "ru": {
376
+ "Hello World": "Привет мир",
377
+ "Save changes": "Сохранить изменения"
378
+ }
379
+ }
380
+ ```
381
+
382
+ ### UI Feedback & Notifications
383
+
384
+ **Toast Notifications:**
385
+ ```javascript
386
+ showToast('Success message', 'success') // Green toast
387
+ showToast('Error occurred', 'error') // Red toast
388
+ showToast('Information', 'info') // Blue toast
389
+ showToast('Warning', 'warning') // Yellow toast
390
+ ```
391
+
392
+ **Inline Messages:**
393
+ ```javascript
394
+ showMessage('messageId', 'Success!', 'success')
395
+ showMessage('errorContainer', 'Validation failed', 'error')
396
+ ```
397
+
398
+ **Modal Dialogs:**
399
+ ```javascript
400
+ showModal('confirmModal', 'Item saved successfully', 'success')
401
+ showModal('errorModal', 'Operation failed', 'error')
402
+ ```
403
+
404
+ ### Navigation & Page Actions
405
+
406
+ **Navigation Functions:**
407
+ ```javascript
408
+ navigateBack() // Go back in history or to home
409
+ redirectTo('/posts') // Safe redirect with validation
410
+ reloadPage() // Reload with loading indicator
411
+ refreshSection('#content') // Refresh specific section
412
+
413
+ // SPA-style navigation
414
+ navigateToPage('/posts/123') // Loads via AJAX, updates #main
415
+ ```
416
+
417
+ **Content Management:**
418
+ ```javascript
419
+ updateContent('#results', newHtml, 'replace') // Replace content
420
+ updateContent('#list', itemHtml, 'append') // Add to end
421
+ updateContent('#list', itemHtml, 'prepend') // Add to beginning
422
+ removeElement('#item-123') // Animate and remove
423
+ ```
424
+
425
+ ### Form Handling & Strategy System
426
+
427
+ **Form Strategy Configuration:**
428
+ ```html
429
+ <!-- Form with strategy attributes -->
430
+ <form data-strategy='["toast", "back"]'
431
+ data-entity-name="Post"
432
+ data-field-types='{"age": "number", "active": "boolean"}'>
433
+ <input name="title" type="text" required>
434
+ <input name="age" type="number">
435
+ <input name="active" type="checkbox">
436
+ <button type="submit">Save</button>
437
+ </form>
438
+ ```
439
+
440
+ **Available Strategies:**
441
+ - `toast` - Show success toast notification
442
+ - `back` - Navigate back using browser history
443
+ - `message` - Show inline message in specific element
444
+ - `modal` - Show modal dialog
445
+ - `redirect` - Redirect to specific URL
446
+ - `refresh` - Reload the page
447
+ - `remove` - Remove form element
448
+
449
+ **Manual Form Submission:**
450
+ ```javascript
451
+ const form = document.querySelector('#myForm');
452
+ submitForm(form, ['toast', 'back'], {
453
+ entityName: 'Post',
454
+ basePath: '/posts',
455
+ messageId: 'form-message'
456
+ });
457
+ ```
458
+
459
+ **Success Handling:**
460
+ ```javascript
461
+ handleFormSuccess(response, ['toast', 'back'], {
462
+ entityName: 'Post',
463
+ basePath: '/posts',
464
+ messageId: 'success-msg',
465
+ modalId: 'success-modal'
466
+ });
467
+ ```
468
+
469
+ ### Form Validation & Type Conversion
470
+
471
+ **Client-side Validation Setup:**
472
+ ```javascript
473
+ setupFormValidation('#createForm'); // Adds required field validation
474
+ ```
475
+
476
+ **Field Type Conversion:**
477
+ ```javascript
478
+ // Automatic conversion based on data-field-types
479
+ convertFieldValue('123', 'number') // Returns 123 (number)
480
+ convertFieldValue('true', 'boolean') // Returns true (boolean)
481
+ convertFieldValue('text', 'string') // Returns 'text' (string)
482
+ ```
483
+
484
+ ### Loading States & Utilities
485
+
486
+ **Loading Indicators:**
487
+ ```javascript
488
+ showLoading('#form') // Show spinner on form
489
+ hideLoading('#form') // Hide spinner
490
+ showLoading('#main') // Show spinner on main content
491
+ ```
492
+
493
+ **Utility Functions:**
494
+ ```javascript
495
+ debounce(searchFunction, 300) // Debounce for search inputs
496
+ getElementSafely('#selector') // Safe element selection
497
+ clearForm('#myForm') // Reset form and clear validation
498
+ ```
499
+
500
+ ### Event Handling & SPA Integration
501
+
502
+ **Automatic Link Handling:**
503
+ - Internal links automatically use AJAX navigation
504
+ - External links work normally
505
+ - Links with `data-external` skip AJAX handling
506
+
507
+ **Automatic Form Handling:**
508
+ - Forms with `data-strategy` use AJAX submission
509
+ - Regular forms work normally
510
+ - Automatic JSON conversion from FormData
511
+
512
+ **Custom Event Listeners:**
513
+ ```javascript
514
+ // Re-initialize after dynamic content loading
515
+ initializeEventListeners();
516
+
517
+ // Handle specific link navigation
518
+ document.querySelector('#myLink').addEventListener('click', (e) => {
519
+ e.preventDefault();
520
+ navigateToPage('/custom/path');
521
+ });
522
+ ```
523
+
524
+ ### Global App Object
525
+
526
+ **Accessing Functions:**
527
+ ```javascript
528
+ // All functions available under window.App
529
+ App.showToast('Message', 'success');
530
+ App.navigateBack();
531
+ App.t('Translate this');
532
+ App.setLang('pl');
533
+ App.showLoading('#content');
534
+ ```
535
+
536
+ ### Template Data Binding
537
+ ```html
538
+ <!-- List with pagination -->
539
+ <tbody x-for="modules" x-row="module">
540
+ <tr>
541
+ <td>{{ module.name }}</td>
542
+ <td><a href="/module/{{ module.id }}">View</a></td>
543
+ </tr>
544
+ </tbody>
545
+
546
+ <!-- Form with validation errors -->
547
+ <div x-if="errors.name" class="text-danger">{{ errors.name }}</div>
548
+ <input type="text" name="name" value="{{ formData.name || '' }}" class="form-control">
549
+
550
+ <!-- Form with strategy attributes -->
551
+ <form data-strategy='["toast", "back"]'
552
+ data-entity-name="Module"
553
+ data-field-types='{"count": "number", "active": "boolean"}'>
554
+ <!-- form fields -->
555
+ </form>
556
+ ```
package/package.json ADDED
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "@currentjs/gen",
3
+ "version": "0.1.1",
4
+ "description": "CLI code generator",
5
+ "license": "LGPL-3.0",
6
+ "author": "Konstantin Zavalny",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/currentjs/gen.git"
10
+ },
11
+ "homepage": "https://github.com/currentjs/gen",
12
+ "bugs": "https://github.com/currentjs/gen/issues",
13
+ "keywords": [
14
+ "currentjs",
15
+ "generator",
16
+ "cli",
17
+ "code",
18
+ "generator"
19
+ ],
20
+ "bin": {
21
+ "current": "dist/cli.js",
22
+ "currentjs": "dist/cli.js"
23
+ },
24
+ "files": [
25
+ "dist",
26
+ "howto.md",
27
+ "CHANGELOG.md"
28
+ ],
29
+ "scripts": {
30
+ "build": "tsc -p tsconfig.json",
31
+ "clean": "rm -rf dist",
32
+ "prepack": "npm run build"
33
+ },
34
+ "engines": {
35
+ "node": ">=18"
36
+ },
37
+ "dependencies": {
38
+ "yaml": "^2.8.0"
39
+ },
40
+ "devDependencies": {
41
+ "@types/node": "^22.18.0",
42
+ "typescript": "^5.6.3"
43
+ }
44
+ }