@an5/orm 1.0.8 → 1.1.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 (73) hide show
  1. package/README.md +174 -175
  2. package/dist/an5Metadata.js +64 -0
  3. package/dist/an5Orm.d.ts +92 -3
  4. package/dist/an5Orm.js +697 -206
  5. package/dist/config.d.ts +9 -1
  6. package/dist/config.js +13 -18
  7. package/dist/errors.d.ts +1 -1
  8. package/dist/errors.js +1 -1
  9. package/dist/generator/src/api.d.ts +35 -0
  10. package/dist/generator/src/api.js +58 -0
  11. package/dist/generator/src/code-generator.d.ts +14 -13
  12. package/dist/generator/src/code-generator.js +249 -225
  13. package/dist/generator/src/config.d.ts +162 -0
  14. package/dist/generator/src/config.js +354 -0
  15. package/dist/generator/src/dialect.d.ts +88 -0
  16. package/dist/generator/src/dialect.js +318 -0
  17. package/dist/generator/src/dotnet-generator.d.ts +21 -11
  18. package/dist/generator/src/dotnet-generator.js +1053 -546
  19. package/dist/generator/src/field-types.d.ts +96 -0
  20. package/dist/generator/src/field-types.js +433 -0
  21. package/dist/generator/src/golang-generator.d.ts +36 -0
  22. package/dist/generator/src/golang-generator.js +1229 -0
  23. package/dist/generator/src/index.d.ts +1 -1
  24. package/dist/generator/src/index.js +137 -88
  25. package/dist/generator/src/metadata-generator.d.ts +11 -8
  26. package/dist/generator/src/metadata-generator.js +105 -90
  27. package/dist/generator/src/parser.d.ts +37 -11
  28. package/dist/generator/src/parser.js +208 -206
  29. package/dist/generator/src/push-apply.d.ts +37 -0
  30. package/dist/generator/src/push-apply.js +109 -0
  31. package/dist/generator/src/push-schema.d.ts +93 -0
  32. package/dist/generator/src/push-schema.js +189 -0
  33. package/dist/generator/src/python-generator.d.ts +37 -9
  34. package/dist/generator/src/python-generator.js +428 -105
  35. package/dist/generator/src/rust-generator.d.ts +38 -0
  36. package/dist/generator/src/rust-generator.js +971 -0
  37. package/dist/generator/src/suggest.d.ts +17 -0
  38. package/dist/generator/src/suggest.js +45 -0
  39. package/dist/generator/src/type-kinds.d.ts +27 -0
  40. package/dist/generator/src/type-kinds.js +72 -0
  41. package/dist/generator/src/types.d.ts +60 -27
  42. package/dist/generator/src/types.js +41 -2
  43. package/dist/index.d.ts +3 -2
  44. package/dist/index.js +19 -8
  45. package/dist/logger.js +1 -1
  46. package/dist/migration-core.d.ts +102 -0
  47. package/dist/migration-core.js +731 -0
  48. package/dist/orm.d.ts +147 -0
  49. package/dist/orm.js +1654 -0
  50. package/dist/provider-support.d.ts +27 -0
  51. package/dist/provider-support.js +50 -0
  52. package/dist/scripts/release-cli.d.ts +2 -2
  53. package/dist/scripts/release-cli.js +115 -115
  54. package/dist/sql-utils.d.ts +3 -1
  55. package/dist/sql-utils.js +94 -24
  56. package/generator/src/api.ts +45 -0
  57. package/generator/src/code-generator.ts +259 -230
  58. package/generator/src/config.ts +496 -0
  59. package/generator/src/dialect.ts +415 -0
  60. package/generator/src/dotnet-generator.ts +1071 -544
  61. package/generator/src/field-types.ts +473 -0
  62. package/generator/src/golang-generator.ts +1267 -0
  63. package/generator/src/index.ts +146 -116
  64. package/generator/src/metadata-generator.ts +116 -101
  65. package/generator/src/parser.ts +234 -202
  66. package/generator/src/push-apply.ts +148 -0
  67. package/generator/src/push-schema.ts +250 -0
  68. package/generator/src/python-generator.ts +480 -114
  69. package/generator/src/rust-generator.ts +974 -0
  70. package/generator/src/suggest.ts +41 -0
  71. package/generator/src/type-kinds.ts +78 -0
  72. package/generator/src/types.ts +77 -29
  73. package/package.json +32 -6
@@ -0,0 +1,17 @@
1
+ /**
2
+ * "Did you mean" for typos.
3
+ *
4
+ * Lives on its own because two callers need it and neither should own it:
5
+ * the config loader (a mistyped option key) and the field type registry (a
6
+ * type written for the wrong database). Both want the nearest candidate out
7
+ * of a known list, or nothing at all when the input is not close enough that
8
+ * a suggestion would be honest.
9
+ */
10
+ /** Levenshtein distance between two strings. */
11
+ export declare function editDistance(a: string, b: string): number;
12
+ /**
13
+ * The candidate closest to `input`, or null when none is close enough to be a
14
+ * plausible typo. Comparing case-insensitively keeps `nvarchar` from suggesting
15
+ * something unrelated just because of capitalisation.
16
+ */
17
+ export declare function suggest(input: string, candidates: readonly string[]): string | null;
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+ /**
3
+ * "Did you mean" for typos.
4
+ *
5
+ * Lives on its own because two callers need it and neither should own it:
6
+ * the config loader (a mistyped option key) and the field type registry (a
7
+ * type written for the wrong database). Both want the nearest candidate out
8
+ * of a known list, or nothing at all when the input is not close enough that
9
+ * a suggestion would be honest.
10
+ */
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.editDistance = editDistance;
13
+ exports.suggest = suggest;
14
+ /** Levenshtein distance between two strings. */
15
+ function editDistance(a, b) {
16
+ const rows = [];
17
+ for (let i = 0; i <= a.length; i++)
18
+ rows.push([i, ...new Array(b.length).fill(0)]);
19
+ for (let j = 0; j <= b.length; j++)
20
+ rows[0][j] = j;
21
+ for (let i = 1; i <= a.length; i++) {
22
+ for (let j = 1; j <= b.length; j++) {
23
+ const cost = a[i - 1] === b[j - 1] ? 0 : 1;
24
+ rows[i][j] = Math.min(rows[i - 1][j] + 1, rows[i][j - 1] + 1, rows[i - 1][j - 1] + cost);
25
+ }
26
+ }
27
+ return rows[a.length][b.length];
28
+ }
29
+ /**
30
+ * The candidate closest to `input`, or null when none is close enough to be a
31
+ * plausible typo. Comparing case-insensitively keeps `nvarchar` from suggesting
32
+ * something unrelated just because of capitalisation.
33
+ */
34
+ function suggest(input, candidates) {
35
+ let best = null;
36
+ let bestDistance = Infinity;
37
+ for (const candidate of candidates) {
38
+ const distance = editDistance(input.toLowerCase(), candidate.toLowerCase());
39
+ if (distance < bestDistance) {
40
+ bestDistance = distance;
41
+ best = candidate;
42
+ }
43
+ }
44
+ return best !== null && bestDistance <= Math.max(2, Math.floor(input.length / 3)) ? best : null;
45
+ }
@@ -0,0 +1,27 @@
1
+ /**
2
+ * What a field *is*, for the generators that need a real type.
3
+ *
4
+ * The parser gives every generator the same TypeScript type, and that type loses
5
+ * what a language needs: `INT`, `FLOAT` and `DECIMAL` all arrive as `number`, so
6
+ * the Go client generated every numeric column as a `string`, and the Python, Rust
7
+ * and .NET clients turned a `DECIMAL` into an integer type. The declared type is
8
+ * right there in `Field.sqlType`, so it decides — with the TypeScript type as the
9
+ * fallback for metadata generated before that was recorded.
10
+ */
11
+ import { Provider } from './field-types';
12
+ /** The categories a generated language type can be built from. */
13
+ export type FieldKind = 'int' | 'bigint' | 'float' | 'bool' | 'date' | 'bytes' | 'json' | 'vector' | 'string';
14
+ export interface KindInput {
15
+ /** The TypeScript type the parser produced, e.g. `number | bigint`. */
16
+ type: string;
17
+ /** The type as written in the schema, e.g. `DECIMAL(10,2)`. */
18
+ sqlType?: string | undefined;
19
+ }
20
+ /**
21
+ * The category a field belongs to.
22
+ *
23
+ * `TIMESTAMP` is the reason `provider` is a parameter: it is a rowversion on SQL
24
+ * Server and a point in time everywhere else, and the same word has to produce
25
+ * bytes in one and a date in the other.
26
+ */
27
+ export declare function fieldKind(field: KindInput, provider?: Provider | undefined): FieldKind;
@@ -0,0 +1,72 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.fieldKind = fieldKind;
4
+ const INT = ['INT', 'INTEGER', 'SMALLINT', 'TINYINT', 'MEDIUMINT', 'INT2', 'INT4', 'SERIAL', 'SMALLSERIAL', 'YEAR'];
5
+ const BIGINT = ['BIGINT', 'INT8', 'BIGSERIAL', 'UNSIGNED BIG INT'];
6
+ const FLOAT = ['FLOAT', 'REAL', 'DOUBLE', 'DOUBLE PRECISION', 'DECIMAL', 'NUMERIC', 'MONEY', 'SMALLMONEY', 'FIXED'];
7
+ const BOOL = ['BIT', 'BOOL', 'BOOLEAN'];
8
+ const DATE = [
9
+ 'DATE', 'DATETIME', 'DATETIME2', 'SMALLDATETIME', 'DATETIMEOFFSET',
10
+ 'TIME', 'TIMETZ', 'TIMESTAMPTZ', 'TIME WITH TIME ZONE', 'TIME WITHOUT TIME ZONE',
11
+ 'TIMESTAMP WITH TIME ZONE', 'TIMESTAMP WITHOUT TIME ZONE',
12
+ ];
13
+ const BYTES = ['BINARY', 'VARBINARY', 'IMAGE', 'BLOB', 'TINYBLOB', 'MEDIUMBLOB', 'LONGBLOB', 'BYTEA', 'ROWVERSION', 'BYTES'];
14
+ const JSON = ['JSON', 'JSONB', 'SQL_VARIANT'];
15
+ /** `DECIMAL(10,2)` → `DECIMAL`. */
16
+ function declaredBase(sqlType) {
17
+ const withoutParams = sqlType.replace(/\([^)]*\)/g, ' ').trim();
18
+ return withoutParams.replace(/\s+/g, ' ').toUpperCase();
19
+ }
20
+ /**
21
+ * The category a field belongs to.
22
+ *
23
+ * `TIMESTAMP` is the reason `provider` is a parameter: it is a rowversion on SQL
24
+ * Server and a point in time everywhere else, and the same word has to produce
25
+ * bytes in one and a date in the other.
26
+ */
27
+ function fieldKind(field, provider) {
28
+ const base = field.sqlType ? declaredBase(field.sqlType) : '';
29
+ if (base) {
30
+ if (base === 'TIMESTAMP')
31
+ return provider === 'mssql' ? 'bytes' : 'date';
32
+ if (INT.includes(base))
33
+ return 'int';
34
+ if (BIGINT.includes(base))
35
+ return 'bigint';
36
+ if (FLOAT.includes(base))
37
+ return 'float';
38
+ if (BOOL.includes(base))
39
+ return 'bool';
40
+ if (DATE.includes(base) || base === 'TIMESTAMP')
41
+ return 'date';
42
+ if (BYTES.includes(base))
43
+ return 'bytes';
44
+ if (JSON.includes(base))
45
+ return 'json';
46
+ if (base === 'VECTOR')
47
+ return 'vector';
48
+ return 'string';
49
+ }
50
+ // No declared type: fall back to what the TypeScript type can still tell us. A
51
+ // plain `number` is an integer here, which is what every generator assumed
52
+ // before `sqlType` was available.
53
+ const raw = field.type.trim().toLowerCase();
54
+ // Checked before the brackets are stripped, or `number[] | string` — the vector
55
+ // type — would read as a number.
56
+ if (raw.includes('[]'))
57
+ return 'vector';
58
+ const ts = raw.replace(/[?\]]/g, '').trim();
59
+ if (ts.startsWith('number | bigint'))
60
+ return 'bigint';
61
+ if (ts.startsWith('number'))
62
+ return 'int';
63
+ if (ts.startsWith('date'))
64
+ return 'date';
65
+ if (ts.startsWith('bool'))
66
+ return 'bool';
67
+ if (ts.startsWith('buffer'))
68
+ return 'bytes';
69
+ if (ts === 'any')
70
+ return 'json';
71
+ return 'string';
72
+ }
@@ -1,27 +1,60 @@
1
- export interface Field {
2
- name: string;
3
- type: string;
4
- sqlType: string;
5
- isOptional: boolean;
6
- hasDefault: boolean;
7
- isId: boolean;
8
- description?: string;
9
- }
10
- export interface Relation {
11
- name: string;
12
- type: string;
13
- isArray: boolean;
14
- isOptional: boolean;
15
- foreignKey: string;
16
- localKey: string;
17
- relationName: string;
18
- }
19
- export interface Model {
20
- name: string;
21
- tableName: string;
22
- schemaName: string;
23
- fields: Field[];
24
- relations: Relation[];
25
- compoundUniques?: string[][];
26
- description?: string;
27
- }
1
+ import { Provider } from './field-types';
2
+ export interface Field {
3
+ name: string;
4
+ type: string;
5
+ sqlType: string;
6
+ isOptional: boolean;
7
+ hasDefault: boolean;
8
+ isId: boolean;
9
+ description?: string;
10
+ }
11
+ export interface Relation {
12
+ name: string;
13
+ type: string;
14
+ isArray: boolean;
15
+ isOptional: boolean;
16
+ foreignKey: string;
17
+ localKey: string;
18
+ relationName: string;
19
+ /** From a trailing @description("...") on the relation line. */
20
+ description?: string;
21
+ }
22
+ export interface Model {
23
+ name: string;
24
+ tableName: string;
25
+ /** Empty for a database with no schemas, or when `@@schema("")` says so. */
26
+ schemaName: string;
27
+ /**
28
+ * The database this schema targets. Set by `SchemaParser`, and what decides how a
29
+ * table name is written — see `bracketedTableName`.
30
+ */
31
+ provider?: Provider | undefined;
32
+ fields: Field[];
33
+ relations: Relation[];
34
+ compoundUniques?: string[][];
35
+ description?: string;
36
+ }
37
+ /**
38
+ * The table name as it goes into the generated metadata.
39
+ *
40
+ * SQL Server keeps the bracketed form it has always had. Every other provider gets
41
+ * the bare name, with the schema as a plain prefix, because the brackets are not
42
+ * portable: `[dbo].[users]` is invalid SQL in PostgreSQL, and on SQLite it fails with
43
+ * "no such table: dbo.users" — which is why the adapters had to strip it afterwards.
44
+ * A bare name is correct everywhere once the adapter quotes it, and the adapters
45
+ * already quote per dialect (`quote()` in `@an5/adapters`, `An5DbContext.Quote()` in
46
+ * the .NET client), so the one form that needs no translation is the one emitted.
47
+ *
48
+ * `dbo` is SQL Server's default schema and only SQL Server's: with `@@schema("")` —
49
+ * an empty schema, meant for databases that have no schema concept — the prefix has
50
+ * to go, because `[].[users]` is not valid SQL. The `[${schemaName}].[${tableName}]`
51
+ * formula used to be written out in six places, so every dialect got `[dbo]`.
52
+ */
53
+ export declare function bracketedTableName(model: Model): string;
54
+ /**
55
+ * The table name as `schema.table`, for clients that pass a string instead of SQL.
56
+ *
57
+ * Unquoted for the same reason as `bracketedTableName`: these strings go to the same
58
+ * per-dialect quoting.
59
+ */
60
+ export declare function dottedTableName(model: Model): string;
@@ -1,2 +1,41 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.bracketedTableName = bracketedTableName;
4
+ exports.dottedTableName = dottedTableName;
5
+ /**
6
+ * The table name as it goes into the generated metadata.
7
+ *
8
+ * SQL Server keeps the bracketed form it has always had. Every other provider gets
9
+ * the bare name, with the schema as a plain prefix, because the brackets are not
10
+ * portable: `[dbo].[users]` is invalid SQL in PostgreSQL, and on SQLite it fails with
11
+ * "no such table: dbo.users" — which is why the adapters had to strip it afterwards.
12
+ * A bare name is correct everywhere once the adapter quotes it, and the adapters
13
+ * already quote per dialect (`quote()` in `@an5/adapters`, `An5DbContext.Quote()` in
14
+ * the .NET client), so the one form that needs no translation is the one emitted.
15
+ *
16
+ * `dbo` is SQL Server's default schema and only SQL Server's: with `@@schema("")` —
17
+ * an empty schema, meant for databases that have no schema concept — the prefix has
18
+ * to go, because `[].[users]` is not valid SQL. The `[${schemaName}].[${tableName}]`
19
+ * formula used to be written out in six places, so every dialect got `[dbo]`.
20
+ */
21
+ function bracketedTableName(model) {
22
+ const qualified = model.schemaName
23
+ ? `${model.schemaName}.${model.tableName}`
24
+ : model.tableName;
25
+ if ((model.provider ?? 'mssql') !== 'mssql')
26
+ return qualified;
27
+ return model.schemaName
28
+ ? `[${model.schemaName}].[${model.tableName}]`
29
+ : `[${model.tableName}]`;
30
+ }
31
+ /**
32
+ * The table name as `schema.table`, for clients that pass a string instead of SQL.
33
+ *
34
+ * Unquoted for the same reason as `bracketedTableName`: these strings go to the same
35
+ * per-dialect quoting.
36
+ */
37
+ function dottedTableName(model) {
38
+ return model.schemaName
39
+ ? `${model.schemaName}.${model.tableName}`
40
+ : model.tableName;
41
+ }
package/dist/index.d.ts CHANGED
@@ -1,6 +1,7 @@
1
- export { An5ORM, an5Orm, default } from "./an5Orm";
2
- export type { Middleware, MiddlewareParams } from "./an5Orm";
3
1
  export { An5ClientKnownRequestError } from "./errors";
4
2
  export { DEFAULT_METADATA } from "./metadata";
5
3
  export type { RelationDef, ModelFieldMeta, An5Metadata } from "./metadata";
4
+ export { quoteIdentifier, quoteTableIdentifier, sanitizeParamName, normalizeSortDirection, toNonNegativeInt, buildOrderBy, parseWhere, } from "./sql-utils";
5
+ export { generateDiff, buildMigrationFile, buildCreateTableSql, generateColumnDiff, parseSchemaText, } from "./migration-core";
6
+ export { An5Adapter, createAn5Adapter, AdapterTableClient, } from "@an5/adapters";
6
7
  //# sourceMappingURL=index.d.ts.map
package/dist/index.js CHANGED
@@ -1,15 +1,26 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.DEFAULT_METADATA = exports.An5ClientKnownRequestError = exports.default = exports.an5Orm = exports.An5ORM = void 0;
7
- var an5Orm_1 = require("./an5Orm");
8
- Object.defineProperty(exports, "An5ORM", { enumerable: true, get: function () { return an5Orm_1.An5ORM; } });
9
- Object.defineProperty(exports, "an5Orm", { enumerable: true, get: function () { return an5Orm_1.an5Orm; } });
10
- Object.defineProperty(exports, "default", { enumerable: true, get: function () { return __importDefault(an5Orm_1).default; } });
3
+ exports.AdapterTableClient = exports.createAn5Adapter = exports.An5Adapter = exports.parseSchemaText = exports.generateColumnDiff = exports.buildCreateTableSql = exports.buildMigrationFile = exports.generateDiff = exports.parseWhere = exports.buildOrderBy = exports.toNonNegativeInt = exports.normalizeSortDirection = exports.sanitizeParamName = exports.quoteTableIdentifier = exports.quoteIdentifier = exports.DEFAULT_METADATA = exports.An5ClientKnownRequestError = void 0;
11
4
  var errors_1 = require("./errors");
12
5
  Object.defineProperty(exports, "An5ClientKnownRequestError", { enumerable: true, get: function () { return errors_1.An5ClientKnownRequestError; } });
13
6
  var metadata_1 = require("./metadata");
14
7
  Object.defineProperty(exports, "DEFAULT_METADATA", { enumerable: true, get: function () { return metadata_1.DEFAULT_METADATA; } });
8
+ var sql_utils_1 = require("./sql-utils");
9
+ Object.defineProperty(exports, "quoteIdentifier", { enumerable: true, get: function () { return sql_utils_1.quoteIdentifier; } });
10
+ Object.defineProperty(exports, "quoteTableIdentifier", { enumerable: true, get: function () { return sql_utils_1.quoteTableIdentifier; } });
11
+ Object.defineProperty(exports, "sanitizeParamName", { enumerable: true, get: function () { return sql_utils_1.sanitizeParamName; } });
12
+ Object.defineProperty(exports, "normalizeSortDirection", { enumerable: true, get: function () { return sql_utils_1.normalizeSortDirection; } });
13
+ Object.defineProperty(exports, "toNonNegativeInt", { enumerable: true, get: function () { return sql_utils_1.toNonNegativeInt; } });
14
+ Object.defineProperty(exports, "buildOrderBy", { enumerable: true, get: function () { return sql_utils_1.buildOrderBy; } });
15
+ Object.defineProperty(exports, "parseWhere", { enumerable: true, get: function () { return sql_utils_1.parseWhere; } });
16
+ var migration_core_1 = require("./migration-core");
17
+ Object.defineProperty(exports, "generateDiff", { enumerable: true, get: function () { return migration_core_1.generateDiff; } });
18
+ Object.defineProperty(exports, "buildMigrationFile", { enumerable: true, get: function () { return migration_core_1.buildMigrationFile; } });
19
+ Object.defineProperty(exports, "buildCreateTableSql", { enumerable: true, get: function () { return migration_core_1.buildCreateTableSql; } });
20
+ Object.defineProperty(exports, "generateColumnDiff", { enumerable: true, get: function () { return migration_core_1.generateColumnDiff; } });
21
+ Object.defineProperty(exports, "parseSchemaText", { enumerable: true, get: function () { return migration_core_1.parseSchemaText; } });
22
+ var adapters_1 = require("@an5/adapters");
23
+ Object.defineProperty(exports, "An5Adapter", { enumerable: true, get: function () { return adapters_1.An5Adapter; } });
24
+ Object.defineProperty(exports, "createAn5Adapter", { enumerable: true, get: function () { return adapters_1.createAn5Adapter; } });
25
+ Object.defineProperty(exports, "AdapterTableClient", { enumerable: true, get: function () { return adapters_1.AdapterTableClient; } });
15
26
  //# sourceMappingURL=index.js.map
package/dist/logger.js CHANGED
@@ -84,7 +84,7 @@ class Logger {
84
84
  this.log('warn', message, options);
85
85
  }
86
86
  error(message, error, options) {
87
- this.log('error', message, { ...options, error });
87
+ this.log('error', message, { ...options, ...(error !== undefined ? { error } : {}) });
88
88
  }
89
89
  child(context) {
90
90
  return new Logger({
@@ -0,0 +1,102 @@
1
+ import { Provider } from './generator/src/field-types';
2
+ export interface SchemaField {
3
+ name: string;
4
+ sqlType: string;
5
+ isOptional: boolean;
6
+ isId: boolean;
7
+ isUnique: boolean;
8
+ uniqueName?: string | undefined;
9
+ defaultValue?: string | undefined;
10
+ }
11
+ export interface SchemaIndexDefinition {
12
+ fields: string[];
13
+ name?: string;
14
+ includeFields?: string[];
15
+ filter?: string;
16
+ options?: string;
17
+ }
18
+ export interface SchemaModel {
19
+ name: string;
20
+ /**
21
+ * The table to create, schema-qualified when the model named a schema other than
22
+ * `dbo`. `dbo` stays implicit so an unqualified model produces the same SQL it
23
+ * always has.
24
+ */
25
+ tableName: string;
26
+ fields: SchemaField[];
27
+ compoundUniques: Array<string[] | SchemaIndexDefinition>;
28
+ indexes: Array<string[] | SchemaIndexDefinition>;
29
+ }
30
+ export interface DbColumn {
31
+ columnName: string;
32
+ dataType: string;
33
+ maxLength?: number;
34
+ precision?: number;
35
+ scale?: number;
36
+ isNullable: boolean;
37
+ isPrimaryKey: boolean;
38
+ isIdentity: boolean;
39
+ defaultValue?: string;
40
+ }
41
+ export interface MigrationOp {
42
+ type: 'CREATE_TABLE' | 'ADD_COLUMN' | 'DROP_COLUMN' | 'ALTER_COLUMN' | 'ADD_INDEX' | 'ADD_UNIQUE' | 'DROP_INDEX' | 'DROP_UNIQUE' | 'DROP_TABLE';
43
+ table: string;
44
+ column?: string;
45
+ details?: string;
46
+ sql?: string;
47
+ previousSqlType?: string;
48
+ previousNullable?: boolean;
49
+ riskWarnings?: string[];
50
+ preflightSql?: string[];
51
+ }
52
+ export interface TableArtifacts {
53
+ indexes?: string[];
54
+ uniqueConstraints?: string[];
55
+ }
56
+ export interface MigrationSections {
57
+ preflight: string;
58
+ up: string;
59
+ down: string;
60
+ hasDown: boolean;
61
+ }
62
+ export interface AppliedMigrationRef {
63
+ id: string;
64
+ }
65
+ export interface MigrationCommandOptions {
66
+ dryRun: boolean;
67
+ rest: string[];
68
+ }
69
+ export declare function parseSqlType(raw: string): string;
70
+ export declare function formatDbColumnSqlType(column: DbColumn): string;
71
+ export declare function mapDefault(val: string): string;
72
+ export declare function safeIdentifierName(raw: string): string;
73
+ export declare function quoteTableName(raw: string): string;
74
+ export declare function tableIdentityName(raw: string): string;
75
+ export declare function buildAlterColumnWarnings(previousSqlType: string, nextSqlType: string, previousNullable: boolean, nextNullable: boolean): string[];
76
+ export declare function buildAlterColumnPreflightSql(tableName: string, columnName: string, previousSqlType: string, nextSqlType: string, previousNullable: boolean, nextNullable: boolean): string[];
77
+ export declare function buildAddColumnPreflightSql(tableName: string, field: SchemaField): string[];
78
+ export declare function buildUniqueConstraintPreflightSql(tableName: string, fields: string[]): string[];
79
+ /**
80
+ * Reads a `.an5` schema into models to compare against the database.
81
+ *
82
+ * `provider` decides what counts as a column and what counts as a relation; it
83
+ * defaults to SQL Server. A type the provider does not have is reported rather
84
+ * than skipped — skipping it means the migration silently never mentions that
85
+ * column. A token matching a model in the schema is a relation, so that
86
+ * comparison waits until the whole schema has been read.
87
+ */
88
+ export declare function parseSchemaText(text: string, provider?: Provider): SchemaModel[];
89
+ export declare function buildCreateTableSql(model: SchemaModel): string;
90
+ export declare function buildIndexDiff(model: SchemaModel, artifacts: TableArtifacts, ops: MigrationOp[]): void;
91
+ export declare function generateColumnDiff(model: SchemaModel, dbColumns: DbColumn[], ops: MigrationOp[]): void;
92
+ export declare function generateDiff(schemaModels: SchemaModel[], dbTables: string[], introspectTable: (tableName: string) => Promise<DbColumn[]>, introspectArtifacts?: (tableName: string) => Promise<TableArtifacts>): Promise<MigrationOp[]>;
93
+ export declare function buildMigrationFile(timestamp: string, ops: MigrationOp[]): string;
94
+ export declare function buildDownMigrationSql(ops: MigrationOp[]): string;
95
+ export declare function parseMigrationSections(sql: string): MigrationSections;
96
+ export declare function splitSqlBatches(sql: string): string[];
97
+ export declare function parseRollbackSelection(args: string[], applied: AppliedMigrationRef[]): {
98
+ count: number;
99
+ label: string;
100
+ };
101
+ export declare function parseMigrationCommandOptions(args: string[]): MigrationCommandOptions;
102
+ //# sourceMappingURL=migration-core.d.ts.map