@alevnyacow/nzmt 0.5.1 → 0.6.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 (3) hide show
  1. package/README.md +0 -1
  2. package/bin/cli.js +178 -115
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -1,7 +1,6 @@
1
1
  # NZMT - Next Zod Modules Toolkit
2
2
 
3
3
  [![npm version](https://badge.fury.io/js/@alevnyacow%2Fnzmt.svg)](https://badge.fury.io/js/@alevnyacow%2Fnzmt)
4
- ![NPM Downloads](https://img.shields.io/npm/dm/%40alevnyacow%2Fnzmt)
5
4
  ![NPM License](https://img.shields.io/npm/l/%40alevnyacow%2Fnzmt)
6
5
 
7
6
  ## Structure
package/bin/cli.js CHANGED
@@ -91,25 +91,39 @@ function createDefaultConfig() {
91
91
  throw 'No package.json was found'
92
92
  }
93
93
 
94
- fs.writeFileSync(path.resolve(projectRoot, 'nzmt.config.json'), JSON.stringify({
94
+ const prismaClientPathOption = [entityName, ...options].find(x => x.startsWith('prismaClientPath:'))
95
+
96
+ let prismaClientPath = prismaClientPathOption ? prismaClientPathOption.split(':')[1] : undefined
97
+
98
+ fs.writeFileSync(path.resolve(projectRoot, 'nzmt.config.json'), JSON.stringify(prismaClientPath ? {
95
99
  paths: {
96
100
  di: './src/server/di',
97
101
  stores: './src/server/stores',
98
102
  services: './src/server/services',
99
103
  providers: './src/server/providers',
100
104
  controllers: './src/server/controllers',
105
+ infrastructure: './src/server/infrastructure',
101
106
  entities: './src/shared/entities',
102
107
  valueObjects: './src/shared/value-objects',
103
- queries: './src/client/shared/queries'
108
+ queries: './src/client/shared/queries',
104
109
  },
105
110
  store: {
106
111
  prisma: {
107
- import: [
108
- "import { prisma } from '@/server/infrastructure/prisma'",
109
- "import type { Prisma } from '@/server/generated-prisma/client'",
110
- ]
112
+ clientPath: prismaClientPath
111
113
  },
112
114
  }
115
+ } : {
116
+ paths: {
117
+ di: './src/server/di',
118
+ stores: './src/server/stores',
119
+ services: './src/server/services',
120
+ providers: './src/server/providers',
121
+ controllers: './src/server/controllers',
122
+ infrastructure: './src/server/infrastructure',
123
+ entities: './src/shared/entities',
124
+ valueObjects: './src/shared/value-objects',
125
+ queries: './src/client/shared/queries',
126
+ }
113
127
  }, null, '\t'))
114
128
  }
115
129
  }
@@ -267,9 +281,52 @@ function initDI() {
267
281
  ].join('\n'))
268
282
  };
269
283
 
284
+ function initPrisma() {
285
+ const config = loadConfig()
286
+ const prismaClientPath = config?.store?.prisma?.clientPath
287
+ if (!prismaClientPath) {
288
+ return
289
+ }
290
+ const prismaFolder = path.resolve(process.cwd(), config?.paths?.infrastructure, 'prisma')
291
+ fs.mkdirSync(prismaFolder, { recursive: true })
292
+
293
+ fs.writeFileSync(path.resolve(prismaFolder, 'client.ts'), [
294
+ `import { PrismaPg } from '@prisma/adapter-pg'`,
295
+ `import { PrismaClient } from '${prismaClientPath}'`,
296
+ ``,
297
+ `const adapter = new PrismaPg({`,
298
+ `\tconnectionString: process.env.DATABASE_URL`,
299
+ `})`,
300
+ ``,
301
+ `export const prismaClient = new PrismaClient({ adapter })`
302
+ ].join('\n'))
303
+
304
+ fs.writeFileSync(path.resolve(prismaFolder, 'index.ts'), [
305
+ `export * from './client'`
306
+ ].join('\n'))
307
+
308
+ // Update DI
309
+
310
+ const diEntriesPath = path.resolve(process.cwd(), config?.paths?.di, 'entries.di.ts')
311
+
312
+ insertBeforeLineInFile(
313
+ diEntriesPath,
314
+ 'type DIEntries =',
315
+ `import { prismaClient } from '${config?.paths?.infrastructure.replace('./src', '@')}/prisma'\n`
316
+ )
317
+
318
+ insertAfterLineInFile(
319
+ diEntriesPath,
320
+ '// Other',
321
+ `\tPrismaClient: { constantValue: prismaClient },`,
322
+ )
323
+ }
324
+
270
325
  if (command.toLowerCase() === 'init' || command === 'i') {
271
326
  createDefaultConfig()
272
327
  initDI()
328
+ initPrisma()
329
+
273
330
  process.exit(0)
274
331
  }
275
332
 
@@ -324,120 +381,126 @@ function generateStores(lowerCase, upperCase, withEntityPreset) {
324
381
  ].filter(x => typeof x === 'string').join('\n'))
325
382
 
326
383
  // Prisma
384
+ const prismaPath = config.store?.prisma?.clientPath
385
+ if (prismaPath) {
386
+ fs.writeFileSync(path.resolve(folder, `${entityName}.store.prisma.ts`), [
387
+ `import type { Prisma, PrismaClient } from '${prismaPath}'`,
388
+ `import { DITokens } from '${config?.paths?.di?.replace('./src', '@')}'`,
389
+ "import { injectable } from 'inversify'",
390
+ "import { Store } from '@alevnyacow/nzmt'",
391
+ `import { type ${upperCase}Store, ${lowerCase}StoreMetadata } from './${entityName}.store'`,
392
+ "",
393
+ `type Types = Store.Types<${upperCase}Store>`,
394
+ "",
395
+ "const mappers = {",
396
+ `\ttoFindOnePayload: (source: Types['findOnePayload']): Prisma.${upperCase}WhereUniqueInput => {`,
397
+ "\t\treturn {",
398
+ "\t\t\t",
399
+ "\t\t};",
400
+ "\t},",
401
+ `\ttoFindListPayload: (source: Types['findListPayload']): Prisma.${upperCase}WhereInput => {`,
402
+ "\t\treturn {",
403
+ "\t\t\t",
404
+ "\t\t};",
405
+ "\t},",
406
+ `\ttoListModel: (source: Prisma.${upperCase}GetPayload<{}>): Types['listModel'] => {`,
407
+ "\t\treturn {",
408
+ "\t\t\t",
409
+ "\t\t};",
410
+ "\t},",
411
+ `\ttoDetails: (source: Prisma.${upperCase}GetPayload<{ include: { } }>): Types['details'] => {`,
412
+ "\t\treturn {",
413
+ "\t\t\t",
414
+ "\t\t};",
415
+ "\t},",
416
+ `\ttoCreatePayload: (source: Types['createPayload']): Prisma.${upperCase}CreateInput => {`,
417
+ "\t\treturn {",
418
+ "\t\t\t",
419
+ "\t\t};",
420
+ "\t},",
421
+ `\ttoUpdatePayload: (source: Types['updatePayload']): Prisma.${upperCase}UpdateInput => {`,
422
+ "\t\treturn {",
423
+ "\t\t\t",
424
+ "\t\t};",
425
+ "\t}",
426
+ "}",
427
+ "",
428
+ "@injectable()",
429
+ `export class ${upperCase}PrismaStore implements ${upperCase}Store {`,
430
+ `\tprivate method = Store.methods(${lowerCase}StoreMetadata);`,
431
+ "",
432
+ "\tconstructor(@inject('PrismaClient' satisfies DITokens) private readonly prismaClient: PrismaClient) {}",
433
+ "",
434
+ "\tlist = this.method('list', async ({ filter, pagination: { pageSize, zeroBasedIndex } = { pageSize: 1000, zeroBasedIndex: 0 }}) => {",
435
+ `\t\tconst list = await this.prismaClient.${lowerCase}.findMany({`,
436
+ "\t\t\twhere: mappers.toFindListPayload(filter),",
437
+ "\t\t\tskip: zeroBasedIndex * pageSize,",
438
+ "\t\t\ttake: pageSize",
439
+ "\t\t})",
440
+ "\t\t",
441
+ "\t\treturn list.map(mappers.toListModel)",
442
+ "\t});",
443
+ "",
444
+ "\tdetails = this.method('details', async ({ filter }) => {",
445
+ `\t\tconst details = await this.prismaClient.${lowerCase}.findUnique({`,
446
+ "\t\t\twhere: mappers.toFindOnePayload(filter),",
447
+ "\t\t\tinclude: {}",
448
+ "\t\t})",
449
+ "",
450
+ "\t\tif (!details) {",
451
+ "\t\t\treturn null",
452
+ "\t\t}",
453
+ "",
454
+ "\t\treturn mappers.toDetails(details)",
455
+ "\t});",
456
+ "",
457
+ "\tcreate = this.method('create', async ({ payload }) => {",
458
+ `\t\tconst { id } = await this.prismaClient.${lowerCase}.create({`,
459
+ "\t\t\tdata: mappers.toCreatePayload(payload),",
460
+ "\t\t\tselect: { id: true }",
461
+ "\t\t})",
462
+ "",
463
+ "\t\treturn { id }",
464
+ "\t});",
465
+ "",
466
+ "\tupdateOne = this.method('updateOne', async ({ filter, payload }) => {",
467
+ "\t\ttry {",
468
+ `\t\t\tawait this.prismaClient.${lowerCase}.update({`,
469
+ "\t\t\t\twhere: mappers.toFindOnePayload(filter),",
470
+ "\t\t\t\tdata: mappers.toUpdatePayload(payload),",
471
+ "\t\t\t})",
472
+ "",
473
+ "\t\t\treturn { success: true }",
474
+ "\t\t}",
475
+ "\t\tcatch {",
476
+ "\t\t\treturn { success: false }",
477
+ "\t\t}",
478
+ "\t});",
479
+ "",
480
+ "\tdeleteOne = this.method('deleteOne', async ({ filter }) => {",
481
+ "\t\ttry {",
482
+ `\t\t\tawait this.prismaClient.${lowerCase}.delete({`,
483
+ "\t\t\t\twhere: mappers.toFindOnePayload(filter),",
484
+ "\t\t\t})",
485
+ "",
486
+ "\t\t\treturn { success: true }",
487
+ "\t\t}",
488
+ "\t\tcatch {",
489
+ "\t\t\treturn { success: false }",
490
+ "\t\t}",
491
+ "\t});",
492
+ "};"
493
+ ].filter(x => typeof x === 'string').join('\n'))
494
+ }
327
495
 
328
- fs.writeFileSync(path.resolve(folder, `${entityName}.store.prisma.ts`), [
329
- ...config?.store?.prisma?.import ?? [],
330
- "import { injectable } from 'inversify'",
331
- "import { Store } from '@alevnyacow/nzmt'",
332
- `import { type ${upperCase}Store, ${lowerCase}StoreMetadata } from './${entityName}.store'`,
333
- "",
334
- `type Types = Store.Types<${upperCase}Store>`,
335
- "",
336
- "const mappers = {",
337
- `\ttoFindOnePayload: (source: Types['findOnePayload']): Prisma.${upperCase}WhereUniqueInput => {`,
338
- "\t\treturn {",
339
- "\t\t\t",
340
- "\t\t};",
341
- "\t},",
342
- `\ttoFindListPayload: (source: Types['findListPayload']): Prisma.${upperCase}WhereInput => {`,
343
- "\t\treturn {",
344
- "\t\t\t",
345
- "\t\t};",
346
- "\t},",
347
- `\ttoListModel: (source: Prisma.${upperCase}GetPayload<{}>): Types['listModel'] => {`,
348
- "\t\treturn {",
349
- "\t\t\t",
350
- "\t\t};",
351
- "\t},",
352
- `\ttoDetails: (source: Prisma.${upperCase}GetPayload<{ include: { } }>): Types['details'] => {`,
353
- "\t\treturn {",
354
- "\t\t\t",
355
- "\t\t};",
356
- "\t},",
357
- `\ttoCreatePayload: (source: Types['createPayload']): Prisma.${upperCase}CreateInput => {`,
358
- "\t\treturn {",
359
- "\t\t\t",
360
- "\t\t};",
361
- "\t},",
362
- `\ttoUpdatePayload: (source: Types['updatePayload']): Prisma.${upperCase}UpdateInput => {`,
363
- "\t\treturn {",
364
- "\t\t\t",
365
- "\t\t};",
366
- "\t}",
367
- "}",
368
- "",
369
- "@injectable()",
370
- `export class ${upperCase}PrismaStore implements ${upperCase}Store {`,
371
- `\tprivate method = Store.methods(${lowerCase}StoreMetadata);`,
372
- "",
373
- "\tlist = this.method('list', async ({ filter, pagination: { pageSize, zeroBasedIndex } = { pageSize: 1000, zeroBasedIndex: 0 }}) => {",
374
- `\t\tconst list = await prisma.${lowerCase}.findMany({`,
375
- "\t\t\twhere: mappers.toFindListPayload(filter),",
376
- "\t\t\tskip: zeroBasedIndex * pageSize,",
377
- "\t\t\ttake: pageSize",
378
- "\t\t})",
379
- "\t\t",
380
- "\t\treturn list.map(mappers.toListModel)",
381
- "\t});",
382
- "",
383
- "\tdetails = this.method('details', async ({ filter }) => {",
384
- `\t\tconst details = await prisma.${lowerCase}.findUnique({`,
385
- "\t\t\twhere: mappers.toFindOnePayload(filter),",
386
- "\t\t\tinclude: {}",
387
- "\t\t})",
388
- "",
389
- "\t\tif (!details) {",
390
- "\t\t\treturn null",
391
- "\t\t}",
392
- "",
393
- "\t\treturn mappers.toDetails(details)",
394
- "\t});",
395
- "",
396
- "\tcreate = this.method('create', async ({ payload }) => {",
397
- `\t\tconst { id } = await prisma.${lowerCase}.create({`,
398
- "\t\t\tdata: mappers.toCreatePayload(payload),",
399
- "\t\t\tselect: { id: true }",
400
- "\t\t})",
401
- "",
402
- "\t\treturn { id }",
403
- "\t});",
404
- "",
405
- "\tupdateOne = this.method('updateOne', async ({ filter, payload }) => {",
406
- "\t\ttry {",
407
- `\t\t\tawait prisma.${lowerCase}.update({`,
408
- "\t\t\t\twhere: mappers.toFindOnePayload(filter),",
409
- "\t\t\t\tdata: mappers.toUpdatePayload(payload),",
410
- "\t\t\t})",
411
- "",
412
- "\t\t\treturn { success: true }",
413
- "\t\t}",
414
- "\t\tcatch {",
415
- "\t\t\treturn { success: false }",
416
- "\t\t}",
417
- "\t});",
418
- "",
419
- "\tdeleteOne = this.method('deleteOne', async ({ filter }) => {",
420
- "\t\ttry {",
421
- `\t\t\tawait prisma.${lowerCase}.delete({`,
422
- "\t\t\t\twhere: mappers.toFindOnePayload(filter),",
423
- "\t\t\t})",
424
- "",
425
- "\t\t\treturn { success: true }",
426
- "\t\t}",
427
- "\t\tcatch {",
428
- "\t\t\treturn { success: false }",
429
- "\t\t}",
430
- "\t});",
431
- "};"
432
- ].filter(x => typeof x === 'string').join('\n'))
433
496
 
434
497
  // barrel
435
498
 
436
499
  fs.writeFileSync(path.resolve(folder, 'index.ts'), [
437
500
  `export * from './${entityName}.store.ts'`,
438
- `export * from './${entityName}.store.prisma.ts'`,
501
+ prismaPath ? `export * from './${entityName}.store.prisma.ts'` : undefined,
439
502
  `export * from './${entityName}.store.ram.ts'`
440
- ].join('\n'))
503
+ ].filter(x => typeof x === 'string').join('\n'))
441
504
 
442
505
  // update DI
443
506
 
@@ -446,13 +509,13 @@ function generateStores(lowerCase, upperCase, withEntityPreset) {
446
509
  insertBeforeLineInFile(
447
510
  diEntriesPath,
448
511
  'type DIEntries =',
449
- `import { ${upperCase}PrismaStore, ${upperCase}RAMStore } from '${config?.paths?.stores.replace('./src', '@')}/${entityName}'\n`
512
+ prismaPath ? `import { ${upperCase}PrismaStore, ${upperCase}RAMStore } from '${config?.paths?.stores.replace('./src', '@')}/${entityName}'\n` : `import { ${upperCase}RAMStore } from '${config?.paths?.stores.replace('./src', '@')}/${entityName}'\n`
450
513
  )
451
514
 
452
515
  insertAfterLineInFile(
453
516
  diEntriesPath,
454
517
  '// Stores',
455
- `\t${upperCase}Store: { test: [${upperCase}RAMStore, (x) => x.inSingletonScope()], prod: ${upperCase}PrismaStore, dev: ${upperCase}PrismaStore },`,
518
+ prismaPath ? `\t${upperCase}Store: { test: [${upperCase}RAMStore, (x) => x.inSingletonScope()], prod: ${upperCase}PrismaStore, dev: ${upperCase}PrismaStore },` : `\t${upperCase}Store: ${upperCase}RAMStore,`,
456
519
  )
457
520
 
458
521
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alevnyacow/nzmt",
3
- "version": "0.5.1",
3
+ "version": "0.6.1",
4
4
  "description": "Next Zod Modules Toolkit",
5
5
  "repository": {
6
6
  "type": "git",