@nestledjs/api 0.0.10 → 0.0.11

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nestledjs/api",
3
- "version": "0.0.10",
3
+ "version": "0.0.11",
4
4
  "generators": "./generators.json",
5
5
  "type": "commonjs",
6
6
  "main": "./src/index.js",
@@ -17,14 +17,14 @@
17
17
  },
18
18
  "dependencies": {
19
19
  "tslib": "^2.3.0",
20
- "@nx/devkit": "21.2.0",
21
- "@nx/js": "21.2.0",
20
+ "@nx/devkit": "21.2.1",
21
+ "@nx/js": "21.2.1",
22
22
  "@prisma/internals": "^6.9.0",
23
23
  "pluralize": "^8.0.0",
24
24
  "dotenv": "16.4.5",
25
25
  "pg": "^8.13.0"
26
26
  },
27
27
  "peerDependencies": {
28
- "@nestledjs/utils": "0.0.10"
28
+ "@nestledjs/utils": "0.0.11"
29
29
  }
30
30
  }
@@ -1,7 +1,7 @@
1
1
  import { MiddlewareConsumer, Module, NestModule, RequestMethod } from '@nestjs/common'
2
2
  import { LoggerMiddleware } from './applogger.middleware'
3
3
  import { ConfigModule } from '@nestjs/config'
4
- import { appConfig, validationSchema } from './app.config'
4
+ import { configuration, validationSchema } from '@<%= npmScope %>/api/config'
5
5
 
6
6
  // Auto-generated modules with special functions
7
7
  export const coreModules = [
@@ -25,7 +25,7 @@ export const appModules = [
25
25
  @Module({
26
26
  imports: [
27
27
  ConfigModule.forRoot({
28
- load: [appConfig],
28
+ load: [configuration],
29
29
  validationSchema: validationSchema,
30
30
  validationOptions: {
31
31
  allowUnknown: true,
@@ -1,6 +1,6 @@
1
1
  import { Logger } from '@nestjs/common'
2
2
  import { NestFactory } from '@nestjs/core'
3
- import { ConfigService } from '@nestjs/config'
3
+ import { ConfigService } from '@<%= npmScope %>/api/config'
4
4
  import cookieParser from 'cookie-parser'
5
5
 
6
6
  import { AppModule } from './app.module'
@@ -10,16 +10,28 @@ async function bootstrap() {
10
10
  const configService = app.get(ConfigService)
11
11
 
12
12
  // Get individual properties with fallbacks
13
- const prefix = configService.get('app.prefix') || 'api';
14
- const port = configService.get('app.port') || 3000;
15
- const host = configService.get('app.host') || 'localhost';
13
+ const prefix = configService.prefix || 'api';
14
+ const port = configService.port || 3000;
15
+ const host = configService.host || 'localhost';
16
16
 
17
17
  app.setGlobalPrefix(prefix)
18
+
19
+ // Use the apiCorsOrigins getter and handle as array
20
+ const origins = configService.apiCorsOrigins.length
21
+ ? configService.apiCorsOrigins
22
+ : ['http://localhost:4200']; // fallback for dev
23
+
18
24
  app.enableCors({
19
25
  credentials: true,
20
- origin: configService.get('app.api.cors.origin') || '*',
21
- })
22
- app.use(cookieParser(configService.get('app.api.cookie.secret') || 'secret'));
26
+ origin: (origin, callback) => {
27
+ if (!origin) return callback(null, true);
28
+ if (origins.includes(origin)) {
29
+ return callback(null, true);
30
+ }
31
+ return callback(new Error('Not allowed by CORS'));
32
+ },
33
+ });
34
+ app.use(cookieParser(configService.cookie.secret || 'secret'));
23
35
 
24
36
  await app.listen(port, host, () => {
25
37
  Logger.log(`Listening at http://${host}:${port}/${prefix}`)
@@ -33,11 +33,11 @@ function default_1(tree, schema) {
33
33
  try {
34
34
  // Get the workspace root directory
35
35
  const workspaceRoot = tree.root;
36
- // Create apps directory if it doesn't exist
36
+ // Create the apps directory if it doesn't exist
37
37
  if (!tree.exists('apps')) {
38
38
  tree.write('apps/.gitkeep', '');
39
39
  }
40
- // Run the Nx generator command directly from the workspace root with proper workspace layout
40
+ // Run the Nx generator command directly from the workspace root with the proper workspace layout
41
41
  (0, child_process_1.execSync)('nx g @nx/nest:application --name api --directory apps/api --no-interactive', {
42
42
  stdio: 'inherit',
43
43
  cwd: workspaceRoot,
@@ -50,13 +50,12 @@ function default_1(tree, schema) {
50
50
  (0, devkit_1.generateFiles)(tree, (0, devkit_1.joinPathFragments)(__dirname, './files'), path.join('apps', 'api'), Object.assign(Object.assign({}, schema), { tmpl: '', npmScope: (0, get_npm_scope_1.getNpmScope)(tree) }));
51
51
  // Add dev:api script to package.json
52
52
  (0, devkit_1.updateJson)(tree, 'package.json', (json) => {
53
- if (!json.scripts) {
54
- json.scripts = {};
55
- }
53
+ var _a;
54
+ (_a = json.scripts) !== null && _a !== void 0 ? _a : (json.scripts = {});
56
55
  json.scripts['dev:api'] = 'nx serve api --skip-nx-cache';
57
56
  return json;
58
57
  });
59
- // Update the build target in apps/api/project.json to use custom webpack command
58
+ // Update the build target in apps/api/project.json to use the custom webpack command
60
59
  const projectJsonPath = path.join('apps', 'api', 'project.json');
61
60
  if (tree.exists(projectJsonPath)) {
62
61
  (0, devkit_1.updateJson)(tree, projectJsonPath, (json) => {
@@ -1 +1 @@
1
- {"version":3,"file":"generator.js","sourceRoot":"","sources":["../../../../../generators/api/src/app/generator.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"generator.js","sourceRoot":"","sources":["../../../../../generators/api/src/app/generator.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- export * from './lib/config.module'
1
+ export * from './lib/api-config.module'
2
2
  export * from './lib/config.service'
3
3
  export * from './lib/configuration'
4
4
  export * from './lib/validation'
@@ -14,8 +14,22 @@ export class ConfigService {
14
14
  return this.config.get<string[]>('api.cors.origin') ?? []
15
15
  }
16
16
 
17
- get cookie(): { name: string; options: CookieOptions } {
18
- return this.config.getOrThrow<{ name: string; options: CookieOptions }>('api.cookie')
17
+ get cookie(): { name: string; secret: string; options: CookieOptions } {
18
+ return this.config.getOrThrow<{ name: string; secret: string; options: CookieOptions }>(
19
+ 'api.cookie',
20
+ )
21
+ }
22
+
23
+ get prefix(): string {
24
+ return this.config.getOrThrow<string>('prefix')
25
+ }
26
+
27
+ get port(): number {
28
+ return this.config.getOrThrow<number>('port')
29
+ }
30
+
31
+ get host(): string {
32
+ return this.config.getOrThrow<string>('host')
19
33
  }
20
34
 
21
35
  get appEmail(): string {
@@ -7,6 +7,7 @@ export const configuration = () => ({
7
7
  api: {
8
8
  cookie: {
9
9
  name: process.env['API_COOKIE_NAME'],
10
+ secret: process.env['API_COOKIE_SECRET'] || 'secret',
10
11
  options: {
11
12
  domain: process.env['API_COOKIE_DOMAIN'],
12
13
  httpOnly: true,
@@ -8,7 +8,7 @@ function generateLibraries(tree_1) {
8
8
  return tslib_1.__awaiter(this, arguments, void 0, function* (tree, options = {}) {
9
9
  const templateRootPath = (0, devkit_1.joinPathFragments)(__dirname, './files');
10
10
  const overwrite = options.overwrite === true;
11
- yield (0, utils_1.apiLibraryGenerator)(tree, { name: 'config', overwrite }, templateRootPath);
11
+ yield (0, utils_1.apiLibraryGenerator)(tree, { name: 'config', overwrite, customName: true }, templateRootPath);
12
12
  yield (0, devkit_1.formatFiles)(tree);
13
13
  return () => {
14
14
  (0, devkit_1.installPackagesTask)(tree);
@@ -1 +1 @@
1
- {"version":3,"file":"generator.js","sourceRoot":"","sources":["../../../../../generators/api/src/config/generator.ts"],"names":[],"mappings":";;AAIA,oCAWC;;AAfD,uCAAsF;AACtF,4CAAsD;AAGtD,SAA8B,iBAAiB;iEAAC,IAAU,EAAE,UAAoC,EAAE;QAChG,MAAM,gBAAgB,GAAG,IAAA,0BAAiB,EAAC,SAAS,EAAE,SAAS,CAAC,CAAA;QAChE,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,KAAK,IAAI,CAAA;QAE5C,MAAM,IAAA,2BAAmB,EAAC,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,gBAAgB,CAAC,CAAA;QAEhF,MAAM,IAAA,oBAAW,EAAC,IAAI,CAAC,CAAA;QAEvB,OAAO,GAAG,EAAE;YACV,IAAA,4BAAmB,EAAC,IAAI,CAAC,CAAA;QAC3B,CAAC,CAAA;IACH,CAAC;CAAA"}
1
+ {"version":3,"file":"generator.js","sourceRoot":"","sources":["../../../../../generators/api/src/config/generator.ts"],"names":[],"mappings":";;AAIA,oCAWC;;AAfD,uCAAsF;AACtF,4CAAsD;AAGtD,SAA8B,iBAAiB;iEAAC,IAAU,EAAE,UAAoC,EAAE;QAChG,MAAM,gBAAgB,GAAG,IAAA,0BAAiB,EAAC,SAAS,EAAE,SAAS,CAAC,CAAA;QAChE,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,KAAK,IAAI,CAAA;QAE5C,MAAM,IAAA,2BAAmB,EAAC,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,UAAU,EAAE,IAAI,EAAE,EAAE,gBAAgB,CAAC,CAAA;QAElG,MAAM,IAAA,oBAAW,EAAC,IAAI,CAAC,CAAA;QAEvB,OAAO,GAAG,EAAE;YACV,IAAA,4BAAmB,EAAC,IAAI,CAAC,CAAA;QAC3B,CAAC,CAAA;IACH,CAAC;CAAA"}
@@ -0,0 +1 @@
1
+ export * from './lib/graphql-select'
@@ -0,0 +1,52 @@
1
+ import graphqlFields from 'graphql-fields'
2
+ import { Prisma } from '@<%= npmScope %>/api/prisma'
3
+ import type { DMMF } from '@prisma/client/runtime/library'
4
+ import { GraphQLResolveInfo } from 'graphql/type'
5
+
6
+ const dmmf = Prisma.dmmf
7
+
8
+ function getNamedType(type: any): string {
9
+ if (type.ofType) return getNamedType(type.ofType)
10
+ return type.name
11
+ }
12
+
13
+ function getModelFromTypeName(typeName: string) {
14
+ return dmmf.datamodel.models.find(m => m.name === typeName)
15
+ }
16
+
17
+ function buildSelectTree(fieldTree: any, model: any): any {
18
+ const result: Record<string, any> = {}
19
+
20
+ for (const key in fieldTree) {
21
+ const field = model.fields.find((f: DMMF.Field) => f.name === key)
22
+ if (!field) continue
23
+
24
+ if (field.relationName && typeof fieldTree[key] === 'object') {
25
+ const relatedModel = dmmf.datamodel.models.find(m => m.name === field.type)
26
+ if (relatedModel) {
27
+ result[key] = {
28
+ select: buildSelectTree(fieldTree[key], relatedModel),
29
+ }
30
+ }
31
+ } else {
32
+ result[key] = true
33
+ }
34
+ }
35
+
36
+ return result
37
+ }
38
+
39
+ /**
40
+ * Automatically converts a GraphQL `info` object into a Prisma `select` object.
41
+ */
42
+ export function createSelect(info: GraphQLResolveInfo) {
43
+ const returnTypeName = getNamedType(info.returnType)
44
+ const model = getModelFromTypeName(returnTypeName)
45
+
46
+ if (!model) {
47
+ throw new Error(`Model "${returnTypeName}" not found in Prisma schema.`)
48
+ }
49
+
50
+ const rawFields = graphqlFields(info)
51
+ return buildSelectTree(rawFields, model)
52
+ }
@@ -16,12 +16,16 @@ function generateLibraries(tree_1) {
16
16
  '@nestjs/axios': '^3.0.0',
17
17
  '@prisma/client': '^6.9.0',
18
18
  '@apollo/server': '^4.9.0',
19
+ 'graphql-fields': '^2.0.3',
20
+ };
21
+ const devDependencies = {
22
+ '@types/graphql-fields': '^1.3.9',
19
23
  };
20
- const devDependencies = {};
21
24
  yield (0, utils_1.installPlugins)(tree, dependencies, devDependencies);
22
25
  yield (0, utils_1.apiLibraryGenerator)(tree, { name: 'core', overwrite }, templateRootPath, 'data-access');
23
26
  yield (0, utils_1.apiLibraryGenerator)(tree, { name: 'core', overwrite }, templateRootPath, 'feature', true);
24
27
  yield (0, utils_1.apiLibraryGenerator)(tree, { name: 'core', overwrite }, templateRootPath, 'models');
28
+ yield (0, utils_1.apiLibraryGenerator)(tree, { name: 'core', overwrite }, templateRootPath, 'helpers');
25
29
  yield (0, devkit_1.formatFiles)(tree);
26
30
  return () => {
27
31
  (0, devkit_1.installPackagesTask)(tree);
@@ -1 +1 @@
1
- {"version":3,"file":"generator.js","sourceRoot":"","sources":["../../../../../generators/api/src/core/generator.ts"],"names":[],"mappings":";;AAIA,oCA8BC;;AAlCD,uCAAyG;AACzG,4CAAsE;AAGtE,SAA8B,iBAAiB;iEAC7C,IAAU,EACV,UAAkC,EAAE;QAEpC,MAAM,gBAAgB,GAAG,IAAA,0BAAiB,EAAC,SAAS,EAAE,SAAS,CAAC,CAAA;QAChE,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,KAAK,IAAI,CAAA;QAE5C,MAAM,YAAY,GAAG;YACnB,mBAAmB,EAAE,QAAQ;YAC7B,iBAAiB,EAAE,SAAS;YAC5B,gBAAgB,EAAE,SAAS;YAC3B,kBAAkB,EAAE,SAAS;YAC7B,eAAe,EAAE,QAAQ;YACzB,gBAAgB,EAAE,QAAQ;YAC1B,gBAAgB,EAAE,QAAQ;SAC3B,CAAA;QAED,MAAM,eAAe,GAAG,EAAE,CAAA;QAE1B,MAAM,IAAA,sBAAc,EAAC,IAAI,EAAE,YAAY,EAAE,eAAe,CAAC,CAAA;QAEzD,MAAM,IAAA,2BAAmB,EAAC,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,gBAAgB,EAAE,aAAa,CAAC,CAAA;QAC7F,MAAM,IAAA,2BAAmB,EAAC,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,gBAAgB,EAAE,SAAS,EAAE,IAAI,CAAC,CAAA;QAC/F,MAAM,IAAA,2BAAmB,EAAC,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,gBAAgB,EAAE,QAAQ,CAAC,CAAA;QAExF,MAAM,IAAA,oBAAW,EAAC,IAAI,CAAC,CAAA;QAEvB,OAAO,GAAG,EAAE;YACV,IAAA,4BAAmB,EAAC,IAAI,CAAC,CAAA;QAC3B,CAAC,CAAA;IACH,CAAC;CAAA"}
1
+ {"version":3,"file":"generator.js","sourceRoot":"","sources":["../../../../../generators/api/src/core/generator.ts"],"names":[],"mappings":";;AAIA,oCAkCC;;AAtCD,uCAAyG;AACzG,4CAAsE;AAGtE,SAA8B,iBAAiB;iEAC7C,IAAU,EACV,UAAkC,EAAE;QAEpC,MAAM,gBAAgB,GAAG,IAAA,0BAAiB,EAAC,SAAS,EAAE,SAAS,CAAC,CAAA;QAChE,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,KAAK,IAAI,CAAA;QAE5C,MAAM,YAAY,GAAG;YACnB,mBAAmB,EAAE,QAAQ;YAC7B,iBAAiB,EAAE,SAAS;YAC5B,gBAAgB,EAAE,SAAS;YAC3B,kBAAkB,EAAE,SAAS;YAC7B,eAAe,EAAE,QAAQ;YACzB,gBAAgB,EAAE,QAAQ;YAC1B,gBAAgB,EAAE,QAAQ;YAC1B,gBAAgB,EAAE,QAAQ;SAC3B,CAAA;QAED,MAAM,eAAe,GAAG;YACtB,uBAAuB,EAAE,QAAQ;SAClC,CAAA;QAED,MAAM,IAAA,sBAAc,EAAC,IAAI,EAAE,YAAY,EAAE,eAAe,CAAC,CAAA;QAEzD,MAAM,IAAA,2BAAmB,EAAC,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,gBAAgB,EAAE,aAAa,CAAC,CAAA;QAC7F,MAAM,IAAA,2BAAmB,EAAC,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,gBAAgB,EAAE,SAAS,EAAE,IAAI,CAAC,CAAA;QAC/F,MAAM,IAAA,2BAAmB,EAAC,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,gBAAgB,EAAE,QAAQ,CAAC,CAAA;QACxF,MAAM,IAAA,2BAAmB,EAAC,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,gBAAgB,EAAE,SAAS,CAAC,CAAA;QAEzF,MAAM,IAAA,oBAAW,EAAC,IAAI,CAAC,CAAA;QAEvB,OAAO,GAAG,EAAE;YACV,IAAA,4BAAmB,EAAC,IAAI,CAAC,CAAA;QAC3B,CAAC,CAAA;IACH,CAAC;CAAA"}
@@ -1,6 +1,6 @@
1
1
  import { Injectable } from '@nestjs/common'
2
2
  import { ApiCoreDataAccessService } from '@<%= npmScope %>/api/core/data-access'
3
- import { PrismaSelect } from '@paljs/plugins'
3
+ import { createSelect } from '@<%= npmScope %>/api/core/helpers'
4
4
  import type { GraphQLResolveInfo } from 'graphql'
5
5
  import * as dto from './dto'
6
6
 
@@ -14,18 +14,16 @@ export class ApiCrudDataAccessService {
14
14
 
15
15
  <% for (const model of models) { %>
16
16
  async create<%= model.modelName.charAt(0).toUpperCase() + model.modelName.slice(1) %>(info: GraphQLResolveInfo, input: dto.Create<%= model.modelName %>Input) {
17
- const select = new PrismaSelect(info).value
18
17
  return this.data['<%= model.modelPropertyName %>'].create({
19
18
  data: input,
20
- ...select,
19
+ select: createSelect(info),
21
20
  });
22
21
  }
23
22
 
24
23
  async <%= (model.pluralModelName === model.modelName ? model.pluralModelName + 'List' : model.pluralModelName).charAt(0).toLowerCase() + (model.pluralModelName === model.modelName ? model.pluralModelName + 'List' : model.pluralModelName).slice(1) %>(info: GraphQLResolveInfo, input?: dto.List<%= model.modelName %>Input) {
25
- const select = new PrismaSelect(info).value
26
24
  return this.data['<%= model.modelPropertyName %>'].findMany({
27
25
  ...this.data.filter(input),
28
- ...select,
26
+ select: createSelect(info),
29
27
  });
30
28
  }
31
29
 
@@ -47,19 +45,17 @@ export class ApiCrudDataAccessService {
47
45
  }
48
46
 
49
47
  async <%= model.modelName.charAt(0).toLowerCase() + model.modelName.slice(1) %>(info: GraphQLResolveInfo, id: string) {
50
- const select = new PrismaSelect(info).value
51
48
  return this.data['<%= model.modelPropertyName %>'].findUnique({
52
49
  where: { id },
53
- ...select,
50
+ select: createSelect(info),
54
51
  });
55
52
  }
56
53
 
57
54
  async update<%= model.modelName.charAt(0).toUpperCase() + model.modelName.slice(1) %>(info: GraphQLResolveInfo, id: string, input: dto.Update<%= model.modelName %>Input) {
58
- const select = new PrismaSelect(info).value
59
55
  return this.data['<%= model.modelPropertyName %>'].update({
60
56
  where: { id },
61
57
  data: input,
62
- ...select,
58
+ select: createSelect(info),
63
59
  });
64
60
  }
65
61
 
@@ -6,26 +6,19 @@ let usesInt = false;
6
6
  let usesFloat = false;
7
7
  let usesID = false;
8
8
  let enumNames = new Set();
9
+ let usesPartialType = false;
10
+ const alwaysOptionalFields = ['id', 'createdAt', 'updatedAt'];
9
11
 
10
12
  // First pass to determine necessary imports and enums
11
13
  for (const model of models) {
12
14
  for (const field of model.fields) {
15
+ if (field.kind === 'object') continue; // Skip relation fields entirely
13
16
  if (field.type === 'Int') usesInt = true;
14
17
  if (field.type === 'Float' || field.type === 'Decimal') usesFloat = true;
15
18
  if (field.type === 'Json') usesGraphQLJSON = true;
16
-
17
- if (field.type === 'ID') { // Explicit ID field
18
- usesID = true;
19
- } else if (field.kind === 'object') {
20
- // Check if a corresponding scalar ID field (e.g., 'userId') exists for this object field (e.g., 'user')
21
- const correspondingIdFieldName = `${field.name}Id`;
22
- const hasCorrespondingIdField = model.fields.some(f => f.name === correspondingIdFieldName && f.kind !== 'object');
23
- if (!hasCorrespondingIdField) {
24
- // If no pre-existing '...Id' scalar, we'll generate one, so 'ID' import is needed.
25
- usesID = true;
26
- }
27
- } else if (field.kind === 'enum') {
28
- enumNames.add(field.type);
19
+ if (field.type === 'ID') usesID = true;
20
+ if (field.kind === 'enum') {
21
+ enumNames.add(field.type);
29
22
  }
30
23
  }
31
24
  }
@@ -33,9 +26,9 @@ for (const model of models) {
33
26
  if (usesInt) gqlImports.add('Int');
34
27
  if (usesFloat) gqlImports.add('Float');
35
28
  if (usesID) gqlImports.add('ID');
29
+ usesPartialType = models.length > 0; // If we generate any Update input, we need PartialType
36
30
  %>
37
31
  import { <%= Array.from(gqlImports).join(', ') %> } from '@nestjs/graphql'
38
-
39
32
  <% if (enumNames.size > 0) { %>import { <%= Array.from(enumNames).join(', ') %> } from '@<%= npmScope %>/api/core/models'
40
33
  <% } %><% if (usesGraphQLJSON) { %>import { GraphQLJSON } from 'graphql-type-json'<% } %>
41
34
  import { CorePagingInput } from '@<%= npmScope %>/api/core/data-access'
@@ -44,180 +37,118 @@ import { CorePagingInput } from '@<%= npmScope %>/api/core/data-access'
44
37
  @InputType()
45
38
  export class Create<%= model.modelName %>Input {
46
39
  <% for (const field of model.fields) { %>
40
+ <% if (field.kind === 'object') { continue; } %>
47
41
  <%
48
- let shouldSkipField = false;
49
42
  let baseGqlType;
50
43
  let tsType;
51
- let effectiveFieldName = field.name;
52
-
53
- if (field.kind === 'object') {
54
- const correspondingIdFieldName = `${field.name}Id`;
55
- const hasCorrespondingIdField = model.fields.some(f => f.name === correspondingIdFieldName && f.kind !== 'object');
56
- if (hasCorrespondingIdField) {
57
- shouldSkipField = true; // Skip this object field; its ID is handled by the existing scalar field.
58
- } else {
59
- // No corresponding '...Id' scalar found, so generate an ID field for this relation.
60
- baseGqlType = 'ID';
61
- tsType = 'string';
62
- effectiveFieldName = correspondingIdFieldName;
63
- }
44
+ if (field.type === 'String') { baseGqlType = 'String'; tsType = 'string'; }
45
+ else if (field.type === 'Int') { baseGqlType = 'Int'; tsType = 'number'; }
46
+ else if (field.type === 'Float') { baseGqlType = 'Float'; tsType = 'number'; }
47
+ else if (field.type === 'Decimal') { baseGqlType = 'Float'; tsType = 'number'; }
48
+ else if (field.type === 'Boolean') { baseGqlType = 'Boolean'; tsType = 'boolean'; }
49
+ else if (field.type === 'DateTime') { baseGqlType = 'Date'; tsType = 'Date'; }
50
+ else if (field.type === 'Json') { baseGqlType = 'GraphQLJSON'; tsType = 'typeof GraphQLJSON'; }
51
+ else if (field.type === 'ID') { baseGqlType = 'ID'; tsType = 'string'; }
52
+ else if (field.kind === 'enum') {
53
+ baseGqlType = field.type;
54
+ tsType = field.type;
64
55
  } else {
65
- // Handle non-object (scalar, enum, or explicit ID) fields
66
- effectiveFieldName = field.name;
67
- if (field.type === 'String') { baseGqlType = 'String'; tsType = 'string'; }
68
- else if (field.type === 'Int') { baseGqlType = 'Int'; tsType = 'number'; }
69
- else if (field.type === 'Float') { baseGqlType = 'Float'; tsType = 'number'; }
70
- else if (field.type === 'Decimal') { baseGqlType = 'Float'; tsType = 'number'; }
71
- else if (field.type === 'Boolean') { baseGqlType = 'Boolean'; tsType = 'boolean'; }
72
- else if (field.type === 'DateTime') { baseGqlType = 'Date'; tsType = 'Date'; }
73
- else if (field.type === 'Json') { baseGqlType = 'GraphQLJSON'; tsType = 'typeof GraphQLJSON'; }
74
- else if (field.type === 'ID') { baseGqlType = 'ID'; tsType = 'string'; }
75
- else if (field.kind === 'enum') {
76
- baseGqlType = field.type;
77
- tsType = field.type;
78
- } else { // Fallback, should ideally not be reached if all model types are known
79
- baseGqlType = 'String'; tsType = 'string';
80
- }
56
+ baseGqlType = 'String'; tsType = 'string';
81
57
  }
82
-
83
58
  let fieldDecoratorTypeArg = '';
84
59
  let finalTsType = tsType;
85
-
86
- if (!shouldSkipField) {
87
- if (field.isList) { // Use original field's isList property
88
- fieldDecoratorTypeArg = `() => [${baseGqlType}]`; // baseGqlType is 'ID' if transformed from object list
89
- finalTsType = tsType + '[]'; // tsType is 'string' for ID, so 'string[]'
90
- } else {
91
- // For non-list fields (scalars or single objects transformed to ID)
92
- if (baseGqlType !== 'String' && baseGqlType !== 'Boolean') {
93
- fieldDecoratorTypeArg = `() => ${baseGqlType}`;
94
- }
95
- // finalTsType is already 'tsType', which is correct
96
- }
60
+ let isOptional = false;
61
+ if (field.isList) {
62
+ fieldDecoratorTypeArg = `() => [${baseGqlType}]`;
63
+ finalTsType = tsType + '[]';
64
+ } else {
65
+ if (baseGqlType !== 'String' && baseGqlType !== 'Boolean') {
66
+ fieldDecoratorTypeArg = `() => ${baseGqlType}`;
67
+ }
68
+ }
69
+ // Always optional for id, createdAt, updatedAt
70
+ if (alwaysOptionalFields.includes(field.name)) {
71
+ isOptional = true;
72
+ } else {
73
+ isOptional = !field.isRequired;
97
74
  }
98
75
  %>
99
- <% if (!shouldSkipField) { %>
100
- @Field(<% if (fieldDecoratorTypeArg) { %><%- fieldDecoratorTypeArg %>, <% } %>{ nullable: true })
101
- <%= effectiveFieldName %>?: <%= finalTsType %>
102
- <% } %>
76
+ @Field(<% if (fieldDecoratorTypeArg) { %><%- fieldDecoratorTypeArg %>, <% } %>{ nullable: <%= isOptional ? 'true' : 'false' %> })
77
+ <%= field.name %><%= isOptional ? '?' : '!' %>: <%= finalTsType %>
103
78
  <% } %>
104
79
  }
105
80
 
106
81
  @InputType()
107
82
  export class Update<%= model.modelName %>Input {
108
83
  <% for (const field of model.fields) { %>
84
+ <% if (field.kind === 'object') { continue; } %>
109
85
  <%
110
- let shouldSkipField = false;
111
86
  let baseGqlType;
112
87
  let tsType;
113
- let effectiveFieldName = field.name;
114
-
115
- if (field.kind === 'object') {
116
- const correspondingIdFieldName = `${field.name}Id`;
117
- const hasCorrespondingIdField = model.fields.some(f => f.name === correspondingIdFieldName && f.kind !== 'object');
118
- if (hasCorrespondingIdField) {
119
- shouldSkipField = true;
120
- } else {
121
- baseGqlType = 'ID';
122
- tsType = 'string';
123
- effectiveFieldName = correspondingIdFieldName;
124
- }
88
+ if (field.type === 'String') { baseGqlType = 'String'; tsType = 'string'; }
89
+ else if (field.type === 'Int') { baseGqlType = 'Int'; tsType = 'number'; }
90
+ else if (field.type === 'Float') { baseGqlType = 'Float'; tsType = 'number'; }
91
+ else if (field.type === 'Decimal') { baseGqlType = 'Float'; tsType = 'number'; }
92
+ else if (field.type === 'Boolean') { baseGqlType = 'Boolean'; tsType = 'boolean'; }
93
+ else if (field.type === 'DateTime') { baseGqlType = 'Date'; tsType = 'Date'; }
94
+ else if (field.type === 'Json') { baseGqlType = 'GraphQLJSON'; tsType = 'typeof GraphQLJSON'; }
95
+ else if (field.type === 'ID') { baseGqlType = 'ID'; tsType = 'string'; }
96
+ else if (field.kind === 'enum') {
97
+ baseGqlType = field.type;
98
+ tsType = field.type;
125
99
  } else {
126
- effectiveFieldName = field.name;
127
- if (field.type === 'String') { baseGqlType = 'String'; tsType = 'string'; }
128
- else if (field.type === 'Int') { baseGqlType = 'Int'; tsType = 'number'; }
129
- else if (field.type === 'Float') { baseGqlType = 'Float'; tsType = 'number'; }
130
- else if (field.type === 'Decimal') { baseGqlType = 'Float'; tsType = 'number'; }
131
- else if (field.type === 'Boolean') { baseGqlType = 'Boolean'; tsType = 'boolean'; }
132
- else if (field.type === 'DateTime') { baseGqlType = 'Date'; tsType = 'Date'; }
133
- else if (field.type === 'Json') { baseGqlType = 'GraphQLJSON'; tsType = 'typeof GraphQLJSON'; }
134
- else if (field.type === 'ID') { baseGqlType = 'ID'; tsType = 'string'; }
135
- else if (field.kind === 'enum') {
136
- baseGqlType = field.type;
137
- tsType = field.type;
138
- } else {
139
- baseGqlType = 'String'; tsType = 'string';
140
- }
100
+ baseGqlType = 'String'; tsType = 'string';
141
101
  }
142
-
143
102
  let fieldDecoratorTypeArg = '';
144
103
  let finalTsType = tsType;
145
-
146
- if (!shouldSkipField) {
147
- if (field.isList) {
148
- fieldDecoratorTypeArg = `() => [${baseGqlType}]`;
149
- finalTsType = tsType + '[]';
150
- } else {
151
- if (baseGqlType !== 'String' && baseGqlType !== 'Boolean') {
152
- fieldDecoratorTypeArg = `() => ${baseGqlType}`;
153
- }
154
- }
104
+ if (field.isList) {
105
+ fieldDecoratorTypeArg = `() => [${baseGqlType}]`;
106
+ finalTsType = tsType + '[]';
107
+ } else {
108
+ if (baseGqlType !== 'String' && baseGqlType !== 'Boolean') {
109
+ fieldDecoratorTypeArg = `() => ${baseGqlType}`;
110
+ }
155
111
  }
156
112
  %>
157
- <% if (!shouldSkipField) { %>
158
113
  @Field(<% if (fieldDecoratorTypeArg) { %><%- fieldDecoratorTypeArg %>, <% } %>{ nullable: true })
159
- <%= effectiveFieldName %>?: <%= finalTsType %>
160
- <% } %>
114
+ <%= field.name %>?: <%= finalTsType %>
161
115
  <% } %>
162
116
  }
163
117
 
164
118
  @InputType()
165
119
  export class List<%= model.modelName %>Input extends CorePagingInput {
166
120
  <% for (const field of model.fields) { %>
121
+ <% if (field.kind === 'object') { continue; } %>
167
122
  <%
168
- let shouldSkipField = false;
169
123
  let baseGqlType;
170
124
  let tsType;
171
- let effectiveFieldName = field.name;
172
-
173
- if (field.kind === 'object') {
174
- const correspondingIdFieldName = `${field.name}Id`;
175
- const hasCorrespondingIdField = model.fields.some(f => f.name === correspondingIdFieldName && f.kind !== 'object');
176
- if (hasCorrespondingIdField) {
177
- shouldSkipField = true;
178
- } else {
179
- // For ListInput, if no direct ...Id field, we create one for filtering by relation ID
180
- baseGqlType = 'ID';
181
- tsType = 'string';
182
- effectiveFieldName = correspondingIdFieldName;
183
- }
125
+ if (field.type === 'String') { baseGqlType = 'String'; tsType = 'string'; }
126
+ else if (field.type === 'Int') { baseGqlType = 'Int'; tsType = 'number'; }
127
+ else if (field.type === 'Float') { baseGqlType = 'Float'; tsType = 'number'; }
128
+ else if (field.type === 'Decimal') { baseGqlType = 'Float'; tsType = 'number'; }
129
+ else if (field.type === 'Boolean') { baseGqlType = 'Boolean'; tsType = 'boolean'; }
130
+ else if (field.type === 'DateTime') { baseGqlType = 'Date'; tsType = 'Date'; }
131
+ else if (field.type === 'Json') { baseGqlType = 'GraphQLJSON'; tsType = 'typeof GraphQLJSON'; }
132
+ else if (field.type === 'ID') { baseGqlType = 'ID'; tsType = 'string'; }
133
+ else if (field.kind === 'enum') {
134
+ baseGqlType = field.type;
135
+ tsType = field.type;
184
136
  } else {
185
- // Handle non-object fields for filtering
186
- effectiveFieldName = field.name;
187
- if (field.type === 'String') { baseGqlType = 'String'; tsType = 'string'; }
188
- else if (field.type === 'Int') { baseGqlType = 'Int'; tsType = 'number'; }
189
- else if (field.type === 'Float') { baseGqlType = 'Float'; tsType = 'number'; }
190
- else if (field.type === 'Decimal') { baseGqlType = 'Float'; tsType = 'number'; }
191
- else if (field.type === 'Boolean') { baseGqlType = 'Boolean'; tsType = 'boolean'; }
192
- else if (field.type === 'DateTime') { baseGqlType = 'Date'; tsType = 'Date'; }
193
- else if (field.type === 'Json') { baseGqlType = 'GraphQLJSON'; tsType = 'typeof GraphQLJSON'; }
194
- else if (field.type === 'ID') { baseGqlType = 'ID'; tsType = 'string'; }
195
- else if (field.kind === 'enum') {
196
- baseGqlType = field.type;
197
- tsType = field.type;
198
- } else {
199
- baseGqlType = 'String'; tsType = 'string';
200
- }
137
+ baseGqlType = 'String'; tsType = 'string';
201
138
  }
202
-
203
139
  let fieldDecoratorTypeArg = '';
204
140
  let finalTsType = tsType;
205
-
206
- if (!shouldSkipField) {
207
- if (field.isList) {
208
- fieldDecoratorTypeArg = `() => [${baseGqlType}]`;
209
- finalTsType = tsType + '[]';
210
- } else {
211
- if (baseGqlType !== 'String' && baseGqlType !== 'Boolean') {
212
- fieldDecoratorTypeArg = `() => ${baseGqlType}`;
213
- }
214
- }
141
+ if (field.isList) {
142
+ fieldDecoratorTypeArg = `() => [${baseGqlType}]`;
143
+ finalTsType = tsType + '[]';
144
+ } else {
145
+ if (baseGqlType !== 'String' && baseGqlType !== 'Boolean') {
146
+ fieldDecoratorTypeArg = `() => ${baseGqlType}`;
147
+ }
215
148
  }
216
149
  %>
217
- <% if (!shouldSkipField) { %>
218
150
  @Field(<% if (fieldDecoratorTypeArg) { %><%- fieldDecoratorTypeArg %>, <% } %>{ nullable: true })
219
- <%= effectiveFieldName %>?: <%= finalTsType %>
220
- <% } %>
151
+ <%= field.name %>?: <%= finalTsType %>
221
152
  <% } %>
222
153
  }
223
154
 
@@ -22,7 +22,6 @@ function apiSetupGenerator(tree) {
22
22
  '@nestjs/jwt': '^11.0.0',
23
23
  '@nestjs/passport': '^11.0.5',
24
24
  '@nestjs/platform-express': '^11.1.3',
25
- '@paljs/plugins': '^8.2.0',
26
25
  axios: '^1.9.0',
27
26
  bcryptjs: '^3.0.2',
28
27
  express: '^5.1.0',
@@ -44,11 +43,11 @@ function apiSetupGenerator(tree) {
44
43
  'cookie-parser': '^1.4.7',
45
44
  'passport-jwt': '^4.0.1',
46
45
  }, {
47
- nx: '21.2.0',
48
- '@nx/js': '21.2.0',
49
- '@nx/nest': '21.2.0',
50
- '@nx/node': '21.2.0',
51
- '@nx/webpack': '21.2.0',
46
+ nx: '21.2.1',
47
+ '@nx/js': '21.2.1',
48
+ '@nx/nest': '21.2.1',
49
+ '@nx/node': '21.2.1',
50
+ '@nx/webpack': '21.2.1',
52
51
  '@nestjs/schematics': '^11.0.5',
53
52
  '@nestjs/testing': '^11.1.3',
54
53
  '@prisma/extension-optimize': '2.0.0',
@@ -1 +1 @@
1
- {"version":3,"file":"generator.js","sourceRoot":"","sources":["../../../../../generators/api/src/setup/generator.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"generator.js","sourceRoot":"","sources":["../../../../../generators/api/src/setup/generator.ts"],"names":[],"mappings":";;AASA,8CA8FC;;AAvGD,uCAAkF;AAClF,4CAAiF;AAEjF,SAAS,WAAW,CAAC,IAAU;IAC7B,MAAM,SAAS,GAAG,QAAQ,CAAA;IAC1B,MAAM,OAAO,GAAG,oCAAoC,CAAA;IACpD,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,OAAO,CAAC,CAAA;AAChC,CAAC;AAED,SAAsB,iBAAiB,CAAC,IAAU;;QAChD,mBAAmB;QACnB,IAAA,qCAA4B,EAC1B,IAAI,EACJ;YACE,gBAAgB,EAAE,SAAS;YAC3B,eAAe,EAAE,QAAQ;YACzB,gBAAgB,EAAE,SAAS;YAC3B,gBAAgB,EAAE,QAAQ;YAC1B,cAAc,EAAE,SAAS;YACzB,iBAAiB,EAAE,SAAS;YAC5B,aAAa,EAAE,SAAS;YACxB,kBAAkB,EAAE,SAAS;YAC7B,0BAA0B,EAAE,SAAS;YACrC,KAAK,EAAE,QAAQ;YACf,QAAQ,EAAE,QAAQ;YAClB,OAAO,EAAE,QAAQ;YACjB,OAAO,EAAE,UAAU;YACnB,0BAA0B,EAAE,OAAO;YACnC,iBAAiB,EAAE,SAAS;YAC5B,uBAAuB,EAAE,QAAQ;YACjC,YAAY,EAAE,QAAQ;YACtB,GAAG,EAAE,UAAU;YACf,UAAU,EAAE,QAAQ;YACpB,kBAAkB,EAAE,QAAQ;YAC5B,IAAI,EAAE,QAAQ;YACd,cAAc,EAAE,aAAa;YAC7B,gBAAgB,EAAE,QAAQ;YAC1B,iBAAiB,EAAE,SAAS;YAC5B,mBAAmB,EAAE,QAAQ;YAC7B,6BAA6B,EAAE,QAAQ;YACvC,OAAO,EAAE,QAAQ;YACjB,eAAe,EAAE,QAAQ;YACzB,cAAc,EAAE,QAAQ;SACzB,EACD;YACE,EAAE,EAAE,QAAQ;YACZ,QAAQ,EAAE,QAAQ;YAClB,UAAU,EAAE,QAAQ;YACpB,UAAU,EAAE,QAAQ;YACpB,aAAa,EAAE,QAAQ;YACvB,oBAAoB,EAAE,SAAS;YAC/B,iBAAiB,EAAE,SAAS;YAC5B,4BAA4B,EAAE,OAAO;YACrC,oBAAoB,EAAE,UAAU;YAChC,UAAU,EAAE,QAAQ;YACpB,WAAW,EAAE,SAAS;YACtB,sBAAsB,EAAE,QAAQ;YAChC,gBAAgB,EAAE,QAAQ;YAC1B,mBAAmB,EAAE,QAAQ;YAC7B,qBAAqB,EAAE,QAAQ;YAC/B,aAAa,EAAE,SAAS;YACxB,mBAAmB,EAAE,QAAQ;YAC7B,YAAY,EAAE,SAAS;YACvB,IAAI,EAAE,SAAS;YACf,uBAAuB,EAAE,SAAS;YAClC,EAAE,EAAE,QAAQ;YACZ,MAAM,EAAE,QAAQ;YAChB,SAAS,EAAE,QAAQ;YACnB,IAAI,EAAE,QAAQ;YACd,WAAW,EAAE,QAAQ;YACrB,aAAa,EAAE,QAAQ;YACvB,wBAAwB,EAAE,QAAQ;YAClC,+BAA+B,EAAE,QAAQ;YACzC,6BAA6B,EAAE,QAAQ;YACvC,mBAAmB,EAAE,QAAQ;SAC9B,CACF,CAAA;QAED,qDAAqD;QACrD,MAAM,eAAe,GAAG;YACtB,oBAAoB;YACpB,iBAAiB;YACjB,gBAAgB;YAChB,4BAA4B;YAC5B,iBAAiB;YACjB,SAAS;YACT,IAAI;YACJ,QAAQ;YACR,SAAS;YACT,6BAA6B;YAC7B,cAAc;YACd,cAAc;YACd,SAAS;YACT,eAAe;YACf,WAAW;SACZ,CAAA;QACD,IAAA,iCAAyB,EAAC,IAAI,EAAE,EAAE,qBAAqB,EAAE,eAAe,EAAE,CAAC,CAAA;QAE3E,iDAAiD;QACjD,WAAW,CAAC,IAAI,CAAC,CAAA;QAEjB,gEAAgE;QAChE,OAAO,IAAA,2BAAmB,GAAE,CAAA;IAC9B,CAAC;CAAA;AAED,kBAAe,iBAAiB,CAAA"}
@@ -1,66 +0,0 @@
1
- import { registerAs } from '@nestjs/config'
2
- import Joi from 'joi'
3
-
4
- export const appConfig = registerAs('app', () => ({
5
- prefix: 'api',
6
- environment: process.env.NODE_ENV,
7
- host: process.env.HOST,
8
- port: process.env.PORT ? parseInt(process.env.PORT, 10) : 3000,
9
- apiUrl: process.env.API_URL,
10
- webPort: process.env.WEB_PORT ? parseInt(process.env.WEB_PORT, 10) : 4200,
11
- api: {
12
- cookie: {
13
- name: process.env.API_COOKIE_NAME,
14
- secret: process.env.API_COOKIE_SECRET,
15
- options: {
16
- domain: process.env.API_COOKIE_DOMAIN,
17
- httpOnly: true,
18
- secure: true,
19
- sameSite: 'none',
20
- path: '/',
21
- },
22
- },
23
- cors: {
24
- origin: [process.env.SITE_URL],
25
- },
26
- },
27
- siteUrl: process.env.SITE_URL || (process.env.API_URL ? process.env.API_URL.replace('/api', '') : ''),
28
- app: {
29
- email: process.env.APP_EMAIL,
30
- supportEmail: process.env.APP_SUPPORT_EMAIL,
31
- adminEmails: process.env.APP_ADMIN_EMAILS,
32
- name: process.env.APP_NAME,
33
- },
34
- smtp: {
35
- host: process.env.SMTP_HOST,
36
- port: process.env.SMTP_PORT ? parseInt(process.env.SMTP_PORT, 10) : 587,
37
- user: process.env.SMTP_USER,
38
- pass: process.env.SMTP_PASS,
39
- ignoreTLS: true,
40
- },
41
- twilio: {
42
- accountSid: process.env.TWILIO_ACCOUNT_SID,
43
- authToken: process.env.TWILIO_AUTH_TOKEN,
44
- fromNumber: process.env.TWILIO_FROM_NUMBER,
45
- },
46
- }))
47
-
48
- export const validationSchema = Joi.object({
49
- NODE_ENV: Joi.string().valid('development', 'production', 'test'),
50
- HOST: Joi.string().alphanum().default('localhost'),
51
- PORT: Joi.number().default(3000),
52
- WEB_PORT: Joi.number().default(4200),
53
- WEB_URL: Joi.string().default(`http://${process.env.HOST || 'localhost'}:${process.env.WEB_PORT}`),
54
- API_COOKIE_DOMAIN: Joi.string().default('localhost'),
55
- API_COOKIE_NAME: Joi.string().default('__session'),
56
- API_URL: Joi.string().default(`http://${process.env.HOST || 'localhost'}:${process.env.PORT}/api`),
57
- APP_NAME: Joi.string().required(),
58
- APP_EMAIL: Joi.string().email().required(),
59
- APP_SUPPORT_EMAIL: Joi.string().email().required(),
60
- APP_ADMIN_EMAILS: Joi.string().required(),
61
- SITE_URL: Joi.string().uri().required(),
62
- SMTP_HOST: Joi.string().required(),
63
- SMTP_PORT: Joi.string().required(),
64
- SMTP_USER: Joi.string().required(),
65
- SMTP_PASS: Joi.string().required(),
66
- })