@domain-first/project-structure 1.1.3 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/config-file.d.ts +1 -0
- package/dist/index.cjs +292 -172
- package/dist/index.js +292 -172
- package/dist/use-cases/index.d.ts +1 -0
- package/dist/use-cases/scaffold-react-widget.d.ts +2 -0
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -124,7 +124,8 @@ const configSchema = external_zod_default().object({
|
|
|
124
124
|
'@domain-first/wire',
|
|
125
125
|
'@domain-first/handlers-rest'
|
|
126
126
|
])),
|
|
127
|
-
defaultPersistenceLayerImplementation: external_zod_default().string()
|
|
127
|
+
defaultPersistenceLayerImplementation: external_zod_default().string(),
|
|
128
|
+
useReact: external_zod_default().boolean()
|
|
128
129
|
});
|
|
129
130
|
class ConfigFile {
|
|
130
131
|
data;
|
|
@@ -166,10 +167,14 @@ const initializeUseCase = async ()=>{
|
|
|
166
167
|
const defaultPersistenceLayerImplementation = await (0, prompts_namespaceObject.input)({
|
|
167
168
|
message: 'Default persistence layer implementation:'
|
|
168
169
|
});
|
|
170
|
+
const useReact = await (0, prompts_namespaceObject.confirm)({
|
|
171
|
+
message: 'Use React'
|
|
172
|
+
});
|
|
169
173
|
ConfigFile.write({
|
|
170
174
|
rootFolder: rootFolderName,
|
|
171
175
|
domainFirstPackages,
|
|
172
|
-
defaultPersistenceLayerImplementation
|
|
176
|
+
defaultPersistenceLayerImplementation,
|
|
177
|
+
useReact
|
|
173
178
|
});
|
|
174
179
|
const { path } = new ProjectRoot();
|
|
175
180
|
const rootFolder = new Folder(path);
|
|
@@ -277,41 +282,26 @@ export class ${naming.ClassName}${aggregateNaming.ClassName}Repository implement
|
|
|
277
282
|
}
|
|
278
283
|
|
|
279
284
|
`.trim());
|
|
280
|
-
if (ConfigFile.Instance.data.domainFirstPackages.includes('@domain-first/wire')) {
|
|
281
|
-
const wiringFolder = boundedContextFolder.subitem([
|
|
282
|
-
'wiring',
|
|
283
|
-
'infrastructure',
|
|
284
|
-
'repositories',
|
|
285
|
-
naming.fileName
|
|
286
|
-
]);
|
|
287
|
-
wiringFolder.createFile(`wire-${naming.fileName}-${aggregateNaming.fileName}-repository.ts`, `
|
|
288
|
-
import { wireClass } from '@domain-first/wire'
|
|
289
|
-
import { ${naming.ClassName}${aggregateNaming.ClassName}Repository } from '../../../../infrastructure/repositories/${naming.fileName}/${naming.fileName}-${aggregateNaming.fileName}-repository'
|
|
290
|
-
|
|
291
|
-
export const wire${naming.ClassName}${aggregateNaming.ClassName}Repository = wireClass(
|
|
292
|
-
${naming.ClassName}${aggregateNaming.ClassName}Repository,
|
|
293
|
-
[]
|
|
294
|
-
)
|
|
295
|
-
`.trim());
|
|
296
|
-
}
|
|
297
285
|
}
|
|
298
286
|
if (ConfigFile.Instance.data.domainFirstPackages.includes('@domain-first/wire')) {
|
|
299
287
|
const implementationNaming = new UnknownFormatNaming(infrastructureImplementationType);
|
|
300
288
|
const testImplementationNaming = new UnknownFormatNaming(testImplementationType);
|
|
301
289
|
boundedContextFolder.subitem([
|
|
302
290
|
'wiring',
|
|
303
|
-
'domain',
|
|
304
291
|
'repositories'
|
|
305
292
|
]).createFile(`wire-${aggregateNaming.fileName}-repository.ts`, `
|
|
306
|
-
import {
|
|
307
|
-
|
|
293
|
+
import { wireClass } from '@domain-first/wire'
|
|
294
|
+
import { envBranchedWire } from '../../../../shared/wiring/env-branched-wire'
|
|
295
|
+
${implementationTypes.map((x)=>new UnknownFormatNaming(x)).map(({ ClassName, fileName })=>`import { ${ClassName}${aggregateNaming.ClassName}Repository } from '../../infrastructure/repositories/${fileName}/${fileName}-${aggregateNaming.fileName}-repository'`).join('\n')}
|
|
296
|
+
|
|
297
|
+
${implementationTypes.map((x)=>new UnknownFormatNaming(x)).map(({ ClassName })=>`const wire${ClassName}Implementation = wireClass(${ClassName}${aggregateNaming.ClassName}Repository, [])`).join('\n\n')}
|
|
308
298
|
|
|
309
299
|
export const wire${aggregateNaming.ClassName}Repository = envBranchedWire({
|
|
310
|
-
test: wire${addTestImplementation ? testImplementationNaming.ClassName : implementationNaming.ClassName}
|
|
311
|
-
development: wire${implementationNaming.ClassName}
|
|
312
|
-
production: wire${implementationNaming.ClassName}
|
|
300
|
+
test: wire${addTestImplementation ? testImplementationNaming.ClassName : implementationNaming.ClassName}Implementation,
|
|
301
|
+
development: wire${implementationNaming.ClassName}Implementation,
|
|
302
|
+
production: wire${implementationNaming.ClassName}Implementation
|
|
313
303
|
})
|
|
314
|
-
`.trim());
|
|
304
|
+
`.trim());
|
|
315
305
|
}
|
|
316
306
|
}
|
|
317
307
|
};
|
|
@@ -322,14 +312,8 @@ const scaffoldNewApplicationPort = async (boundedContextFolder)=>{
|
|
|
322
312
|
const naming = new UnknownFormatNaming(name);
|
|
323
313
|
const wiringFolder = boundedContextFolder.subitem([
|
|
324
314
|
'wiring',
|
|
325
|
-
'application',
|
|
326
315
|
'ports'
|
|
327
316
|
]);
|
|
328
|
-
const infraFolder = boundedContextFolder.subitem([
|
|
329
|
-
'wiring',
|
|
330
|
-
'infrastructure',
|
|
331
|
-
'application-ports'
|
|
332
|
-
]);
|
|
333
317
|
const applicationPortsFolder = boundedContextFolder.subitem([
|
|
334
318
|
'application',
|
|
335
319
|
'ports'
|
|
@@ -369,29 +353,24 @@ export class ${currentNaming.ClassName} extends ${naming.ClassName} {
|
|
|
369
353
|
|
|
370
354
|
}
|
|
371
355
|
`);
|
|
372
|
-
if (ConfigFile.Instance.data.domainFirstPackages.includes('@domain-first/wire')) infraFolder.subitem([
|
|
373
|
-
implementation
|
|
374
|
-
]).createFile(`wire-${currentNaming.fileName}.ts`, `
|
|
375
|
-
import { wireClass } from '@domain-first/wire'
|
|
376
|
-
import { ${currentNaming.ClassName} } from '../../../../infrastructure/application-adapters/${implementation}/${currentNaming.fileName}'
|
|
377
|
-
|
|
378
|
-
export const wire${currentNaming.ClassName} = wireClass(
|
|
379
|
-
${currentNaming.ClassName},
|
|
380
|
-
[]
|
|
381
|
-
)
|
|
382
|
-
`.trim());
|
|
383
356
|
}
|
|
384
357
|
if (ConfigFile.Instance.data.domainFirstPackages.includes('@domain-first/wire')) wiringFolder.createFile(`wire-${naming.fileName}.ts`, `
|
|
385
|
-
import {
|
|
358
|
+
import { wireClass } from '@domain-first/wire'
|
|
359
|
+
import { envBranchedWire } from '../../../${'shared' === boundedContextFolder.name ? '' : '../'}shared/wiring/env-branched-wire'
|
|
360
|
+
${implementationTypes.map((x)=>({
|
|
361
|
+
naming: new UnknownFormatNaming(`${x}-${naming.fileName}`),
|
|
362
|
+
implementation: x
|
|
363
|
+
})).map(({ naming: { ClassName, fileName }, implementation })=>`import { ${ClassName} } from '../../infrastructure/application-adapters/${implementation}/${fileName}'`).join('\n')}
|
|
364
|
+
|
|
386
365
|
${implementationTypes.map((x)=>({
|
|
387
366
|
naming: new UnknownFormatNaming(`${x}-${naming.fileName}`),
|
|
388
367
|
implementation: x
|
|
389
|
-
})).map(({ naming: { ClassName
|
|
368
|
+
})).map(({ naming: { ClassName }, implementation })=>`const wire${new UnknownFormatNaming(implementation).ClassName}Implementation = wireClass(${ClassName}, [])`).join('\n\n')}
|
|
390
369
|
|
|
391
370
|
export const wire${naming.ClassName} = envBranchedWire({
|
|
392
|
-
test: wire${new UnknownFormatNaming(`${implementationTypes.at(-1)}
|
|
393
|
-
development: wire${new UnknownFormatNaming(`${implementationTypes.at(0)}
|
|
394
|
-
production: wire${new UnknownFormatNaming(`${implementationTypes.at(0)}
|
|
371
|
+
test: wire${new UnknownFormatNaming(`${implementationTypes.at(-1)}-implementation`).ClassName},
|
|
372
|
+
development: wire${new UnknownFormatNaming(`${implementationTypes.at(0)}-implementation`).ClassName},
|
|
373
|
+
production: wire${new UnknownFormatNaming(`${implementationTypes.at(0)}-implementation`).ClassName}
|
|
395
374
|
})
|
|
396
375
|
|
|
397
376
|
`.trim());
|
|
@@ -431,9 +410,14 @@ const scaffoldNewCommand = async (boundedContextFolder)=>{
|
|
|
431
410
|
message: 'Name: '
|
|
432
411
|
});
|
|
433
412
|
const naming = new UnknownFormatNaming(commandName);
|
|
434
|
-
const
|
|
435
|
-
|
|
413
|
+
const commandType = await (0, prompts_namespaceObject.select)({
|
|
414
|
+
choices: [
|
|
415
|
+
'Execution (with infrastructure implementation)',
|
|
416
|
+
'Orchestrator (no infrastructure implementation)'
|
|
417
|
+
],
|
|
418
|
+
message: 'Command type'
|
|
436
419
|
});
|
|
420
|
+
const isOrchestrator = 'Orchestrator (no infrastructure implementation)' === commandType;
|
|
437
421
|
if (!isOrchestrator) {
|
|
438
422
|
const implementationType = await (0, prompts_namespaceObject.input)({
|
|
439
423
|
message: 'Command infrastructure implementation type:',
|
|
@@ -457,81 +441,73 @@ const scaffoldNewCommand = async (boundedContextFolder)=>{
|
|
|
457
441
|
infrastructureFolder.subitem([
|
|
458
442
|
formatNaming.fileName
|
|
459
443
|
]).createFile(`${formatNaming.fileName}-${naming.fileName}-command.ts`, ConfigFile.Instance.data.domainFirstPackages.includes('@domain-first/handlers') ? `
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
export class ${formatNaming.ClassName}${naming.ClassName}Command implements ${naming.ClassName}Command {
|
|
464
|
-
constructor() {}
|
|
444
|
+
import { defineHandler } from '@domain-first/handlers'
|
|
445
|
+
import { ${naming.ClassName}Command } from '../../../application/commands/execution/${naming.fileName}-command'
|
|
465
446
|
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
handler: async (input) => {
|
|
470
|
-
return {}
|
|
471
|
-
}
|
|
472
|
-
})
|
|
447
|
+
export class ${formatNaming.ClassName}${naming.ClassName}Command extends ${naming.ClassName}Command {
|
|
448
|
+
constructor() {
|
|
449
|
+
super()
|
|
473
450
|
}
|
|
474
|
-
`.trim() : `
|
|
475
|
-
import { ${naming.ClassName}Command } from '../../../domain/commands/${naming.fileName}-command'
|
|
476
451
|
|
|
477
|
-
|
|
452
|
+
handle = defineHandler({
|
|
453
|
+
inputSchema: ${naming.ClassName}Command.inputSchema,
|
|
454
|
+
outputSchema: ${naming.ClassName}Command.outputSchema,
|
|
455
|
+
handler: async (input) => {
|
|
456
|
+
return {}
|
|
457
|
+
}
|
|
458
|
+
})
|
|
459
|
+
}
|
|
460
|
+
`.trim() : `
|
|
461
|
+
import { ${naming.ClassName}Command } from '../../../domain/commands/${naming.fileName}-command'
|
|
478
462
|
|
|
463
|
+
export class ${formatNaming.ClassName}${naming.ClassName}Command extends ${naming.ClassName}Command {
|
|
464
|
+
constructor() {
|
|
465
|
+
super()
|
|
479
466
|
}
|
|
467
|
+
}
|
|
480
468
|
`.trim());
|
|
481
|
-
if (ConfigFile.Instance.data.domainFirstPackages.includes('@domain-first/wire')) {
|
|
482
|
-
const wiringFolder = boundedContextFolder.subitem([
|
|
483
|
-
'wiring',
|
|
484
|
-
'infrastructure',
|
|
485
|
-
'commands',
|
|
486
|
-
formatNaming.fileName
|
|
487
|
-
]);
|
|
488
|
-
wiringFolder.createFile(`wire-${formatNaming.fileName}-${naming.fileName}-command.ts`, `
|
|
489
|
-
import { wireClass } from '@domain-first/wire'
|
|
490
|
-
import { ${formatNaming.ClassName}${naming.ClassName}Command } from '../../../../infrastructure/commands/${formatNaming.fileName}/${formatNaming.fileName}-${naming.fileName}-command'
|
|
491
|
-
|
|
492
|
-
export const wire${formatNaming.ClassName}${naming.ClassName}Command = wireClass(
|
|
493
|
-
${formatNaming.ClassName}${naming.ClassName}Command,
|
|
494
|
-
[]
|
|
495
|
-
)
|
|
496
|
-
|
|
497
|
-
`.trim());
|
|
498
|
-
}
|
|
499
469
|
}
|
|
500
|
-
if (ConfigFile.Instance.data.domainFirstPackages.includes('@domain-first/handlers')) commandsFolder.
|
|
501
|
-
|
|
470
|
+
if (ConfigFile.Instance.data.domainFirstPackages.includes('@domain-first/handlers')) commandsFolder.subitem([
|
|
471
|
+
'execution'
|
|
472
|
+
]).createFile(`${naming.fileName}-command.ts`, `
|
|
473
|
+
import type { Handler } from '@domain-first/handlers'
|
|
502
474
|
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
475
|
+
export abstract class ${naming.ClassName}Command {
|
|
476
|
+
static inputSchema = {}
|
|
477
|
+
static outputSchema = {}
|
|
506
478
|
|
|
507
|
-
|
|
508
|
-
|
|
479
|
+
abstract handle: Handler<typeof ${naming.ClassName}Command.inputSchema, typeof ${naming.ClassName}Command.outputSchema>
|
|
480
|
+
}
|
|
509
481
|
`.trim());
|
|
510
482
|
else commandsFolder.createFile(`${naming.fileName}-command.ts`, `
|
|
511
|
-
|
|
483
|
+
export abstract class ${naming.ClassName}Command {
|
|
512
484
|
|
|
513
|
-
|
|
485
|
+
}`.trim());
|
|
514
486
|
if (ConfigFile.Instance.data.domainFirstPackages.includes('@domain-first/wire')) {
|
|
515
487
|
const implementationNaming = new UnknownFormatNaming(implementationType);
|
|
516
488
|
const testImplementationNaming = new UnknownFormatNaming(testImplementationType);
|
|
517
489
|
boundedContextFolder.subitem([
|
|
518
490
|
'wiring',
|
|
519
|
-
'application',
|
|
520
491
|
'commands'
|
|
521
492
|
]).createFile(`wire-${naming.fileName}-command.ts`, `
|
|
522
|
-
|
|
523
|
-
|
|
493
|
+
import { wireClass } from '@domain-first/wire'
|
|
494
|
+
import { envBranchedWire } from '../../../../shared/wiring/env-branched-wire'
|
|
495
|
+
${implementationTypes.map((x)=>new UnknownFormatNaming(x)).map(({ ClassName, fileName })=>`import { ${ClassName}${naming.ClassName}Command } from '../../infrastructure/commands/${fileName}/${fileName}-${naming.fileName}-command'`).join('\n')}
|
|
524
496
|
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
}
|
|
497
|
+
${implementationTypes.map((x)=>new UnknownFormatNaming(x)).map(({ ClassName })=>`const wire${ClassName}Implementation = wireClass(${ClassName}${naming.ClassName}Command, [])`).join('\n\n')}
|
|
498
|
+
|
|
499
|
+
export const wire${naming.ClassName}Command = envBranchedWire({
|
|
500
|
+
test: wire${addTestImplementation ? testImplementationNaming.ClassName : implementationNaming.ClassName}Implementation,
|
|
501
|
+
development: wire${implementationNaming.ClassName}Implementation,
|
|
502
|
+
production: wire${implementationNaming.ClassName}Implementation
|
|
503
|
+
})
|
|
530
504
|
`.trim());
|
|
531
505
|
}
|
|
532
506
|
return;
|
|
533
507
|
}
|
|
534
|
-
if (ConfigFile.Instance.data.domainFirstPackages.includes('@domain-first/handlers')) commandsFolder.
|
|
508
|
+
if (ConfigFile.Instance.data.domainFirstPackages.includes('@domain-first/handlers')) commandsFolder.subitem([
|
|
509
|
+
'orchestration'
|
|
510
|
+
]).createFile(`${naming.fileName}-command.ts`, `
|
|
535
511
|
import { defineHandler } from '@domain-first/handlers'
|
|
536
512
|
|
|
537
513
|
export class ${naming.ClassName}Command {
|
|
@@ -547,7 +523,9 @@ export class ${naming.ClassName}Command {
|
|
|
547
523
|
})
|
|
548
524
|
}
|
|
549
525
|
`.trim());
|
|
550
|
-
else commandsFolder.
|
|
526
|
+
else commandsFolder.subitem([
|
|
527
|
+
'orchestration'
|
|
528
|
+
]).createFile(`${naming.fileName}-command.ts`, `
|
|
551
529
|
export class ${naming.ClassName}Command {
|
|
552
530
|
|
|
553
531
|
}`.trim());
|
|
@@ -557,7 +535,7 @@ export class ${naming.ClassName}Command {
|
|
|
557
535
|
'commands'
|
|
558
536
|
]).createFile(`wire-${naming.fileName}-command.ts`, `
|
|
559
537
|
import { wireClass } from '@domain-first/wire'
|
|
560
|
-
import { ${naming.ClassName}Command } from '../../../application/commands/${naming.fileName}-command'
|
|
538
|
+
import { ${naming.ClassName}Command } from '../../../application/commands/orchestration/${naming.fileName}-command'
|
|
561
539
|
|
|
562
540
|
export const wire${naming.ClassName}Command = wireClass(${naming.ClassName}Command, [])
|
|
563
541
|
`.trim());
|
|
@@ -609,7 +587,7 @@ const scaffoldNewErrorUseCase = async (boundedContextFolder)=>{
|
|
|
609
587
|
message: 'Error name:'
|
|
610
588
|
});
|
|
611
589
|
const naming = new UnknownFormatNaming(errorName);
|
|
612
|
-
currentErrorFolder.file('index.ts').addLine(`export const ${naming.ClassName}Error = ${new UnknownFormatNaming(boundedContextFolder.name).ClassName}Errors.define('${naming.fileName}')`, '\n\n');
|
|
590
|
+
currentErrorFolder.file('index.ts').addLine(`export const ${naming.ClassName}${new UnknownFormatNaming(boundedContextFolder.name).ClassName}Error = ${new UnknownFormatNaming(boundedContextFolder.name).ClassName}Errors.define('${naming.fileName}')`, '\n\n');
|
|
613
591
|
return;
|
|
614
592
|
}
|
|
615
593
|
if ('New namespace' === selectedVariant) {
|
|
@@ -620,17 +598,18 @@ const scaffoldNewErrorUseCase = async (boundedContextFolder)=>{
|
|
|
620
598
|
currentErrorFolder.createFile(`${fileName}.ts`, `
|
|
621
599
|
import { errorNamespace } from '@domain-first/errors'
|
|
622
600
|
|
|
623
|
-
const ${ClassName}Errors = errorNamespace('${boundedContextFolder.name}').subnamespace('${fileName}')
|
|
601
|
+
export const ${ClassName}${new UnknownFormatNaming(boundedContextFolder.name).ClassName}Errors = errorNamespace('${boundedContextFolder.name}').subnamespace('${fileName}')
|
|
624
602
|
`);
|
|
625
|
-
currentErrorFolder.file('index.ts').addLine(`export * from './${fileName}'
|
|
603
|
+
currentErrorFolder.file('index.ts').addLine(`export * from './${fileName}'`, '\n\n');
|
|
626
604
|
return;
|
|
627
605
|
}
|
|
628
606
|
const namespace = selectedVariant.substring(23);
|
|
607
|
+
const namespaceNaming = new UnknownFormatNaming(namespace);
|
|
629
608
|
const errorName = await (0, prompts_namespaceObject.input)({
|
|
630
609
|
message: 'Error name:'
|
|
631
610
|
});
|
|
632
611
|
const { ClassName, fileName } = new UnknownFormatNaming(errorName);
|
|
633
|
-
currentErrorFolder.file(`${namespace}.ts`).addLine(`export const ${ClassName}Error = ${new UnknownFormatNaming(
|
|
612
|
+
currentErrorFolder.file(`${namespace}.ts`).addLine(`export const ${ClassName}${namespaceNaming.ClassName}${new UnknownFormatNaming(boundedContextFolder.name).ClassName}Error = ${namespaceNaming.ClassName}${new UnknownFormatNaming(boundedContextFolder.name).ClassName}Errors.define('${fileName}')`, '\n\n');
|
|
634
613
|
};
|
|
635
614
|
const scaffoldNewHandlersRestEndpoint = async (boundedContextFolder)=>{
|
|
636
615
|
const restPresentationFolder = boundedContextFolder.subitem([
|
|
@@ -649,11 +628,27 @@ const scaffoldNewHandlersRestEndpoint = async (boundedContextFolder)=>{
|
|
|
649
628
|
controller = await (0, prompts_namespaceObject.input)({
|
|
650
629
|
message: 'Name: '
|
|
651
630
|
});
|
|
652
|
-
if (ConfigFile.Instance.data.domainFirstPackages.includes('@domain-first/wire'))
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
631
|
+
if (ConfigFile.Instance.data.domainFirstPackages.includes('@domain-first/wire')) {
|
|
632
|
+
boundedContextFolder.subitem([
|
|
633
|
+
'wiring',
|
|
634
|
+
'presentation',
|
|
635
|
+
'rest'
|
|
636
|
+
]).file('index.ts').addLine(`export * from './${controller}'`);
|
|
637
|
+
const sharedRestFolder = boundedContextFolder.subitem([
|
|
638
|
+
'..',
|
|
639
|
+
'..',
|
|
640
|
+
'presentation',
|
|
641
|
+
'rest'
|
|
642
|
+
]);
|
|
643
|
+
sharedRestFolder.file('wires.ts').addLine(`export * from '../../bounded-contexts/${boundedContextFolder.name}/wiring/presentation/rest/${controller}'`);
|
|
644
|
+
if (!sharedRestFolder.file('index.ts').exists) sharedRestFolder.createFile('index.ts', `
|
|
645
|
+
import * as wires from './wires'
|
|
646
|
+
|
|
647
|
+
const restWires = Object.values(wires)
|
|
648
|
+
|
|
649
|
+
export const restHandlers = restWires.map(x => x().handle)
|
|
650
|
+
`.trim());
|
|
651
|
+
}
|
|
657
652
|
}
|
|
658
653
|
const method = await (0, prompts_namespaceObject.select)({
|
|
659
654
|
message: 'Method:',
|
|
@@ -671,9 +666,10 @@ const scaffoldNewHandlersRestEndpoint = async (boundedContextFolder)=>{
|
|
|
671
666
|
const controllerFolder = restPresentationFolder.subitem([
|
|
672
667
|
controller
|
|
673
668
|
]);
|
|
669
|
+
const endpointFolder = controllerFolder.subitem(path);
|
|
674
670
|
const nameBase = `${controller}-${path.length ? `${path.join('-')}-` : ''}${method}-endpoint`;
|
|
675
671
|
const endpointNaming = new UnknownFormatNaming(nameBase);
|
|
676
|
-
|
|
672
|
+
endpointFolder.createFile(`${method.toUpperCase()}.ts`, `
|
|
677
673
|
import { EndpointGenerator } from '@domain-first/handlers-rest'
|
|
678
674
|
|
|
679
675
|
export class ${endpointNaming.ClassName} {
|
|
@@ -689,7 +685,6 @@ export class ${endpointNaming.ClassName} {
|
|
|
689
685
|
tags: ['${boundedContextFolder.name}: ${controller}'],
|
|
690
686
|
})
|
|
691
687
|
}
|
|
692
|
-
|
|
693
688
|
}
|
|
694
689
|
`.trim());
|
|
695
690
|
if (ConfigFile.Instance.data.domainFirstPackages.includes('@domain-first/wire')) {
|
|
@@ -703,7 +698,7 @@ export class ${endpointNaming.ClassName} {
|
|
|
703
698
|
const wireNaming = new UnknownFormatNaming(wireNameBase);
|
|
704
699
|
wiringFolder.createFile(`${wireNaming.fileName}.ts`, `
|
|
705
700
|
import { wireClass } from '@domain-first/wire'
|
|
706
|
-
import { ${endpointNaming.ClassName} } from '../../../../presentation/rest/${controller}/${
|
|
701
|
+
import { ${endpointNaming.ClassName} } from '../../../../presentation/rest/${controller}/${path.length ? `${path.join('/')}/` : ''}${method.toUpperCase()}'
|
|
707
702
|
|
|
708
703
|
export const wire${endpointNaming.ClassName} = wireClass(
|
|
709
704
|
${endpointNaming.ClassName},
|
|
@@ -726,9 +721,14 @@ const scaffoldNewQuery = async (boundedContextFolder)=>{
|
|
|
726
721
|
message: 'Name: '
|
|
727
722
|
});
|
|
728
723
|
const naming = new UnknownFormatNaming(queryName);
|
|
729
|
-
const
|
|
730
|
-
|
|
724
|
+
const queryType = await (0, prompts_namespaceObject.select)({
|
|
725
|
+
choices: [
|
|
726
|
+
'Execution (with infrastructure implementation)',
|
|
727
|
+
'Orchestrator (no infrastructure implementation)'
|
|
728
|
+
],
|
|
729
|
+
message: 'Query type'
|
|
731
730
|
});
|
|
731
|
+
const isOrchestrator = 'Orchestrator (no infrastructure implementation)' === queryType;
|
|
732
732
|
if (!isOrchestrator) {
|
|
733
733
|
const implementationType = await (0, prompts_namespaceObject.input)({
|
|
734
734
|
message: 'Query infrastructure implementation type:',
|
|
@@ -752,80 +752,73 @@ const scaffoldNewQuery = async (boundedContextFolder)=>{
|
|
|
752
752
|
infrastructureFolder.subitem([
|
|
753
753
|
formatNaming.fileName
|
|
754
754
|
]).createFile(`${formatNaming.fileName}-${naming.fileName}-query.ts`, ConfigFile.Instance.data.domainFirstPackages.includes('@domain-first/handlers') ? `
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
export class ${formatNaming.ClassName}${naming.ClassName}Query implements ${naming.ClassName}Query {
|
|
759
|
-
constructor() {}
|
|
755
|
+
import { defineHandler } from '@domain-first/handlers'
|
|
756
|
+
import { ${naming.ClassName}Query } from '../../../application/queries/execution/${naming.fileName}-query'
|
|
760
757
|
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
handler: async (input) => {
|
|
765
|
-
return {}
|
|
766
|
-
}
|
|
767
|
-
})
|
|
758
|
+
export class ${formatNaming.ClassName}${naming.ClassName}Query extends ${naming.ClassName}Query {
|
|
759
|
+
constructor() {
|
|
760
|
+
super()
|
|
768
761
|
}
|
|
769
|
-
`.trim() : `
|
|
770
|
-
import { ${naming.ClassName}Query } from '../../../domain/queries/${naming.fileName}-query'
|
|
771
762
|
|
|
772
|
-
|
|
763
|
+
handle = defineHandler({
|
|
764
|
+
inputSchema: ${naming.ClassName}Query.inputSchema,
|
|
765
|
+
outputSchema: ${naming.ClassName}Query.outputSchema,
|
|
766
|
+
handler: async (input) => {
|
|
767
|
+
return {}
|
|
768
|
+
}
|
|
769
|
+
})
|
|
770
|
+
}
|
|
771
|
+
`.trim() : `
|
|
772
|
+
import { ${naming.ClassName}Query } from '../../../domain/queries/${naming.fileName}-query'
|
|
773
773
|
|
|
774
|
+
export class ${formatNaming.ClassName}${naming.ClassName}Query extends ${naming.ClassName}Query {
|
|
775
|
+
constructor() {
|
|
776
|
+
super()
|
|
774
777
|
}
|
|
778
|
+
}
|
|
775
779
|
`.trim());
|
|
776
|
-
if (ConfigFile.Instance.data.domainFirstPackages.includes('@domain-first/wire')) {
|
|
777
|
-
const wiringFolder = boundedContextFolder.subitem([
|
|
778
|
-
'wiring',
|
|
779
|
-
'infrastructure',
|
|
780
|
-
'queries',
|
|
781
|
-
formatNaming.fileName
|
|
782
|
-
]);
|
|
783
|
-
wiringFolder.createFile(`wire-${formatNaming.fileName}-${naming.fileName}-query.ts`, `
|
|
784
|
-
import { wireClass } from '@domain-first/wire'
|
|
785
|
-
import { ${formatNaming.ClassName}${naming.ClassName}Query } from '../../../../infrastructure/queries/${formatNaming.fileName}/${formatNaming.fileName}-${naming.fileName}-query'
|
|
786
|
-
|
|
787
|
-
export const wire${formatNaming.ClassName}${naming.ClassName}Query = wireClass(
|
|
788
|
-
${formatNaming.ClassName}${naming.ClassName}Query,
|
|
789
|
-
[]
|
|
790
|
-
)
|
|
791
|
-
`.trim());
|
|
792
|
-
}
|
|
793
780
|
}
|
|
794
|
-
if (ConfigFile.Instance.data.domainFirstPackages.includes('@domain-first/handlers')) queriesFolder.
|
|
795
|
-
|
|
781
|
+
if (ConfigFile.Instance.data.domainFirstPackages.includes('@domain-first/handlers')) queriesFolder.subitem([
|
|
782
|
+
'execution'
|
|
783
|
+
]).createFile(`${naming.fileName}-query.ts`, `
|
|
784
|
+
import type { Handler } from '@domain-first/handlers'
|
|
796
785
|
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
786
|
+
export abstract class ${naming.ClassName}Query {
|
|
787
|
+
static inputSchema = {}
|
|
788
|
+
static outputSchema = {}
|
|
800
789
|
|
|
801
|
-
|
|
802
|
-
|
|
790
|
+
abstract handle: Handler<typeof ${naming.ClassName}Query.inputSchema, typeof ${naming.ClassName}Query.outputSchema>
|
|
791
|
+
}
|
|
803
792
|
`.trim());
|
|
804
793
|
else queriesFolder.createFile(`${naming.fileName}-query.ts`, `
|
|
805
|
-
|
|
794
|
+
export abstract class ${naming.ClassName}Query {
|
|
806
795
|
|
|
807
|
-
|
|
796
|
+
}`.trim());
|
|
808
797
|
if (ConfigFile.Instance.data.domainFirstPackages.includes('@domain-first/wire')) {
|
|
809
798
|
const implementationNaming = new UnknownFormatNaming(implementationType);
|
|
810
799
|
const testImplementationNaming = new UnknownFormatNaming(testImplementationType);
|
|
811
800
|
boundedContextFolder.subitem([
|
|
812
801
|
'wiring',
|
|
813
|
-
'application',
|
|
814
802
|
'queries'
|
|
815
803
|
]).createFile(`wire-${naming.fileName}-query.ts`, `
|
|
816
|
-
|
|
817
|
-
|
|
804
|
+
import { wireClass } from '@domain-first/wire'
|
|
805
|
+
import { envBranchedWire } from '../../../../shared/wiring/env-branched-wire'
|
|
806
|
+
${implementationTypes.map((x)=>new UnknownFormatNaming(x)).map(({ ClassName, fileName })=>`import { ${ClassName}${naming.ClassName}Query } from '../../infrastructure/queries/${fileName}/${fileName}-${naming.fileName}-query'`).join('\n')}
|
|
818
807
|
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
}
|
|
808
|
+
${implementationTypes.map((x)=>new UnknownFormatNaming(x)).map(({ ClassName })=>`const wire${ClassName}Implementation = wireClass(${ClassName}${naming.ClassName}Query, [])`).join('\n\n')}
|
|
809
|
+
|
|
810
|
+
export const wire${naming.ClassName}Query = envBranchedWire({
|
|
811
|
+
test: wire${addTestImplementation ? testImplementationNaming.ClassName : implementationNaming.ClassName}Implementation,
|
|
812
|
+
development: wire${implementationNaming.ClassName}Implementation,
|
|
813
|
+
production: wire${implementationNaming.ClassName}Implementation
|
|
814
|
+
})
|
|
824
815
|
`.trim());
|
|
825
816
|
}
|
|
826
817
|
return;
|
|
827
818
|
}
|
|
828
|
-
if (ConfigFile.Instance.data.domainFirstPackages.includes('@domain-first/handlers')) queriesFolder.
|
|
819
|
+
if (ConfigFile.Instance.data.domainFirstPackages.includes('@domain-first/handlers')) queriesFolder.subitem([
|
|
820
|
+
'orchestration'
|
|
821
|
+
]).createFile(`${naming.fileName}-query.ts`, `
|
|
829
822
|
import { defineHandler } from '@domain-first/handlers'
|
|
830
823
|
|
|
831
824
|
export class ${naming.ClassName}Query {
|
|
@@ -841,7 +834,9 @@ export class ${naming.ClassName}Query {
|
|
|
841
834
|
})
|
|
842
835
|
}
|
|
843
836
|
`.trim());
|
|
844
|
-
else queriesFolder.
|
|
837
|
+
else queriesFolder.subitem([
|
|
838
|
+
'orchestration'
|
|
839
|
+
]).createFile(`${naming.fileName}-query.ts`, `
|
|
845
840
|
export class ${naming.ClassName}Query {
|
|
846
841
|
|
|
847
842
|
}`.trim());
|
|
@@ -851,7 +846,7 @@ export class ${naming.ClassName}Query {
|
|
|
851
846
|
'queries'
|
|
852
847
|
]).createFile(`wire-${naming.fileName}-query.ts`, `
|
|
853
848
|
import { wireClass } from '@domain-first/wire'
|
|
854
|
-
import { ${naming.ClassName}Query } from '../../../application/queries/${naming.fileName}-query'
|
|
849
|
+
import { ${naming.ClassName}Query } from '../../../application/queries/orchestration/${naming.fileName}-query'
|
|
855
850
|
|
|
856
851
|
export const wire${naming.ClassName}Query = wireClass(${naming.ClassName}Query, [])
|
|
857
852
|
`.trim());
|
|
@@ -889,11 +884,10 @@ export class ${naming.ClassName}UseCase {
|
|
|
889
884
|
`.trim());
|
|
890
885
|
if (ConfigFile.Instance.data.domainFirstPackages.includes('@domain-first/wire')) boundedContextFolder.subitem([
|
|
891
886
|
'wiring',
|
|
892
|
-
'application',
|
|
893
887
|
'use-cases'
|
|
894
888
|
]).createFile(`wire-${naming.fileName}-use-case.ts`, `
|
|
895
889
|
import { wireClass } from '@domain-first/wire'
|
|
896
|
-
import { ${naming.ClassName}UseCase } from '
|
|
890
|
+
import { ${naming.ClassName}UseCase } from '../../application/use-cases/${naming.fileName}-use-case'
|
|
897
891
|
|
|
898
892
|
export const wire${naming.ClassName}UseCase = wireClass(
|
|
899
893
|
${naming.ClassName}UseCase,
|
|
@@ -902,6 +896,109 @@ export const wire${naming.ClassName}UseCase = wireClass(
|
|
|
902
896
|
|
|
903
897
|
`.trim());
|
|
904
898
|
};
|
|
899
|
+
const scaffoldReactWidget = async (presentationReactFolder)=>{
|
|
900
|
+
const widgetName = await (0, prompts_namespaceObject.input)({
|
|
901
|
+
message: 'Name: '
|
|
902
|
+
});
|
|
903
|
+
const widgetType = await (0, prompts_namespaceObject.select)({
|
|
904
|
+
choices: [
|
|
905
|
+
'monolithic',
|
|
906
|
+
'with separated ui',
|
|
907
|
+
'headless'
|
|
908
|
+
],
|
|
909
|
+
message: 'Type: '
|
|
910
|
+
});
|
|
911
|
+
const { ClassName, fileName } = new UnknownFormatNaming(widgetName);
|
|
912
|
+
const folder = presentationReactFolder.subitem([
|
|
913
|
+
'widgets',
|
|
914
|
+
fileName
|
|
915
|
+
]);
|
|
916
|
+
switch(widgetType){
|
|
917
|
+
case 'monolithic':
|
|
918
|
+
folder.createFile('index.tsx', `
|
|
919
|
+
import { type FC } from 'react'
|
|
920
|
+
|
|
921
|
+
export type ${ClassName}WidgetProps = {}
|
|
922
|
+
|
|
923
|
+
export const ${ClassName}Widget: FC<${ClassName}WidgetProps> = (props) => {
|
|
924
|
+
return <></>
|
|
925
|
+
}
|
|
926
|
+
`.trim());
|
|
927
|
+
break;
|
|
928
|
+
case 'with separated ui':
|
|
929
|
+
folder.createFile('types.ts', `
|
|
930
|
+
export type ${ClassName}WidgetProps = { }
|
|
931
|
+
|
|
932
|
+
export type ${ClassName}WidgetUIProps = { }
|
|
933
|
+
`.trim());
|
|
934
|
+
folder.createFile('index.tsx', `
|
|
935
|
+
import { type FC } from 'react'
|
|
936
|
+
import type { ${ClassName}WidgetProps } from './types'
|
|
937
|
+
import { ${ClassName}WidgetUI } from './ui'
|
|
938
|
+
import { useUIModel } from './hooks/use-ui-model'
|
|
939
|
+
|
|
940
|
+
export const ${ClassName}Widget: FC<${ClassName}WidgetProps> = (props) => {
|
|
941
|
+
const uiModel = useUIModel(props)
|
|
942
|
+
return <${ClassName}WidgetUI {...uiModel} />
|
|
943
|
+
}
|
|
944
|
+
|
|
945
|
+
export type { ${ClassName}WidgetProps }
|
|
946
|
+
`.trim());
|
|
947
|
+
folder.subitem([
|
|
948
|
+
'ui'
|
|
949
|
+
]).createFile('index.tsx', `
|
|
950
|
+
import { FC } from 'react'
|
|
951
|
+
import type { ${ClassName}WidgetUIProps } from '../types'
|
|
952
|
+
|
|
953
|
+
export const ${ClassName}WidgetUI: FC<${ClassName}WidgetUIProps> = (props) => {
|
|
954
|
+
return <></>
|
|
955
|
+
}
|
|
956
|
+
`.trim());
|
|
957
|
+
folder.subitem([
|
|
958
|
+
'hooks'
|
|
959
|
+
]).createFile('use-ui-model.ts', `
|
|
960
|
+
import type { ${ClassName}WidgetProps, ${ClassName}WidgetUIProps } from '../types'
|
|
961
|
+
|
|
962
|
+
export const useUIModel = (widgetProps: ${ClassName}WidgetProps): ${ClassName}WidgetUIProps => {
|
|
963
|
+
return {}
|
|
964
|
+
}
|
|
965
|
+
`.trim());
|
|
966
|
+
break;
|
|
967
|
+
case 'headless':
|
|
968
|
+
folder.createFile('types.ts', `
|
|
969
|
+
import { type FC } from 'react'
|
|
970
|
+
|
|
971
|
+
export type ${ClassName}WidgetUIProps = { }
|
|
972
|
+
|
|
973
|
+
export type ${ClassName}WidgetProps = {
|
|
974
|
+
UI: FC<${ClassName}WidgetUIProps>
|
|
975
|
+
}
|
|
976
|
+
|
|
977
|
+
`.trim());
|
|
978
|
+
folder.createFile('index.tsx', `
|
|
979
|
+
import { type FC } from 'react'
|
|
980
|
+
import type { ${ClassName}WidgetProps } from './types'
|
|
981
|
+
import { useUIModel } from './hooks/use-ui-model'
|
|
982
|
+
|
|
983
|
+
export const ${ClassName}Widget: FC<${ClassName}WidgetProps> = (props) => {
|
|
984
|
+
const uiModel = useUIModel(props)
|
|
985
|
+
return <props.UI {...uiModel} />
|
|
986
|
+
}
|
|
987
|
+
|
|
988
|
+
export type { ${ClassName}WidgetProps }
|
|
989
|
+
`.trim());
|
|
990
|
+
folder.subitem([
|
|
991
|
+
'hooks'
|
|
992
|
+
]).createFile('use-ui-model.ts', `
|
|
993
|
+
import type { ${ClassName}WidgetProps, ${ClassName}WidgetUIProps } from '../types'
|
|
994
|
+
|
|
995
|
+
export const useUIModel = (widgetProps: Omit<${ClassName}WidgetProps, 'UI'>): ${ClassName}WidgetUIProps => {
|
|
996
|
+
return {}
|
|
997
|
+
}
|
|
998
|
+
`.trim());
|
|
999
|
+
break;
|
|
1000
|
+
}
|
|
1001
|
+
};
|
|
905
1002
|
const main = async ()=>{
|
|
906
1003
|
if (!ConfigFile.exists) return void await initializeUseCase();
|
|
907
1004
|
const rootPath = new ProjectRoot().path;
|
|
@@ -918,18 +1015,41 @@ const main = async ()=>{
|
|
|
918
1015
|
};
|
|
919
1016
|
const options = [
|
|
920
1017
|
...currentBoundedContextOptions,
|
|
1018
|
+
ConfigFile.Instance.data.useReact ? {
|
|
1019
|
+
name: 'Scaffold React module',
|
|
1020
|
+
action: 'Scaffold React module'
|
|
1021
|
+
} : void 0,
|
|
921
1022
|
{
|
|
922
1023
|
name: 'Shared Layer',
|
|
923
1024
|
action: 'Scaffold in bounded context'
|
|
924
1025
|
},
|
|
925
1026
|
scaffoldNewBoundedContext
|
|
926
|
-
];
|
|
1027
|
+
].filter((x)=>!!x);
|
|
927
1028
|
const result = await (0, prompts_namespaceObject.select)({
|
|
928
1029
|
message: '@domain-first/project-structure',
|
|
929
1030
|
choices: options.map((x)=>x.name)
|
|
930
1031
|
});
|
|
931
1032
|
const { action, name } = options.find((x)=>x.name === result);
|
|
932
1033
|
switch(action){
|
|
1034
|
+
case 'Scaffold React module':
|
|
1035
|
+
{
|
|
1036
|
+
const action = await (0, prompts_namespaceObject.select)({
|
|
1037
|
+
message: 'Module: ',
|
|
1038
|
+
choices: [
|
|
1039
|
+
'New widget'
|
|
1040
|
+
]
|
|
1041
|
+
});
|
|
1042
|
+
switch(action){
|
|
1043
|
+
case 'New widget':
|
|
1044
|
+
return void await scaffoldReactWidget(new Folder(rootPath).subitem([
|
|
1045
|
+
ConfigFile.Instance.data.rootFolder,
|
|
1046
|
+
'presentation',
|
|
1047
|
+
'react'
|
|
1048
|
+
]));
|
|
1049
|
+
default:
|
|
1050
|
+
return;
|
|
1051
|
+
}
|
|
1052
|
+
}
|
|
933
1053
|
case 'Scaffold new bounded context':
|
|
934
1054
|
return void await scaffoldNewBoundedContextUseCase();
|
|
935
1055
|
case 'Scaffold in bounded context':
|