true-pg 0.5.0 → 0.5.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.
@@ -1,149 +1,148 @@
1
1
  import { Canonical, FunctionReturnTypeKind, } from "../extractor/index.js";
2
- import { allowed_kind_names, createGenerator, Nodes } from "../types.js";
2
+ import { allowed_kind_names, createGenerator } from "../types.js";
3
+ import { Import } from "../imports.js";
3
4
  import { builtins } from "./builtins.js";
4
5
  import { toPascalCase, join, quote, quoteI } from "../util.js";
5
6
  export const Kysely = createGenerator(opts => {
6
7
  const defaultSchema = opts?.defaultSchema ?? "public";
7
- const ky = (imports, name) => imports.add(new Nodes.ExternalImport({
8
- name,
9
- module: "kysely",
10
- typeOnly: true,
11
- star: false,
12
- }));
13
- const add = (imports, type) => {
14
- if (type.schema === "pg_catalog")
15
- return;
16
- imports.add(new Nodes.InternalImport({
17
- name: generator.formatType(type),
18
- canonical_type: type,
8
+ const ky = (ctx, name) => {
9
+ ctx.imports.add(new Import({
10
+ from: "kysely",
11
+ namedImports: [name],
19
12
  typeOnly: true,
20
- star: false,
21
13
  }));
22
14
  };
23
15
  const column = (
24
16
  /** "this" */
25
- generator,
26
- /** @out Append used types to this array */
27
- imports,
17
+ generator, ctx,
28
18
  /** Information about the column */
29
19
  col) => {
30
- let base = generator.formatType(col.type);
31
- if (col.type.dimensions > 0)
32
- base += "[]".repeat(col.type.dimensions);
33
- if (col.isNullable)
34
- base += " | null";
20
+ let base = generator.formatType(ctx, col.type, { nullable: col.isNullable });
35
21
  let qualified = base;
36
22
  if (col.generated === "ALWAYS") {
37
23
  qualified = `GeneratedAlways<${qualified}>`;
38
- ky(imports, "GeneratedAlways");
24
+ ky(ctx, "GeneratedAlways");
39
25
  }
40
26
  else if (col.generated === "BY DEFAULT") {
41
27
  qualified = `Generated<${qualified}>`;
42
- ky(imports, "Generated");
28
+ ky(ctx, "Generated");
43
29
  }
44
30
  else if (col.defaultValue) {
45
31
  qualified = `Generated<${qualified}>`;
46
- ky(imports, "Generated");
32
+ ky(ctx, "Generated");
47
33
  }
48
34
  let out = col.comment ? `/** ${col.comment} */\n\t` : "";
49
35
  out += quoteI(col.name);
50
36
  // TODO: update imports for non-primitive types
51
37
  out += `: ${qualified}`;
52
- add(imports, col.type);
53
38
  return `\t${out};\n`;
54
39
  };
55
- const composite_attribute = (generator, imports, attr) => {
40
+ const composite_attribute = (ctx, generator, attr) => {
56
41
  let out = quoteI(attr.name);
57
42
  if (attr.isNullable)
58
43
  out += "?";
59
- out += `: ${generator.formatType(attr.type)}`;
60
- add(imports, attr.type);
61
- if (attr.type.dimensions > 0)
62
- out += "[]".repeat(attr.type.dimensions);
63
- if (attr.isNullable)
64
- out += " | null";
44
+ out += ": ";
45
+ out += generator.formatType(ctx, attr.type, { nullable: attr.isNullable });
65
46
  return out;
66
47
  };
67
48
  const generator = {
68
- formatSchema(name) {
49
+ formatSchemaName(name) {
69
50
  return toPascalCase(name) + "Schema";
70
51
  },
71
- formatSchemaType(type) {
52
+ formatSchemaMemberName(type) {
72
53
  return toPascalCase(type.name);
73
54
  },
74
- formatType(type) {
55
+ formatType(ctx, type, attr) {
56
+ let base;
75
57
  if (type.kind === FunctionReturnTypeKind.ExistingTable) {
76
- return toPascalCase(type.name);
58
+ base = toPascalCase(type.name);
77
59
  }
78
60
  else if (type.schema === "pg_catalog") {
79
61
  const name = type.canonical_name;
80
62
  const format = builtins[name];
81
63
  if (format)
82
- return format;
83
- opts?.warnings?.push(`(kysely) Unknown builtin type: ${name}. Pass customBuiltinMap to map this type. Defaulting to "unknown".`);
84
- return "unknown";
64
+ base = format;
65
+ else {
66
+ opts?.warnings?.add(`(kysely) Unknown builtin type: ${name}. Pass 'kysely.builtinMap' to map this type. Defaulting to "unknown".`);
67
+ base = "unknown";
68
+ }
85
69
  }
86
- return toPascalCase(type.name);
70
+ else
71
+ base = toPascalCase(type.name);
72
+ if (type.schema !== "pg_catalog") {
73
+ // before adding modifiers, add the import
74
+ ctx.imports.add(Import.fromInternal({
75
+ source: ctx.source,
76
+ type,
77
+ withName: base,
78
+ typeOnly: true,
79
+ }));
80
+ }
81
+ if ("dimensions" in type)
82
+ base += "[]".repeat(type.dimensions);
83
+ if (attr?.nullable)
84
+ base += " | null";
85
+ return base;
87
86
  },
88
- table(imports, table) {
87
+ table(ctx, table) {
89
88
  let out = "";
90
89
  if (table.comment)
91
90
  out += `/** ${table.comment} */\n`;
92
- out += `export interface ${this.formatSchemaType(table)} {\n`;
91
+ out += `export interface ${this.formatSchemaMemberName(table)} {\n`;
93
92
  for (const col of table.columns)
94
- out += column(this, imports, col);
93
+ out += column(this, ctx, col);
95
94
  out += "}";
96
95
  return out;
97
96
  },
98
- view(imports, view) {
97
+ view(ctx, view) {
99
98
  let out = "";
100
99
  if (view.comment)
101
100
  out += `/** ${view.comment} */\n`;
102
- out += `export interface ${this.formatSchemaType(view)} {\n`;
101
+ out += `export interface ${this.formatSchemaMemberName(view)} {\n`;
103
102
  for (const col of view.columns)
104
- out += column(this, imports, col);
103
+ out += column(this, ctx, col);
105
104
  out += "}";
106
105
  return out;
107
106
  },
108
- materializedView(imports, materializedView) {
107
+ materializedView(ctx, materializedView) {
109
108
  let out = "";
110
109
  if (materializedView.comment)
111
110
  out += `/** ${materializedView.comment} */\n`;
112
- out += `export interface ${this.formatSchemaType(materializedView)} {\n`;
111
+ out += `export interface ${this.formatSchemaMemberName(materializedView)} {\n`;
113
112
  for (const col of materializedView.columns)
114
- out += column(this, imports, col);
113
+ out += column(this, ctx, col);
115
114
  out += "}";
116
115
  return out;
117
116
  },
118
- enum(imports, en) {
117
+ enum(ctx, en) {
119
118
  let out = "";
120
119
  if (en.comment)
121
120
  out += `/** ${en.comment} */\n`;
122
- out += `export type ${this.formatSchemaType(en)} = ${en.values.map(v => `"${v}"`).join(" | ")};`;
121
+ out += `export type ${this.formatSchemaMemberName(en)} = ${en.values.map(v => `"${v}"`).join(" | ")};`;
123
122
  return out;
124
123
  },
125
- composite(imports, type) {
124
+ composite(ctx, type) {
126
125
  let out = "";
127
126
  if (type.comment)
128
127
  out += `/** ${type.comment} */\n`;
129
- out += `export interface ${this.formatSchemaType(type)} {\n`;
130
- const props = type.canonical.attributes.map(c => composite_attribute(this, imports, c)).map(t => `\t${t};`);
128
+ out += `export interface ${this.formatSchemaMemberName(type)} {\n`;
129
+ const props = type.canonical.attributes.map(c => composite_attribute(ctx, this, c)).map(t => `\t${t};`);
131
130
  out += props.join("\n");
132
131
  out += "\n}";
133
132
  return out;
134
133
  },
135
- domain(imports, type) {
134
+ domain(ctx, type) {
136
135
  let out = "";
137
- out += `export type ${this.formatSchemaType(type)} = ${this.formatType(type.canonical.domain_base_type)};`;
136
+ out += `export type ${this.formatSchemaMemberName(type)} = ${this.formatType(ctx, type.canonical.domain_base_type)};`;
138
137
  return out;
139
138
  },
140
- range(imports, type) {
139
+ range(ctx, type) {
141
140
  let out = "";
142
141
  // force this to be string because range has to be passed as a string to Kysely
143
- out += `export type ${this.formatSchemaType(type)} = string;`;
142
+ out += `export type ${this.formatSchemaMemberName(type)} = string;`;
144
143
  return out;
145
144
  },
146
- function(imports, type) {
145
+ function(ctx, type) {
147
146
  let out = "";
148
147
  out += "/**\n";
149
148
  if (type.comment)
@@ -152,7 +151,7 @@ export const Kysely = createGenerator(opts => {
152
151
  out += ` * @parallelSafety ${type.parallelSafety}\n`;
153
152
  out += ` * @isStrict ${type.isStrict}\n`;
154
153
  out += " */\n";
155
- out += `export interface ${this.formatSchemaType(type)} {\n\t`;
154
+ out += `export interface ${this.formatSchemaMemberName(type)} {\n\t`;
156
155
  // Get the input parameters (those that appear in function signature)
157
156
  const inputParams = type.parameters.filter(p => p.mode === "IN" || p.mode === "INOUT" || p.mode === "VARIADIC");
158
157
  if (inputParams.length === 0) {
@@ -162,10 +161,7 @@ export const Kysely = createGenerator(opts => {
162
161
  out += "(";
163
162
  out += inputParams[0].name;
164
163
  out += ": ";
165
- out += this.formatType(inputParams[0].type);
166
- add(imports, inputParams[0].type);
167
- if (inputParams[0].type.dimensions > 0)
168
- out += "[]".repeat(inputParams[0].type.dimensions);
164
+ out += this.formatType(ctx, inputParams[0].type);
169
165
  out += "): ";
170
166
  }
171
167
  else if (inputParams.length > 0) {
@@ -177,10 +173,7 @@ export const Kysely = createGenerator(opts => {
177
173
  out += `\t\t${paramName}`;
178
174
  if (param.hasDefault && !isVariadic)
179
175
  out += "?";
180
- out += `: ${this.formatType(param.type)}`;
181
- add(imports, param.type);
182
- if (param.type.dimensions > 0)
183
- out += "[]".repeat(param.type.dimensions);
176
+ out += `: ${this.formatType(ctx, param.type)}`;
184
177
  if (!isVariadic)
185
178
  out += ",";
186
179
  out += "\n";
@@ -194,24 +187,17 @@ export const Kysely = createGenerator(opts => {
194
187
  out += "{\n";
195
188
  for (const col of type.returnType.columns) {
196
189
  out += `\t\t"${col.name}": `;
197
- out += this.formatType(col.type);
198
- add(imports, col.type);
199
- if (col.type.dimensions > 0)
200
- out += "[]".repeat(col.type.dimensions);
190
+ out += this.formatType(ctx, col.type);
201
191
  out += `;\n`;
202
192
  }
203
193
  out += "\t}";
204
194
  }
205
195
  }
206
196
  else if (type.returnType.kind === FunctionReturnTypeKind.ExistingTable) {
207
- out += this.formatType(type.returnType);
208
- add(imports, type.returnType);
197
+ out += this.formatType(ctx, type.returnType);
209
198
  }
210
199
  else {
211
- out += this.formatType(type.returnType.type);
212
- add(imports, type.returnType.type);
213
- if (type.returnType.type.dimensions > 0)
214
- out += "[]".repeat(type.returnType.type.dimensions);
200
+ out += this.formatType(ctx, type.returnType.type);
215
201
  }
216
202
  // Add additional array brackets if it returns a set
217
203
  if (type.returnType.isSet) {
@@ -220,24 +206,25 @@ export const Kysely = createGenerator(opts => {
220
206
  out += ";\n}";
221
207
  return out;
222
208
  },
223
- schemaKindIndex(schema, kind, main_generator) {
209
+ schemaKindIndex(ctx, schema, kind, main_generator) {
224
210
  const generator = main_generator ?? this;
225
211
  const imports = schema[kind];
226
212
  if (imports.length === 0)
227
213
  return "";
228
214
  return imports
229
215
  .map(each => {
230
- const name = this.formatSchemaType(each);
231
- const file = generator.formatSchemaType(each);
216
+ const name = generator.formatSchemaMemberName(each);
217
+ const file = generator.formatSchemaMemberName(each);
232
218
  return `export type { ${name} } from "./${file}.ts";`;
233
219
  })
234
220
  .join("\n");
235
221
  },
236
- schemaIndex(schema) {
222
+ schemaIndex(ctx, schema) {
237
223
  const actual_kinds = allowed_kind_names.filter(kind => schema[kind].length);
224
+ // we could in theory use the imports from GeneratorContext here, but this works fine
238
225
  let out = actual_kinds.map(kind => `import type * as ${kind} from "./${kind}/index.ts";`).join("\n");
239
226
  out += "\n\n";
240
- out += `export interface ${this.formatSchema(schema.name)} {\n`;
227
+ out += `export interface ${this.formatSchemaName(schema.name)} {\n`;
241
228
  for (const kind of actual_kinds) {
242
229
  const items = schema[kind];
243
230
  if (items.length === 0)
@@ -245,7 +232,7 @@ export const Kysely = createGenerator(opts => {
245
232
  out += `\t${kind}: {\n`;
246
233
  const formatted = items
247
234
  .map(each => {
248
- const formatted = this.formatSchemaType(each);
235
+ const formatted = generator.formatSchemaMemberName(each);
249
236
  return { ...each, formatted };
250
237
  })
251
238
  .filter(x => x !== undefined);
@@ -260,10 +247,10 @@ export const Kysely = createGenerator(opts => {
260
247
  out += "}";
261
248
  return out;
262
249
  },
263
- fullIndex(schemas) {
250
+ fullIndex(ctx, schemas) {
264
251
  const parts = [];
265
252
  parts.push(schemas
266
- .map(s => `import type { ${this.formatSchema(s.name)} } from "./${s.name}/index.ts";`)
253
+ .map(s => `import type { ${generator.formatSchemaName(s.name)} } from "./${s.name}/index.ts";`)
267
254
  .join("\n"));
268
255
  {
269
256
  let iface = `export interface Database {\n`;
@@ -275,7 +262,7 @@ export const Kysely = createGenerator(opts => {
275
262
  const seen = new Set();
276
263
  const formatted = tables
277
264
  .map(each => {
278
- const formatted = this.formatSchemaType(each);
265
+ const formatted = generator.formatSchemaMemberName(each);
279
266
  // skip clashing names
280
267
  if (seen.has(formatted))
281
268
  return;
@@ -294,7 +281,7 @@ export const Kysely = createGenerator(opts => {
294
281
  else
295
282
  qualified = t.name;
296
283
  qualified = quoteI(qualified);
297
- return `\t${qualified}: ${this.formatSchema(schema.name)}[${quote(t.kind + "s")}][${quote(t.name)}];`;
284
+ return `\t${qualified}: ${generator.formatSchemaName(schema.name)}[${quote(t.kind + "s")}][${quote(t.name)}];`;
298
285
  })
299
286
  .join("\n");
300
287
  return out;
@@ -303,7 +290,7 @@ export const Kysely = createGenerator(opts => {
303
290
  iface += "\n}";
304
291
  parts.push(iface);
305
292
  }
306
- parts.push(schemas.map(s => `export type { ${this.formatSchema(s.name)} };`).join("\n"));
293
+ parts.push(schemas.map(s => `export type { ${generator.formatSchemaName(s.name)} };`).join("\n"));
307
294
  return join(parts);
308
295
  },
309
296
  };
package/lib/types.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { Canonical, type TableDetails, type ViewDetails, type MaterializedViewDetails, type EnumDetails, type CompositeTypeDetails, type DomainDetails, type RangeDetails, type FunctionDetails, type SchemaType, type Schema, type FunctionReturnType } from "./extractor/index.ts";
2
+ import type { ImportList } from "./imports.ts";
2
3
  export declare const allowed_kind_names: readonly ["tables", "views", "materializedViews", "enums", "composites", "functions", "domains", "ranges"];
3
4
  export type allowed_kind_names = (typeof allowed_kind_names)[number];
4
5
  export interface FolderStructure {
@@ -23,118 +24,72 @@ export interface FolderStructure {
23
24
  };
24
25
  };
25
26
  }
26
- export declare namespace Nodes {
27
- class ExternalImport {
28
- name: string;
29
- typeOnly: boolean;
30
- star: boolean;
31
- external: true;
32
- module: string;
33
- constructor(args: {
34
- name: string;
35
- module: string;
36
- typeOnly: boolean;
37
- star: boolean;
38
- });
39
- }
40
- class InternalImport {
41
- name: string;
42
- canonical_type: Canonical | FunctionReturnType.ExistingTable;
43
- typeOnly: boolean;
44
- star: boolean;
45
- external: false;
46
- constructor(args: {
47
- name: string;
48
- canonical_type: Canonical | FunctionReturnType.ExistingTable;
49
- typeOnly: boolean;
50
- star: boolean;
51
- });
52
- }
53
- class ImportList {
54
- imports: (ExternalImport | InternalImport)[];
55
- constructor(imports: (ExternalImport | InternalImport)[]);
56
- static merge(lists: ImportList[]): ImportList;
57
- add(item: ExternalImport | InternalImport): void;
58
- stringify(context_file: string, files: FolderStructure): string;
59
- }
60
- interface Export {
61
- name: string;
62
- kind: SchemaType["kind"];
63
- schema: string;
64
- star: boolean;
65
- }
66
- }
67
27
  export interface CreateGeneratorOpts {
68
28
  defaultSchema?: string;
69
- warnings: string[];
29
+ warnings: Set<string>;
70
30
  }
71
31
  export interface createGenerator {
72
32
  (opts?: CreateGeneratorOpts): SchemaGenerator;
73
33
  }
74
34
  export declare const createGenerator: (generatorCreator: createGenerator) => createGenerator;
35
+ export interface GeneratorContext {
36
+ /** The source file path */
37
+ source: string;
38
+ /** Append types to import */
39
+ imports: ImportList;
40
+ }
41
+ export interface FormatTypeAttributes {
42
+ nullable?: boolean;
43
+ generated?: boolean;
44
+ identity?: boolean;
45
+ }
75
46
  export interface SchemaGenerator {
76
47
  /**
77
48
  * Use this function to define a name mapping for schema names.
78
49
  * This is useful if you want to use a different name for a schema in the generated code.
79
50
  * Example: "public" -> "PublicSchema"
80
51
  */
81
- formatSchema(name: string): string;
52
+ formatSchemaName(name: string): string;
82
53
  /**
83
- * Use this function to define a name mapping for schema types.
84
- * This is useful if you want to use a different name for a type in the generated code.
54
+ * Use this function to define a name mapping for schema members.
55
+ * This is useful if you want to use a different name for a member in the generated code.
85
56
  * Example: "users" -> "UsersTable"
86
57
  */
87
- formatSchemaType(type: SchemaType): string;
58
+ formatSchemaMemberName(type: SchemaType): string;
88
59
  /**
89
60
  * Use this function to define a name mapping for type names.
90
61
  * This is useful if you want to use a different name for a type in the generated code.
91
62
  * Example: "users" -> "UsersTable"
92
63
  */
93
- formatType(type: Canonical | FunctionReturnType.ExistingTable): string;
94
- table(
95
- /** @out Append used types to this array */
96
- imports: Nodes.ImportList,
64
+ formatType(ctx: GeneratorContext, type: Canonical | FunctionReturnType.ExistingTable, attr?: FormatTypeAttributes): string;
65
+ table(ctx: GeneratorContext,
97
66
  /** Information about the table */
98
67
  table: TableDetails): string;
99
- view(
100
- /** @out Append used types to this array */
101
- imports: Nodes.ImportList,
68
+ view(ctx: GeneratorContext,
102
69
  /** Information about the view */
103
70
  view: ViewDetails): string;
104
- materializedView(
105
- /** @out Append used types to this array */
106
- imports: Nodes.ImportList,
71
+ materializedView(ctx: GeneratorContext,
107
72
  /** Information about the materialized view */
108
73
  materializedView: MaterializedViewDetails): string;
109
- enum(
110
- /** @out Append used types to this array */
111
- imports: Nodes.ImportList,
74
+ enum(ctx: GeneratorContext,
112
75
  /** Information about the enum */
113
76
  en: EnumDetails): string;
114
- composite(
115
- /** @out Append used types to this array */
116
- imports: Nodes.ImportList,
77
+ composite(ctx: GeneratorContext,
117
78
  /** Information about the composite type */
118
79
  type: CompositeTypeDetails): string;
119
- domain(
120
- /** @out Append used types to this array */
121
- imports: Nodes.ImportList,
80
+ domain(ctx: GeneratorContext,
122
81
  /** Information about the domain */
123
82
  type: DomainDetails): string;
124
- range(
125
- /** @out Append used types to this array */
126
- imports: Nodes.ImportList,
83
+ range(ctx: GeneratorContext,
127
84
  /** Information about the range */
128
85
  type: RangeDetails): string;
129
- function(
130
- /** @out Append used types to this array */
131
- imports: Nodes.ImportList,
86
+ function(ctx: GeneratorContext,
132
87
  /** Information about the function */
133
88
  type: FunctionDetails): string;
134
89
  /** create the file `$out/$schema.name/$kind/index.ts` */
135
- schemaKindIndex(schema: Schema, kind: Exclude<keyof Schema, "name">, main_generator?: SchemaGenerator): string;
90
+ schemaKindIndex(ctx: GeneratorContext, schema: Schema, kind: Exclude<keyof Schema, "name">, main_generator?: SchemaGenerator): string;
136
91
  /** create the file `$out/$schema.name/index.ts` */
137
- schemaIndex(schema: Schema, main_generator?: SchemaGenerator): string;
92
+ schemaIndex(ctx: GeneratorContext, schema: Schema, main_generator?: SchemaGenerator): string;
138
93
  /** create the file `$out/index.ts` */
139
- fullIndex(schemas: Schema[], main_generator?: SchemaGenerator): string;
94
+ fullIndex(ctx: GeneratorContext, schemas: Schema[], main_generator?: SchemaGenerator): string;
140
95
  }
package/lib/types.js CHANGED
@@ -1,6 +1,4 @@
1
1
  import { Canonical, } from "./extractor/index.js";
2
- import { dirname, relative } from "node:path/posix";
3
- import { join } from "./util.js";
4
2
  // To be updated when we add support for other kinds
5
3
  export const allowed_kind_names = [
6
4
  "tables",
@@ -12,168 +10,5 @@ export const allowed_kind_names = [
12
10
  "domains",
13
11
  "ranges",
14
12
  ];
15
- export var Nodes;
16
- (function (Nodes) {
17
- class ExternalImport {
18
- // what to import
19
- name;
20
- // use `type` syntax?
21
- typeOnly;
22
- // use `* as` syntax?
23
- star;
24
- // this is an external import
25
- external;
26
- // what module to import from
27
- module;
28
- constructor(args) {
29
- this.name = args.name;
30
- this.typeOnly = args.typeOnly;
31
- this.star = args.star;
32
- this.external = true;
33
- this.module = args.module;
34
- }
35
- }
36
- Nodes.ExternalImport = ExternalImport;
37
- class InternalImport {
38
- // what to import
39
- name;
40
- // underlying type that is being imported
41
- canonical_type;
42
- // use `type` syntax?
43
- typeOnly;
44
- // use `* as` syntax?
45
- star;
46
- // this is an internal import
47
- external;
48
- constructor(args) {
49
- this.name = args.name;
50
- this.canonical_type = args.canonical_type;
51
- this.star = args.star;
52
- this.typeOnly = args.typeOnly;
53
- this.external = false;
54
- }
55
- }
56
- Nodes.InternalImport = InternalImport;
57
- class ImportList {
58
- imports;
59
- constructor(imports) {
60
- this.imports = imports;
61
- }
62
- static merge(lists) {
63
- return new ImportList(lists.flatMap(l => l.imports));
64
- }
65
- add(item) {
66
- this.imports.push(item);
67
- }
68
- stringify(context_file, files) {
69
- const externals = this.imports.filter(i => i.external);
70
- const internals = this.imports.filter(i => !i.external);
71
- const modulegroups = {};
72
- for (const item of externals) {
73
- const group = modulegroups[item.module];
74
- if (group)
75
- group.push(item);
76
- else
77
- modulegroups[item.module] = [item];
78
- }
79
- const out = [];
80
- // TODO: normalise external and internal imports and handle the stringification of the imports in a single place
81
- {
82
- // EXTERNAL IMPORTS
83
- const imports = [];
84
- for (const module in modulegroups) {
85
- const items = modulegroups[module];
86
- const star = items.find(i => i.star);
87
- const unique = items.filter((i, index, arr) => {
88
- if (i.star)
89
- return false;
90
- if (arr.findIndex(i2 => i2.name === i.name) !== index)
91
- return false;
92
- return true;
93
- });
94
- const bits = [];
95
- const typeOnlys = unique.filter(i => i.typeOnly);
96
- const values = unique.filter(i => !i.typeOnly);
97
- // if no values to import, use `import type { ... }` instead of `import { type ... }`
98
- const typeInline = values.length !== 0;
99
- let import_line = `import `;
100
- for (const type of typeOnlys)
101
- bits.push(typeInline ? "type " : "" + type.name);
102
- for (const type of values)
103
- bits.push(type.name);
104
- if (bits.length)
105
- import_line += (typeInline ? "" : "type ") + "{ " + bits.join(", ") + " }";
106
- if (bits.length && star)
107
- import_line += `, `;
108
- if (star)
109
- import_line += `* as ${star.name}`;
110
- if (bits.length || star)
111
- import_line += ` from `;
112
- import_line += `"${module}";`;
113
- imports.push(import_line);
114
- }
115
- out.push(join(imports, "\n"));
116
- }
117
- {
118
- // INTERNAL IMPORTS
119
- const imports = [];
120
- const unique_types = internals
121
- .filter(({ name: name1, canonical_type: int }, index, arr) => {
122
- return (arr.findIndex(({ name: name2, canonical_type: int2 }) => {
123
- return (
124
- // adapter-assigned name
125
- name2 === name1 &&
126
- // canonical type details
127
- int2.name === int.name &&
128
- int2.schema === int.schema &&
129
- int2.kind === int.kind);
130
- }) === index);
131
- })
132
- .filter(imp => imp.canonical_type.kind === Canonical.Kind.Base ||
133
- allowed_kind_names.includes(`${imp.canonical_type.kind}s`))
134
- .map(imp => {
135
- const t = imp.canonical_type;
136
- const schema = files.children[t.schema];
137
- const kind = schema.children[`${t.kind}s`];
138
- const type = kind.children[t.name];
139
- const located_file = `${files.name}/${schema.name}/${kind.kind}/${type.name}.ts`;
140
- return { ...imp, located_file };
141
- });
142
- const group_by_file = {};
143
- for (const type of unique_types) {
144
- const file = group_by_file[type.located_file] || [];
145
- file.push(type);
146
- group_by_file[type.located_file] = file;
147
- }
148
- for (const group in group_by_file) {
149
- let relative_path = relative(dirname(context_file), group);
150
- if (/^[^\.+\/]/.test(relative_path))
151
- relative_path = "./" + relative_path;
152
- const items = group_by_file[group];
153
- const typeOnlys = items.filter(i => i.typeOnly);
154
- const values = items.filter(i => !i.typeOnly);
155
- const star = values.find(i => i.star);
156
- let import_line = "import ";
157
- const bits = [];
158
- // if no values to import, use `import type { ... }` instead of `import { type ... }`
159
- const typeInline = values.length !== 0;
160
- for (const type of typeOnlys)
161
- bits.push((typeInline ? "type " : "") + type.name);
162
- for (const type of values)
163
- bits.push(type.name);
164
- if (bits.length)
165
- import_line += (typeInline ? "" : "type ") + "{ " + bits.join(", ") + " }";
166
- if (star)
167
- import_line += `* as ${star.name}`;
168
- import_line += ` from "${relative_path}";`;
169
- imports.push(import_line);
170
- }
171
- out.push(join(imports, "\n"));
172
- }
173
- return join(out);
174
- }
175
- }
176
- Nodes.ImportList = ImportList;
177
- })(Nodes || (Nodes = {}));
178
13
  /* convenience function to create a generator with type inference */
179
14
  export const createGenerator = (generatorCreator) => generatorCreator;