true-pg 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +17 -17
- package/lib/bin.js +16 -16
- package/lib/config.d.ts +6 -6
- package/lib/config.js +8 -8
- package/lib/extractor/index.d.ts +9 -8
- package/lib/extractor/index.js +10 -12
- package/lib/extractor/pgtype.d.ts +6 -6
- package/lib/extractor/pgtype.js +7 -1
- package/lib/imports.d.ts +41 -0
- package/lib/imports.js +102 -0
- package/lib/index.js +75 -63
- package/lib/kysely/index.js +87 -95
- package/lib/types.d.ts +32 -77
- package/lib/types.js +2 -176
- package/lib/util.d.ts +2 -0
- package/lib/util.js +13 -0
- package/lib/zod/index.js +100 -98
- package/package.json +3 -2
package/README.md
CHANGED
@@ -15,7 +15,7 @@ bun add true-pg
|
|
15
15
|
## Quickstart
|
16
16
|
|
17
17
|
```bash
|
18
|
-
npx true-pg --all-
|
18
|
+
npx true-pg --all-generators --uri postgres://user:password@localhost:5432/database --out ./models
|
19
19
|
```
|
20
20
|
|
21
21
|
This will generate a `models` directory with the following structure:
|
@@ -68,8 +68,8 @@ Options:
|
|
68
68
|
- `-c, --config [path]` - Path to config file (JSON)
|
69
69
|
- `-u, --uri [uri]` - Database URI (Postgres only!)
|
70
70
|
- `-o, --out [path]` - Path to output directory (defaults to "models")
|
71
|
-
- `-
|
72
|
-
- `-A, --all-
|
71
|
+
- `-g, --generator [generator]` - Generator to use (e.g. `kysely`, `zod`). Can be specified multiple times.
|
72
|
+
- `-A, --all-generators` - Enable all built-in generators
|
73
73
|
|
74
74
|
You can configure true-pg either through command-line arguments or a config file.
|
75
75
|
|
@@ -89,7 +89,7 @@ import { config } from "true-pg";
|
|
89
89
|
export default config({
|
90
90
|
uri: "postgres://user:password@localhost:5432/database",
|
91
91
|
out: "src/models",
|
92
|
-
|
92
|
+
generators: ["kysely", "zod"],
|
93
93
|
defaultSchema: "public",
|
94
94
|
});
|
95
95
|
```
|
@@ -101,7 +101,7 @@ export default config({
|
|
101
101
|
| `uri` | PostgreSQL connection URI | Required, or config |
|
102
102
|
| `config` | Knex connection config object | Required, or uri |
|
103
103
|
| `out` | Output directory for generated files | `"models"` |
|
104
|
-
| `
|
104
|
+
| `generators` | Generators to use (e.g. `kysely`, `zod`) | `"kysely"` |
|
105
105
|
| `defaultSchema` | Default schema to use (Kysely schema will be unprefixed) | `"public"` |
|
106
106
|
|
107
107
|
## Customising Code Generation
|
@@ -118,28 +118,28 @@ You can create a custom generator to control how code is generated:
|
|
118
118
|
import { createGenerator, generate } from "true-pg";
|
119
119
|
|
120
120
|
const generator = createGenerator(opts => ({
|
121
|
-
|
122
|
-
|
123
|
-
formatType: type => `${type}Interface`,
|
124
|
-
table: (
|
121
|
+
formatSchemaName: name => `${name}Schema`,
|
122
|
+
formatSchemaMemberName: type => `${type.name}Type`,
|
123
|
+
formatType: (ctx, type) => `${type}Interface`,
|
124
|
+
table: (ctx, table) => {
|
125
125
|
// Custom table type generation
|
126
126
|
},
|
127
|
-
enum: (
|
127
|
+
enum: (ctx, en) => {
|
128
128
|
// Custom enum type generation
|
129
129
|
},
|
130
|
-
composite: (
|
130
|
+
composite: (ctx, composite) => {
|
131
131
|
// Custom composite type generation
|
132
132
|
},
|
133
|
-
function: (
|
133
|
+
function: (ctx, func) => {
|
134
134
|
// Custom function type generation
|
135
135
|
},
|
136
|
-
schemaKindIndex: (schema, kind) => {
|
136
|
+
schemaKindIndex: (ctx, schema, kind) => {
|
137
137
|
// Custom schema kind index generation
|
138
138
|
},
|
139
|
-
schemaIndex: schema => {
|
139
|
+
schemaIndex: (ctx, schema) => {
|
140
140
|
// Custom schema index generation
|
141
141
|
},
|
142
|
-
fullIndex: schemas => {
|
142
|
+
fullIndex: (ctx, schemas) => {
|
143
143
|
// Custom full index generation
|
144
144
|
},
|
145
145
|
}));
|
@@ -147,14 +147,14 @@ const generator = createGenerator(opts => ({
|
|
147
147
|
await generate(
|
148
148
|
{
|
149
149
|
uri: "postgres://user:password@localhost:5432/database",
|
150
|
-
|
150
|
+
generators: [], // empty array to disable generators
|
151
151
|
out: "src/models",
|
152
152
|
},
|
153
153
|
[generator],
|
154
154
|
);
|
155
155
|
```
|
156
156
|
|
157
|
-
Filenames will be created using the `format*` methods of the FIRST generator passed to `generate` or via the `--
|
157
|
+
Filenames will be created using the `format*` methods of the FIRST generator passed to `generate` or via the `--generator` CLI option.
|
158
158
|
|
159
159
|
## Schema Generator Interface
|
160
160
|
|
package/lib/bin.js
CHANGED
@@ -1,18 +1,18 @@
|
|
1
1
|
#!/usr/bin/env node
|
2
2
|
import mri from "mri";
|
3
3
|
import { generate } from "./index.js";
|
4
|
-
import {
|
4
|
+
import { generators } from "./config.js";
|
5
5
|
const args = process.argv.slice(2);
|
6
6
|
const opts = mri(args, {
|
7
|
-
boolean: ["help", "all-
|
8
|
-
string: ["config", "uri", "out", "
|
7
|
+
boolean: ["help", "all-generators"],
|
8
|
+
string: ["config", "uri", "out", "generator"],
|
9
9
|
alias: {
|
10
10
|
h: "help",
|
11
11
|
c: "config",
|
12
12
|
u: "uri",
|
13
13
|
o: "out",
|
14
|
-
a: "
|
15
|
-
A: "all-
|
14
|
+
a: "generator",
|
15
|
+
A: "all-generators",
|
16
16
|
},
|
17
17
|
});
|
18
18
|
import { cosmiconfig } from "cosmiconfig";
|
@@ -31,27 +31,27 @@ if (help) {
|
|
31
31
|
log(" -h, --help Show help");
|
32
32
|
log(" -u, --uri [uri] Database URI (Postgres only!)");
|
33
33
|
log(" -o, --out [path] Path to output directory");
|
34
|
-
log(" -
|
35
|
-
log(" -A, --all-
|
34
|
+
log(" -g, --generator [generator] Output generator to use (default: 'kysely')");
|
35
|
+
log(" -A, --all-generators Output all generators");
|
36
36
|
log(" -c, --config [path] Path to config file");
|
37
37
|
log(" Defaults to '.truepgrc.json' or '.config/.truepgrc.json'");
|
38
38
|
log("Example:");
|
39
|
-
log(" true-pg -u postgres://user:pass@localhost:5432/my-database -o models -
|
39
|
+
log(" true-pg -u postgres://user:pass@localhost:5432/my-database -o models -g kysely -g zod");
|
40
40
|
log();
|
41
41
|
if (opts.help)
|
42
42
|
process.exit(0);
|
43
43
|
else
|
44
44
|
process.exit(1);
|
45
45
|
}
|
46
|
-
if (opts["all-
|
47
|
-
opts.
|
48
|
-
if (!(opts.
|
49
|
-
console.warn('No
|
50
|
-
// allow single
|
51
|
-
if (typeof opts.
|
52
|
-
opts.
|
46
|
+
if (opts["all-generators"])
|
47
|
+
opts.generator = Object.keys(generators);
|
48
|
+
if (!(opts.generator || config.generators))
|
49
|
+
console.warn('No generators specified, using default: ["kysely"]');
|
50
|
+
// allow single generator or comma-separated list of generators
|
51
|
+
if (typeof opts.generator === "string")
|
52
|
+
opts.generator = opts.generator.split(",");
|
53
53
|
// CLI args take precedence over config file
|
54
54
|
config.uri = opts.uri ?? config.uri;
|
55
55
|
config.out = opts.out ?? config.out;
|
56
|
-
config.
|
56
|
+
config.generators = opts.generator ?? config.generators ?? ["kysely"];
|
57
57
|
await generate(config);
|
package/lib/config.d.ts
CHANGED
@@ -4,8 +4,8 @@ export type ExtractorConfig = Exclude<ConstructorParameters<typeof Extractor>[0]
|
|
4
4
|
export interface BaseConfig {
|
5
5
|
/** The output directory for the generated models. Default: "models" */
|
6
6
|
out?: string;
|
7
|
-
/**
|
8
|
-
|
7
|
+
/** Generators to enable. Currently supported generators are "kysely" and "zod". Default: ["kysely"] */
|
8
|
+
generators?: ("kysely" | "zod")[];
|
9
9
|
/** The default schema to use for the generated models. These will be unprefixed in the final `Database` interface. Default: "public" */
|
10
10
|
defaultSchema?: string;
|
11
11
|
}
|
@@ -22,27 +22,27 @@ export interface ConfigConfig extends BaseConfig {
|
|
22
22
|
config: ExtractorConfig["config"];
|
23
23
|
}
|
24
24
|
export type TruePGConfig = Deunionise<PgConfig | UriConfig | ConfigConfig>;
|
25
|
-
export declare const
|
25
|
+
export declare const generators: {
|
26
26
|
kysely: import("./types.ts").createGenerator;
|
27
27
|
zod: import("./types.ts").createGenerator;
|
28
28
|
};
|
29
29
|
export declare function config(opts: TruePGConfig): {
|
30
30
|
out: string;
|
31
|
-
|
31
|
+
generators: ("kysely" | "zod")[];
|
32
32
|
defaultSchema: string;
|
33
33
|
pg: ExtractorConfig["pg"];
|
34
34
|
uri?: undefined;
|
35
35
|
config?: undefined;
|
36
36
|
} | {
|
37
37
|
out: string;
|
38
|
-
|
38
|
+
generators: ("kysely" | "zod")[];
|
39
39
|
defaultSchema: string;
|
40
40
|
uri: ExtractorConfig["uri"];
|
41
41
|
pg?: undefined;
|
42
42
|
config?: undefined;
|
43
43
|
} | {
|
44
44
|
out: string;
|
45
|
-
|
45
|
+
generators: ("kysely" | "zod")[];
|
46
46
|
defaultSchema: string;
|
47
47
|
config: ExtractorConfig["config"];
|
48
48
|
pg?: undefined;
|
package/lib/config.js
CHANGED
@@ -2,19 +2,19 @@ import { normalize as normalise } from "node:path";
|
|
2
2
|
import {} from "./util.js";
|
3
3
|
import { Kysely } from "./kysely/index.js";
|
4
4
|
import { Zod } from "./zod/index.js";
|
5
|
-
export const
|
5
|
+
export const generators = {
|
6
6
|
kysely: Kysely,
|
7
7
|
zod: Zod,
|
8
8
|
};
|
9
|
-
const
|
9
|
+
const availableGenerators = Object.keys(generators);
|
10
10
|
export function config(opts) {
|
11
11
|
const out = normalise(opts.out || "./models");
|
12
|
-
const
|
12
|
+
const generators = opts.generators || ["kysely"];
|
13
13
|
const defaultSchema = opts.defaultSchema || "public";
|
14
|
-
for (const
|
15
|
-
if (!
|
16
|
-
console.error('Requested
|
17
|
-
console.error("Available
|
14
|
+
for (const generator of opts.generators ?? []) {
|
15
|
+
if (!availableGenerators.includes(generator)) {
|
16
|
+
console.error('Requested generator "%s" not found.', generator);
|
17
|
+
console.error("Available generators: %s", availableGenerators.join(", "));
|
18
18
|
console.error("See documentation for more information.");
|
19
19
|
process.exit(1);
|
20
20
|
}
|
@@ -26,7 +26,7 @@ export function config(opts) {
|
|
26
26
|
return {
|
27
27
|
...opts,
|
28
28
|
out,
|
29
|
-
|
29
|
+
generators,
|
30
30
|
defaultSchema,
|
31
31
|
};
|
32
32
|
}
|
package/lib/extractor/index.d.ts
CHANGED
@@ -9,6 +9,7 @@ import { type FunctionDetails } from "./kinds/function.ts";
|
|
9
9
|
import { type DomainDetails } from "./kinds/domain.ts";
|
10
10
|
import { type RangeDetails } from "./kinds/range.ts";
|
11
11
|
import type { PgType } from "./pgtype.ts";
|
12
|
+
export { pgTypeKinds, type PgType, type Kind } from "./pgtype.ts";
|
12
13
|
import { Canonical } from "./canonicalise.ts";
|
13
14
|
export { Canonical };
|
14
15
|
export type { TableDetails, ViewDetails, MaterializedViewDetails, EnumDetails, CompositeTypeDetails, FunctionDetails, DomainDetails, RangeDetails, };
|
@@ -23,14 +24,14 @@ export { FunctionReturnTypeKind } from "./kinds/function.ts";
|
|
23
24
|
*/
|
24
25
|
export type Schema = {
|
25
26
|
name: string;
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
27
|
+
table: TableDetails[];
|
28
|
+
view: ViewDetails[];
|
29
|
+
materializedView: MaterializedViewDetails[];
|
30
|
+
enum: EnumDetails[];
|
31
|
+
composite: CompositeTypeDetails[];
|
32
|
+
function: FunctionDetails[];
|
33
|
+
domain: DomainDetails[];
|
34
|
+
range: RangeDetails[];
|
34
35
|
};
|
35
36
|
export type SchemaType = TableDetails | ViewDetails | MaterializedViewDetails | EnumDetails | CompositeTypeDetails | FunctionDetails | DomainDetails | RangeDetails;
|
36
37
|
/**
|
package/lib/extractor/index.js
CHANGED
@@ -10,18 +10,19 @@ import extractFunction, {} from "./kinds/function.js";
|
|
10
10
|
import extractDomain, {} from "./kinds/domain.js";
|
11
11
|
import extractRange, {} from "./kinds/range.js";
|
12
12
|
import fetchTypes from "./fetchTypes.js";
|
13
|
+
export { pgTypeKinds } from "./pgtype.js";
|
13
14
|
import { canonicalise, Canonical } from "./canonicalise.js";
|
14
15
|
export { Canonical };
|
15
16
|
export { FunctionReturnTypeKind } from "./kinds/function.js";
|
16
17
|
const emptySchema = {
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
18
|
+
table: [],
|
19
|
+
view: [],
|
20
|
+
materializedView: [],
|
21
|
+
enum: [],
|
22
|
+
composite: [],
|
23
|
+
function: [],
|
24
|
+
domain: [],
|
25
|
+
range: [],
|
25
26
|
};
|
26
27
|
const populatorMap = {
|
27
28
|
table: extractTable,
|
@@ -133,10 +134,7 @@ export class Extractor {
|
|
133
134
|
...emptySchema,
|
134
135
|
};
|
135
136
|
}
|
136
|
-
schemas[p.schemaName][
|
137
|
-
...schemas[p.schemaName][`${p.kind}s`],
|
138
|
-
p,
|
139
|
-
];
|
137
|
+
schemas[p.schemaName][p.kind] = [...schemas[p.schemaName][p.kind], p];
|
140
138
|
}
|
141
139
|
const result =
|
142
140
|
// options?.resolveViews
|
@@ -1,9 +1,9 @@
|
|
1
1
|
export declare const typeKindMap: {
|
2
|
-
readonly d: "domain";
|
3
2
|
readonly e: "enum";
|
3
|
+
readonly d: "domain";
|
4
4
|
readonly r: "range";
|
5
5
|
};
|
6
|
-
type TypeKind = (typeof typeKindMap)[keyof typeof typeKindMap];
|
6
|
+
export type TypeKind = (typeof typeKindMap)[keyof typeof typeKindMap];
|
7
7
|
export declare const classKindMap: {
|
8
8
|
readonly r: "table";
|
9
9
|
readonly p: "table";
|
@@ -11,12 +11,13 @@ export declare const classKindMap: {
|
|
11
11
|
readonly m: "materializedView";
|
12
12
|
readonly c: "composite";
|
13
13
|
};
|
14
|
-
type ClassKind = (typeof classKindMap)[keyof typeof classKindMap];
|
14
|
+
export type ClassKind = (typeof classKindMap)[keyof typeof classKindMap];
|
15
15
|
export declare const routineKindMap: {
|
16
16
|
readonly f: "function";
|
17
17
|
};
|
18
|
-
type RoutineKind = (typeof routineKindMap)[keyof typeof routineKindMap];
|
19
|
-
export
|
18
|
+
export type RoutineKind = (typeof routineKindMap)[keyof typeof routineKindMap];
|
19
|
+
export declare const pgTypeKinds: ("function" | "enum" | "domain" | "range" | "table" | "view" | "materializedView" | "composite")[];
|
20
|
+
export type Kind = (typeof pgTypeKinds)[number];
|
20
21
|
/**
|
21
22
|
* Base type for Postgres objects.
|
22
23
|
*/
|
@@ -38,4 +39,3 @@ export type PgType<K extends Kind = Kind> = {
|
|
38
39
|
*/
|
39
40
|
comment: string | null;
|
40
41
|
};
|
41
|
-
export {};
|
package/lib/extractor/pgtype.js
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
export const typeKindMap = {
|
2
|
-
d: "domain",
|
3
2
|
e: "enum",
|
3
|
+
d: "domain",
|
4
4
|
r: "range",
|
5
5
|
// Not supported (yet):
|
6
6
|
// m: 'multiRange',
|
@@ -28,3 +28,9 @@ export const routineKindMap = {
|
|
28
28
|
// a: 'aggregate',
|
29
29
|
// w: 'windowFunction',
|
30
30
|
};
|
31
|
+
const unique = (arr) => [...new Set(arr)];
|
32
|
+
export const pgTypeKinds = unique([
|
33
|
+
...Object.values(classKindMap),
|
34
|
+
...Object.values(typeKindMap),
|
35
|
+
...Object.values(routineKindMap),
|
36
|
+
]);
|
package/lib/imports.d.ts
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
import type { Canonical } from "./extractor/index.ts";
|
2
|
+
import type { FunctionReturnType } from "./extractor/index.ts";
|
3
|
+
import type { allowed_kind_names, FolderStructure } from "./types.ts";
|
4
|
+
export interface ImportIdentifier {
|
5
|
+
name: string;
|
6
|
+
alias?: string;
|
7
|
+
typeOnly?: boolean;
|
8
|
+
}
|
9
|
+
type Supported<T> = {
|
10
|
+
[key in allowed_kind_names]: T extends {
|
11
|
+
kind: key;
|
12
|
+
} ? T : never;
|
13
|
+
}[allowed_kind_names];
|
14
|
+
export declare class Import {
|
15
|
+
from: string | ((files: FolderStructure) => string);
|
16
|
+
namedImports?: (string | ImportIdentifier)[];
|
17
|
+
star?: string;
|
18
|
+
default?: string;
|
19
|
+
typeOnly?: boolean;
|
20
|
+
constructor(args: {
|
21
|
+
from: string | ((files: FolderStructure) => string);
|
22
|
+
namedImports?: (string | ImportIdentifier)[];
|
23
|
+
star?: string;
|
24
|
+
default?: string;
|
25
|
+
typeOnly?: boolean;
|
26
|
+
});
|
27
|
+
static fromInternal(opts: {
|
28
|
+
source: string;
|
29
|
+
type: Supported<Canonical | FunctionReturnType.ExistingTable>;
|
30
|
+
withName?: string;
|
31
|
+
typeOnly?: boolean;
|
32
|
+
}): Import;
|
33
|
+
}
|
34
|
+
export declare class ImportList {
|
35
|
+
imports: Import[];
|
36
|
+
constructor(imports?: Import[]);
|
37
|
+
static merge(lists: ImportList[]): ImportList;
|
38
|
+
add(item: Import): void;
|
39
|
+
stringify(files: FolderStructure): string;
|
40
|
+
}
|
41
|
+
export {};
|
package/lib/imports.js
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
import { dirname, relative } from "node:path";
|
2
|
+
import { eq } from "./util.js";
|
3
|
+
export class Import {
|
4
|
+
from;
|
5
|
+
namedImports;
|
6
|
+
star;
|
7
|
+
default;
|
8
|
+
typeOnly;
|
9
|
+
constructor(args) {
|
10
|
+
this.from = args.from;
|
11
|
+
this.namedImports = args.namedImports;
|
12
|
+
this.star = args.star;
|
13
|
+
this.default = args.default;
|
14
|
+
this.typeOnly = args.typeOnly ?? false;
|
15
|
+
}
|
16
|
+
static fromInternal(opts) {
|
17
|
+
const t = opts.type;
|
18
|
+
return new Import({
|
19
|
+
from: files => {
|
20
|
+
const schema = files.children[t.schema];
|
21
|
+
const kind = schema.children[t.kind];
|
22
|
+
const type = kind.children[t.name];
|
23
|
+
const path = `${files.name}/${schema.name}/${kind.kind}s/${type.name}.ts`;
|
24
|
+
return relative(dirname(opts.source), path);
|
25
|
+
},
|
26
|
+
namedImports: [opts.withName ?? t.name],
|
27
|
+
typeOnly: opts.typeOnly,
|
28
|
+
});
|
29
|
+
}
|
30
|
+
}
|
31
|
+
export class ImportList {
|
32
|
+
imports;
|
33
|
+
constructor(imports = []) {
|
34
|
+
this.imports = imports;
|
35
|
+
}
|
36
|
+
static merge(lists) {
|
37
|
+
return new ImportList(lists.flatMap(l => l.imports));
|
38
|
+
}
|
39
|
+
add(item) {
|
40
|
+
this.imports.push(item);
|
41
|
+
}
|
42
|
+
stringify(files) {
|
43
|
+
const modulegroups = {};
|
44
|
+
for (const item of this.imports) {
|
45
|
+
const from = typeof item.from === "function" ? item.from(files) : item.from;
|
46
|
+
const group = modulegroups[from];
|
47
|
+
if (group)
|
48
|
+
group.push(item);
|
49
|
+
else
|
50
|
+
modulegroups[from] = [item];
|
51
|
+
}
|
52
|
+
const imports = [];
|
53
|
+
const modules = Object.keys(modulegroups).sort((a, b) => {
|
54
|
+
const dotA = a.startsWith(".");
|
55
|
+
const dotB = b.startsWith(".");
|
56
|
+
// we could do localeCompare instead of 0, but 0 maintains order of fields for imports
|
57
|
+
return dotA === dotB ? 0 : dotA ? 1 : -1;
|
58
|
+
});
|
59
|
+
let broke = false;
|
60
|
+
for (const from of modules) {
|
61
|
+
if (!broke && from.startsWith(".")) {
|
62
|
+
imports.push("");
|
63
|
+
broke = true;
|
64
|
+
}
|
65
|
+
const items = modulegroups[from];
|
66
|
+
// unique named imports from this module
|
67
|
+
const namedImports = items
|
68
|
+
.flatMap(s => s.namedImports?.map(i => (typeof i === "string" ? { name: i, typeOnly: s.typeOnly } : i)) ?? [])
|
69
|
+
.filter((imp, index, arr) => {
|
70
|
+
if (arr.findIndex(i => eq(i, imp)) !== index)
|
71
|
+
return false;
|
72
|
+
return true;
|
73
|
+
});
|
74
|
+
const allTypeOnly = namedImports.every(i => i.typeOnly);
|
75
|
+
const namedImportPart = namedImports
|
76
|
+
.map(i => (!allTypeOnly && i.typeOnly ? "type " : "") + i.name)
|
77
|
+
.join(", ");
|
78
|
+
const namedImportLine = namedImportPart
|
79
|
+
? `import ${allTypeOnly ? "type " : ""}{ ${namedImportPart} } from "${from}";`
|
80
|
+
: undefined;
|
81
|
+
// all star imports from this module
|
82
|
+
const stars = items.filter(i => i.star).filter((i, index, arr) => arr.findIndex(j => eq(j, i)) === index);
|
83
|
+
const starImportLines = stars.map(i => `import ${i.typeOnly ? "type " : ""}* as ${i.star} from "${from}";`);
|
84
|
+
// all default imports from this module
|
85
|
+
const defaults = items
|
86
|
+
.filter(i => i.default)
|
87
|
+
.filter((i, index, arr) => arr.findIndex(j => eq(j, i)) === index);
|
88
|
+
const defaultImportLines = defaults.map(i => `import ${i.typeOnly ? "type " : ""}${i.default} from "${from}";`);
|
89
|
+
const sideEffectImports = items.find(i => !i.default && !i.star && !i.namedImports?.length);
|
90
|
+
const sideEffectImportLine = sideEffectImports ? `import "${sideEffectImports.from}";` : undefined;
|
91
|
+
if (sideEffectImportLine)
|
92
|
+
imports.push(sideEffectImportLine);
|
93
|
+
if (namedImportLine)
|
94
|
+
imports.push(namedImportLine);
|
95
|
+
if (starImportLines.length)
|
96
|
+
imports.push(...starImportLines);
|
97
|
+
if (defaultImportLines.length)
|
98
|
+
imports.push(...defaultImportLines);
|
99
|
+
}
|
100
|
+
return imports.join("\n");
|
101
|
+
}
|
102
|
+
}
|