@autobe/utils 0.29.2 → 0.30.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.
Files changed (48) hide show
  1. package/lib/AutoBeEscaper.d.ts +4 -0
  2. package/lib/AutoBeEscaper.js +85 -0
  3. package/lib/AutoBeEscaper.js.map +1 -0
  4. package/lib/StringUtil.d.ts +1 -0
  5. package/lib/StringUtil.js +15 -36
  6. package/lib/StringUtil.js.map +1 -1
  7. package/lib/aggregate/AutoBeProcessAggregateFactory.js +9 -0
  8. package/lib/aggregate/AutoBeProcessAggregateFactory.js.map +1 -1
  9. package/lib/index.d.ts +1 -0
  10. package/lib/index.js +1 -0
  11. package/lib/index.js.map +1 -1
  12. package/lib/interface/AutoBeOpenApiEndpointComparator.d.ts +1 -0
  13. package/lib/interface/AutoBeOpenApiEndpointComparator.js +4 -0
  14. package/lib/interface/AutoBeOpenApiEndpointComparator.js.map +1 -1
  15. package/lib/interface/AutoBeOpenApiTypeChecker.d.ts +14 -0
  16. package/lib/interface/AutoBeOpenApiTypeChecker.js +67 -0
  17. package/lib/interface/AutoBeOpenApiTypeChecker.js.map +1 -1
  18. package/lib/interface/invertOpenApiDocument.d.ts +1 -1
  19. package/lib/interface/invertOpenApiDocument.js +22 -7
  20. package/lib/interface/invertOpenApiDocument.js.map +1 -1
  21. package/lib/interface/missedOpenApiSchemas.js +3 -3
  22. package/lib/interface/missedOpenApiSchemas.js.map +1 -1
  23. package/lib/interface/revertOpenApiAccessor.js +2 -2
  24. package/lib/interface/revertOpenApiAccessor.js.map +1 -1
  25. package/lib/interface/transformOpenApiDocument.d.ts +2 -2
  26. package/lib/interface/transformOpenApiDocument.js +14 -11
  27. package/lib/interface/transformOpenApiDocument.js.map +1 -1
  28. package/lib/prisma/writePrismaApplication.d.ts +2 -2
  29. package/lib/prisma/writePrismaApplication.js +38 -29
  30. package/lib/prisma/writePrismaApplication.js.map +1 -1
  31. package/lib/test/validateTestExpression.js +3 -1
  32. package/lib/test/validateTestExpression.js.map +1 -1
  33. package/lib/test/validateTestStatement.js +3 -1
  34. package/lib/test/validateTestStatement.js.map +1 -1
  35. package/package.json +5 -5
  36. package/src/AutoBeEscaper.ts +83 -0
  37. package/src/StringUtil.ts +16 -41
  38. package/src/aggregate/AutoBeProcessAggregateFactory.ts +9 -0
  39. package/src/index.ts +1 -0
  40. package/src/interface/AutoBeOpenApiEndpointComparator.ts +7 -0
  41. package/src/interface/AutoBeOpenApiTypeChecker.ts +84 -0
  42. package/src/interface/invertOpenApiDocument.ts +21 -9
  43. package/src/interface/missedOpenApiSchemas.ts +1 -1
  44. package/src/interface/revertOpenApiAccessor.ts +2 -2
  45. package/src/interface/transformOpenApiDocument.ts +18 -15
  46. package/src/prisma/writePrismaApplication.ts +80 -63
  47. package/src/test/validateTestExpression.ts +7 -1
  48. package/src/test/validateTestStatement.ts +7 -1
@@ -1,10 +1,6 @@
1
1
  import { AutoBeOpenApi } from "@autobe/interface";
2
- import {
3
- HttpMigration,
4
- IHttpMigrateApplication,
5
- OpenApi,
6
- OpenApiTypeChecker,
7
- } from "@samchon/openapi";
2
+ import { IHttpMigrateApplication, OpenApi } from "@typia/interface";
3
+ import { HttpMigration, OpenApiTypeChecker } from "@typia/utils";
8
4
 
9
5
  export function invertOpenApiDocument(
10
6
  document: OpenApi.IDocument,
@@ -16,18 +12,24 @@ export function invertOpenApiDocument(
16
12
  .map(
17
13
  (r) =>
18
14
  ({
19
- specification: empty("specification"),
20
15
  authorizationType: null,
21
16
  method: r.method as "post",
22
17
  path: r.path,
23
- summary: r.operation().summary ?? empty("summary"),
24
- description: r.operation().description ?? empty("description"),
18
+ description:
19
+ writeDescription(r.operation()) ?? empty("description"),
20
+ specification: r.operation()
21
+ ? // biome-ignore lint: intended
22
+ ((r.operation() as any)["x-autobe-specification"] ??
23
+ empty("x-autobe-specification"))
24
+ : empty("x-autobe-specification"),
25
+ accessor: r.accessor,
25
26
  parameters: r.parameters.map(
26
27
  (p) =>
27
28
  ({
28
29
  name: p.name,
29
30
  description:
30
31
  p.parameter().description ?? empty("description"),
32
+ // biome-ignore lint: intended
31
33
  schema: p.schema as any,
32
34
  }) satisfies AutoBeOpenApi.IParameter,
33
35
  ),
@@ -63,6 +65,16 @@ export function invertOpenApiDocument(
63
65
  };
64
66
  }
65
67
 
68
+ function writeDescription(operation: OpenApi.IOperation): string | undefined {
69
+ if (operation.summary === undefined && operation.description === undefined)
70
+ return undefined;
71
+ if (operation.summary === undefined) return operation.description;
72
+ else if (operation.description === undefined) return operation.summary;
73
+ else if (operation.description.startsWith(operation.summary))
74
+ return operation.description;
75
+ return `${operation.summary}${operation.summary.endsWith(".") ? "" : "."}\n\n${operation.description}`;
76
+ }
77
+
66
78
  function empty(key: string): string {
67
79
  return `Describe ${key} as much as possible with clear and concise words.`;
68
80
  }
@@ -1,5 +1,5 @@
1
1
  import { AutoBeOpenApi } from "@autobe/interface";
2
- import { OpenApiTypeChecker } from "@samchon/openapi";
2
+ import { OpenApiTypeChecker } from "@typia/utils";
3
3
 
4
4
  export const missedOpenApiSchemas = (
5
5
  document: AutoBeOpenApi.IDocument,
@@ -1,10 +1,10 @@
1
1
  import { AutoBeOpenApi } from "@autobe/interface";
2
2
  import {
3
- HttpMigration,
4
3
  IHttpMigrateApplication,
5
4
  IHttpMigrateRoute,
6
5
  OpenApi,
7
- } from "@samchon/openapi";
6
+ } from "@typia/interface";
7
+ import { HttpMigration } from "@typia/utils";
8
8
 
9
9
  import { transformOpenApiDocument } from "./transformOpenApiDocument";
10
10
 
@@ -1,16 +1,17 @@
1
1
  import { AutoBeOpenApi } from "@autobe/interface";
2
2
  import {
3
- HttpMigration,
4
3
  IHttpMigrateApplication,
5
4
  OpenApi,
6
- OpenApiV3_1,
7
- } from "@samchon/openapi";
5
+ OpenApiV3_2,
6
+ } from "@typia/interface";
7
+ import { HttpMigration, OpenApiConverter } from "@typia/utils";
8
8
  import { HashMap } from "tstl";
9
9
 
10
+ import { StringUtil } from "../StringUtil";
10
11
  import { AutoBeOpenApiEndpointComparator } from "./AutoBeOpenApiEndpointComparator";
11
12
 
12
13
  export function transformOpenApiDocument(
13
- document: AutoBeOpenApi.IDocument,
14
+ input: AutoBeOpenApi.IDocument,
14
15
  ): OpenApi.IDocument {
15
16
  const dict: HashMap<AutoBeOpenApi.IEndpoint, string> = new HashMap(
16
17
  AutoBeOpenApiEndpointComparator.hashCode,
@@ -18,11 +19,11 @@ export function transformOpenApiDocument(
18
19
  );
19
20
  const paths: Record<string, OpenApi.IPath> = {};
20
21
 
21
- for (const op of document.operations) {
22
+ for (const op of input.operations) {
22
23
  dict.set(op, op.name);
23
24
  paths[op.path] ??= {};
24
25
  paths[op.path][op.method] = {
25
- summary: op.summary,
26
+ summary: StringUtil.summary(op.description),
26
27
  description:
27
28
  op.description +
28
29
  (op.authorizationType !== null &&
@@ -33,8 +34,8 @@ export function transformOpenApiDocument(
33
34
  name: p.name,
34
35
  in: "path",
35
36
  schema: p.schema,
36
- description: p.description,
37
37
  required: true,
38
+ description: p.description,
38
39
  })),
39
40
  requestBody: op.requestBody
40
41
  ? {
@@ -64,28 +65,30 @@ export function transformOpenApiDocument(
64
65
  }
65
66
  : undefined,
66
67
  ...{
68
+ "x-autobe-authorization-type": op.authorizationType,
69
+ "x-autobe-authorization-actor": op.authorizationActor,
67
70
  "x-autobe-prerequisites": op.prerequisites,
68
- "x-autobe-specification": op.specification,
69
71
  "x-samchon-accessor": op.accessor,
72
+ "x-autobe-specification": op.specification,
70
73
  },
71
74
  };
72
75
  }
73
76
 
74
- const result: OpenApi.IDocument = OpenApi.convert({
75
- openapi: "3.1.0",
77
+ const document: OpenApi.IDocument = OpenApiConverter.upgradeDocument({
78
+ openapi: "3.2.0",
76
79
  paths,
77
- components: document.components,
78
- } as OpenApiV3_1.IDocument);
79
- const migrate: IHttpMigrateApplication = HttpMigration.application(result);
80
+ components: input.components,
81
+ } as OpenApiV3_2.IDocument);
82
+ const migrate: IHttpMigrateApplication = HttpMigration.application(document);
80
83
  migrate.routes.forEach((r) => {
81
84
  if (r.method === "head") return;
82
85
  const name: string = dict.get({
83
- method: r.method,
86
+ method: r.method as "post",
84
87
  path: r.path,
85
88
  });
86
89
  if (r.accessor.length >= 2 && r.accessor.at(-2) === name) r.accessor.pop();
87
90
  r.accessor[r.accessor.length - 1] = name;
88
91
  r.operation()["x-samchon-accessor"] = r.accessor;
89
92
  });
90
- return result;
93
+ return document;
91
94
  }
@@ -1,4 +1,4 @@
1
- import { AutoBePrisma } from "@autobe/interface";
1
+ import { AutoBeDatabase } from "@autobe/interface";
2
2
  import crypto from "crypto";
3
3
 
4
4
  import { ArrayUtil } from "../ArrayUtil";
@@ -7,7 +7,7 @@ import { StringUtil } from "../StringUtil";
7
7
 
8
8
  export function writePrismaApplication(props: {
9
9
  dbms: "postgres" | "sqlite";
10
- application: AutoBePrisma.IApplication;
10
+ application: AutoBeDatabase.IApplication;
11
11
  }): Record<string, string> {
12
12
  for (const file of props.application.files)
13
13
  for (const model of file.models) fillMappingName(model);
@@ -30,8 +30,8 @@ export function writePrismaApplication(props: {
30
30
 
31
31
  function writeFile(props: {
32
32
  dbms: "postgres" | "sqlite";
33
- application: AutoBePrisma.IApplication;
34
- file: AutoBePrisma.IFile;
33
+ application: AutoBeDatabase.IApplication;
34
+ file: AutoBeDatabase.IFile;
35
35
  }): string {
36
36
  return props.file.models
37
37
  .map((model) =>
@@ -45,9 +45,9 @@ function writeFile(props: {
45
45
 
46
46
  function writeModel(props: {
47
47
  dbms: "postgres" | "sqlite";
48
- application: AutoBePrisma.IApplication;
49
- file: AutoBePrisma.IFile;
50
- model: AutoBePrisma.IModel;
48
+ application: AutoBeDatabase.IApplication;
49
+ file: AutoBeDatabase.IFile;
50
+ model: AutoBeDatabase.IModel;
51
51
  }): string {
52
52
  return [
53
53
  writeComment(
@@ -67,8 +67,8 @@ function writeModel(props: {
67
67
  ].join("\n");
68
68
  }
69
69
 
70
- function fillMappingName(model: AutoBePrisma.IModel): void {
71
- const group: Map<string, AutoBePrisma.IForeignField[]> = new Map();
70
+ function fillMappingName(model: AutoBeDatabase.IModel): void {
71
+ const group: Map<string, AutoBeDatabase.IForeignField[]> = new Map();
72
72
  for (const ff of model.foreignFields) {
73
73
  MapUtil.take(group, ff.relation.targetModel, () => []).push(ff);
74
74
  if (ff.relation.targetModel == model.name)
@@ -85,7 +85,7 @@ function fillMappingName(model: AutoBePrisma.IModel): void {
85
85
  ----------------------------------------------------------- */
86
86
  function writeColumns(props: {
87
87
  dbms: "postgres" | "sqlite";
88
- model: AutoBePrisma.IModel;
88
+ model: AutoBeDatabase.IModel;
89
89
  }): string[] {
90
90
  return [
91
91
  "//----",
@@ -119,8 +119,8 @@ function writeColumns(props: {
119
119
 
120
120
  function writePrimary(props: {
121
121
  dbms: "postgres" | "sqlite";
122
- model: AutoBePrisma.IModel;
123
- field: AutoBePrisma.IPrimaryField;
122
+ model: AutoBeDatabase.IModel;
123
+ field: AutoBeDatabase.IPrimaryField;
124
124
  }): string {
125
125
  const type: string | undefined =
126
126
  props.dbms === "postgres" ? POSTGRES_PHYSICAL_TYPES.uuid : undefined;
@@ -137,7 +137,7 @@ function writePrimary(props: {
137
137
 
138
138
  function writeField(props: {
139
139
  dbms: "postgres" | "sqlite";
140
- field: AutoBePrisma.IPlainField;
140
+ field: AutoBeDatabase.IPlainField;
141
141
  }): string {
142
142
  const logical: string = LOGICAL_TYPES[props.field.type];
143
143
  const physical: string | undefined =
@@ -161,12 +161,13 @@ function writeField(props: {
161
161
  ----------------------------------------------------------- */
162
162
  function writeRelations(props: {
163
163
  dbms: "postgres" | "sqlite";
164
- application: AutoBePrisma.IApplication;
165
- model: AutoBePrisma.IModel;
164
+ application: AutoBeDatabase.IApplication;
165
+ model: AutoBeDatabase.IModel;
166
166
  }): string[] {
167
167
  interface IHasRelationship {
168
168
  modelName: string;
169
169
  unique: boolean;
170
+ oppositeName: string;
170
171
  mappingName?: string;
171
172
  }
172
173
  const hasRelationships: IHasRelationship[] = props.application.files
@@ -180,12 +181,13 @@ function writeRelations(props: {
180
181
  .map((otherForeign) => ({
181
182
  modelName: otherModel.name,
182
183
  unique: otherForeign.unique,
184
+ oppositeName: otherForeign.relation.oppositeName,
183
185
  mappingName: otherForeign.relation.mappingName,
184
186
  })),
185
187
  ),
186
188
  )
187
189
  .flat(2);
188
- const foreignIndexes: AutoBePrisma.IForeignField[] =
190
+ const foreignIndexes: AutoBeDatabase.IForeignField[] =
189
191
  props.model.foreignFields.filter((f) => {
190
192
  if (f.unique === true)
191
193
  return props.model.uniqueIndexes.every(
@@ -196,28 +198,52 @@ function writeRelations(props: {
196
198
  props.model.plainIndexes.every((p) => p.fieldNames[0] !== f.name)
197
199
  );
198
200
  });
199
- const contents: string[][] = [
200
- props.model.foreignFields.map((foreign) =>
201
- writeConstraint({
202
- dbms: props.dbms,
203
- model: props.model,
204
- foreign,
205
- }),
206
- ),
207
- hasRelationships.map((r) =>
208
- [
209
- r.mappingName ?? r.modelName,
210
- `${r.modelName}${r.unique ? "?" : "[]"}`,
211
- ...(r.mappingName ? [`@relation("${r.mappingName}")`] : []),
212
- ].join(" "),
201
+
202
+ const print = (title: string, content: string[]): string[] => {
203
+ if (content.length === 0) return [];
204
+ return [
205
+ // title
206
+ "//----",
207
+ ...title.split("\n").map((l) => `// ${l}`),
208
+ "//----",
209
+ // main content
210
+ ...content,
211
+ ];
212
+ };
213
+ return ArrayUtil.paddle([
214
+ print(
215
+ StringUtil.trim`
216
+ BELONGED RELATIONS,
217
+ - format: (propertyKey targetModel constraint)
218
+ `,
219
+ props.model.foreignFields.map((foreign) =>
220
+ writeConstraint({
221
+ dbms: props.dbms,
222
+ model: props.model,
223
+ foreign,
224
+ }),
225
+ ),
213
226
  ),
214
- foreignIndexes.map((field) =>
215
- writeForeignIndex({
216
- model: props.model,
217
- field,
218
- }),
227
+ print(
228
+ StringUtil.trim`
229
+ HAS RELATIONS
230
+ - format: (propertyKey targetModel)
231
+ `,
232
+ hasRelationships.map((r) =>
233
+ [
234
+ r.oppositeName ?? r.mappingName ?? r.modelName, // for legacy histories
235
+ `${r.modelName}${r.unique ? "?" : "[]"}`,
236
+ ...(r.mappingName ? [`@relation("${r.mappingName}")`] : []),
237
+ ].join(" "),
238
+ ),
219
239
  ),
220
- [
240
+ print("INDEXES", [
241
+ ...foreignIndexes.map((field) =>
242
+ writeForeignIndex({
243
+ model: props.model,
244
+ field,
245
+ }),
246
+ ),
221
247
  ...props.model.uniqueIndexes.map((unique) =>
222
248
  writeUniqueIndex({
223
249
  model: props.model,
@@ -238,22 +264,14 @@ function writeRelations(props: {
238
264
  }),
239
265
  )
240
266
  : []),
241
- ],
242
- ];
243
- if (contents.every((c) => c.length === 0)) return [];
244
- return [
245
- "//----",
246
- "// RELATIONS",
247
- "//----",
248
- // paddled content
249
- ...ArrayUtil.paddle(contents),
250
- ];
267
+ ]),
268
+ ]);
251
269
  }
252
270
 
253
271
  function writeConstraint(props: {
254
272
  dbms: "postgres" | "sqlite";
255
- model: AutoBePrisma.IModel;
256
- foreign: AutoBePrisma.IForeignField;
273
+ model: AutoBeDatabase.IModel;
274
+ foreign: AutoBeDatabase.IForeignField;
257
275
  }): string {
258
276
  // spellchecker:ignore-next-line
259
277
  const name: string = `${props.model.name}_${props.foreign.name}_rela`;
@@ -281,8 +299,8 @@ function writeConstraint(props: {
281
299
  }
282
300
 
283
301
  function writeForeignIndex(props: {
284
- model: AutoBePrisma.IModel;
285
- field: AutoBePrisma.IForeignField;
302
+ model: AutoBeDatabase.IModel;
303
+ field: AutoBeDatabase.IForeignField;
286
304
  }): string {
287
305
  const name: string = `${props.model.name}_${props.field.name}_fkey`;
288
306
  const prefix: string = `@@${props.field.unique === true ? "unique" : "index"}([${props.field.name}]`;
@@ -294,8 +312,8 @@ function writeForeignIndex(props: {
294
312
  }
295
313
 
296
314
  function writeUniqueIndex(props: {
297
- model: AutoBePrisma.IModel;
298
- unique: AutoBePrisma.IUniqueIndex;
315
+ model: AutoBeDatabase.IModel;
316
+ unique: AutoBeDatabase.IUniqueIndex;
299
317
  }): string {
300
318
  const name: string = `${props.model.name}_${props.unique.fieldNames.join("_")}_key`;
301
319
  const prefix: string = `@@unique([${props.unique.fieldNames.join(", ")}]`;
@@ -307,8 +325,8 @@ function writeUniqueIndex(props: {
307
325
  }
308
326
 
309
327
  function writePlainIndex(props: {
310
- model: AutoBePrisma.IModel;
311
- plain: AutoBePrisma.IPlainIndex;
328
+ model: AutoBeDatabase.IModel;
329
+ plain: AutoBeDatabase.IPlainIndex;
312
330
  }): string {
313
331
  const name: string = `${props.model.name}_${props.plain.fieldNames.join("_")}_idx`;
314
332
  const prefix: string = `@@index([${props.plain.fieldNames.join(", ")}]`;
@@ -320,8 +338,8 @@ function writePlainIndex(props: {
320
338
  }
321
339
 
322
340
  function writeGinIndex(props: {
323
- model: AutoBePrisma.IModel;
324
- gin: AutoBePrisma.IGinIndex;
341
+ model: AutoBeDatabase.IModel;
342
+ gin: AutoBeDatabase.IGinIndex;
325
343
  }): string {
326
344
  const name: string = `${props.model.name}_${props.gin.fieldName}_idx`;
327
345
  const prefix: string = `@@index([${props.gin.fieldName}(ops: raw("gin_trgm_ops"))], type: Gin`;
@@ -342,7 +360,6 @@ function writeComment(content: string, length: number): string {
342
360
  .split("\n")
343
361
  .map((line) => line.trim())
344
362
  .map((line) => {
345
- // 77자에서 "/// " 4자를 뺀 73자가 실제 컨텐츠 최대 길이
346
363
  if (line.length <= length - 4) return [line];
347
364
  const words: string[] = line.split(" ");
348
365
  const result: string[] = [];
@@ -407,13 +424,13 @@ const POSTGRES_PHYSICAL_TYPES = {
407
424
 
408
425
  const POSTGRES_MAIN_FILE = StringUtil.trim`
409
426
  generator client {
410
- provider = "prisma-client-js"
411
- engineType = "client"
427
+ provider = "prisma-client"
412
428
  previewFeatures = ["postgresqlExtensions", "views"]
429
+ output = "../../src/prisma"
430
+ moduleFormat = "cjs"
413
431
  }
414
432
  datasource db {
415
433
  provider = "postgresql"
416
- url = env("DATABASE_URL")
417
434
  extensions = [pg_trgm]
418
435
  }
419
436
  generator markdown {
@@ -423,12 +440,12 @@ const POSTGRES_MAIN_FILE = StringUtil.trim`
423
440
  `;
424
441
  const SQLITE_MAIN_FILE = StringUtil.trim`
425
442
  generator client {
426
- provider = "prisma-client-js"
427
- engineType = "client"
443
+ provider = "prisma-client"
444
+ output = "../../src/prisma"
445
+ moduleFormat = "cjs"
428
446
  }
429
447
  datasource db {
430
448
  provider = "sqlite"
431
- url = "file:../db.sqlite"
432
449
  }
433
450
  generator markdown {
434
451
  provider = "prisma-markdown"
@@ -7,4 +7,10 @@ export const validateTestExpression = (
7
7
  ctx: IAutoBeTextValidateContext,
8
8
  item: AutoBeTest.IExpression,
9
9
  path: string,
10
- ): void => AutoBeTestExpressionValidator[item.type](ctx, item as any, path);
10
+ ): void =>
11
+ AutoBeTestExpressionValidator[item.type](
12
+ ctx,
13
+ // biome-ignore lint: intended
14
+ item as any,
15
+ path,
16
+ );
@@ -7,4 +7,10 @@ export const validateTestStatement = (
7
7
  ctx: IAutoBeTextValidateContext,
8
8
  item: AutoBeTest.IStatement,
9
9
  path: string,
10
- ): void => AutoBeTestStatementValidator[item.type](ctx, item as any, path);
10
+ ): void =>
11
+ AutoBeTestStatementValidator[item.type](
12
+ ctx,
13
+ // biome-ignore lint: intended
14
+ item as any,
15
+ path,
16
+ );