@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.js
CHANGED
|
@@ -94,7 +94,8 @@ const configSchema = zod.object({
|
|
|
94
94
|
'@domain-first/wire',
|
|
95
95
|
'@domain-first/handlers-rest'
|
|
96
96
|
])),
|
|
97
|
-
defaultPersistenceLayerImplementation: zod.string()
|
|
97
|
+
defaultPersistenceLayerImplementation: zod.string(),
|
|
98
|
+
useReact: zod.boolean()
|
|
98
99
|
});
|
|
99
100
|
class ConfigFile {
|
|
100
101
|
data;
|
|
@@ -136,10 +137,14 @@ const initializeUseCase = async ()=>{
|
|
|
136
137
|
const defaultPersistenceLayerImplementation = await input({
|
|
137
138
|
message: 'Default persistence layer implementation:'
|
|
138
139
|
});
|
|
140
|
+
const useReact = await prompts_confirm({
|
|
141
|
+
message: 'Use React'
|
|
142
|
+
});
|
|
139
143
|
ConfigFile.write({
|
|
140
144
|
rootFolder: rootFolderName,
|
|
141
145
|
domainFirstPackages,
|
|
142
|
-
defaultPersistenceLayerImplementation
|
|
146
|
+
defaultPersistenceLayerImplementation,
|
|
147
|
+
useReact
|
|
143
148
|
});
|
|
144
149
|
const { path } = new ProjectRoot();
|
|
145
150
|
const rootFolder = new Folder(path);
|
|
@@ -247,41 +252,26 @@ export class ${naming.ClassName}${aggregateNaming.ClassName}Repository implement
|
|
|
247
252
|
}
|
|
248
253
|
|
|
249
254
|
`.trim());
|
|
250
|
-
if (ConfigFile.Instance.data.domainFirstPackages.includes('@domain-first/wire')) {
|
|
251
|
-
const wiringFolder = boundedContextFolder.subitem([
|
|
252
|
-
'wiring',
|
|
253
|
-
'infrastructure',
|
|
254
|
-
'repositories',
|
|
255
|
-
naming.fileName
|
|
256
|
-
]);
|
|
257
|
-
wiringFolder.createFile(`wire-${naming.fileName}-${aggregateNaming.fileName}-repository.ts`, `
|
|
258
|
-
import { wireClass } from '@domain-first/wire'
|
|
259
|
-
import { ${naming.ClassName}${aggregateNaming.ClassName}Repository } from '../../../../infrastructure/repositories/${naming.fileName}/${naming.fileName}-${aggregateNaming.fileName}-repository'
|
|
260
|
-
|
|
261
|
-
export const wire${naming.ClassName}${aggregateNaming.ClassName}Repository = wireClass(
|
|
262
|
-
${naming.ClassName}${aggregateNaming.ClassName}Repository,
|
|
263
|
-
[]
|
|
264
|
-
)
|
|
265
|
-
`.trim());
|
|
266
|
-
}
|
|
267
255
|
}
|
|
268
256
|
if (ConfigFile.Instance.data.domainFirstPackages.includes('@domain-first/wire')) {
|
|
269
257
|
const implementationNaming = new UnknownFormatNaming(infrastructureImplementationType);
|
|
270
258
|
const testImplementationNaming = new UnknownFormatNaming(testImplementationType);
|
|
271
259
|
boundedContextFolder.subitem([
|
|
272
260
|
'wiring',
|
|
273
|
-
'domain',
|
|
274
261
|
'repositories'
|
|
275
262
|
]).createFile(`wire-${aggregateNaming.fileName}-repository.ts`, `
|
|
276
|
-
import {
|
|
277
|
-
|
|
263
|
+
import { wireClass } from '@domain-first/wire'
|
|
264
|
+
import { envBranchedWire } from '../../../../shared/wiring/env-branched-wire'
|
|
265
|
+
${implementationTypes.map((x)=>new UnknownFormatNaming(x)).map(({ ClassName, fileName })=>`import { ${ClassName}${aggregateNaming.ClassName}Repository } from '../../infrastructure/repositories/${fileName}/${fileName}-${aggregateNaming.fileName}-repository'`).join('\n')}
|
|
266
|
+
|
|
267
|
+
${implementationTypes.map((x)=>new UnknownFormatNaming(x)).map(({ ClassName })=>`const wire${ClassName}Implementation = wireClass(${ClassName}${aggregateNaming.ClassName}Repository, [])`).join('\n\n')}
|
|
278
268
|
|
|
279
269
|
export const wire${aggregateNaming.ClassName}Repository = envBranchedWire({
|
|
280
|
-
test: wire${addTestImplementation ? testImplementationNaming.ClassName : implementationNaming.ClassName}
|
|
281
|
-
development: wire${implementationNaming.ClassName}
|
|
282
|
-
production: wire${implementationNaming.ClassName}
|
|
270
|
+
test: wire${addTestImplementation ? testImplementationNaming.ClassName : implementationNaming.ClassName}Implementation,
|
|
271
|
+
development: wire${implementationNaming.ClassName}Implementation,
|
|
272
|
+
production: wire${implementationNaming.ClassName}Implementation
|
|
283
273
|
})
|
|
284
|
-
`.trim());
|
|
274
|
+
`.trim());
|
|
285
275
|
}
|
|
286
276
|
}
|
|
287
277
|
};
|
|
@@ -292,14 +282,8 @@ const scaffoldNewApplicationPort = async (boundedContextFolder)=>{
|
|
|
292
282
|
const naming = new UnknownFormatNaming(name);
|
|
293
283
|
const wiringFolder = boundedContextFolder.subitem([
|
|
294
284
|
'wiring',
|
|
295
|
-
'application',
|
|
296
285
|
'ports'
|
|
297
286
|
]);
|
|
298
|
-
const infraFolder = boundedContextFolder.subitem([
|
|
299
|
-
'wiring',
|
|
300
|
-
'infrastructure',
|
|
301
|
-
'application-ports'
|
|
302
|
-
]);
|
|
303
287
|
const applicationPortsFolder = boundedContextFolder.subitem([
|
|
304
288
|
'application',
|
|
305
289
|
'ports'
|
|
@@ -339,29 +323,24 @@ export class ${currentNaming.ClassName} extends ${naming.ClassName} {
|
|
|
339
323
|
|
|
340
324
|
}
|
|
341
325
|
`);
|
|
342
|
-
if (ConfigFile.Instance.data.domainFirstPackages.includes('@domain-first/wire')) infraFolder.subitem([
|
|
343
|
-
implementation
|
|
344
|
-
]).createFile(`wire-${currentNaming.fileName}.ts`, `
|
|
345
|
-
import { wireClass } from '@domain-first/wire'
|
|
346
|
-
import { ${currentNaming.ClassName} } from '../../../../infrastructure/application-adapters/${implementation}/${currentNaming.fileName}'
|
|
347
|
-
|
|
348
|
-
export const wire${currentNaming.ClassName} = wireClass(
|
|
349
|
-
${currentNaming.ClassName},
|
|
350
|
-
[]
|
|
351
|
-
)
|
|
352
|
-
`.trim());
|
|
353
326
|
}
|
|
354
327
|
if (ConfigFile.Instance.data.domainFirstPackages.includes('@domain-first/wire')) wiringFolder.createFile(`wire-${naming.fileName}.ts`, `
|
|
355
|
-
import {
|
|
328
|
+
import { wireClass } from '@domain-first/wire'
|
|
329
|
+
import { envBranchedWire } from '../../../${'shared' === boundedContextFolder.name ? '' : '../'}shared/wiring/env-branched-wire'
|
|
330
|
+
${implementationTypes.map((x)=>({
|
|
331
|
+
naming: new UnknownFormatNaming(`${x}-${naming.fileName}`),
|
|
332
|
+
implementation: x
|
|
333
|
+
})).map(({ naming: { ClassName, fileName }, implementation })=>`import { ${ClassName} } from '../../infrastructure/application-adapters/${implementation}/${fileName}'`).join('\n')}
|
|
334
|
+
|
|
356
335
|
${implementationTypes.map((x)=>({
|
|
357
336
|
naming: new UnknownFormatNaming(`${x}-${naming.fileName}`),
|
|
358
337
|
implementation: x
|
|
359
|
-
})).map(({ naming: { ClassName
|
|
338
|
+
})).map(({ naming: { ClassName }, implementation })=>`const wire${new UnknownFormatNaming(implementation).ClassName}Implementation = wireClass(${ClassName}, [])`).join('\n\n')}
|
|
360
339
|
|
|
361
340
|
export const wire${naming.ClassName} = envBranchedWire({
|
|
362
|
-
test: wire${new UnknownFormatNaming(`${implementationTypes.at(-1)}
|
|
363
|
-
development: wire${new UnknownFormatNaming(`${implementationTypes.at(0)}
|
|
364
|
-
production: wire${new UnknownFormatNaming(`${implementationTypes.at(0)}
|
|
341
|
+
test: wire${new UnknownFormatNaming(`${implementationTypes.at(-1)}-implementation`).ClassName},
|
|
342
|
+
development: wire${new UnknownFormatNaming(`${implementationTypes.at(0)}-implementation`).ClassName},
|
|
343
|
+
production: wire${new UnknownFormatNaming(`${implementationTypes.at(0)}-implementation`).ClassName}
|
|
365
344
|
})
|
|
366
345
|
|
|
367
346
|
`.trim());
|
|
@@ -401,9 +380,14 @@ const scaffoldNewCommand = async (boundedContextFolder)=>{
|
|
|
401
380
|
message: 'Name: '
|
|
402
381
|
});
|
|
403
382
|
const naming = new UnknownFormatNaming(commandName);
|
|
404
|
-
const
|
|
405
|
-
|
|
383
|
+
const commandType = await prompts_select({
|
|
384
|
+
choices: [
|
|
385
|
+
'Execution (with infrastructure implementation)',
|
|
386
|
+
'Orchestrator (no infrastructure implementation)'
|
|
387
|
+
],
|
|
388
|
+
message: 'Command type'
|
|
406
389
|
});
|
|
390
|
+
const isOrchestrator = 'Orchestrator (no infrastructure implementation)' === commandType;
|
|
407
391
|
if (!isOrchestrator) {
|
|
408
392
|
const implementationType = await input({
|
|
409
393
|
message: 'Command infrastructure implementation type:',
|
|
@@ -427,81 +411,73 @@ const scaffoldNewCommand = async (boundedContextFolder)=>{
|
|
|
427
411
|
infrastructureFolder.subitem([
|
|
428
412
|
formatNaming.fileName
|
|
429
413
|
]).createFile(`${formatNaming.fileName}-${naming.fileName}-command.ts`, ConfigFile.Instance.data.domainFirstPackages.includes('@domain-first/handlers') ? `
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
export class ${formatNaming.ClassName}${naming.ClassName}Command implements ${naming.ClassName}Command {
|
|
434
|
-
constructor() {}
|
|
414
|
+
import { defineHandler } from '@domain-first/handlers'
|
|
415
|
+
import { ${naming.ClassName}Command } from '../../../application/commands/execution/${naming.fileName}-command'
|
|
435
416
|
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
handler: async (input) => {
|
|
440
|
-
return {}
|
|
441
|
-
}
|
|
442
|
-
})
|
|
417
|
+
export class ${formatNaming.ClassName}${naming.ClassName}Command extends ${naming.ClassName}Command {
|
|
418
|
+
constructor() {
|
|
419
|
+
super()
|
|
443
420
|
}
|
|
444
|
-
`.trim() : `
|
|
445
|
-
import { ${naming.ClassName}Command } from '../../../domain/commands/${naming.fileName}-command'
|
|
446
421
|
|
|
447
|
-
|
|
422
|
+
handle = defineHandler({
|
|
423
|
+
inputSchema: ${naming.ClassName}Command.inputSchema,
|
|
424
|
+
outputSchema: ${naming.ClassName}Command.outputSchema,
|
|
425
|
+
handler: async (input) => {
|
|
426
|
+
return {}
|
|
427
|
+
}
|
|
428
|
+
})
|
|
429
|
+
}
|
|
430
|
+
`.trim() : `
|
|
431
|
+
import { ${naming.ClassName}Command } from '../../../domain/commands/${naming.fileName}-command'
|
|
448
432
|
|
|
433
|
+
export class ${formatNaming.ClassName}${naming.ClassName}Command extends ${naming.ClassName}Command {
|
|
434
|
+
constructor() {
|
|
435
|
+
super()
|
|
449
436
|
}
|
|
437
|
+
}
|
|
450
438
|
`.trim());
|
|
451
|
-
if (ConfigFile.Instance.data.domainFirstPackages.includes('@domain-first/wire')) {
|
|
452
|
-
const wiringFolder = boundedContextFolder.subitem([
|
|
453
|
-
'wiring',
|
|
454
|
-
'infrastructure',
|
|
455
|
-
'commands',
|
|
456
|
-
formatNaming.fileName
|
|
457
|
-
]);
|
|
458
|
-
wiringFolder.createFile(`wire-${formatNaming.fileName}-${naming.fileName}-command.ts`, `
|
|
459
|
-
import { wireClass } from '@domain-first/wire'
|
|
460
|
-
import { ${formatNaming.ClassName}${naming.ClassName}Command } from '../../../../infrastructure/commands/${formatNaming.fileName}/${formatNaming.fileName}-${naming.fileName}-command'
|
|
461
|
-
|
|
462
|
-
export const wire${formatNaming.ClassName}${naming.ClassName}Command = wireClass(
|
|
463
|
-
${formatNaming.ClassName}${naming.ClassName}Command,
|
|
464
|
-
[]
|
|
465
|
-
)
|
|
466
|
-
|
|
467
|
-
`.trim());
|
|
468
|
-
}
|
|
469
439
|
}
|
|
470
|
-
if (ConfigFile.Instance.data.domainFirstPackages.includes('@domain-first/handlers')) commandsFolder.
|
|
471
|
-
|
|
440
|
+
if (ConfigFile.Instance.data.domainFirstPackages.includes('@domain-first/handlers')) commandsFolder.subitem([
|
|
441
|
+
'execution'
|
|
442
|
+
]).createFile(`${naming.fileName}-command.ts`, `
|
|
443
|
+
import type { Handler } from '@domain-first/handlers'
|
|
472
444
|
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
445
|
+
export abstract class ${naming.ClassName}Command {
|
|
446
|
+
static inputSchema = {}
|
|
447
|
+
static outputSchema = {}
|
|
476
448
|
|
|
477
|
-
|
|
478
|
-
|
|
449
|
+
abstract handle: Handler<typeof ${naming.ClassName}Command.inputSchema, typeof ${naming.ClassName}Command.outputSchema>
|
|
450
|
+
}
|
|
479
451
|
`.trim());
|
|
480
452
|
else commandsFolder.createFile(`${naming.fileName}-command.ts`, `
|
|
481
|
-
|
|
453
|
+
export abstract class ${naming.ClassName}Command {
|
|
482
454
|
|
|
483
|
-
|
|
455
|
+
}`.trim());
|
|
484
456
|
if (ConfigFile.Instance.data.domainFirstPackages.includes('@domain-first/wire')) {
|
|
485
457
|
const implementationNaming = new UnknownFormatNaming(implementationType);
|
|
486
458
|
const testImplementationNaming = new UnknownFormatNaming(testImplementationType);
|
|
487
459
|
boundedContextFolder.subitem([
|
|
488
460
|
'wiring',
|
|
489
|
-
'application',
|
|
490
461
|
'commands'
|
|
491
462
|
]).createFile(`wire-${naming.fileName}-command.ts`, `
|
|
492
|
-
|
|
493
|
-
|
|
463
|
+
import { wireClass } from '@domain-first/wire'
|
|
464
|
+
import { envBranchedWire } from '../../../../shared/wiring/env-branched-wire'
|
|
465
|
+
${implementationTypes.map((x)=>new UnknownFormatNaming(x)).map(({ ClassName, fileName })=>`import { ${ClassName}${naming.ClassName}Command } from '../../infrastructure/commands/${fileName}/${fileName}-${naming.fileName}-command'`).join('\n')}
|
|
494
466
|
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
}
|
|
467
|
+
${implementationTypes.map((x)=>new UnknownFormatNaming(x)).map(({ ClassName })=>`const wire${ClassName}Implementation = wireClass(${ClassName}${naming.ClassName}Command, [])`).join('\n\n')}
|
|
468
|
+
|
|
469
|
+
export const wire${naming.ClassName}Command = envBranchedWire({
|
|
470
|
+
test: wire${addTestImplementation ? testImplementationNaming.ClassName : implementationNaming.ClassName}Implementation,
|
|
471
|
+
development: wire${implementationNaming.ClassName}Implementation,
|
|
472
|
+
production: wire${implementationNaming.ClassName}Implementation
|
|
473
|
+
})
|
|
500
474
|
`.trim());
|
|
501
475
|
}
|
|
502
476
|
return;
|
|
503
477
|
}
|
|
504
|
-
if (ConfigFile.Instance.data.domainFirstPackages.includes('@domain-first/handlers')) commandsFolder.
|
|
478
|
+
if (ConfigFile.Instance.data.domainFirstPackages.includes('@domain-first/handlers')) commandsFolder.subitem([
|
|
479
|
+
'orchestration'
|
|
480
|
+
]).createFile(`${naming.fileName}-command.ts`, `
|
|
505
481
|
import { defineHandler } from '@domain-first/handlers'
|
|
506
482
|
|
|
507
483
|
export class ${naming.ClassName}Command {
|
|
@@ -517,7 +493,9 @@ export class ${naming.ClassName}Command {
|
|
|
517
493
|
})
|
|
518
494
|
}
|
|
519
495
|
`.trim());
|
|
520
|
-
else commandsFolder.
|
|
496
|
+
else commandsFolder.subitem([
|
|
497
|
+
'orchestration'
|
|
498
|
+
]).createFile(`${naming.fileName}-command.ts`, `
|
|
521
499
|
export class ${naming.ClassName}Command {
|
|
522
500
|
|
|
523
501
|
}`.trim());
|
|
@@ -527,7 +505,7 @@ export class ${naming.ClassName}Command {
|
|
|
527
505
|
'commands'
|
|
528
506
|
]).createFile(`wire-${naming.fileName}-command.ts`, `
|
|
529
507
|
import { wireClass } from '@domain-first/wire'
|
|
530
|
-
import { ${naming.ClassName}Command } from '../../../application/commands/${naming.fileName}-command'
|
|
508
|
+
import { ${naming.ClassName}Command } from '../../../application/commands/orchestration/${naming.fileName}-command'
|
|
531
509
|
|
|
532
510
|
export const wire${naming.ClassName}Command = wireClass(${naming.ClassName}Command, [])
|
|
533
511
|
`.trim());
|
|
@@ -579,7 +557,7 @@ const scaffoldNewErrorUseCase = async (boundedContextFolder)=>{
|
|
|
579
557
|
message: 'Error name:'
|
|
580
558
|
});
|
|
581
559
|
const naming = new UnknownFormatNaming(errorName);
|
|
582
|
-
currentErrorFolder.file('index.ts').addLine(`export const ${naming.ClassName}Error = ${new UnknownFormatNaming(boundedContextFolder.name).ClassName}Errors.define('${naming.fileName}')`, '\n\n');
|
|
560
|
+
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');
|
|
583
561
|
return;
|
|
584
562
|
}
|
|
585
563
|
if ('New namespace' === selectedVariant) {
|
|
@@ -590,17 +568,18 @@ const scaffoldNewErrorUseCase = async (boundedContextFolder)=>{
|
|
|
590
568
|
currentErrorFolder.createFile(`${fileName}.ts`, `
|
|
591
569
|
import { errorNamespace } from '@domain-first/errors'
|
|
592
570
|
|
|
593
|
-
const ${ClassName}Errors = errorNamespace('${boundedContextFolder.name}').subnamespace('${fileName}')
|
|
571
|
+
export const ${ClassName}${new UnknownFormatNaming(boundedContextFolder.name).ClassName}Errors = errorNamespace('${boundedContextFolder.name}').subnamespace('${fileName}')
|
|
594
572
|
`);
|
|
595
|
-
currentErrorFolder.file('index.ts').addLine(`export * from './${fileName}'
|
|
573
|
+
currentErrorFolder.file('index.ts').addLine(`export * from './${fileName}'`, '\n\n');
|
|
596
574
|
return;
|
|
597
575
|
}
|
|
598
576
|
const namespace = selectedVariant.substring(23);
|
|
577
|
+
const namespaceNaming = new UnknownFormatNaming(namespace);
|
|
599
578
|
const errorName = await input({
|
|
600
579
|
message: 'Error name:'
|
|
601
580
|
});
|
|
602
581
|
const { ClassName, fileName } = new UnknownFormatNaming(errorName);
|
|
603
|
-
currentErrorFolder.file(`${namespace}.ts`).addLine(`export const ${ClassName}Error = ${new UnknownFormatNaming(
|
|
582
|
+
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');
|
|
604
583
|
};
|
|
605
584
|
const scaffoldNewHandlersRestEndpoint = async (boundedContextFolder)=>{
|
|
606
585
|
const restPresentationFolder = boundedContextFolder.subitem([
|
|
@@ -619,11 +598,27 @@ const scaffoldNewHandlersRestEndpoint = async (boundedContextFolder)=>{
|
|
|
619
598
|
controller = await input({
|
|
620
599
|
message: 'Name: '
|
|
621
600
|
});
|
|
622
|
-
if (ConfigFile.Instance.data.domainFirstPackages.includes('@domain-first/wire'))
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
601
|
+
if (ConfigFile.Instance.data.domainFirstPackages.includes('@domain-first/wire')) {
|
|
602
|
+
boundedContextFolder.subitem([
|
|
603
|
+
'wiring',
|
|
604
|
+
'presentation',
|
|
605
|
+
'rest'
|
|
606
|
+
]).file('index.ts').addLine(`export * from './${controller}'`);
|
|
607
|
+
const sharedRestFolder = boundedContextFolder.subitem([
|
|
608
|
+
'..',
|
|
609
|
+
'..',
|
|
610
|
+
'presentation',
|
|
611
|
+
'rest'
|
|
612
|
+
]);
|
|
613
|
+
sharedRestFolder.file('wires.ts').addLine(`export * from '../../bounded-contexts/${boundedContextFolder.name}/wiring/presentation/rest/${controller}'`);
|
|
614
|
+
if (!sharedRestFolder.file('index.ts').exists) sharedRestFolder.createFile('index.ts', `
|
|
615
|
+
import * as wires from './wires'
|
|
616
|
+
|
|
617
|
+
const restWires = Object.values(wires)
|
|
618
|
+
|
|
619
|
+
export const restHandlers = restWires.map(x => x().handle)
|
|
620
|
+
`.trim());
|
|
621
|
+
}
|
|
627
622
|
}
|
|
628
623
|
const method = await prompts_select({
|
|
629
624
|
message: 'Method:',
|
|
@@ -641,9 +636,10 @@ const scaffoldNewHandlersRestEndpoint = async (boundedContextFolder)=>{
|
|
|
641
636
|
const controllerFolder = restPresentationFolder.subitem([
|
|
642
637
|
controller
|
|
643
638
|
]);
|
|
639
|
+
const endpointFolder = controllerFolder.subitem(path);
|
|
644
640
|
const nameBase = `${controller}-${path.length ? `${path.join('-')}-` : ''}${method}-endpoint`;
|
|
645
641
|
const endpointNaming = new UnknownFormatNaming(nameBase);
|
|
646
|
-
|
|
642
|
+
endpointFolder.createFile(`${method.toUpperCase()}.ts`, `
|
|
647
643
|
import { EndpointGenerator } from '@domain-first/handlers-rest'
|
|
648
644
|
|
|
649
645
|
export class ${endpointNaming.ClassName} {
|
|
@@ -659,7 +655,6 @@ export class ${endpointNaming.ClassName} {
|
|
|
659
655
|
tags: ['${boundedContextFolder.name}: ${controller}'],
|
|
660
656
|
})
|
|
661
657
|
}
|
|
662
|
-
|
|
663
658
|
}
|
|
664
659
|
`.trim());
|
|
665
660
|
if (ConfigFile.Instance.data.domainFirstPackages.includes('@domain-first/wire')) {
|
|
@@ -673,7 +668,7 @@ export class ${endpointNaming.ClassName} {
|
|
|
673
668
|
const wireNaming = new UnknownFormatNaming(wireNameBase);
|
|
674
669
|
wiringFolder.createFile(`${wireNaming.fileName}.ts`, `
|
|
675
670
|
import { wireClass } from '@domain-first/wire'
|
|
676
|
-
import { ${endpointNaming.ClassName} } from '../../../../presentation/rest/${controller}/${
|
|
671
|
+
import { ${endpointNaming.ClassName} } from '../../../../presentation/rest/${controller}/${path.length ? `${path.join('/')}/` : ''}${method.toUpperCase()}'
|
|
677
672
|
|
|
678
673
|
export const wire${endpointNaming.ClassName} = wireClass(
|
|
679
674
|
${endpointNaming.ClassName},
|
|
@@ -696,9 +691,14 @@ const scaffoldNewQuery = async (boundedContextFolder)=>{
|
|
|
696
691
|
message: 'Name: '
|
|
697
692
|
});
|
|
698
693
|
const naming = new UnknownFormatNaming(queryName);
|
|
699
|
-
const
|
|
700
|
-
|
|
694
|
+
const queryType = await prompts_select({
|
|
695
|
+
choices: [
|
|
696
|
+
'Execution (with infrastructure implementation)',
|
|
697
|
+
'Orchestrator (no infrastructure implementation)'
|
|
698
|
+
],
|
|
699
|
+
message: 'Query type'
|
|
701
700
|
});
|
|
701
|
+
const isOrchestrator = 'Orchestrator (no infrastructure implementation)' === queryType;
|
|
702
702
|
if (!isOrchestrator) {
|
|
703
703
|
const implementationType = await input({
|
|
704
704
|
message: 'Query infrastructure implementation type:',
|
|
@@ -722,80 +722,73 @@ const scaffoldNewQuery = async (boundedContextFolder)=>{
|
|
|
722
722
|
infrastructureFolder.subitem([
|
|
723
723
|
formatNaming.fileName
|
|
724
724
|
]).createFile(`${formatNaming.fileName}-${naming.fileName}-query.ts`, ConfigFile.Instance.data.domainFirstPackages.includes('@domain-first/handlers') ? `
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
export class ${formatNaming.ClassName}${naming.ClassName}Query implements ${naming.ClassName}Query {
|
|
729
|
-
constructor() {}
|
|
725
|
+
import { defineHandler } from '@domain-first/handlers'
|
|
726
|
+
import { ${naming.ClassName}Query } from '../../../application/queries/execution/${naming.fileName}-query'
|
|
730
727
|
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
handler: async (input) => {
|
|
735
|
-
return {}
|
|
736
|
-
}
|
|
737
|
-
})
|
|
728
|
+
export class ${formatNaming.ClassName}${naming.ClassName}Query extends ${naming.ClassName}Query {
|
|
729
|
+
constructor() {
|
|
730
|
+
super()
|
|
738
731
|
}
|
|
739
|
-
`.trim() : `
|
|
740
|
-
import { ${naming.ClassName}Query } from '../../../domain/queries/${naming.fileName}-query'
|
|
741
732
|
|
|
742
|
-
|
|
733
|
+
handle = defineHandler({
|
|
734
|
+
inputSchema: ${naming.ClassName}Query.inputSchema,
|
|
735
|
+
outputSchema: ${naming.ClassName}Query.outputSchema,
|
|
736
|
+
handler: async (input) => {
|
|
737
|
+
return {}
|
|
738
|
+
}
|
|
739
|
+
})
|
|
740
|
+
}
|
|
741
|
+
`.trim() : `
|
|
742
|
+
import { ${naming.ClassName}Query } from '../../../domain/queries/${naming.fileName}-query'
|
|
743
743
|
|
|
744
|
+
export class ${formatNaming.ClassName}${naming.ClassName}Query extends ${naming.ClassName}Query {
|
|
745
|
+
constructor() {
|
|
746
|
+
super()
|
|
744
747
|
}
|
|
748
|
+
}
|
|
745
749
|
`.trim());
|
|
746
|
-
if (ConfigFile.Instance.data.domainFirstPackages.includes('@domain-first/wire')) {
|
|
747
|
-
const wiringFolder = boundedContextFolder.subitem([
|
|
748
|
-
'wiring',
|
|
749
|
-
'infrastructure',
|
|
750
|
-
'queries',
|
|
751
|
-
formatNaming.fileName
|
|
752
|
-
]);
|
|
753
|
-
wiringFolder.createFile(`wire-${formatNaming.fileName}-${naming.fileName}-query.ts`, `
|
|
754
|
-
import { wireClass } from '@domain-first/wire'
|
|
755
|
-
import { ${formatNaming.ClassName}${naming.ClassName}Query } from '../../../../infrastructure/queries/${formatNaming.fileName}/${formatNaming.fileName}-${naming.fileName}-query'
|
|
756
|
-
|
|
757
|
-
export const wire${formatNaming.ClassName}${naming.ClassName}Query = wireClass(
|
|
758
|
-
${formatNaming.ClassName}${naming.ClassName}Query,
|
|
759
|
-
[]
|
|
760
|
-
)
|
|
761
|
-
`.trim());
|
|
762
|
-
}
|
|
763
750
|
}
|
|
764
|
-
if (ConfigFile.Instance.data.domainFirstPackages.includes('@domain-first/handlers')) queriesFolder.
|
|
765
|
-
|
|
751
|
+
if (ConfigFile.Instance.data.domainFirstPackages.includes('@domain-first/handlers')) queriesFolder.subitem([
|
|
752
|
+
'execution'
|
|
753
|
+
]).createFile(`${naming.fileName}-query.ts`, `
|
|
754
|
+
import type { Handler } from '@domain-first/handlers'
|
|
766
755
|
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
756
|
+
export abstract class ${naming.ClassName}Query {
|
|
757
|
+
static inputSchema = {}
|
|
758
|
+
static outputSchema = {}
|
|
770
759
|
|
|
771
|
-
|
|
772
|
-
|
|
760
|
+
abstract handle: Handler<typeof ${naming.ClassName}Query.inputSchema, typeof ${naming.ClassName}Query.outputSchema>
|
|
761
|
+
}
|
|
773
762
|
`.trim());
|
|
774
763
|
else queriesFolder.createFile(`${naming.fileName}-query.ts`, `
|
|
775
|
-
|
|
764
|
+
export abstract class ${naming.ClassName}Query {
|
|
776
765
|
|
|
777
|
-
|
|
766
|
+
}`.trim());
|
|
778
767
|
if (ConfigFile.Instance.data.domainFirstPackages.includes('@domain-first/wire')) {
|
|
779
768
|
const implementationNaming = new UnknownFormatNaming(implementationType);
|
|
780
769
|
const testImplementationNaming = new UnknownFormatNaming(testImplementationType);
|
|
781
770
|
boundedContextFolder.subitem([
|
|
782
771
|
'wiring',
|
|
783
|
-
'application',
|
|
784
772
|
'queries'
|
|
785
773
|
]).createFile(`wire-${naming.fileName}-query.ts`, `
|
|
786
|
-
|
|
787
|
-
|
|
774
|
+
import { wireClass } from '@domain-first/wire'
|
|
775
|
+
import { envBranchedWire } from '../../../../shared/wiring/env-branched-wire'
|
|
776
|
+
${implementationTypes.map((x)=>new UnknownFormatNaming(x)).map(({ ClassName, fileName })=>`import { ${ClassName}${naming.ClassName}Query } from '../../infrastructure/queries/${fileName}/${fileName}-${naming.fileName}-query'`).join('\n')}
|
|
788
777
|
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
}
|
|
778
|
+
${implementationTypes.map((x)=>new UnknownFormatNaming(x)).map(({ ClassName })=>`const wire${ClassName}Implementation = wireClass(${ClassName}${naming.ClassName}Query, [])`).join('\n\n')}
|
|
779
|
+
|
|
780
|
+
export const wire${naming.ClassName}Query = envBranchedWire({
|
|
781
|
+
test: wire${addTestImplementation ? testImplementationNaming.ClassName : implementationNaming.ClassName}Implementation,
|
|
782
|
+
development: wire${implementationNaming.ClassName}Implementation,
|
|
783
|
+
production: wire${implementationNaming.ClassName}Implementation
|
|
784
|
+
})
|
|
794
785
|
`.trim());
|
|
795
786
|
}
|
|
796
787
|
return;
|
|
797
788
|
}
|
|
798
|
-
if (ConfigFile.Instance.data.domainFirstPackages.includes('@domain-first/handlers')) queriesFolder.
|
|
789
|
+
if (ConfigFile.Instance.data.domainFirstPackages.includes('@domain-first/handlers')) queriesFolder.subitem([
|
|
790
|
+
'orchestration'
|
|
791
|
+
]).createFile(`${naming.fileName}-query.ts`, `
|
|
799
792
|
import { defineHandler } from '@domain-first/handlers'
|
|
800
793
|
|
|
801
794
|
export class ${naming.ClassName}Query {
|
|
@@ -811,7 +804,9 @@ export class ${naming.ClassName}Query {
|
|
|
811
804
|
})
|
|
812
805
|
}
|
|
813
806
|
`.trim());
|
|
814
|
-
else queriesFolder.
|
|
807
|
+
else queriesFolder.subitem([
|
|
808
|
+
'orchestration'
|
|
809
|
+
]).createFile(`${naming.fileName}-query.ts`, `
|
|
815
810
|
export class ${naming.ClassName}Query {
|
|
816
811
|
|
|
817
812
|
}`.trim());
|
|
@@ -821,7 +816,7 @@ export class ${naming.ClassName}Query {
|
|
|
821
816
|
'queries'
|
|
822
817
|
]).createFile(`wire-${naming.fileName}-query.ts`, `
|
|
823
818
|
import { wireClass } from '@domain-first/wire'
|
|
824
|
-
import { ${naming.ClassName}Query } from '../../../application/queries/${naming.fileName}-query'
|
|
819
|
+
import { ${naming.ClassName}Query } from '../../../application/queries/orchestration/${naming.fileName}-query'
|
|
825
820
|
|
|
826
821
|
export const wire${naming.ClassName}Query = wireClass(${naming.ClassName}Query, [])
|
|
827
822
|
`.trim());
|
|
@@ -859,11 +854,10 @@ export class ${naming.ClassName}UseCase {
|
|
|
859
854
|
`.trim());
|
|
860
855
|
if (ConfigFile.Instance.data.domainFirstPackages.includes('@domain-first/wire')) boundedContextFolder.subitem([
|
|
861
856
|
'wiring',
|
|
862
|
-
'application',
|
|
863
857
|
'use-cases'
|
|
864
858
|
]).createFile(`wire-${naming.fileName}-use-case.ts`, `
|
|
865
859
|
import { wireClass } from '@domain-first/wire'
|
|
866
|
-
import { ${naming.ClassName}UseCase } from '
|
|
860
|
+
import { ${naming.ClassName}UseCase } from '../../application/use-cases/${naming.fileName}-use-case'
|
|
867
861
|
|
|
868
862
|
export const wire${naming.ClassName}UseCase = wireClass(
|
|
869
863
|
${naming.ClassName}UseCase,
|
|
@@ -872,6 +866,109 @@ export const wire${naming.ClassName}UseCase = wireClass(
|
|
|
872
866
|
|
|
873
867
|
`.trim());
|
|
874
868
|
};
|
|
869
|
+
const scaffoldReactWidget = async (presentationReactFolder)=>{
|
|
870
|
+
const widgetName = await input({
|
|
871
|
+
message: 'Name: '
|
|
872
|
+
});
|
|
873
|
+
const widgetType = await prompts_select({
|
|
874
|
+
choices: [
|
|
875
|
+
'monolithic',
|
|
876
|
+
'with separated ui',
|
|
877
|
+
'headless'
|
|
878
|
+
],
|
|
879
|
+
message: 'Type: '
|
|
880
|
+
});
|
|
881
|
+
const { ClassName, fileName } = new UnknownFormatNaming(widgetName);
|
|
882
|
+
const folder = presentationReactFolder.subitem([
|
|
883
|
+
'widgets',
|
|
884
|
+
fileName
|
|
885
|
+
]);
|
|
886
|
+
switch(widgetType){
|
|
887
|
+
case 'monolithic':
|
|
888
|
+
folder.createFile('index.tsx', `
|
|
889
|
+
import { type FC } from 'react'
|
|
890
|
+
|
|
891
|
+
export type ${ClassName}WidgetProps = {}
|
|
892
|
+
|
|
893
|
+
export const ${ClassName}Widget: FC<${ClassName}WidgetProps> = (props) => {
|
|
894
|
+
return <></>
|
|
895
|
+
}
|
|
896
|
+
`.trim());
|
|
897
|
+
break;
|
|
898
|
+
case 'with separated ui':
|
|
899
|
+
folder.createFile('types.ts', `
|
|
900
|
+
export type ${ClassName}WidgetProps = { }
|
|
901
|
+
|
|
902
|
+
export type ${ClassName}WidgetUIProps = { }
|
|
903
|
+
`.trim());
|
|
904
|
+
folder.createFile('index.tsx', `
|
|
905
|
+
import { type FC } from 'react'
|
|
906
|
+
import type { ${ClassName}WidgetProps } from './types'
|
|
907
|
+
import { ${ClassName}WidgetUI } from './ui'
|
|
908
|
+
import { useUIModel } from './hooks/use-ui-model'
|
|
909
|
+
|
|
910
|
+
export const ${ClassName}Widget: FC<${ClassName}WidgetProps> = (props) => {
|
|
911
|
+
const uiModel = useUIModel(props)
|
|
912
|
+
return <${ClassName}WidgetUI {...uiModel} />
|
|
913
|
+
}
|
|
914
|
+
|
|
915
|
+
export type { ${ClassName}WidgetProps }
|
|
916
|
+
`.trim());
|
|
917
|
+
folder.subitem([
|
|
918
|
+
'ui'
|
|
919
|
+
]).createFile('index.tsx', `
|
|
920
|
+
import { FC } from 'react'
|
|
921
|
+
import type { ${ClassName}WidgetUIProps } from '../types'
|
|
922
|
+
|
|
923
|
+
export const ${ClassName}WidgetUI: FC<${ClassName}WidgetUIProps> = (props) => {
|
|
924
|
+
return <></>
|
|
925
|
+
}
|
|
926
|
+
`.trim());
|
|
927
|
+
folder.subitem([
|
|
928
|
+
'hooks'
|
|
929
|
+
]).createFile('use-ui-model.ts', `
|
|
930
|
+
import type { ${ClassName}WidgetProps, ${ClassName}WidgetUIProps } from '../types'
|
|
931
|
+
|
|
932
|
+
export const useUIModel = (widgetProps: ${ClassName}WidgetProps): ${ClassName}WidgetUIProps => {
|
|
933
|
+
return {}
|
|
934
|
+
}
|
|
935
|
+
`.trim());
|
|
936
|
+
break;
|
|
937
|
+
case 'headless':
|
|
938
|
+
folder.createFile('types.ts', `
|
|
939
|
+
import { type FC } from 'react'
|
|
940
|
+
|
|
941
|
+
export type ${ClassName}WidgetUIProps = { }
|
|
942
|
+
|
|
943
|
+
export type ${ClassName}WidgetProps = {
|
|
944
|
+
UI: FC<${ClassName}WidgetUIProps>
|
|
945
|
+
}
|
|
946
|
+
|
|
947
|
+
`.trim());
|
|
948
|
+
folder.createFile('index.tsx', `
|
|
949
|
+
import { type FC } from 'react'
|
|
950
|
+
import type { ${ClassName}WidgetProps } from './types'
|
|
951
|
+
import { useUIModel } from './hooks/use-ui-model'
|
|
952
|
+
|
|
953
|
+
export const ${ClassName}Widget: FC<${ClassName}WidgetProps> = (props) => {
|
|
954
|
+
const uiModel = useUIModel(props)
|
|
955
|
+
return <props.UI {...uiModel} />
|
|
956
|
+
}
|
|
957
|
+
|
|
958
|
+
export type { ${ClassName}WidgetProps }
|
|
959
|
+
`.trim());
|
|
960
|
+
folder.subitem([
|
|
961
|
+
'hooks'
|
|
962
|
+
]).createFile('use-ui-model.ts', `
|
|
963
|
+
import type { ${ClassName}WidgetProps, ${ClassName}WidgetUIProps } from '../types'
|
|
964
|
+
|
|
965
|
+
export const useUIModel = (widgetProps: Omit<${ClassName}WidgetProps, 'UI'>): ${ClassName}WidgetUIProps => {
|
|
966
|
+
return {}
|
|
967
|
+
}
|
|
968
|
+
`.trim());
|
|
969
|
+
break;
|
|
970
|
+
}
|
|
971
|
+
};
|
|
875
972
|
const main = async ()=>{
|
|
876
973
|
if (!ConfigFile.exists) return void await initializeUseCase();
|
|
877
974
|
const rootPath = new ProjectRoot().path;
|
|
@@ -888,18 +985,41 @@ const main = async ()=>{
|
|
|
888
985
|
};
|
|
889
986
|
const options = [
|
|
890
987
|
...currentBoundedContextOptions,
|
|
988
|
+
ConfigFile.Instance.data.useReact ? {
|
|
989
|
+
name: 'Scaffold React module',
|
|
990
|
+
action: 'Scaffold React module'
|
|
991
|
+
} : void 0,
|
|
891
992
|
{
|
|
892
993
|
name: 'Shared Layer',
|
|
893
994
|
action: 'Scaffold in bounded context'
|
|
894
995
|
},
|
|
895
996
|
scaffoldNewBoundedContext
|
|
896
|
-
];
|
|
997
|
+
].filter((x)=>!!x);
|
|
897
998
|
const result = await prompts_select({
|
|
898
999
|
message: '@domain-first/project-structure',
|
|
899
1000
|
choices: options.map((x)=>x.name)
|
|
900
1001
|
});
|
|
901
1002
|
const { action, name } = options.find((x)=>x.name === result);
|
|
902
1003
|
switch(action){
|
|
1004
|
+
case 'Scaffold React module':
|
|
1005
|
+
{
|
|
1006
|
+
const action = await prompts_select({
|
|
1007
|
+
message: 'Module: ',
|
|
1008
|
+
choices: [
|
|
1009
|
+
'New widget'
|
|
1010
|
+
]
|
|
1011
|
+
});
|
|
1012
|
+
switch(action){
|
|
1013
|
+
case 'New widget':
|
|
1014
|
+
return void await scaffoldReactWidget(new Folder(rootPath).subitem([
|
|
1015
|
+
ConfigFile.Instance.data.rootFolder,
|
|
1016
|
+
'presentation',
|
|
1017
|
+
'react'
|
|
1018
|
+
]));
|
|
1019
|
+
default:
|
|
1020
|
+
return;
|
|
1021
|
+
}
|
|
1022
|
+
}
|
|
903
1023
|
case 'Scaffold new bounded context':
|
|
904
1024
|
return void await scaffoldNewBoundedContextUseCase();
|
|
905
1025
|
case 'Scaffold in bounded context':
|