true-pg 0.7.0 → 0.8.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 (41) hide show
  1. package/lib/extractor/adapter.d.ts +8 -5
  2. package/lib/extractor/adapter.js +27 -12
  3. package/lib/extractor/canonicalise/composite.d.ts +7 -0
  4. package/lib/extractor/canonicalise/composite.js +53 -0
  5. package/lib/extractor/canonicalise/domain.d.ts +12 -0
  6. package/lib/extractor/canonicalise/domain.js +77 -0
  7. package/lib/extractor/canonicalise/enum.d.ts +8 -0
  8. package/lib/extractor/canonicalise/enum.js +22 -0
  9. package/lib/extractor/canonicalise/index.d.ts +11 -0
  10. package/lib/extractor/canonicalise/index.js +148 -0
  11. package/lib/extractor/canonicalise/parse.d.ts +43 -0
  12. package/lib/extractor/canonicalise/parse.js +50 -0
  13. package/lib/extractor/canonicalise/range.d.ts +11 -0
  14. package/lib/extractor/canonicalise/range.js +36 -0
  15. package/lib/extractor/canonicalise/resolve.d.ts +19 -0
  16. package/lib/extractor/canonicalise/resolve.js +59 -0
  17. package/lib/extractor/canonicalise/types.d.ts +70 -0
  18. package/lib/extractor/canonicalise/types.js +13 -0
  19. package/lib/extractor/index.d.ts +5 -2
  20. package/lib/extractor/index.js +5 -7
  21. package/lib/extractor/kinds/composite.d.ts +1 -1
  22. package/lib/extractor/kinds/composite.js +1 -1
  23. package/lib/extractor/kinds/domain.d.ts +1 -1
  24. package/lib/extractor/kinds/domain.js +1 -1
  25. package/lib/extractor/kinds/function.d.ts +1 -1
  26. package/lib/extractor/kinds/function.js +5 -7
  27. package/lib/extractor/kinds/materialized-view.d.ts +1 -1
  28. package/lib/extractor/kinds/materialized-view.js +4 -7
  29. package/lib/extractor/kinds/range.d.ts +1 -1
  30. package/lib/extractor/kinds/range.js +1 -2
  31. package/lib/extractor/kinds/table.d.ts +1 -1
  32. package/lib/extractor/kinds/table.js +2 -7
  33. package/lib/extractor/kinds/view.d.ts +1 -1
  34. package/lib/extractor/kinds/view.js +4 -7
  35. package/lib/imports.test.js +6 -14
  36. package/lib/index.js +2 -2
  37. package/lib/util.d.ts +3 -6
  38. package/lib/util.js +15 -11
  39. package/package.json +1 -1
  40. package/lib/extractor/canonicalise.d.ts +0 -110
  41. package/lib/extractor/canonicalise.js +0 -384
@@ -0,0 +1,70 @@
1
+ export declare namespace Canonical {
2
+ enum Kind {
3
+ Base = "base",
4
+ Composite = "composite",
5
+ Domain = "domain",
6
+ Enum = "enum",
7
+ Range = "range",
8
+ Pseudo = "pseudo",
9
+ Unknown = "unknown"
10
+ }
11
+ interface Abstract {
12
+ original_type: string;
13
+ canonical_name: string;
14
+ schema: string;
15
+ name: string;
16
+ kind: Kind;
17
+ dimensions: number;
18
+ modifiers?: string | null;
19
+ }
20
+ interface Base extends Abstract {
21
+ kind: Kind.Base;
22
+ }
23
+ interface Enum extends Abstract {
24
+ kind: Kind.Enum;
25
+ enum_values: string[];
26
+ }
27
+ interface CompositeAttribute {
28
+ name: string;
29
+ index: number;
30
+ type: Canonical;
31
+ comment: string | null;
32
+ defaultValue: any;
33
+ isNullable: boolean;
34
+ /**
35
+ * Whether the attribute is an identity attribute.
36
+ */
37
+ isIdentity: boolean;
38
+ /**
39
+ * Behavior of the generated attribute. "ALWAYS" if always generated,
40
+ * "NEVER" if never generated, "BY DEFAULT" if generated when a value
41
+ * is not provided.
42
+ */
43
+ generated: "ALWAYS" | "NEVER" | "BY DEFAULT";
44
+ }
45
+ interface Composite extends Abstract {
46
+ kind: Kind.Composite;
47
+ attributes: CompositeAttribute[];
48
+ }
49
+ interface Domain extends Abstract {
50
+ kind: Kind.Domain;
51
+ domain_base_type: Canonical;
52
+ }
53
+ interface Range extends Abstract {
54
+ kind: Kind.Range;
55
+ range_subtype: Canonical;
56
+ }
57
+ interface Pseudo extends Abstract {
58
+ kind: Kind.Pseudo;
59
+ }
60
+ }
61
+ export type Canonical = Canonical.Base | Canonical.Enum | Canonical.Composite | Canonical.Domain | Canonical.Range | Canonical.Pseudo;
62
+ type Exclusive<T> = Omit<T, Exclude<keyof Canonical.Abstract, "kind" | "canonical_name">>;
63
+ export type ExclusiveBase = Exclusive<Canonical.Base>;
64
+ export type ExclusiveEnum = Exclusive<Canonical.Enum>;
65
+ export type ExclusiveComposite = Exclusive<Canonical.Composite>;
66
+ export type ExclusiveDomain = Exclusive<Canonical.Domain>;
67
+ export type ExclusiveRange = Exclusive<Canonical.Range>;
68
+ export type ExclusivePseudo = Exclusive<Canonical.Pseudo>;
69
+ export type ExclusiveCanonProps = ExclusiveBase | ExclusiveEnum | ExclusiveComposite | ExclusiveDomain | ExclusiveRange | ExclusivePseudo;
70
+ export {};
@@ -0,0 +1,13 @@
1
+ export var Canonical;
2
+ (function (Canonical) {
3
+ let Kind;
4
+ (function (Kind) {
5
+ Kind["Base"] = "base";
6
+ Kind["Composite"] = "composite";
7
+ Kind["Domain"] = "domain";
8
+ Kind["Enum"] = "enum";
9
+ Kind["Range"] = "range";
10
+ Kind["Pseudo"] = "pseudo";
11
+ Kind["Unknown"] = "unknown";
12
+ })(Kind = Canonical.Kind || (Canonical.Kind = {}));
13
+ })(Canonical || (Canonical = {}));
@@ -11,7 +11,7 @@ import { type DomainDetails } from "./kinds/domain.ts";
11
11
  import { type RangeDetails } from "./kinds/range.ts";
12
12
  import type { PgType } from "./pgtype.ts";
13
13
  export { pgTypeKinds, type PgType, type Kind } from "./pgtype.ts";
14
- import { Canonical } from "./canonicalise.ts";
14
+ import { Canonical } from "./canonicalise/index.ts";
15
15
  export { Canonical };
16
16
  export type { TableDetails, ViewDetails, MaterializedViewDetails, EnumDetails, CompositeTypeDetails, FunctionDetails, DomainDetails, RangeDetails, };
17
17
  export type { TableColumn } from "./kinds/table.ts";
@@ -92,5 +92,8 @@ export declare class Extractor {
92
92
  * @param options - Optional options
93
93
  * @returns A record of all the schemas extracted, indexed by schema name.
94
94
  */
95
- extractSchemas(options?: ExtractSchemaOptions): Promise<Record<string, Schema>>;
95
+ extractSchemas(options?: ExtractSchemaOptions): Promise<{
96
+ schemas: Record<string, Schema>;
97
+ queryCount: number;
98
+ }>;
96
99
  }
@@ -11,7 +11,7 @@ import extractDomain, {} from "./kinds/domain.js";
11
11
  import extractRange, {} from "./kinds/range.js";
12
12
  import fetchTypes from "./fetchTypes.js";
13
13
  export { pgTypeKinds } from "./pgtype.js";
14
- import { canonicalise, Canonical, canonicaliseFromOids } from "./canonicalise.js";
14
+ import { Canonical } from "./canonicalise/index.js";
15
15
  export { Canonical };
16
16
  export { FunctionReturnTypeKind } from "./kinds/function.js";
17
17
  const emptySchema = {
@@ -133,13 +133,11 @@ export class Extractor {
133
133
  }
134
134
  schemas[p.schemaName][p.kind] = [...schemas[p.schemaName][p.kind], p];
135
135
  }
136
- const result =
137
- // options?.resolveViews
138
- // ? resolveViewColumns(schemas)
139
- // :
140
- schemas;
136
+ // resolve all canonical types and patch the results into their placeholders
137
+ await db.resolve();
138
+ const queryCount = db.queryCount;
141
139
  options?.onProgressEnd?.();
142
140
  await db.close();
143
- return result;
141
+ return { schemas, queryCount };
144
142
  }
145
143
  }
@@ -1,6 +1,6 @@
1
1
  import type { DbAdapter } from "../adapter.ts";
2
2
  import type { PgType } from "../pgtype.ts";
3
- import type { Canonical } from "../canonicalise.ts";
3
+ import type { Canonical } from "../canonicalise/index.ts";
4
4
  /**
5
5
  * Composite type in a schema with details.
6
6
  */
@@ -2,7 +2,7 @@ const extractComposite = async (db, composite) => {
2
2
  // Form the fully qualified type name
3
3
  const fullTypeName = `"${composite.schemaName}"."${composite.name}"`;
4
4
  // Get canonical type information with all the metadata
5
- const [canonical] = await db.canonicalise([fullTypeName]);
5
+ const canonical = db.enqueue(fullTypeName);
6
6
  // Return the composite type with its canonical representation
7
7
  return {
8
8
  ...composite,
@@ -1,6 +1,6 @@
1
1
  import type { DbAdapter } from "../adapter.ts";
2
2
  import type { PgType } from "../pgtype.ts";
3
- import type { Canonical } from "../canonicalise.ts";
3
+ import type { Canonical } from "../canonicalise/index.ts";
4
4
  /**
5
5
  * Domain type in a schema with details.
6
6
  */
@@ -2,7 +2,7 @@ const extractDomain = async (db, domain) => {
2
2
  // Form the fully qualified type name
3
3
  const fullTypeName = `"${domain.schemaName}"."${domain.name}"`;
4
4
  // Get canonical type information with all the metadata
5
- const [canonical] = await db.canonicalise([fullTypeName]);
5
+ const canonical = db.enqueue(fullTypeName);
6
6
  // Return the composite type with its canonical representation
7
7
  return {
8
8
  ...domain,
@@ -1,6 +1,6 @@
1
1
  import type { DbAdapter } from "../adapter.ts";
2
2
  import type { PgType } from "../pgtype.ts";
3
- import type { Canonical } from "../canonicalise.ts";
3
+ import type { Canonical } from "../canonicalise/index.ts";
4
4
  declare const parameterModeMap: {
5
5
  readonly i: "IN";
6
6
  readonly o: "OUT";
@@ -74,13 +74,13 @@ async function extractFunction(db, pgType) {
74
74
  if (row.arg_names && !row.arg_modes)
75
75
  row.arg_modes = row.arg_names.map(() => "i");
76
76
  const argModes = row.arg_modes?.map(mode => parameterModeMap[mode]) ?? [];
77
- const canonical_arg_types = row.arg_types ? await db.canonicalise(row.arg_types) : [];
77
+ const canonical_arg_types = row.arg_types ? row.arg_types.map(type => db.enqueue(type)) : [];
78
78
  let returnType;
79
79
  const tableMatch = row.declared_return_type.match(/^TABLE\((.*)\)$/i);
80
80
  if (tableMatch) {
81
81
  const columnDefs = parsePostgresTableDefinition(row.declared_return_type);
82
82
  const columnTypes = columnDefs.map(col => col.type);
83
- const canonicalColumnTypes = await db.canonicalise(columnTypes);
83
+ const canonicalColumnTypes = columnTypes.map(type => db.enqueue(type));
84
84
  returnType = {
85
85
  kind: FunctionReturnTypeKind.InlineTable,
86
86
  columns: columnDefs.map((col, i) => ({
@@ -110,7 +110,7 @@ async function extractFunction(db, pgType) {
110
110
  else if (
111
111
  // "c" = composite type
112
112
  row.return_type_relation_kind === "c") {
113
- const canonicalReturnType = (await db.canonicalise([row.return_type_string]))[0];
113
+ const canonicalReturnType = db.enqueue(row.return_type_string);
114
114
  returnType = {
115
115
  kind: FunctionReturnTypeKind.Regular,
116
116
  type: canonicalReturnType,
@@ -119,19 +119,17 @@ async function extractFunction(db, pgType) {
119
119
  }
120
120
  else {
121
121
  console.warn(`Composite return type '${row.return_type_string}' has unexpected relkind '${row.return_type_relation_kind}' for function ${pgType.schemaName}.${row.name}`);
122
- const canonicalReturnType = (await db.canonicalise([row.return_type_string]))[0];
123
122
  returnType = {
124
123
  kind: FunctionReturnTypeKind.Regular,
125
- type: canonicalReturnType,
124
+ type: db.enqueue(row.return_type_string),
126
125
  isSet: row.returns_set,
127
126
  };
128
127
  }
129
128
  }
130
129
  else {
131
- const canonicalReturnType = (await db.canonicalise([row.return_type_string]))[0];
132
130
  returnType = {
133
131
  kind: FunctionReturnTypeKind.Regular,
134
- type: canonicalReturnType,
132
+ type: db.enqueue(row.return_type_string),
135
133
  isSet: row.returns_set,
136
134
  };
137
135
  }
@@ -1,6 +1,6 @@
1
1
  import type { DbAdapter } from "../adapter.ts";
2
2
  import type { PgType } from "../pgtype.ts";
3
- import type { Canonical } from "../canonicalise.ts";
3
+ import type { Canonical } from "../canonicalise/index.ts";
4
4
  export interface MaterializedViewColumn {
5
5
  name: string;
6
6
  type: Canonical;
@@ -1,5 +1,5 @@
1
1
  const extractMaterializedView = async (db, mview) => {
2
- // 1. Query for columns (using pg_attribute for potentially more accurate nullability)
2
+ // Query for columns (using pg_attribute for potentially more accurate nullability)
3
3
  const columnQuery = await db.query(`
4
4
  SELECT
5
5
  attr.attname AS "name",
@@ -23,17 +23,14 @@ const extractMaterializedView = async (db, mview) => {
23
23
  AND NOT attr.attisdropped
24
24
  ORDER BY attr.attnum;
25
25
  `, [mview.name, mview.schemaName]);
26
- // 2. Get canonical types
27
- const definedTypes = columnQuery.map(row => row.definedType);
28
- const canonicalTypes = await db.canonicalise(definedTypes);
29
- const columns = columnQuery.map((row, index) => ({
26
+ const columns = columnQuery.map(row => ({
30
27
  name: row.name,
31
- type: canonicalTypes[index],
28
+ type: db.enqueue(row.definedType),
32
29
  isNullable: row.isNullable,
33
30
  ordinalPosition: row.ordinalPosition,
34
31
  comment: row.comment,
35
32
  }));
36
- // 3. Query for materialized view definition, comment, and properties
33
+ // Query for materialized view definition, comment, and properties
37
34
  const mviewInfoQuery = await db.query(`
38
35
  SELECT
39
36
  m.definition,
@@ -1,6 +1,6 @@
1
1
  import type { DbAdapter } from "../adapter.ts";
2
2
  import type { PgType } from "../pgtype.ts";
3
- import type { Canonical } from "../canonicalise.ts";
3
+ import type { Canonical } from "../canonicalise/index.ts";
4
4
  /**
5
5
  * Range type in a schema with details.
6
6
  */
@@ -1,8 +1,7 @@
1
1
  const extractRange = async (db, range) => {
2
2
  // Form the fully qualified type name
3
3
  const fullTypeName = `"${range.schemaName}"."${range.name}"`;
4
- // Get canonical type information with all the metadata
5
- const [canonical] = await db.canonicalise([fullTypeName]);
4
+ const canonical = db.enqueue(fullTypeName);
6
5
  // Return the composite type with its canonical representation
7
6
  return {
8
7
  ...range,
@@ -1,6 +1,6 @@
1
1
  import { DbAdapter } from "../adapter.ts";
2
2
  import type { PgType } from "../pgtype.ts";
3
- import type { Canonical } from "../canonicalise.ts";
3
+ import type { Canonical } from "../canonicalise/index.ts";
4
4
  export declare const updateActionMap: {
5
5
  readonly a: "NO ACTION";
6
6
  readonly r: "RESTRICT";
@@ -105,14 +105,10 @@ const extractTable = async (db, table) => {
105
105
  AND NOT attr.attisdropped
106
106
  ORDER BY col.ordinal_position;
107
107
  `, [table.name, table.schemaName]);
108
- // Get the expanded type names from the query result
109
- const definedTypes = columnsQuery.map(row => row.definedType);
110
- // Use canonicaliseTypes to get detailed type information
111
- const canonicalTypes = await db.canonicalise(definedTypes);
112
108
  // Combine the column information with the canonical type information
113
- const columns = columnsQuery.map((row, index) => ({
109
+ const columns = columnsQuery.map(row => ({
114
110
  name: row.name,
115
- type: canonicalTypes[index],
111
+ type: db.enqueue(row.definedType),
116
112
  comment: row.comment,
117
113
  defaultValue: row.defaultValue,
118
114
  isPrimaryKey: row.isPrimaryKey,
@@ -122,7 +118,6 @@ const extractTable = async (db, table) => {
122
118
  isIdentity: row.isIdentity,
123
119
  isUpdatable: row.isUpdatable,
124
120
  generated: row.generated,
125
- informationSchemaValue: row.informationSchemaValue,
126
121
  }));
127
122
  const indicesQuery = await db.query(`
128
123
  WITH index_columns AS (
@@ -1,6 +1,6 @@
1
1
  import type { DbAdapter } from "../adapter.ts";
2
2
  import type { PgType } from "../pgtype.ts";
3
- import type { Canonical } from "../canonicalise.ts";
3
+ import type { Canonical } from "../canonicalise/index.ts";
4
4
  export interface ViewColumn {
5
5
  name: string;
6
6
  type: Canonical;
@@ -1,5 +1,5 @@
1
1
  const extractView = async (db, view) => {
2
- // 1. Query for columns (information_schema.columns + pg_attribute)
2
+ // Query for columns (information_schema.columns + pg_attribute)
3
3
  const columnQuery = await db.query(`
4
4
  SELECT
5
5
  col.column_name AS "name",
@@ -22,17 +22,14 @@ const extractView = async (db, view) => {
22
22
  AND NOT attr.attisdropped -- Exclude dropped columns
23
23
  ORDER BY col.ordinal_position;
24
24
  `, [view.name, view.schemaName]);
25
- // 2. Get canonical types
26
- const definedTypes = columnQuery.map(row => row.definedType);
27
- const canonicalTypes = await db.canonicalise(definedTypes);
28
- const columns = columnQuery.map((row, index) => ({
25
+ const columns = columnQuery.map(row => ({
29
26
  name: row.name,
30
- type: canonicalTypes[index],
27
+ type: db.enqueue(row.definedType),
31
28
  isNullable: row.isNullable,
32
29
  isUpdatable: row.isUpdatable,
33
30
  ordinalPosition: row.ordinalPosition,
34
31
  }));
35
- // 3. Query for view definition, comment, and other properties
32
+ // Query for view definition, comment, and other properties
36
33
  const viewInfoQuery = await db.query(`
37
34
  SELECT
38
35
  d.description AS "comment",
@@ -1,4 +1,4 @@
1
- import { Canonical } from "./extractor/canonicalise.js";
1
+ import { Canonical } from "./extractor/canonicalise/index.js";
2
2
  import { Import, ImportList } from "./imports.js";
3
3
  import { describe, it, expect } from "bun:test";
4
4
  const files = {
@@ -92,8 +92,7 @@ describe("Import Class", () => {
92
92
  },
93
93
  });
94
94
  expect(importInstance).toBeInstanceOf(Import);
95
- expect(typeof importInstance.from === "function" ||
96
- typeof importInstance.from === "string").toBe(true);
95
+ expect(typeof importInstance.from === "function" || typeof importInstance.from === "string").toBe(true);
97
96
  if (typeof importInstance.from === "function") {
98
97
  const generatedPath = importInstance.from(files);
99
98
  expect(generatedPath).toBe("../enums/testEnum.ts");
@@ -113,8 +112,7 @@ describe("Import Class", () => {
113
112
  },
114
113
  });
115
114
  expect(importInstance).toBeInstanceOf(Import);
116
- expect(typeof importInstance.from === "function" ||
117
- typeof importInstance.from === "string").toBe(true);
115
+ expect(typeof importInstance.from === "function" || typeof importInstance.from === "string").toBe(true);
118
116
  if (typeof importInstance.from === "function") {
119
117
  const generatedPath = importInstance.from(files);
120
118
  expect(generatedPath).toBe("../enums/testEnum.ts");
@@ -141,19 +139,13 @@ describe("ImportList Class", () => {
141
139
  expect(importList.imports[0]).toBe(newImport);
142
140
  });
143
141
  it("should merge import lists correctly", () => {
144
- const list1 = new ImportList([
145
- new Import({ from: "module1", namedImports: ["a"] }),
146
- ]);
147
- const list2 = new ImportList([
148
- new Import({ from: "module2", namedImports: ["b"] }),
149
- ]);
142
+ const list1 = new ImportList([new Import({ from: "module1", namedImports: ["a"] })]);
143
+ const list2 = new ImportList([new Import({ from: "module2", namedImports: ["b"] })]);
150
144
  const mergedList = ImportList.merge([list1, list2]);
151
145
  expect(mergedList.imports).toHaveLength(2);
152
146
  });
153
147
  it("should merge import lists correctly with empty list", () => {
154
- const list1 = new ImportList([
155
- new Import({ from: "module1", namedImports: ["a"] }),
156
- ]);
148
+ const list1 = new ImportList([new Import({ from: "module1", namedImports: ["a"] })]);
157
149
  const list2 = new ImportList([]);
158
150
  const mergedList = ImportList.merge([list1, list2]);
159
151
  expect(mergedList.imports).toHaveLength(1);
package/lib/index.js CHANGED
@@ -217,8 +217,8 @@ export async function generate(opts, generators) {
217
217
  const out = validated.out;
218
218
  const extractor = new Extractor(opts);
219
219
  const start = performance.now();
220
- const schemas = await extractor.extractSchemas();
221
- console.log("Extracted schemas %s\n", time(start));
220
+ const { schemas, queryCount } = await extractor.extractSchemas();
221
+ console.log("Extracted schemas %s (made %s queries)\n", time(start), queryCount);
222
222
  console.info("Generators enabled: %s\n", validated.generators.join(", "));
223
223
  generators = validated.generators.map(generator => builtin_generators[generator]).concat(generators ?? []);
224
224
  console.log("Clearing directory and generating schemas at '%s'\n", out);
package/lib/util.d.ts CHANGED
@@ -1,10 +1,4 @@
1
1
  export declare const unreachable: (value: never) => never;
2
- export declare class Deferred<T> {
3
- resolve: (value: T) => void;
4
- reject: (reason?: any) => void;
5
- promise: Promise<T>;
6
- constructor();
7
- }
8
2
  export declare const eq: <T>(a: T, b: T) => boolean;
9
3
  export declare const toPascalCase: (str: string) => string;
10
4
  export declare const to_snake_case: (str: string) => string;
@@ -20,4 +14,7 @@ export type Simplify<T> = {
20
14
  export declare const parens: (str: string, type?: string) => string;
21
15
  export declare const quote: (str: string, using?: string) => string;
22
16
  export declare const quoteI: (str: string, using?: string) => string;
17
+ export declare const removeNulls: <T>(o: T) => T;
18
+ export declare const pos: (num: number) => number | undefined;
19
+ export declare const minifyQuery: (query: string) => string;
23
20
  export {};
package/lib/util.js CHANGED
@@ -1,17 +1,6 @@
1
1
  export const unreachable = (value) => {
2
2
  throw new Error(`Fatal: Reached unreachable code: ${value}`);
3
3
  };
4
- export class Deferred {
5
- resolve;
6
- reject;
7
- promise;
8
- constructor() {
9
- this.promise = new Promise((resolve, reject) => {
10
- this.resolve = resolve;
11
- this.reject = reject;
12
- });
13
- }
14
- }
15
4
  export const eq = (a, b) => {
16
5
  if (a === b)
17
6
  return true;
@@ -142,3 +131,18 @@ const isIdentifierInvalid = (str) => {
142
131
  export const parens = (str, type = "()") => `${type[0]}${str}${type[1]}`;
143
132
  export const quote = (str, using = '"') => `${using}${str.replaceAll(using, "\\" + using)}${using}`;
144
133
  export const quoteI = (str, using = '"') => (isIdentifierInvalid(str) ? quote(str, using) : str);
134
+ export const removeNulls = (o) => {
135
+ for (const key in o)
136
+ if (o[key] == null)
137
+ delete o[key];
138
+ return o;
139
+ };
140
+ export const pos = (num) => (num < 0 ? undefined : num);
141
+ export const minifyQuery = (query) => {
142
+ return query
143
+ .split("\n")
144
+ .map(line => line.slice(0, pos(line.indexOf("--"))))
145
+ .join("\n")
146
+ .replaceAll(/\s+/g, " ")
147
+ .trim();
148
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "true-pg",
3
- "version": "0.7.0",
3
+ "version": "0.8.0",
4
4
  "type": "module",
5
5
  "module": "lib/index.js",
6
6
  "main": "lib/index.js",
@@ -1,110 +0,0 @@
1
- import { DbAdapter } from "./adapter.ts";
2
- interface ParsedTypeName {
3
- /** Name after removing modifiers and brackets, e.g. "varchar" in "varchar(50)" */
4
- base: string;
5
- /** Modifiers, e.g. "50" in "varchar(50)" */
6
- modifiers: string | null;
7
- /** Number of dimensions from explicit brackets, e.g. 1 in "int[]" */
8
- dimensions: number;
9
- /** Original type name, e.g. "varchar(50)" */
10
- original: string;
11
- }
12
- /**
13
- * Parses a PostgreSQL type name string to extract its base name,
14
- * modifiers, and dimensions from explicit '[]' brackets.
15
- *
16
- * Examples:
17
- *
18
- * - `parseTypeName("varchar(50)")`
19
- *
20
- * `⤷ { baseTypeName: "varchar", modifiers: "50", dimensions: 0, originalTypeName: "varchar(50)" }`
21
- *
22
- * - `parseTypeName("int[]")`
23
- *
24
- * `⤷ { baseTypeName: "int", modifiers: null, dimensions: 1, originalTypeName: "int[]" }`
25
- *
26
- * - `parseTypeName("public.my_table[][]")`
27
- *
28
- * `⤷ { baseTypeName: "public.my_table", modifiers: null, dimensions: 2, originalTypeName: "public.my_table[][]" }`
29
- *
30
- * - `parseTypeName("numeric(10, 2)[]")`
31
- *
32
- * `⤷ { baseTypeName: "numeric", modifiers: "10, 2", dimensions: 1, originalTypeName: "numeric(10, 2)[]" }`
33
- *
34
- * - `parseTypeName("geometry(Point, 4326)")`
35
- *
36
- * `⤷ { baseTypeName: "geometry", modifiers: "Point, 4326", dimensions: 0, originalTypeName: "geometry(Point, 4326)" }`
37
- *
38
- * - `parseTypeName("_text")`
39
- *
40
- * `⤷ { baseTypeName: "_text", modifiers: null, dimensions: 0, originalTypeName: "_text" }`
41
- *
42
- * Internal arrays aren't handled here
43
- */
44
- export declare function parseTypeName(type: string): ParsedTypeName;
45
- export declare namespace Canonical {
46
- enum Kind {
47
- Base = "base",
48
- Composite = "composite",
49
- Domain = "domain",
50
- Enum = "enum",
51
- Range = "range",
52
- Pseudo = "pseudo",
53
- Unknown = "unknown"
54
- }
55
- interface Abstract {
56
- original_type: string;
57
- canonical_name: string;
58
- schema: string;
59
- name: string;
60
- kind: Kind;
61
- dimensions: number;
62
- modifiers?: string | null;
63
- }
64
- interface Base extends Abstract {
65
- kind: Kind.Base;
66
- }
67
- interface Enum extends Abstract {
68
- kind: Kind.Enum;
69
- enum_values: string[];
70
- }
71
- interface CompositeAttribute {
72
- name: string;
73
- index: number;
74
- type: Canonical;
75
- comment: string | null;
76
- defaultValue: any;
77
- isNullable: boolean;
78
- /**
79
- * Whether the attribute is an identity attribute.
80
- */
81
- isIdentity: boolean;
82
- /**
83
- * Behavior of the generated attribute. "ALWAYS" if always generated,
84
- * "NEVER" if never generated, "BY DEFAULT" if generated when a value
85
- * is not provided.
86
- */
87
- generated: "ALWAYS" | "NEVER" | "BY DEFAULT";
88
- }
89
- interface Composite extends Abstract {
90
- kind: Kind.Composite;
91
- attributes: CompositeAttribute[];
92
- }
93
- interface Domain extends Abstract {
94
- kind: Kind.Domain;
95
- domain_base_type: Canonical;
96
- }
97
- interface Range extends Abstract {
98
- kind: Kind.Range;
99
- range_subtype: Canonical;
100
- }
101
- interface Pseudo extends Abstract {
102
- kind: Kind.Pseudo;
103
- }
104
- }
105
- export type Canonical = Canonical.Base | Canonical.Enum | Canonical.Composite | Canonical.Domain | Canonical.Range | Canonical.Pseudo;
106
- type ExclusiveCanonProps = Omit<Canonical, keyof Canonical.Abstract>;
107
- export declare const canonicalise: (db: DbAdapter, types: string[], rawTypeCache: Map<string, Promise<Canonical>>, canonicalCache: Map<string, Promise<ExclusiveCanonProps>>) => Promise<Canonical[]>;
108
- export declare const oidsToQualifiedNames: (db: DbAdapter, oids: number[]) => Promise<string[]>;
109
- export declare const canonicaliseFromOids: (db: DbAdapter, oids: number[]) => Promise<Canonical[]>;
110
- export {};