@autobe/compiler 0.18.0 → 0.19.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 (33) hide show
  1. package/lib/interface/AutoBeInterfaceCompiler.js +2 -2
  2. package/lib/interface/AutoBeInterfaceCompiler.js.map +1 -1
  3. package/lib/prisma/validatePrismaApplication.js +259 -73
  4. package/lib/prisma/validatePrismaApplication.js.map +1 -1
  5. package/lib/prisma/writePrismaApplication.js +1 -2
  6. package/lib/prisma/writePrismaApplication.js.map +1 -1
  7. package/lib/raw/AutoBeCompilerRealizeTemplate.js +3 -2
  8. package/lib/raw/AutoBeCompilerRealizeTemplate.js.map +1 -1
  9. package/lib/raw/AutoBeCompilerTestTemplate.js +1 -1
  10. package/lib/raw/nestjs.json +7 -7
  11. package/lib/raw/test.json +2 -2
  12. package/lib/realize/writeRealizeControllers.js +3 -2
  13. package/lib/realize/writeRealizeControllers.js.map +1 -1
  14. package/lib/utils/FilePrinter.js +11 -11
  15. package/lib/utils/FilePrinter.js.map +1 -1
  16. package/package.json +10 -9
  17. package/src/interface/AutoBeInterfaceCompiler.ts +3 -3
  18. package/src/prisma/validatePrismaApplication.ts +265 -79
  19. package/src/prisma/writePrismaApplication.ts +1 -2
  20. package/src/raw/AutoBeCompilerRealizeTemplate.ts +3 -2
  21. package/src/raw/AutoBeCompilerTestTemplate.ts +1 -1
  22. package/src/raw/nestjs.json +7 -7
  23. package/src/raw/test.json +2 -2
  24. package/src/realize/writeRealizeControllers.ts +3 -3
  25. package/src/utils/FilePrinter.ts +10 -9
  26. package/lib/interface/createMigrateApplication.d.ts +0 -3
  27. package/lib/interface/createMigrateApplication.js +0 -15
  28. package/lib/interface/createMigrateApplication.js.map +0 -1
  29. package/lib/utils/MapUtil.d.ts +0 -3
  30. package/lib/utils/MapUtil.js +0 -16
  31. package/lib/utils/MapUtil.js.map +0 -1
  32. package/src/interface/createMigrateApplication.ts +0 -18
  33. package/src/utils/MapUtil.ts +0 -10
@@ -1,9 +1,7 @@
1
1
  import { AutoBePrisma, IAutoBePrismaValidation } from "@autobe/interface";
2
- import { StringUtil } from "@autobe/utils";
2
+ import { MapUtil, StringUtil } from "@autobe/utils";
3
3
  import { HashMap, hash } from "tstl";
4
4
 
5
- import { MapUtil } from "../utils/MapUtil";
6
-
7
5
  export function validatePrismaApplication(
8
6
  application: AutoBePrisma.IApplication,
9
7
  ): IAutoBePrismaValidation {
@@ -85,15 +83,16 @@ function validateDuplicatedFiles(
85
83
  path: `application.files[${container.index}]`,
86
84
  table: null,
87
85
  field: null,
88
- message: [
89
- `File ${container.file.filename} is duplicated.`,
90
- "",
91
- "Accessors of the other duplicated files are:",
92
- "",
93
- ...array
86
+ message: StringUtil.trim`
87
+ File ${container.file.filename} is duplicated.
88
+
89
+ Accessors of the other duplicated files are:
90
+
91
+ ${array
94
92
  .filter((_oppo, j) => i !== j)
95
- .map((oppo) => `- application.files[${oppo.index}]`),
96
- ].join("\n"),
93
+ .map((oppo) => `- application.files[${oppo.index}]`)
94
+ .join("\n")},
95
+ `,
97
96
  });
98
97
  });
99
98
  return errors;
@@ -123,18 +122,19 @@ function validateDuplicatedModels(
123
122
  path: `application.files[${container.fileIndex}].models[${container.modelIndex}]`,
124
123
  table: container.model.name,
125
124
  field: null,
126
- message: [
127
- `Model ${container.model.name} is duplicated.`,
128
- "",
129
- "Accessors of the other duplicated models are:",
130
- "",
131
- ...array
125
+ message: StringUtil.trim`
126
+ Model ${container.model.name} is duplicated.
127
+
128
+ Accessors of the other duplicated models are:
129
+
130
+ ${array
132
131
  .filter((_oppo, j) => i !== j)
133
132
  .map(
134
133
  (oppo) =>
135
134
  `- application.files[${oppo.fileIndex}].models[${oppo.modelIndex}]`,
136
- ),
137
- ].join("\n"),
135
+ )
136
+ .join("\n")},
137
+ `,
138
138
  });
139
139
  });
140
140
  return errors;
@@ -152,11 +152,14 @@ function validateDuplicatedFields(
152
152
  MapUtil.take(group, model.primaryField.name, () => []).push(
153
153
  `${accessor}.primaryField.name`,
154
154
  );
155
- model.foreignFields.forEach((field, i) =>
155
+ model.foreignFields.forEach((field, i) => {
156
156
  MapUtil.take(group, field.name, () => []).push(
157
157
  `${accessor}.foreignFields[${i}].name`,
158
- ),
159
- );
158
+ );
159
+ MapUtil.take(group, field.relation.name, () => []).push(
160
+ `${accessor}.foreignFields[${i}].relation.name`,
161
+ );
162
+ });
160
163
  model.plainFields.forEach((field, i) =>
161
164
  MapUtil.take(group, field.name, () => []).push(
162
165
  `${accessor}.plainFields[${i}].name`,
@@ -169,13 +172,16 @@ function validateDuplicatedFields(
169
172
  path,
170
173
  table: model.name,
171
174
  field,
172
- message: [
173
- `Field ${field} is duplicated.`,
174
- "",
175
- "Accessors of the other duplicated fields are:",
176
- "",
177
- ...array.filter((_oppo, j) => i !== j).map((a) => `- ${a}`),
178
- ].join("\n"),
175
+ message: StringUtil.trim`
176
+ Field ${field} is duplicated.
177
+
178
+ Accessors of the other duplicated fields are:
179
+
180
+ ${array
181
+ .filter((_oppo, j) => i !== j)
182
+ .map((a) => `- ${a}`)
183
+ .join("\n")},
184
+ `,
179
185
  });
180
186
  });
181
187
 
@@ -187,12 +193,37 @@ function validateDuplicatedFields(
187
193
  table: model.name,
188
194
  field: field.name,
189
195
  message: StringUtil.trim`
190
- There's a same named table in the application.
191
-
192
- Check whether the field has been designed for denormalization
193
- like pre-calculation. If do so, remove the field.
194
-
195
- Otherwise, change the field name to something else.
196
+ Field name conflicts with an existing table name.
197
+
198
+ **What happened?**
199
+ The field "${field.name}" in model "${model.name}" has the same name as another table "${field.name}".
200
+ This can cause confusion and potential issues in the generated code.
201
+
202
+ **Why is this a problem?**
203
+ - Naming conflicts can lead to ambiguous references in your code
204
+ - It may cause issues with Prisma's relation inference
205
+ - It makes the schema harder to understand and maintain
206
+
207
+ **How to fix this:**
208
+
209
+ 1. **If this is a denormalization field (pre-calculated value):**
210
+ - Consider if this field is really necessary
211
+ - If it's storing aggregated data from the related table, it might be better to calculate it dynamically
212
+ - Remove the field if it's redundant
213
+
214
+ 2. **If this is a legitimate field:**
215
+ - Rename the field to be more descriptive
216
+ - Good naming examples:
217
+ - Instead of "user", use "user_name" or "user_id"
218
+ - Instead of "order", use "order_status" or "order_count"
219
+ - Instead of "product", use "product_name" or "product_code"
220
+
221
+ 3. **Naming best practices:**
222
+ - Use specific, descriptive names that indicate the field's purpose
223
+ - Avoid using table names as field names
224
+ - Consider adding a suffix or prefix to clarify the field's role
225
+
226
+ Please rename the field or remove it if unnecessary.
196
227
  `,
197
228
  });
198
229
  });
@@ -232,13 +263,16 @@ function validateDuplicatedIndexes(
232
263
  path,
233
264
  table: model.name,
234
265
  field: null,
235
- message: [
236
- `Duplicated index found (${fieldNames.join(", ")}).`,
237
- "",
238
- "Accessors of the other duplicated indexes are:",
239
- "",
240
- ...array.filter((_oppo, j) => i !== j).map((a) => `- ${a}`),
241
- ].join("\n"),
266
+ message: StringUtil.trim`
267
+ Duplicated index found (${fieldNames.join(", ")}).
268
+
269
+ Accessors of the other duplicated indexes are:
270
+
271
+ ${array
272
+ .filter((_oppo, j) => i !== j)
273
+ .map((a) => `- ${a}`)
274
+ .join("\n")},
275
+ `,
242
276
  });
243
277
  });
244
278
 
@@ -278,13 +312,44 @@ function validateDuplicatedIndexes(
278
312
  table: model.name,
279
313
  field: null,
280
314
  message: StringUtil.trim`
281
- Subset unique index found (${subset.join(", ")}).
282
-
283
- You have defined an unique index with multiple fields,
284
- but its subset is already defined as an unique index.
285
-
286
- Consider to change the unique index to a plain index,
287
- or drop the redundant unique index please.
315
+ Redundant subset unique index detected.
316
+
317
+ **What is a subset unique index problem?**
318
+ When you have a unique index on multiple fields, any subset of those fields is automatically unique too.
319
+ This is a fundamental property of unique constraints in databases.
320
+
321
+ **Current situation:**
322
+ - You have a unique index on: (${unique.fieldNames.join(", ")})
323
+ - But there's already a unique index on its subset: (${subset.join(", ")})
324
+ - This makes the larger unique index redundant for uniqueness purposes
325
+
326
+ **Why is this a problem?**
327
+ 1. **Logical redundancy**: If (A) is unique, then (A, B) is automatically unique
328
+ 2. **Performance overhead**: Maintaining unnecessary indexes slows down write operations
329
+ 3. **Storage waste**: Each index consumes disk space
330
+ 4. **Confusion**: It's unclear which uniqueness constraint is the intended one
331
+
332
+ **Example to illustrate:**
333
+ If email is unique, then (email, name) is automatically unique because:
334
+ - No two records can have the same email
335
+ - Therefore, no two records can have the same (email, name) combination
336
+
337
+ **How to fix:**
338
+ Choose one of these solutions based on your needs:
339
+
340
+ 1. **If you need uniqueness only:**
341
+ - Keep just the subset unique index: (${subset.join(", ")})
342
+ - Remove the larger unique index
343
+
344
+ 2. **If you need the multi-field index for query performance:**
345
+ - Keep the subset as unique index: (${subset.join(", ")})
346
+ - Change the larger index to a plain (non-unique) index for performance
347
+
348
+ 3. **If the subset unique was added by mistake:**
349
+ - Remove the subset unique index
350
+ - Keep the multi-field unique index
351
+
352
+ Please review your uniqueness requirements and adjust accordingly.
288
353
  `,
289
354
  });
290
355
  });
@@ -303,12 +368,42 @@ function validateDuplicatedIndexes(
303
368
  table: model.name,
304
369
  field: null,
305
370
  message: StringUtil.trim`
306
- Superset plain index found (${y.fieldNames.join(", ")}).
307
-
308
- You have defined a plain index with multiple fields,
309
- but its superset is already defined as another plain index.
310
-
311
- As subset index is vulnerable, drop this plain index please.
371
+ Inefficient subset index detected - superset index exists.
372
+
373
+ **What is a subset/superset index problem?**
374
+ In database indexing, when you have an index on (A, B, C), it can efficiently serve queries
375
+ that filter by A, or by (A, B), or by (A, B, C). This is called index prefix matching.
376
+
377
+ **Current situation:**
378
+ - You have a plain index on: (${x.fieldNames.join(", ")})
379
+ - But there's already a plain index on its superset: (${y.fieldNames.join(", ")})
380
+ - The subset index is redundant because the superset can handle the same queries
381
+
382
+ **Why is this a problem?**
383
+ 1. **Query efficiency**: The superset index can handle all queries the subset can
384
+ 2. **Storage waste**: You're maintaining two indexes where one would suffice
385
+ 3. **Write performance**: Each index slows down INSERT, UPDATE, and DELETE operations
386
+ 4. **Maintenance overhead**: More indexes mean more work for the database
387
+
388
+ **How indexes work (example):**
389
+ If you have an index on (country, city, street):
390
+ - ✅ Can efficiently find by country
391
+ - ✅ Can efficiently find by country + city
392
+ - ✅ Can efficiently find by country + city + street
393
+ - ❌ Cannot efficiently find by city alone
394
+ - ❌ Cannot efficiently find by street alone
395
+
396
+ **How to fix:**
397
+ Remove the subset index (${x.fieldNames.join(", ")}) because:
398
+ - The superset index (${y.fieldNames.join(", ")}) already covers these queries
399
+ - You'll save storage space and improve write performance
400
+ - Query performance will remain the same
401
+
402
+ **When to keep both indexes:**
403
+ Only if the subset index is UNIQUE (which it isn't in this case), as unique
404
+ constraints serve a different purpose than performance optimization.
405
+
406
+ Please remove the redundant subset index.
312
407
  `,
313
408
  });
314
409
  });
@@ -410,9 +505,37 @@ function validateIndexes(
410
505
  table: model.name,
411
506
  field: null,
412
507
  message: StringUtil.trim`
413
- GIN index can only be used on string typed field.
414
- However, the target field ${gin.fieldName} does not exist
415
- in the {@link plainFields}.
508
+ GIN index cannot be applied to this field.
509
+
510
+ **What is a GIN index?**
511
+ GIN (Generalized Inverted Index) is a special index type in PostgreSQL designed for
512
+ full-text search and operations on complex data types. In AutoBE, GIN indexes are
513
+ used exclusively for string fields to enable efficient text searching.
514
+
515
+ **Current problem:**
516
+ The field "${gin.fieldName}" specified for GIN index does not exist in the plain fields
517
+ of model "${model.name}".
518
+
519
+ **Possible causes:**
520
+ 1. The field name is misspelled
521
+ 2. The field is a foreign key field (not a plain field)
522
+ 3. The field was removed but the index definition remained
523
+
524
+ **How to fix:**
525
+ 1. Check if the field name is correct
526
+ 2. Ensure the field exists in the plainFields array
527
+ 3. Make sure the field is of type "string" (GIN indexes only work with strings)
528
+ 4. If the field doesn't exist, either:
529
+ - Add the missing string field to plainFields
530
+ - Remove this GIN index definition
531
+
532
+ **Example of correct GIN index usage:**
533
+ plainFields: [
534
+ { name: "content", type: "string" } // ✓ Can use GIN index
535
+ ]
536
+ ginIndexes: [
537
+ { fieldName: "content" } // ✓ Correct
538
+ ]
416
539
  `,
417
540
  });
418
541
  else if (model.plainFields[pIndex].type !== "string")
@@ -421,11 +544,43 @@ function validateIndexes(
421
544
  table: model.name,
422
545
  field: model.plainFields[pIndex].name,
423
546
  message: StringUtil.trim`
424
- GIN index can only be used on string typed field.
425
- However, the target field ${gin.fieldName} is not string,
426
- but ${model.plainFields[pIndex].type}.
427
-
428
- - accessor of the wrong typed field: ${`${accessor}.plainFields[${pIndex}].type`},
547
+ GIN index type mismatch - requires string field.
548
+
549
+ **What is a GIN index?**
550
+ GIN (Generalized Inverted Index) is PostgreSQL's specialized index for full-text search.
551
+ It's designed to efficiently search within text content, making it perfect for features like:
552
+ - Search functionality in articles or posts
553
+ - Finding keywords in product descriptions
554
+ - Filtering by text content
555
+
556
+ **Current problem:**
557
+ You're trying to apply a GIN index to field "${gin.fieldName}" which is of type "${model.plainFields[pIndex].type}".
558
+ GIN indexes can ONLY be applied to "string" type fields.
559
+
560
+ **Why string fields only?**
561
+ GIN indexes work by breaking down text into searchable tokens (words, phrases).
562
+ Other data types like numbers, booleans, or dates don't have this text structure.
563
+
564
+ **How to fix:**
565
+
566
+ 1. **If you need text search on this field:**
567
+ - Change the field type to "string"
568
+ - Example: If storing a product code as number, consider storing as string instead
569
+
570
+ 2. **If the field should remain as ${model.plainFields[pIndex].type}:**
571
+ - Remove the GIN index for this field
572
+ - Use a regular index instead (plainIndexes)
573
+ - Consider if you really need an index on this field
574
+
575
+ 3. **Alternative indexing strategies:**
576
+ - For ${model.plainFields[pIndex].type} fields, use plainIndexes for general performance
577
+ - For unique ${model.plainFields[pIndex].type} values, use uniqueIndexes
578
+ - GIN indexes should be reserved for text search scenarios only
579
+
580
+ **Location of the field:**
581
+ - Field definition: ${`${accessor}.plainFields[${pIndex}]`}
582
+
583
+ Please either change the field type to "string" or remove the GIN index.
429
584
  `,
430
585
  });
431
586
  },
@@ -441,6 +596,8 @@ function validateReferences(
441
596
  const errors: IAutoBePrismaValidation.IError[] = [];
442
597
 
443
598
  model.foreignFields.forEach((field, i) => {
599
+ // DUPLICATED NAME
600
+
444
601
  const target = dict.get(field.relation.targetModel);
445
602
  if (target === undefined) {
446
603
  // CHECK EXISTENCE
@@ -461,22 +618,51 @@ function validateReferences(
461
618
  message: StringUtil.trim`
462
619
  Cross-reference dependency detected between models.
463
620
 
464
- - accessor of opposite side: application.files[${target.fileIndex}].models[${target.modelIndex}].foreignFields[${j}].relation.targetModel
465
-
466
- Cross-references (circular dependencies) are not permitted in AutoBe Prisma schemas.
467
-
468
- To resolve this issue:
469
-
470
- 1. Remove one of the foreign key fields from either model
471
- 2. Keep only the foreign key that represents the primary relationship direction
472
- 3. Remove any related indexes that reference the deleted foreign key field
473
-
474
- The foreign key field to remove is typically:
475
-
476
- - A redundant field that can be computed from the existing relationship
477
- - A field that duplicates information already accessible through the primary relationship
478
-
479
- Please eliminate the circular dependency and try again.`,
621
+ **What is Cross-reference dependency?**
622
+ A cross-reference dependency (also known as circular dependency) occurs when two models
623
+ reference each other through foreign key fields. This creates a circular relationship
624
+ where Model A references Model B, and Model B also references Model A.
625
+
626
+ **Current situation:**
627
+ - ${model.name} model has a foreign key field "${field.name}" that references ${field.relation.targetModel}
628
+ - ${field.relation.targetModel} model also has a foreign key field that references ${model.name}
629
+ - Location of opposite reference: application.files[${target.fileIndex}].models[${target.modelIndex}].foreignFields[${j}].relation.targetModel
630
+
631
+ **Why is this a problem?**
632
+ Circular dependencies can cause issues with:
633
+ - Database initialization (which table to create first?)
634
+ - Data insertion (which record to insert first?)
635
+ - Cascading updates and deletes
636
+ - Query performance and complexity
637
+
638
+ **How to fix this:**
639
+ You need to remove one of the foreign key relationships. Here's how to decide:
640
+
641
+ 1. **Identify the primary relationship direction**
642
+ - Which model is the "parent" and which is the "child"?
643
+ - Which relationship is essential for your business logic?
644
+ - Example: In User ↔ Profile, User is typically the parent
645
+
646
+ 2. **Remove the redundant foreign key**
647
+ - Keep the foreign key in the child model pointing to the parent
648
+ - Remove the foreign key in the parent model pointing to the child
649
+ - You can still access the reverse relationship through Prisma's implicit relations
650
+
651
+ 3. **Update any affected indexes**
652
+ - Remove indexes that include the deleted foreign key field
653
+ - Update composite indexes if necessary
654
+
655
+ **Example solution:**
656
+ If you have:
657
+ - User model with profileId foreign key
658
+ - Profile model with userId foreign key
659
+
660
+ You should:
661
+ - Keep userId in Profile (child references parent)
662
+ - Remove profileId from User
663
+ - Access user's profile through: user.profile (Prisma will handle this)
664
+
665
+ Please eliminate the circular dependency and regenerate the schema.`,
480
666
  });
481
667
  }
482
668
  });
@@ -1,9 +1,8 @@
1
1
  import { AutoBePrisma } from "@autobe/interface";
2
- import { StringUtil } from "@autobe/utils";
2
+ import { MapUtil, StringUtil } from "@autobe/utils";
3
3
  import crypto from "crypto";
4
4
 
5
5
  import { ArrayUtil } from "../utils/ArrayUtil";
6
- import { MapUtil } from "../utils/MapUtil";
7
6
 
8
7
  export function writePrismaApplication(props: {
9
8
  dbms: "postgres" | "sqlite";
@@ -1,12 +1,13 @@
1
1
  export const AutoBeCompilerRealizeTemplate: Record<string, string> = {
2
2
  ".env.local": "API_PORT=37001\nJWT_SECRET_KEY=your_jwt_secret_key",
3
3
  ".gitignore": "bin/\ndist/\nlib/\nnode_modules/\n\nprisma/migrations\nprisma/schema/migrations\nprisma/bbs.db\n\n*.DS_Store\npackage-lock.json\npnpm-lock.yaml\n.npmrc",
4
- "package.json": "{\n \"private\": true,\n \"name\": \"@ORGANIZATION/PROJECT\",\n \"version\": \"0.1.0\",\n \"description\": \"Starter kit of Nestia\",\n \"main\": \"lib/index.js\",\n \"scripts\": {\n \"benchmark\": \"node bin/test/benchmark\",\n \"test\": \"node bin/test\",\n \"test:webpack\": \"npm run webpack && node bin/test/webpack.js\",\n \"------------------------BUILDS------------------------\": \"\",\n \"build\": \"npm run build:prisma && npm run build:sdk && npm run build:main && npm run build:test\",\n \"build:api\": \"rimraf packages/api/lib && nestia all && rimraf packages/api/lib && tsc -p packages/api/tsconfig.json && rollup -c packages/api/rollup.config.js\",\n \"build:env\": \"ts-node build/env.ts\",\n \"build:main\": \"rimraf lib && tsc\",\n \"build:sdk\": \"rimraf src/api/functional && nestia sdk\",\n \"build:prisma\": \"prisma generate --schema prisma/schema\",\n \"build:swagger\": \"nestia swagger\",\n \"build:test\": \"rimraf bin && tsc -p test/tsconfig.json\",\n \"dev\": \"npm run build:test -- --watch\",\n \"eslint\": \"eslint src && eslint test\",\n \"eslint:fix\": \"eslint --fix src && eslint --fix test\",\n \"prepare\": \"ts-patch install && npm run build:env && npm run build:prisma\",\n \"prettier\": \"prettier src --write && prettier test --write\",\n \"------------------------WEBPACK------------------------\": \"\",\n \"webpack\": \"rimraf dist && webpack\",\n \"webpack:start\": \"cd dist && node dist/server\",\n \"webpack:test\": \"npm run webpack && node bin/test/webpack.js\",\n \"------------------------DEPLOYS------------------------\": \"\",\n \"package:api\": \"npm run build:api && cd packages/api && npm publish\",\n \"start\": \"node lib/executable/server\",\n \"start:dev\": \"nest start --watch\",\n \"start:swagger\": \"ts-node src/executable/swagger.ts\"\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/samchon/nestia-start\"\n },\n \"keywords\": [\n \"nestia\",\n \"template\",\n \"boilerplate\"\n ],\n \"author\": \"AUTHOR\",\n \"license\": \"AGPL-3.0\",\n \"bugs\": {\n \"url\": \"https://github.com/samchon/nestia-start/issues\"\n },\n \"homepage\": \"https://github.com/samchon/nestia-start#readme\",\n \"devDependencies\": {\n \"@autobe/interface\": \"^0.10.6\",\n \"@nestia/benchmark\": \"^7.3.3\",\n \"@nestia/e2e\": \"^7.3.3\",\n \"@nestia/sdk\": \"^7.3.3\",\n \"@nestjs/cli\": \"^11.0.7\",\n \"@rollup/plugin-terser\": \"^0.4.4\",\n \"@rollup/plugin-typescript\": \"^11.1.6\",\n \"@trivago/prettier-plugin-sort-imports\": \"^4.3.0\",\n \"@types/bcryptjs\": \"^3.0.0\",\n \"@types/cli\": \"^0.11.21\",\n \"@types/cli-progress\": \"^3.11.5\",\n \"@types/express\": \"^4.17.21\",\n \"@types/inquirer\": \"^8.2.5\",\n \"@types/jsonwebtoken\": \"^9.0.5\",\n \"@types/node\": \"^18.11.0\",\n \"@types/uuid\": \"^8.3.4\",\n \"@typescript-eslint/eslint-plugin\": \"^8.1.0\",\n \"@typescript-eslint/parser\": \"^8.1.0\",\n \"chalk\": \"^4.1.2\",\n \"cli\": \"^1.0.1\",\n \"cli-progress\": \"^3.12.0\",\n \"copy-webpack-plugin\": \"^11.0.0\",\n \"eslint-plugin-deprecation\": \"^3.0.0\",\n \"express\": \"^4.18.2\",\n \"fastify\": \"^5.4.0\",\n \"nestia\": \"^7.3.3\",\n \"prettier\": \"^3.2.4\",\n \"prettier-plugin-prisma\": \"^5.0.0\",\n \"prisma-markdown\": \"^3.0.1\",\n \"rimraf\": \"^3.0.2\",\n \"rollup\": \"^4.18.0\",\n \"source-map-support\": \"^0.5.21\",\n \"swagger-ui-express\": \"^5.0.0\",\n \"ts-loader\": \"^9.5.1\",\n \"ts-node\": \"^10.9.1\",\n \"ts-patch\": \"^3.3.0\",\n \"typescript\": \"~5.9.2\",\n \"typescript-transform-paths\": \"^3.5.5\",\n \"webpack\": \"^5.89.0\",\n \"webpack-cli\": \"^5.1.4\",\n \"write-file-webpack-plugin\": \"^4.5.1\"\n },\n \"dependencies\": {\n \"@nestia/core\": \"^7.3.3\",\n \"@nestia/fetcher\": \"^7.3.3\",\n \"@nestjs/common\": \"^11.1.3\",\n \"@nestjs/core\": \"^11.1.3\",\n \"@nestjs/platform-express\": \"^11.1.3\",\n \"@nestjs/platform-fastify\": \"^11.1.3\",\n \"@prisma/client\": \"^6.11.1\",\n \"bcryptjs\": \"^3.0.2\",\n \"commander\": \"10.0.0\",\n \"dotenv\": \"^16.3.1\",\n \"dotenv-expand\": \"^10.0.0\",\n \"inquirer\": \"8.2.5\",\n \"jsonwebtoken\": \"^9.0.2\",\n \"prisma\": \"^6.11.1\",\n \"serialize-error\": \"^4.1.0\",\n \"tgrid\": \"^1.1.0\",\n \"tstl\": \"^3.0.0\",\n \"typia\": \"^9.7.1\",\n \"uuid\": \"^9.0.0\"\n },\n \"stackblitz\": {\n \"startCommand\": \"npm run prepare && npm run build:test && npm run test -- --simultaneous 1\"\n }\n}\n",
5
- "src/MyGlobal.ts": "import { PrismaClient } from \"@prisma/client\";\nimport dotenv from \"dotenv\";\nimport dotenvExpand from \"dotenv-expand\";\nimport { Singleton } from \"tstl\";\nimport typia from \"typia\";\n\n/* eslint-disable */\nexport class MyGlobal {\n public static readonly prisma: PrismaClient = new PrismaClient();\n public static testing: boolean = false;\n public static get env(): MyGlobal.IEnvironments {\n return environments.get();\n }\n}\nexport namespace MyGlobal {\n export interface IEnvironments {\n API_PORT: `${number}`;\n\n /** JWT Secret Key. */\n JWT_SECRET_KEY: string;\n }\n}\nconst environments = new Singleton(() => {\n const env = dotenv.config();\n dotenvExpand.expand(env);\n return typia.assert<MyGlobal.IEnvironments>(process.env);\n});\n",
4
+ "package.json": "{\n \"private\": true,\n \"name\": \"@ORGANIZATION/PROJECT\",\n \"version\": \"0.1.0\",\n \"description\": \"Starter kit of Nestia\",\n \"main\": \"lib/index.js\",\n \"scripts\": {\n \"benchmark\": \"node bin/test/benchmark\",\n \"test\": \"node bin/test\",\n \"test:webpack\": \"npm run webpack && node bin/test/webpack.js\",\n \"------------------------BUILDS------------------------\": \"\",\n \"build\": \"npm run build:prisma && npm run build:sdk && npm run build:main && npm run build:test\",\n \"build:api\": \"rimraf packages/api/lib && nestia all && rimraf packages/api/lib && tsc -p packages/api/tsconfig.json && rollup -c packages/api/rollup.config.js\",\n \"build:env\": \"ts-node build/env.ts\",\n \"build:main\": \"rimraf lib && tsc\",\n \"build:sdk\": \"rimraf src/api/functional && nestia sdk\",\n \"build:prisma\": \"prisma generate --schema prisma/schema\",\n \"build:swagger\": \"nestia swagger\",\n \"build:test\": \"rimraf bin && tsc -p test/tsconfig.json\",\n \"dev\": \"npm run build:test -- --watch\",\n \"eslint\": \"eslint src && eslint test\",\n \"eslint:fix\": \"eslint --fix src && eslint --fix test\",\n \"prepare\": \"ts-patch install && npm run build:env && npm run build:prisma\",\n \"prettier\": \"prettier src --write && prettier test --write\",\n \"------------------------WEBPACK------------------------\": \"\",\n \"webpack\": \"rimraf dist && webpack\",\n \"webpack:start\": \"cd dist && node dist/server\",\n \"webpack:test\": \"npm run webpack && node bin/test/webpack.js\",\n \"------------------------DEPLOYS------------------------\": \"\",\n \"package:api\": \"npm run build:api && cd packages/api && npm publish\",\n \"start\": \"node lib/executable/server\",\n \"start:dev\": \"nest start --watch\",\n \"start:swagger\": \"ts-node src/executable/swagger.ts\"\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/samchon/nestia-start\"\n },\n \"keywords\": [\n \"nestia\",\n \"template\",\n \"boilerplate\"\n ],\n \"author\": \"AUTHOR\",\n \"license\": \"AGPL-3.0\",\n \"bugs\": {\n \"url\": \"https://github.com/samchon/nestia-start/issues\"\n },\n \"homepage\": \"https://github.com/samchon/nestia-start#readme\",\n \"devDependencies\": {\n \"@autobe/interface\": \"^0.10.6\",\n \"@nestia/benchmark\": \"^7.4.0\",\n \"@nestia/e2e\": \"^7.4.0\",\n \"@nestia/sdk\": \"^7.4.0\",\n \"@nestjs/cli\": \"^11.0.7\",\n \"@rollup/plugin-terser\": \"^0.4.4\",\n \"@rollup/plugin-typescript\": \"^11.1.6\",\n \"@trivago/prettier-plugin-sort-imports\": \"^4.3.0\",\n \"@types/bcryptjs\": \"^3.0.0\",\n \"@types/cli\": \"^0.11.21\",\n \"@types/cli-progress\": \"^3.11.5\",\n \"@types/express\": \"^4.17.21\",\n \"@types/inquirer\": \"^8.2.5\",\n \"@types/jsonwebtoken\": \"^9.0.5\",\n \"@types/node\": \"^18.11.0\",\n \"@types/uuid\": \"^8.3.4\",\n \"@typescript-eslint/eslint-plugin\": \"^8.1.0\",\n \"@typescript-eslint/parser\": \"^8.1.0\",\n \"chalk\": \"^4.1.2\",\n \"cli\": \"^1.0.1\",\n \"cli-progress\": \"^3.12.0\",\n \"copy-webpack-plugin\": \"^11.0.0\",\n \"eslint-plugin-deprecation\": \"^3.0.0\",\n \"express\": \"^4.18.2\",\n \"fastify\": \"^5.4.0\",\n \"nestia\": \"^7.4.0\",\n \"prettier\": \"^3.2.4\",\n \"prettier-plugin-prisma\": \"^5.0.0\",\n \"prisma-markdown\": \"^3.0.1\",\n \"rimraf\": \"^3.0.2\",\n \"rollup\": \"^4.18.0\",\n \"source-map-support\": \"^0.5.21\",\n \"swagger-ui-express\": \"^5.0.0\",\n \"ts-loader\": \"^9.5.1\",\n \"ts-node\": \"^10.9.1\",\n \"ts-patch\": \"^3.3.0\",\n \"typescript\": \"~5.9.2\",\n \"typescript-transform-paths\": \"^3.5.5\",\n \"webpack\": \"^5.89.0\",\n \"webpack-cli\": \"^5.1.4\",\n \"write-file-webpack-plugin\": \"^4.5.1\"\n },\n \"dependencies\": {\n \"@nestia/core\": \"^7.4.0\",\n \"@nestia/fetcher\": \"^7.4.0\",\n \"@nestjs/common\": \"^11.1.3\",\n \"@nestjs/core\": \"^11.1.3\",\n \"@nestjs/platform-express\": \"^11.1.3\",\n \"@nestjs/platform-fastify\": \"^11.1.3\",\n \"@prisma/client\": \"^6.11.1\",\n \"bcryptjs\": \"^3.0.2\",\n \"commander\": \"10.0.0\",\n \"dotenv\": \"^16.3.1\",\n \"dotenv-expand\": \"^10.0.0\",\n \"inquirer\": \"8.2.5\",\n \"jsonwebtoken\": \"^9.0.2\",\n \"prisma\": \"^6.11.1\",\n \"serialize-error\": \"^4.1.0\",\n \"tgrid\": \"^1.1.0\",\n \"tstl\": \"^3.0.0\",\n \"typia\": \"^9.7.1\",\n \"uuid\": \"^9.0.0\"\n },\n \"stackblitz\": {\n \"startCommand\": \"npm run prepare && npm run build:test && npm run test -- --simultaneous 1\"\n }\n}\n",
5
+ "src/MyGlobal.ts": "import { PrismaClient } from \"@prisma/client\";\nimport crypto from \"crypto\";\nimport dotenv from \"dotenv\";\nimport dotenvExpand from \"dotenv-expand\";\nimport { Singleton } from \"tstl\";\nimport typia from \"typia\";\n\n/* eslint-disable */\nexport class MyGlobal {\n public static readonly prisma: PrismaClient = new PrismaClient();\n public static testing: boolean = false;\n public static get env(): MyGlobal.IEnvironments {\n return environments.get();\n }\n\n /**\n * Common password utilities for consistent authentication Uses native crypto\n * module for password hashing\n */\n public static readonly password = {\n // Fixed salt for password hashing (consistent across all operations)\n FIXED_SALT: \"autobe-fixed-salt-2024\",\n\n /**\n * Hash a plain password using crypto.pbkdf2 All authentication operations\n * (join, login) MUST use this method\n *\n * @param plainPassword - The plain text password to hash\n * @returns The hashed password as hex string\n */\n async hash(plainPassword: string): Promise<string> {\n return new Promise((resolve, reject) => {\n crypto.pbkdf2(\n plainPassword,\n this.FIXED_SALT,\n 10000,\n 64,\n \"sha512\",\n (err: Error | null, derivedKey: Buffer) => {\n if (err) reject(err);\n else resolve(derivedKey.toString(\"hex\"));\n },\n );\n });\n },\n\n /**\n * Verify a plain password against a hashed password Login operations MUST\n * use this method for password verification\n *\n * @param plainPassword - The plain text password to verify\n * @param hashedPassword - The hashed password from database\n * @returns True if passwords match, false otherwise\n */\n async verify(\n plainPassword: string,\n hashedPassword: string,\n ): Promise<boolean> {\n const hash = await this.hash(plainPassword);\n return hash === hashedPassword;\n },\n };\n}\nexport namespace MyGlobal {\n export interface IEnvironments {\n API_PORT: `${number}`;\n\n /** JWT Secret Key. */\n JWT_SECRET_KEY: string;\n }\n}\nconst environments = new Singleton(() => {\n const env = dotenv.config();\n dotenvExpand.expand(env);\n return typia.assert<MyGlobal.IEnvironments>(process.env);\n});\n",
6
6
  "src/providers/authorize/jwtAuthorize.ts": "import { ForbiddenException, UnauthorizedException } from \"@nestjs/common\";\nimport jwt from \"jsonwebtoken\";\n\nimport { MyGlobal } from \"../../MyGlobal\";\n\nexport function jwtAuthorize(props: {\n request: {\n headers: { authorization?: string };\n };\n}) {\n if (!props.request.headers.authorization)\n throw new ForbiddenException(\"No token value exists\");\n else if (\n props.request.headers.authorization.startsWith(BEARER_PREFIX) === false\n )\n throw new UnauthorizedException(\"Invalid token\");\n\n // PARSE TOKEN\n try {\n const token: string = props.request.headers.authorization.substring(\n BEARER_PREFIX.length,\n );\n\n const verified = jwt.verify(token, MyGlobal.env.JWT_SECRET_KEY);\n\n return verified;\n } catch {\n throw new UnauthorizedException(\"Invalid token\");\n }\n}\n\nconst BEARER_PREFIX = \"Bearer \";\n",
7
7
  "src/setup/MySetupWizard.ts": "import cp from \"child_process\";\n\nimport { MyConfiguration } from \"../MyConfiguration\";\nimport { MyGlobal } from \"../MyGlobal\";\n\nexport namespace MySetupWizard {\n export async function schema(): Promise<void> {\n if (MyGlobal.testing === false)\n throw new Error(\n \"Error on SetupWizard.schema(): unable to reset database in non-test mode.\",\n );\n const execute = (type: string) => (argv: string) =>\n cp.execSync(`npx prisma migrate ${type} --schema=prisma/schema ${argv}`, {\n stdio: \"ignore\",\n cwd: MyConfiguration.ROOT,\n });\n execute(\"reset\")(\"--force\");\n execute(\"dev\")(\"--name init\");\n }\n\n export async function seed(): Promise<void> {}\n}\n",
8
8
  "src/util/toISOStringSafe.ts": "import { tags } from \"typia\";\n\n/**\n * Transforms a value that is either a Date or a string into an ISO 8601\n * formatted string. If it's already a string, it assumes it's already in ISO\n * format.\n */\nexport function toISOStringSafe(\n value: Date | (string & tags.Format<\"date-time\">),\n): string & tags.Format<\"date-time\"> {\n if (value instanceof Date) {\n return value.toISOString() as string & tags.Format<\"date-time\">;\n }\n return value;\n}\n",
9
9
  "test/servant.ts": "import { DynamicExecutor } from \"@nestia/e2e\";\nimport { Driver, WorkerServer } from \"tgrid\";\n\nimport { MyBackend } from \"../src/MyBackend\";\nimport { MyGlobal } from \"../src/MyGlobal\";\nimport { IAutoBeRealizeTestConfig } from \"./autobe/compiler/IAutoBeRealizeTestConfig\";\nimport { IAutoBeRealizeTestListener } from \"./autobe/compiler/IAutoBeRealizeTestListener\";\nimport { IAutoBeRealizeTestOperation } from \"./autobe/compiler/IAutoBeRealizeTestOperation\";\nimport { IAutoBeRealizeTestResult } from \"./autobe/compiler/IAutoBeRealizeTestResult\";\nimport { IAutoBeRealizeTestService } from \"./autobe/compiler/IAutoBeRealizeTestService\";\nimport { TestAutomation } from \"./helpers/TestAutomation\";\n\nclass AutoBeRealizeTestService implements IAutoBeRealizeTestService {\n public constructor(\n private readonly listener: Driver<IAutoBeRealizeTestListener>,\n ) {}\n\n public async execute(\n config: IAutoBeRealizeTestConfig,\n ): Promise<IAutoBeRealizeTestResult> {\n const start: Date = new Date();\n const operations: IAutoBeRealizeTestOperation[] = [];\n await TestAutomation.execute({\n open: async (): Promise<MyBackend> => {\n const backend: MyBackend = new MyBackend();\n await backend.open();\n return backend;\n },\n close: (backend: MyBackend): Promise<void> => backend.close(),\n options: {\n reset: config.reset ?? true,\n simultaneous: config.simultaneous ?? 1,\n },\n onComplete: (exec: DynamicExecutor.IExecution): void => {\n const op: IAutoBeRealizeTestOperation = {\n name: exec.name,\n location: exec.location,\n value: exec.value,\n error: exec.error,\n started_at: exec.started_at,\n completed_at: exec.completed_at,\n };\n this.listener.onOperation(op).catch(() => {});\n operations.push(op);\n },\n onReset: (): void => {\n this.listener.onReset().catch(() => {});\n },\n });\n return {\n reset: config.reset ?? true,\n simultaneous: config.simultaneous ?? 1,\n operations,\n started_at: start.toISOString(),\n completed_at: new Date().toISOString(),\n };\n }\n}\n\nconst main = async (): Promise<void> => {\n const worker: WorkerServer<\n null,\n IAutoBeRealizeTestService,\n IAutoBeRealizeTestListener\n > = new WorkerServer();\n const listener: Driver<IAutoBeRealizeTestListener> = worker.getDriver();\n const service: AutoBeRealizeTestService = new AutoBeRealizeTestService(\n listener,\n );\n\n MyGlobal.testing = true;\n await worker.open(service);\n};\nmain().catch((error) => {\n console.log(error);\n process.exit(-1);\n});\n",
10
+ "tsconfig.json": "{\n \"compilerOptions\": {\n /* Visit https://aka.ms/tsconfig to read more about this file */\n\n /* Projects */\n // \"incremental\": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */\n // \"composite\": true, /* Enable constraints that allow a TypeScript project to be used with project references. */\n // \"tsBuildInfoFile\": \"./.tsbuildinfo\", /* Specify the path to .tsbuildinfo incremental compilation file. */\n // \"disableSourceOfProjectReferenceRedirect\": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */\n // \"disableSolutionSearching\": true, /* Opt a project out of multi-project reference checking when editing. */\n // \"disableReferencedProjectLoad\": true, /* Reduce the number of projects loaded automatically by TypeScript. */\n\n /* Language and Environment */\n \"target\": \"ES2015\", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */\n // \"lib\": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */\n // \"jsx\": \"preserve\", /* Specify what JSX code is generated. */\n \"experimentalDecorators\": true, /* Enable experimental support for TC39 stage 2 draft decorators. */\n \"emitDecoratorMetadata\": true, /* Emit design-type metadata for decorated declarations in source files. */\n // \"jsxFactory\": \"\", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */\n // \"jsxFragmentFactory\": \"\", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */\n // \"jsxImportSource\": \"\", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */\n // \"reactNamespace\": \"\", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */\n // \"noLib\": true, /* Disable including any library files, including the default lib.d.ts. */\n // \"useDefineForClassFields\": true, /* Emit ECMAScript-standard-compliant class fields. */\n // \"moduleDetection\": \"auto\", /* Control what method is used to detect module-format JS files. */\n\n /* Modules */\n \"module\": \"commonjs\", /* Specify what module code is generated. */\n // \"rootDir\": \"./\", /* Specify the root folder within your source files. */\n // \"moduleResolution\": \"node\", /* Specify how TypeScript looks up a file from a given module specifier. */\n // \"baseUrl\": \"./\", /* Specify the base directory to resolve non-relative module names. */\n \"paths\": {\n \"@ORGANIZATION/PROJECT-api/lib/*\": [\"./src/api/*\"],\n \"@ORGANIZATION/PROJECT-api\": [\"./src/api\"],\n }, /* Specify a set of entries that re-map imports to additional lookup locations. */\n // \"rootDirs\": [], /* Allow multiple folders to be treated as one when resolving modules. */\n // \"typeRoots\": [], /* Specify multiple folders that act like './node_modules/@types'. */\n // \"types\": [], /* Specify type package names to be included without being referenced in a source file. */\n // \"allowUmdGlobalAccess\": true, /* Allow accessing UMD globals from modules. */\n // \"moduleSuffixes\": [], /* List of file name suffixes to search when resolving a module. */\n // \"resolveJsonModule\": true, /* Enable importing .json files. */\n // \"noResolve\": true, /* Disallow 'import's, 'require's or '<reference>'s from expanding the number of files TypeScript should add to a project. */\n\n /* JavaScript Support */\n // \"allowJs\": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */\n // \"checkJs\": true, /* Enable error reporting in type-checked JavaScript files. */\n // \"maxNodeModuleJsDepth\": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */\n\n /* Emit */\n // \"declaration\": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */\n // \"declarationMap\": true, /* Create sourcemaps for d.ts files. */\n // \"emitDeclarationOnly\": true, /* Only output d.ts files and not JavaScript files. */\n \"sourceMap\": true, /* Create source map files for emitted JavaScript files. */\n // \"outFile\": \"./\", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */\n \"outDir\": \"./lib\", /* Specify an output folder for all emitted files. */\n // \"removeComments\": true, /* Disable emitting comments. */\n // \"noEmit\": true, /* Disable emitting files from a compilation. */\n // \"importHelpers\": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */\n // \"importsNotUsedAsValues\": \"remove\", /* Specify emit/checking behavior for imports that are only used for types. */\n // \"downlevelIteration\": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */\n // \"sourceRoot\": \"\", /* Specify the root path for debuggers to find the reference source code. */\n // \"mapRoot\": \"\", /* Specify the location where debugger should locate map files instead of generated locations. */\n // \"inlineSourceMap\": true, /* Include sourcemap files inside the emitted JavaScript. */\n // \"inlineSources\": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */\n // \"emitBOM\": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */\n \"newLine\": \"lf\", /* Set the newline character for emitting files. */\n \"stripInternal\": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */\n // \"noEmitHelpers\": true, /* Disable generating custom helper functions like '__extends' in compiled output. */\n // \"noEmitOnError\": true, /* Disable emitting files if any type checking errors are reported. */\n // \"preserveConstEnums\": true, /* Disable erasing 'const enum' declarations in generated code. */\n // \"declarationDir\": \"./\", /* Specify the output directory for generated declaration files. */\n // \"preserveValueImports\": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */\n\n /* Interop Constraints */\n // \"isolatedModules\": true, /* Ensure that each file can be safely transpiled without relying on other imports. */\n // \"allowSyntheticDefaultImports\": true, /* Allow 'import x from y' when a module doesn't have a default export. */\n \"esModuleInterop\": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */\n // \"preserveSymlinks\": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */\n \"forceConsistentCasingInFileNames\": true, /* Ensure that casing is correct in imports. */\n\n /* Type Checking */\n \"strict\": true, /* Enable all strict type-checking options. */\n // \"noImplicitAny\": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */\n // \"strictNullChecks\": true, /* When type checking, take into account 'null' and 'undefined'. */\n // \"strictFunctionTypes\": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */\n // \"strictBindCallApply\": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */\n // \"strictPropertyInitialization\": true, /* Check for class properties that are declared but not set in the constructor. */\n // \"noImplicitThis\": true, /* Enable error reporting when 'this' is given the type 'any'. */\n // \"useUnknownInCatchVariables\": true, /* Default catch clause variables as 'unknown' instead of 'any'. */\n // \"alwaysStrict\": true, /* Ensure 'use strict' is always emitted. */\n \"noUnusedLocals\": false, /* Enable error reporting when local variables aren't read. */\n \"noUnusedParameters\": false, /* Raise an error when a function parameter isn't read. */\n // \"exactOptionalPropertyTypes\": true, /* Interpret optional property types as written, rather than adding 'undefined'. */\n \"noImplicitReturns\": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */\n \"noFallthroughCasesInSwitch\": true, /* Enable error reporting for fallthrough cases in switch statements. */\n // \"noUncheckedIndexedAccess\": true, /* Add 'undefined' to a type when accessed using an index. */\n // \"noImplicitOverride\": true, /* Ensure overriding members in derived classes are marked with an override modifier. */\n // \"noPropertyAccessFromIndexSignature\": true, /* Enforces using indexed accessors for keys declared using an indexed type. */\n // \"allowUnusedLabels\": true, /* Disable error reporting for unused labels. */\n // \"allowUnreachableCode\": true, /* Disable error reporting for unreachable code. */\n\n /* Completeness */\n // \"skipDefaultLibCheck\": true, /* Skip type checking .d.ts files that are included with TypeScript. */\n \"skipLibCheck\": true, /* Skip type checking all .d.ts files. */\n \"plugins\": [\n { \"transform\": \"typescript-transform-paths\" },\n { \"transform\": \"typia/lib/transform\" },\n { \n \"transform\": \"@nestia/core/lib/transform\",\n /**\n * Validate request body.\n * \n * - \"assert\": Use typia.assert() function\n * - \"is\": Use typia.is() function\n * - \"validate\": Use typia.validate() function\n * - \"assertEquals\": Use typia.assertEquals() function\n * - \"equals\": Use typia.equals() function\n * - \"validateEquals\": Use typia.validateEquals() function\n */\n \"validate\": \"validate\",\n /**\n * Validate JSON typed response body.\n * \n * - \"assert\": Use typia.assertStringify() function\n * - \"is\": Use typia.isStringify() function\n * - \"validate\": Use typia.validateStringify() function\n * - \"validate.log\": typia.validateStringify(), but do not throw and just log it\n * - \"stringify\": Use typia.stringify() function, but dangerous\n * - null: Just use JSON.stringify() function, without boosting\n */\n \"stringify\": \"assert\",\n },\n ]\n },\n \"include\": [\n \"src\"\n ],\n \"exclude\": [\n \"node_modules\",\n \"packages\",\n ]\n}\n",
10
11
  "test/autobe/compiler/IAutoBeRealizeTestOperation.ts": "//---------------------------------------------------\n// Cloned from @autobe/interface\n//---------------------------------------------------\nimport { tags } from \"typia\";\n\n/**\n * Detailed result interface representing the execution outcome of an individual\n * E2E test function during comprehensive backend implementation validation.\n *\n * This interface captures comprehensive information about a single test\n * operation execution, including identification details, execution results,\n * error conditions, and precise timing data. Each operation represents the\n * validation of a specific API endpoint or business scenario through Test\n * agent-generated E2E test functions executed against the fully implemented\n * backend application.\n *\n * The operation result provides granular visibility into test execution\n * outcomes, enabling detailed analysis of implementation quality, business\n * logic compliance, and performance characteristics at the individual test\n * level. This detailed tracking supports comprehensive validation reporting and\n * precise identification of implementation issues when they occur.\n *\n * @author Samchon\n */\nexport interface IAutoBeRealizeTestOperation {\n /**\n * Unique identifier name of the executed E2E test function.\n *\n * Specifies the function name that was executed during this test operation,\n * typically corresponding to the Test agent-generated test function\n * identifier. This name provides direct traceability between test results and\n * the specific business scenarios, API endpoints, or validation logic being\n * tested.\n *\n * The test function name serves as the primary identifier for correlating\n * execution results with the original test scenarios, enabling stakeholders\n * to understand which specific functionality was validated and whether the\n * implementation correctly fulfills the intended business requirements and\n * API contracts.\n */\n name: string;\n\n /**\n * File system path location of the executed test function source code.\n *\n * Specifies the relative or absolute path to the test file that contains the\n * executed function within the project structure. This location information\n * enables direct navigation to the test source code for detailed analysis,\n * debugging, result interpretation, or modification purposes.\n *\n * The file location provides essential context for understanding test\n * organization, enables developers to quickly locate and examine the specific\n * test implementation, and supports comprehensive test suite maintenance and\n * documentation activities.\n */\n location: string;\n\n /**\n * Return value or result data produced by the test function execution.\n *\n * Contains the actual value returned by the test function upon completion,\n * regardless of whether execution succeeded or failed. This could include API\n * response objects, validation results, test data, computed values, or any\n * other output that the test function produces as part of its business logic\n * validation or endpoint testing.\n *\n * For successful test executions, this value represents the expected result\n * that demonstrates correct implementation behavior. The return value\n * provides insight into the test execution flow and can be analyzed to verify\n * that API responses match expected formats, business logic produces correct\n * outcomes, and data transformations operate as intended.\n */\n value: unknown;\n\n /**\n * Error information captured during test function execution, if any occurred.\n *\n * Contains detailed error information when the test function encounters\n * exceptions, assertion failures, timeout conditions, or other error states\n * during execution. When null, it indicates that the test completed\n * successfully without encountering any error conditions. When present, the\n * error provides comprehensive diagnostic information for understanding\n * implementation issues or test failures.\n *\n * Error information is crucial for identifying implementation defects, API\n * contract violations, business logic errors, integration failures, or\n * performance issues that prevent the backend application from meeting its\n * requirements. The error details enable developers to pinpoint specific\n * problems and implement necessary corrections to achieve full compliance\n * with validation scenarios.\n */\n error: null | unknown;\n\n /**\n * Precise timestamp when this specific test operation began execution.\n *\n * Records the exact moment when this individual test function started\n * execution, providing the reference point for measuring test duration and\n * understanding the temporal sequence of test operations within the overall\n * validation process. This timestamp enables detailed performance analysis\n * and execution timeline reconstruction.\n *\n * The start timestamp is essential for identifying execution patterns,\n * analyzing test concurrency behavior, measuring individual test performance,\n * and understanding the temporal distribution of test execution within the\n * comprehensive validation suite.\n */\n started_at: string & tags.Format<\"date-time\">;\n\n /**\n * Precise timestamp when this specific test operation finished execution.\n *\n * Records the exact moment when this individual test function completed\n * execution, regardless of whether it succeeded or failed. Combined with the\n * start timestamp, this enables precise calculation of test execution\n * duration and provides completion reference for the overall test timeline.\n *\n * The completion timestamp is valuable for performance analysis of individual\n * test operations, identifying slow-performing test scenarios, understanding\n * test execution efficiency, and maintaining comprehensive audit trails of\n * the validation process. It supports optimization efforts and helps identify\n * potential bottlenecks in either the test implementation or the backend\n * application being validated.\n */\n completed_at: string & tags.Format<\"date-time\">;\n}\n",
11
12
  "test/autobe/compiler/IAutoBeRealizeTestConfig.ts": "//---------------------------------------------------\n// Cloned from @autobe/interface\n//---------------------------------------------------\n/**\n * Configuration interface defining the essential execution parameters required\n * for comprehensive E2E test suite validation against fully implemented backend\n * applications.\n *\n * This interface encapsulates the core execution settings and control\n * parameters necessary to orchestrate the final validation phase of the AutoBE\n * development pipeline. It provides streamlined configuration options that\n * control test execution behavior, database management, and performance\n * characteristics without requiring direct access to implementation files or\n * database schemas.\n *\n * The configuration assumes that the test execution environment has been\n * pre-configured with all necessary resources including generated\n * implementation files, database schemas, and package dependencies. This\n * interface focuses solely on runtime execution parameters that control how the\n * test suite operates within the prepared environment.\n *\n * This lightweight configuration approach enables flexible test execution\n * across different environments while maintaining clear separation between\n * resource provisioning and execution control, supporting both development and\n * production validation scenarios.\n *\n * @author Samchon\n */\nexport interface IAutoBeRealizeTestConfig {\n /**\n * Optional flag indicating whether to perform a complete database reset\n * before test execution.\n *\n * When true, specifies that the test execution should begin with a\n * comprehensive database reset, purging all existing data and reconstructing\n * tables to their initial schema-defined state. When false, test execution\n * proceeds with the current database state, which may contain residual data\n * from previous operations.\n *\n * Database reset is crucial for ensuring test isolation, reproducibility, and\n * deterministic results. Clean state testing eliminates interference from\n * residual data and guarantees that each test execution cycle operates under\n * identical baseline conditions, enabling accurate validation of backend\n * implementation behavior.\n *\n * @default true\n */\n reset?: boolean;\n\n /**\n * Optional specification of the maximum number of test functions to execute\n * concurrently during the test suite run.\n *\n * Defines the concurrent execution limit for E2E test functions to optimize\n * testing performance while maintaining system stability and resource\n * management. This value balances test execution speed with resource\n * consumption and helps prevent system overload during comprehensive\n * validation.\n *\n * Concurrent execution significantly reduces total testing time for large\n * test suites while validating the backend application's ability to handle\n * parallel requests correctly. The simultaneous limit ensures controlled load\n * conditions that provide meaningful performance insights while maintaining\n * test reliability and result accuracy.\n *\n * @default 1\n */\n simultaneous?: number;\n}\n",
12
13
  "test/autobe/compiler/IAutoBeRealizeTestResult.ts": "//---------------------------------------------------\n// Cloned from @autobe/interface\n//---------------------------------------------------\nimport { tags } from \"typia\";\n\nimport { IAutoBeRealizeTestOperation } from \"./IAutoBeRealizeTestOperation\";\n\n/**\n * Comprehensive result interface containing complete information about E2E test\n * suite execution for backend implementation validation.\n *\n * This interface represents the final consolidated results of executing the\n * entire Test agent-generated E2E test suite against the fully implemented\n * backend application. It encapsulates all aspects of the test execution\n * process including configuration parameters, individual operation results, and\n * timing information that collectively determine the validation outcome of the\n * generated backend implementation.\n *\n * The result structure provides stakeholders with comprehensive visibility into\n * the validation process, enabling detailed analysis of backend implementation\n * quality, compliance with requirements, and production readiness assessment\n * based on exhaustive functional testing.\n *\n * @author Samchon\n */\nexport interface IAutoBeRealizeTestResult {\n /**\n * Whether the test execution included a clean database reset before testing.\n *\n * Indicates if the test suite execution began with a complete database reset\n * to ensure clean testing conditions. When true, all existing data was purged\n * and database tables were reconstructed to their initial state before test\n * execution commenced, guaranteeing test isolation and reproducibility.\n *\n * Database reset is essential for ensuring that test results are\n * deterministic and accurately reflect the application's behavior under\n * controlled conditions, free from interference by residual data from\n * previous executions or development activities. This flag helps stakeholders\n * understand the testing conditions and trust the reliability of results.\n */\n reset: boolean;\n\n /**\n * Number of test functions that were executed simultaneously during the test\n * suite run.\n *\n * Specifies the concurrent execution limit that was applied during E2E test\n * function execution to optimize testing performance while maintaining system\n * stability. This value represents the balance between test execution speed\n * and resource consumption that was used to validate the backend\n * implementation's ability to handle concurrent requests.\n *\n * The simultaneous execution count provides insight into the load conditions\n * under which the backend application was validated, helping stakeholders\n * understand the concurrency testing coverage and the application's\n * performance characteristics under parallel request scenarios.\n */\n simultaneous: number;\n\n /**\n * Complete collection of individual test operation results with detailed\n * execution information.\n *\n * Contains the comprehensive array of {@link IAutoBeRealizeTestOperation}\n * results representing every E2E test function that was executed during the\n * validation process. Each operation result includes detailed information\n * about test execution outcomes, return values, error conditions, timing\n * data, and validation status for specific API endpoints or business\n * scenarios.\n *\n * This complete result set enables stakeholders to perform detailed analysis\n * of which functionality passed validation, which tests failed, what specific\n * issues were encountered, and how the backend implementation performs under\n * various test scenarios. The operation results serve as the authoritative\n * record of implementation quality and compliance with established\n * requirements.\n */\n operations: IAutoBeRealizeTestOperation[];\n\n /**\n * Timestamp when the comprehensive test suite execution was initiated.\n *\n * Records the exact moment when the E2E test suite execution began, marking\n * the start of the final validation phase in the AutoBE development pipeline.\n * This timestamp provides the reference point for understanding the complete\n * test execution timeline and measuring the duration of comprehensive backend\n * validation.\n *\n * The start timestamp is essential for performance analysis of the entire\n * validation process, enabling stakeholders to understand test execution\n * efficiency and identify potential optimization opportunities in the testing\n * infrastructure or backend implementation.\n */\n started_at: string & tags.Format<\"date-time\">;\n\n /**\n * Timestamp when the entire test suite execution was finalized.\n *\n * Records the exact moment when all planned E2E test operations finished\n * execution, marking the completion of the comprehensive validation process.\n * This timestamp represents the definitive end point of the AutoBE\n * development pipeline validation phase and provides the completion reference\n * for calculating total validation duration.\n *\n * The completion timestamp serves as the official validation completion\n * marker for stakeholders tracking project delivery milestones and provides\n * essential audit trail information for the complete development and\n * validation cycle. Combined with the start timestamp, it enables precise\n * measurement of the total time required for comprehensive backend\n * validation.\n */\n completed_at: string & tags.Format<\"date-time\">;\n}\n",
@@ -1,5 +1,5 @@
1
1
  export const AutoBeCompilerTestTemplate: Record<string, string> = {
2
- "package.json": "{\n \"private\": true,\n \"name\": \"@ORGANIZATION/PROJECT\",\n \"version\": \"0.1.0\",\n \"description\": \"Starter kit of Nestia\",\n \"main\": \"lib/index.js\",\n \"scripts\": {\n \"benchmark\": \"node bin/test/benchmark\",\n \"test\": \"node bin/test\",\n \"test:webpack\": \"npm run webpack && node bin/test/webpack.js\",\n \"------------------------BUILDS------------------------\": \"\",\n \"build\": \"npm run build:sdk && npm run build:main && npm run build:test\",\n \"build:api\": \"rimraf packages/api/lib && nestia all && rimraf packages/api/lib && tsc -p packages/api/tsconfig.json && rollup -c packages/api/rollup.config.js\",\n \"build:main\": \"rimraf lib && tsc\",\n \"build:sdk\": \"rimraf src/api/functional && nestia sdk\",\n \"build:swagger\": \"npx nestia swagger\",\n \"build:test\": \"rimraf bin && tsc -p test/tsconfig.json\",\n \"dev\": \"npm run build:test -- --watch\",\n \"eslint\": \"eslint src && eslint test\",\n \"eslint:fix\": \"eslint --fix src && eslint --fix test\",\n \"prepare\": \"ts-patch install && ts-node build/env.ts\",\n \"prettier\": \"prettier src --write && prettier test --write\",\n \"------------------------WEBPACK------------------------\": \"\",\n \"webpack\": \"rimraf dist && webpack\",\n \"webpack:start\": \"cd dist && node dist/server\",\n \"webpack:test\": \"npm run webpack && node bin/test/webpack.js\",\n \"------------------------DEPLOYS------------------------\": \"\",\n \"package:api\": \"npm run build:api && cd packages/api && npm publish\",\n \"start\": \"node lib/executable/server\",\n \"start:dev\": \"nest start --watch\",\n \"start:swagger\": \"ts-node src/executable/swagger.ts\"\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/samchon/nestia-start\"\n },\n \"keywords\": [\n \"nestia\",\n \"template\",\n \"boilerplate\"\n ],\n \"author\": \"AUTHOR\",\n \"license\": \"AGPL-3.0\",\n \"bugs\": {\n \"url\": \"https://github.com/samchon/nestia-start/issues\"\n },\n \"homepage\": \"https://github.com/samchon/nestia-start#readme\",\n \"devDependencies\": {\n \"@nestia/benchmark\": \"^7.3.3\",\n \"@nestia/e2e\": \"^7.3.3\",\n \"@nestia/sdk\": \"^7.3.3\",\n \"@nestjs/cli\": \"^11.0.7\",\n \"@rollup/plugin-terser\": \"^0.4.4\",\n \"@rollup/plugin-typescript\": \"^11.1.6\",\n \"@trivago/prettier-plugin-sort-imports\": \"^4.3.0\",\n \"@types/cli\": \"^0.11.21\",\n \"@types/cli-progress\": \"^3.11.5\",\n \"@types/express\": \"^4.17.21\",\n \"@types/inquirer\": \"^8.2.5\",\n \"@types/node\": \"^18.11.0\",\n \"@types/uuid\": \"^8.3.4\",\n \"@typescript-eslint/eslint-plugin\": \"^8.1.0\",\n \"@typescript-eslint/parser\": \"^8.1.0\",\n \"chalk\": \"^4.1.2\",\n \"cli\": \"^1.0.1\",\n \"cli-progress\": \"^3.12.0\",\n \"copy-webpack-plugin\": \"^11.0.0\",\n \"eslint-plugin-deprecation\": \"^3.0.0\",\n \"express\": \"^4.18.2\",\n \"nestia\": \"^7.3.3\",\n \"prettier\": \"^3.2.4\",\n \"prettier-plugin-prisma\": \"^5.0.0\",\n \"prisma-markdown\": \"^3.0.1\",\n \"rimraf\": \"^3.0.2\",\n \"rollup\": \"^4.18.0\",\n \"source-map-support\": \"^0.5.21\",\n \"swagger-ui-express\": \"^5.0.0\",\n \"ts-loader\": \"^9.5.1\",\n \"ts-node\": \"^10.9.1\",\n \"ts-patch\": \"^3.3.0\",\n \"typescript\": \"~5.9.2\",\n \"typescript-transform-paths\": \"^3.5.5\",\n \"webpack\": \"^5.89.0\",\n \"webpack-cli\": \"^5.1.4\",\n \"write-file-webpack-plugin\": \"^4.5.1\"\n },\n \"dependencies\": {\n \"@nestia/core\": \"^7.3.3\",\n \"@nestia/fetcher\": \"^7.3.3\",\n \"@nestjs/common\": \"^11.1.3\",\n \"@nestjs/core\": \"^11.1.3\",\n \"@nestjs/platform-express\": \"^11.1.3\",\n \"@prisma/client\": \"^6.11.1\",\n \"commander\": \"10.0.0\",\n \"dotenv\": \"^16.3.1\",\n \"dotenv-expand\": \"^10.0.0\",\n \"inquirer\": \"8.2.5\",\n \"prisma\": \"^6.11.1\",\n \"serialize-error\": \"^4.1.0\",\n \"tgrid\": \"^1.1.0\",\n \"tstl\": \"^3.0.0\",\n \"typia\": \"^9.7.1\",\n \"uuid\": \"^9.0.0\"\n },\n \"stackblitz\": {\n \"startCommand\": \"npm run prepare && npm run build:test && npm run test -- --simultaneous 1\"\n }\n}\n",
2
+ "package.json": "{\n \"private\": true,\n \"name\": \"@ORGANIZATION/PROJECT\",\n \"version\": \"0.1.0\",\n \"description\": \"Starter kit of Nestia\",\n \"main\": \"lib/index.js\",\n \"scripts\": {\n \"benchmark\": \"node bin/test/benchmark\",\n \"test\": \"node bin/test\",\n \"test:webpack\": \"npm run webpack && node bin/test/webpack.js\",\n \"------------------------BUILDS------------------------\": \"\",\n \"build\": \"npm run build:sdk && npm run build:main && npm run build:test\",\n \"build:api\": \"rimraf packages/api/lib && nestia all && rimraf packages/api/lib && tsc -p packages/api/tsconfig.json && rollup -c packages/api/rollup.config.js\",\n \"build:main\": \"rimraf lib && tsc\",\n \"build:sdk\": \"rimraf src/api/functional && nestia sdk\",\n \"build:swagger\": \"npx nestia swagger\",\n \"build:test\": \"rimraf bin && tsc -p test/tsconfig.json\",\n \"dev\": \"npm run build:test -- --watch\",\n \"eslint\": \"eslint src && eslint test\",\n \"eslint:fix\": \"eslint --fix src && eslint --fix test\",\n \"prepare\": \"ts-patch install && ts-node build/env.ts\",\n \"prettier\": \"prettier src --write && prettier test --write\",\n \"------------------------WEBPACK------------------------\": \"\",\n \"webpack\": \"rimraf dist && webpack\",\n \"webpack:start\": \"cd dist && node dist/server\",\n \"webpack:test\": \"npm run webpack && node bin/test/webpack.js\",\n \"------------------------DEPLOYS------------------------\": \"\",\n \"package:api\": \"npm run build:api && cd packages/api && npm publish\",\n \"start\": \"node lib/executable/server\",\n \"start:dev\": \"nest start --watch\",\n \"start:swagger\": \"ts-node src/executable/swagger.ts\"\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/samchon/nestia-start\"\n },\n \"keywords\": [\n \"nestia\",\n \"template\",\n \"boilerplate\"\n ],\n \"author\": \"AUTHOR\",\n \"license\": \"AGPL-3.0\",\n \"bugs\": {\n \"url\": \"https://github.com/samchon/nestia-start/issues\"\n },\n \"homepage\": \"https://github.com/samchon/nestia-start#readme\",\n \"devDependencies\": {\n \"@nestia/benchmark\": \"^7.4.0\",\n \"@nestia/e2e\": \"^7.4.0\",\n \"@nestia/sdk\": \"^7.4.0\",\n \"@nestjs/cli\": \"^11.0.7\",\n \"@rollup/plugin-terser\": \"^0.4.4\",\n \"@rollup/plugin-typescript\": \"^11.1.6\",\n \"@trivago/prettier-plugin-sort-imports\": \"^4.3.0\",\n \"@types/cli\": \"^0.11.21\",\n \"@types/cli-progress\": \"^3.11.5\",\n \"@types/express\": \"^4.17.21\",\n \"@types/inquirer\": \"^8.2.5\",\n \"@types/node\": \"^18.11.0\",\n \"@types/uuid\": \"^8.3.4\",\n \"@typescript-eslint/eslint-plugin\": \"^8.1.0\",\n \"@typescript-eslint/parser\": \"^8.1.0\",\n \"chalk\": \"^4.1.2\",\n \"cli\": \"^1.0.1\",\n \"cli-progress\": \"^3.12.0\",\n \"copy-webpack-plugin\": \"^11.0.0\",\n \"eslint-plugin-deprecation\": \"^3.0.0\",\n \"express\": \"^4.18.2\",\n \"nestia\": \"^7.4.0\",\n \"prettier\": \"^3.2.4\",\n \"prettier-plugin-prisma\": \"^5.0.0\",\n \"prisma-markdown\": \"^3.0.1\",\n \"rimraf\": \"^3.0.2\",\n \"rollup\": \"^4.18.0\",\n \"source-map-support\": \"^0.5.21\",\n \"swagger-ui-express\": \"^5.0.0\",\n \"ts-loader\": \"^9.5.1\",\n \"ts-node\": \"^10.9.1\",\n \"ts-patch\": \"^3.3.0\",\n \"typescript\": \"~5.9.2\",\n \"typescript-transform-paths\": \"^3.5.5\",\n \"webpack\": \"^5.89.0\",\n \"webpack-cli\": \"^5.1.4\",\n \"write-file-webpack-plugin\": \"^4.5.1\"\n },\n \"dependencies\": {\n \"@nestia/core\": \"^7.4.0\",\n \"@nestia/fetcher\": \"^7.4.0\",\n \"@nestjs/common\": \"^11.1.3\",\n \"@nestjs/core\": \"^11.1.3\",\n \"@nestjs/platform-express\": \"^11.1.3\",\n \"@prisma/client\": \"^6.11.1\",\n \"commander\": \"10.0.0\",\n \"dotenv\": \"^16.3.1\",\n \"dotenv-expand\": \"^10.0.0\",\n \"inquirer\": \"8.2.5\",\n \"prisma\": \"^6.11.1\",\n \"serialize-error\": \"^4.1.0\",\n \"tgrid\": \"^1.1.0\",\n \"tstl\": \"^3.0.0\",\n \"typia\": \"^9.7.1\",\n \"uuid\": \"^9.0.0\"\n },\n \"stackblitz\": {\n \"startCommand\": \"npm run prepare && npm run build:test && npm run test -- --simultaneous 1\"\n }\n}\n",
3
3
  "src/setup/MySetupWizard.ts": "export namespace MySetupWizard {\n export async function schema(): Promise<void> {\n console.log(\"Realize agent has not generated main program yet.\");\n }\n\n export async function seed(): Promise<void> {}\n}\n",
4
4
  "test/helpers/TestAutomation.ts": "import api from \"@ORGANIZATION/PROJECT-api\";\nimport { DynamicExecutor } from \"@nestia/e2e\";\nimport { sleep_for } from \"tstl\";\n\nimport { MyConfiguration } from \"../../src/MyConfiguration\";\nimport { MySetupWizard } from \"../../src/setup/MySetupWizard\";\n\nexport namespace TestAutomation {\n export interface IProps<T> {\n open(options: IOptions): Promise<T>;\n close(backend: T): Promise<void>;\n onComplete(exec: DynamicExecutor.IExecution): void;\n onReset(): void;\n options: IOptions;\n }\n\n export interface IOptions {\n reset: boolean;\n simultaneous: number;\n include?: string[];\n exclude?: string[];\n }\n\n export const execute = async <T>(\n props: IProps<T>,\n ): Promise<DynamicExecutor.IReport> => {\n // RESET\n if (props.options.reset === true) {\n await MySetupWizard.schema();\n await MySetupWizard.seed();\n await props.onReset();\n }\n\n // OPEN BACKEND\n const backend: T = await props.open(props.options);\n const connection: api.IConnection = {\n host: `http://127.0.0.1:${MyConfiguration.API_PORT()}`,\n };\n\n // DO TEST\n const report: DynamicExecutor.IReport = await DynamicExecutor.validate({\n prefix: \"test\",\n location: __dirname + \"/../features\",\n parameters: () => [\n {\n host: connection.host,\n } satisfies api.IConnection,\n ],\n filter: (func) =>\n (!props.options.include?.length ||\n (props.options.include ?? []).some((str) => func.includes(str))) &&\n (!props.options.exclude?.length ||\n (props.options.exclude ?? []).every((str) => !func.includes(str))),\n onComplete: props.onComplete,\n simultaneous: props.options.simultaneous,\n extension: __filename.split(\".\").pop()!,\n });\n\n // TERMINATE\n await sleep_for(2500);\n await props.close(backend);\n return report;\n };\n}\n",
5
5
  "test/helpers/TestAutomationStdio.ts": "import { DynamicExecutor } from \"@nestia/e2e\";\nimport chalk from \"chalk\";\n\nimport { ArgumentParser } from \"./ArgumentParser\";\nimport { TestAutomation } from \"./TestAutomation\";\n\nexport namespace TestAutomationStdio {\n export const getOptions = () =>\n ArgumentParser.parse<TestAutomation.IOptions>(\n async (command, prompt, action) => {\n command.option(\"--reset <true|false>\", \"reset local DB or not\");\n command.option(\n \"--simultaneous <number>\",\n \"number of simultaneous requests\",\n );\n command.option(\"--include <string...>\", \"include feature files\");\n command.option(\"--exclude <string...>\", \"exclude feature files\");\n\n return action(async (options) => {\n // reset\n if (typeof options.reset === \"string\")\n options.reset = options.reset === \"true\";\n options.reset ??= await prompt.boolean(\"reset\")(\"Reset local DB\");\n\n // simultaneous\n options.simultaneous = Number(\n options.simultaneous ??\n (await prompt.number(\"simultaneous\")(\n \"Number of simultaneous requests to make\",\n )),\n );\n if (isNaN(options.simultaneous) || options.simultaneous <= 0)\n options.simultaneous = 1;\n return options as TestAutomation.IOptions;\n });\n },\n );\n\n export const onComplete = (exec: DynamicExecutor.IExecution): void => {\n const trace = (str: string) =>\n console.log(` - ${chalk.green(exec.name)}: ${str}`);\n if (exec.error === null) {\n const elapsed: number =\n new Date(exec.completed_at).getTime() -\n new Date(exec.started_at).getTime();\n trace(`${chalk.yellow(elapsed.toLocaleString())} ms`);\n } else trace(chalk.red(exec.error.name));\n };\n\n export const onReset = (start: Date) => (): void => {\n const now: Date = new Date();\n console.log(\n ` - Reset DB: ${(now.getDate() - start.getDate()).toLocaleString()} ms`,\n );\n };\n\n export const report = (report: DynamicExecutor.IReport): void => {\n const exceptions: Error[] = report.executions\n .filter((exec) => exec.error !== null)\n .map((exec) => exec.error!);\n if (exceptions.length === 0) {\n console.log(\"Success\");\n console.log(\"Elapsed time\", report.time.toLocaleString(), `ms`);\n } else {\n for (const exp of exceptions) console.log(exp);\n console.log(\"Failed\");\n console.log(\"Elapsed time\", report.time.toLocaleString(), `ms`);\n process.exit(-1);\n }\n };\n}\n",