@rvoh/dream 2.36.1 → 2.37.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 (234) hide show
  1. package/dist/cjs/src/db/dataTypes.js +0 -8
  2. package/dist/cjs/src/dream/QueryDriver/Base.js +17 -24
  3. package/dist/cjs/src/dream/QueryDriver/Kysely.js +22 -23
  4. package/dist/cjs/src/dream/QueryDriver/Postgres.js +113 -31
  5. package/dist/cjs/src/helpers/cli/ASTBuilder.js +11 -202
  6. package/dist/cjs/src/helpers/cli/ASTConnectionBuilder.js +97 -75
  7. package/dist/cjs/src/helpers/cli/ASTDbTypesBuilder.js +132 -0
  8. package/dist/cjs/src/helpers/cli/ASTSchemaBuilder.js +37 -81
  9. package/dist/cjs/src/helpers/cli/dbTypesNaming.js +90 -0
  10. package/dist/cjs/src/helpers/cli/tableMatchesPattern.js +21 -0
  11. package/dist/esm/src/db/dataTypes.js +0 -8
  12. package/dist/esm/src/dream/QueryDriver/Base.js +17 -24
  13. package/dist/esm/src/dream/QueryDriver/Kysely.js +22 -23
  14. package/dist/esm/src/dream/QueryDriver/Postgres.js +113 -31
  15. package/dist/esm/src/helpers/cli/ASTBuilder.js +11 -202
  16. package/dist/esm/src/helpers/cli/ASTConnectionBuilder.js +97 -75
  17. package/dist/esm/src/helpers/cli/ASTDbTypesBuilder.js +132 -0
  18. package/dist/esm/src/helpers/cli/ASTSchemaBuilder.js +37 -81
  19. package/dist/esm/src/helpers/cli/dbTypesNaming.js +90 -0
  20. package/dist/esm/src/helpers/cli/tableMatchesPattern.js +21 -0
  21. package/dist/types/src/db/dataTypes.d.ts +0 -2
  22. package/dist/types/src/dream/QueryDriver/Base.d.ts +16 -18
  23. package/dist/types/src/dream/QueryDriver/Kysely.d.ts +0 -9
  24. package/dist/types/src/dream/QueryDriver/Postgres.d.ts +9 -9
  25. package/dist/types/src/dream-app/index.d.ts +12 -12
  26. package/dist/types/src/helpers/cli/ASTBuilder.d.ts +11 -101
  27. package/dist/types/src/helpers/cli/ASTConnectionBuilder.d.ts +40 -37
  28. package/dist/types/src/helpers/cli/ASTDbTypesBuilder.d.ts +26 -0
  29. package/dist/types/src/helpers/cli/ASTSchemaBuilder.d.ts +5 -15
  30. package/dist/types/src/helpers/cli/dbTypesNaming.d.ts +37 -0
  31. package/dist/types/src/helpers/cli/tableMatchesPattern.d.ts +15 -0
  32. package/dist/types/src/package-exports/types.d.ts +1 -1
  33. package/dist/types/src/types/db.d.ts +71 -0
  34. package/dist/types/src/types/types/db.ts +91 -0
  35. package/docs/assets/hierarchy.js +1 -1
  36. package/docs/assets/navigation.js +1 -1
  37. package/docs/assets/search.js +1 -1
  38. package/docs/classes/db.DreamMigrationHelpers.html +11 -11
  39. package/docs/classes/db.KyselyQueryDriver.html +55 -54
  40. package/docs/classes/db.PostgresQueryDriver.html +56 -56
  41. package/docs/classes/db.QueryDriverBase.html +60 -59
  42. package/docs/classes/errors.CannotSaveMissingDream.html +2 -2
  43. package/docs/classes/errors.CheckConstraintViolation.html +3 -3
  44. package/docs/classes/errors.ColumnOverflow.html +3 -3
  45. package/docs/classes/errors.CreateOrFindByFailedToCreateAndFind.html +3 -3
  46. package/docs/classes/errors.DataIncompatibleWithDatabaseField.html +3 -3
  47. package/docs/classes/errors.DataTypeColumnTypeMismatch.html +3 -3
  48. package/docs/classes/errors.DecryptionError.html +2 -2
  49. package/docs/classes/errors.DecryptionParseError.html +2 -2
  50. package/docs/classes/errors.DecryptionRotationError.html +3 -3
  51. package/docs/classes/errors.GlobalNameNotSet.html +3 -3
  52. package/docs/classes/errors.InvalidCalendarDate.html +2 -2
  53. package/docs/classes/errors.InvalidClockTime.html +2 -2
  54. package/docs/classes/errors.InvalidClockTimeTz.html +2 -2
  55. package/docs/classes/errors.InvalidDateTime.html +2 -2
  56. package/docs/classes/errors.MissingSerializersDefinition.html +3 -3
  57. package/docs/classes/errors.NonLoadedAssociation.html +3 -3
  58. package/docs/classes/errors.NotNullViolation.html +3 -3
  59. package/docs/classes/errors.RecordNotFound.html +3 -3
  60. package/docs/classes/errors.SortableScopeDidNotStabilize.html +3 -3
  61. package/docs/classes/errors.SortableScopeLockWaitTimedOut.html +3 -3
  62. package/docs/classes/errors.ValidationError.html +3 -3
  63. package/docs/classes/index.CalendarDate.html +33 -33
  64. package/docs/classes/index.ClockTime.html +32 -32
  65. package/docs/classes/index.ClockTimeTz.html +35 -35
  66. package/docs/classes/index.DateTime.html +86 -86
  67. package/docs/classes/index.Decorators.html +19 -19
  68. package/docs/classes/index.Dream.html +125 -125
  69. package/docs/classes/index.DreamApp.html +11 -11
  70. package/docs/classes/index.DreamTransaction.html +3 -3
  71. package/docs/classes/index.Env.html +5 -5
  72. package/docs/classes/index.Query.html +65 -65
  73. package/docs/classes/system.CliFileWriter.html +4 -4
  74. package/docs/classes/system.DreamBin.html +3 -3
  75. package/docs/classes/system.DreamCLI.html +7 -7
  76. package/docs/classes/system.DreamImporter.html +2 -2
  77. package/docs/classes/system.DreamLogos.html +2 -2
  78. package/docs/classes/system.DreamSerializerBuilder.html +11 -11
  79. package/docs/classes/system.ObjectSerializerBuilder.html +8 -8
  80. package/docs/classes/system.PathHelpers.html +3 -3
  81. package/docs/classes/utils.Encrypt.html +4 -4
  82. package/docs/classes/utils.Range.html +2 -2
  83. package/docs/functions/db.closeAllDbConnections.html +1 -1
  84. package/docs/functions/db.dreamDbConnections.html +1 -1
  85. package/docs/functions/db.untypedDb.html +1 -1
  86. package/docs/functions/db.validateColumn.html +1 -1
  87. package/docs/functions/db.validateTable.html +1 -1
  88. package/docs/functions/errors.pgErrorType.html +1 -1
  89. package/docs/functions/index.DreamSerializer.html +1 -1
  90. package/docs/functions/index.ObjectSerializer.html +1 -1
  91. package/docs/functions/index.ReplicaSafe.html +1 -1
  92. package/docs/functions/index.STI.html +1 -1
  93. package/docs/functions/index.SoftDelete.html +1 -1
  94. package/docs/functions/utils.camelize.html +1 -1
  95. package/docs/functions/utils.capitalize.html +1 -1
  96. package/docs/functions/utils.cloneDeepSafe.html +1 -1
  97. package/docs/functions/utils.compact.html +1 -1
  98. package/docs/functions/utils.groupBy.html +1 -1
  99. package/docs/functions/utils.hyphenize.html +1 -1
  100. package/docs/functions/utils.intersection.html +1 -1
  101. package/docs/functions/utils.isEmpty.html +1 -1
  102. package/docs/functions/utils.normalizeUnicode.html +1 -1
  103. package/docs/functions/utils.pascalize.html +1 -1
  104. package/docs/functions/utils.percent.html +1 -1
  105. package/docs/functions/utils.range.html +1 -1
  106. package/docs/functions/utils.round.html +1 -1
  107. package/docs/functions/utils.sanitizeString.html +1 -1
  108. package/docs/functions/utils.snakeify.html +1 -1
  109. package/docs/functions/utils.sort.html +1 -1
  110. package/docs/functions/utils.sortBy.html +1 -1
  111. package/docs/functions/utils.sortObjectByKey.html +1 -1
  112. package/docs/functions/utils.sortObjectByValue.html +1 -1
  113. package/docs/functions/utils.uncapitalize.html +1 -1
  114. package/docs/functions/utils.uniq.html +1 -1
  115. package/docs/hierarchy.html +1 -1
  116. package/docs/interfaces/openapi.OpenapiDescription.html +2 -2
  117. package/docs/interfaces/openapi.OpenapiSchemaProperties.html +1 -1
  118. package/docs/interfaces/openapi.OpenapiSchemaPropertiesShorthand.html +1 -1
  119. package/docs/interfaces/openapi.OpenapiTypeFieldObject.html +1 -1
  120. package/docs/interfaces/types.BelongsToStatement.html +2 -2
  121. package/docs/interfaces/types.DecoratorContext.html +2 -2
  122. package/docs/interfaces/types.DecryptCallbacks.html +2 -2
  123. package/docs/interfaces/types.DreamAppInitOptions.html +2 -2
  124. package/docs/interfaces/types.DreamAppOpts.html +2 -2
  125. package/docs/interfaces/types.DreamDbConfig.html +6 -6
  126. package/docs/interfaces/types.DurationObject.html +2 -2
  127. package/docs/interfaces/types.EncryptOptions.html +2 -2
  128. package/docs/interfaces/types.EncryptionLegacyKeyUsedEvent.html +4 -4
  129. package/docs/interfaces/types.InternalAnyTypedSerializerRendersMany.html +2 -2
  130. package/docs/interfaces/types.InternalAnyTypedSerializerRendersOne.html +2 -2
  131. package/docs/interfaces/types.IntrospectedColumn.html +17 -0
  132. package/docs/interfaces/types.IntrospectedDatabase.html +7 -0
  133. package/docs/interfaces/types.IntrospectedEnum.html +5 -0
  134. package/docs/interfaces/types.IntrospectedTable.html +11 -0
  135. package/docs/interfaces/types.SerializerRendererOpts.html +2 -2
  136. package/docs/modules/types.html +1 -1
  137. package/docs/types/openapi.CommonOpenapiSchemaObjectFields.html +1 -1
  138. package/docs/types/openapi.OpenapiAllTypes.html +1 -1
  139. package/docs/types/openapi.OpenapiFormats.html +1 -1
  140. package/docs/types/openapi.OpenapiNumberFormats.html +1 -1
  141. package/docs/types/openapi.OpenapiPrimitiveBaseTypes.html +1 -1
  142. package/docs/types/openapi.OpenapiPrimitiveTypes.html +1 -1
  143. package/docs/types/openapi.OpenapiSchemaArray.html +1 -1
  144. package/docs/types/openapi.OpenapiSchemaArrayShorthand.html +1 -1
  145. package/docs/types/openapi.OpenapiSchemaBase.html +1 -1
  146. package/docs/types/openapi.OpenapiSchemaBody.html +1 -1
  147. package/docs/types/openapi.OpenapiSchemaBodyShorthand.html +1 -1
  148. package/docs/types/openapi.OpenapiSchemaCombinatorFields.html +1 -1
  149. package/docs/types/openapi.OpenapiSchemaCommonFields.html +1 -1
  150. package/docs/types/openapi.OpenapiSchemaExpressionAllOf.html +1 -1
  151. package/docs/types/openapi.OpenapiSchemaExpressionAnyOf.html +1 -1
  152. package/docs/types/openapi.OpenapiSchemaExpressionOneOf.html +1 -1
  153. package/docs/types/openapi.OpenapiSchemaExpressionRef.html +2 -2
  154. package/docs/types/openapi.OpenapiSchemaExpressionRefSchemaShorthand.html +2 -2
  155. package/docs/types/openapi.OpenapiSchemaInteger.html +1 -1
  156. package/docs/types/openapi.OpenapiSchemaNull.html +2 -2
  157. package/docs/types/openapi.OpenapiSchemaNumber.html +1 -1
  158. package/docs/types/openapi.OpenapiSchemaObject.html +1 -1
  159. package/docs/types/openapi.OpenapiSchemaObjectAllOf.html +1 -1
  160. package/docs/types/openapi.OpenapiSchemaObjectAllOfShorthand.html +1 -1
  161. package/docs/types/openapi.OpenapiSchemaObjectBase.html +1 -1
  162. package/docs/types/openapi.OpenapiSchemaObjectBaseShorthand.html +1 -1
  163. package/docs/types/openapi.OpenapiSchemaObjectShorthand.html +1 -1
  164. package/docs/types/openapi.OpenapiSchemaPrimitiveGeneric.html +1 -1
  165. package/docs/types/openapi.OpenapiSchemaShorthandExpressionAllOf.html +1 -1
  166. package/docs/types/openapi.OpenapiSchemaShorthandExpressionAnyOf.html +1 -1
  167. package/docs/types/openapi.OpenapiSchemaShorthandExpressionOneOf.html +1 -1
  168. package/docs/types/openapi.OpenapiSchemaShorthandExpressionSerializableRef.html +2 -2
  169. package/docs/types/openapi.OpenapiSchemaShorthandExpressionSerializerRef.html +2 -2
  170. package/docs/types/openapi.OpenapiSchemaShorthandPrimitiveGeneric.html +1 -1
  171. package/docs/types/openapi.OpenapiSchemaString.html +1 -1
  172. package/docs/types/openapi.OpenapiShorthandAllTypes.html +1 -1
  173. package/docs/types/openapi.OpenapiShorthandPrimitiveBaseTypes.html +1 -1
  174. package/docs/types/openapi.OpenapiShorthandPrimitiveTypes.html +1 -1
  175. package/docs/types/openapi.OpenapiTypeField.html +1 -1
  176. package/docs/types/system.DreamAppAllowedPackageManagersEnum.html +1 -1
  177. package/docs/types/types.CalendarDateDurationUnit.html +1 -1
  178. package/docs/types/types.CalendarDateObject.html +1 -1
  179. package/docs/types/types.Camelized.html +1 -1
  180. package/docs/types/types.ClockTimeObject.html +1 -1
  181. package/docs/types/types.DbConnectionType.html +1 -1
  182. package/docs/types/types.DbTypes.html +1 -1
  183. package/docs/types/types.DreamAssociationMetadata.html +1 -1
  184. package/docs/types/types.DreamAttributes.html +1 -1
  185. package/docs/types/types.DreamClassAssociationAndStatement.html +1 -1
  186. package/docs/types/types.DreamClassColumn.html +1 -1
  187. package/docs/types/types.DreamColumn.html +1 -1
  188. package/docs/types/types.DreamColumnNames.html +1 -1
  189. package/docs/types/types.DreamLogLevel.html +1 -1
  190. package/docs/types/types.DreamLogger.html +2 -2
  191. package/docs/types/types.DreamModelSerializerType.html +1 -1
  192. package/docs/types/types.DreamOrViewModelClassSerializerKey.html +1 -1
  193. package/docs/types/types.DreamOrViewModelSerializerKey.html +1 -1
  194. package/docs/types/types.DreamParamSafeAttributes.html +1 -1
  195. package/docs/types/types.DreamParamSafeColumnNames.html +1 -1
  196. package/docs/types/types.DreamSerializable.html +1 -1
  197. package/docs/types/types.DreamSerializableArray.html +1 -1
  198. package/docs/types/types.DreamSerializerKey.html +1 -1
  199. package/docs/types/types.DreamSerializers.html +1 -1
  200. package/docs/types/types.DreamVirtualColumns.html +1 -1
  201. package/docs/types/types.DurationUnit.html +1 -1
  202. package/docs/types/types.EncryptAlgorithm.html +1 -1
  203. package/docs/types/types.HasManyStatement.html +1 -1
  204. package/docs/types/types.HasOneStatement.html +1 -1
  205. package/docs/types/types.Hyphenized.html +1 -1
  206. package/docs/types/types.IntrospectedValueType.html +5 -0
  207. package/docs/types/types.Pascalized.html +1 -1
  208. package/docs/types/types.PrimaryKeyType.html +1 -1
  209. package/docs/types/types.RoundingPrecision.html +1 -1
  210. package/docs/types/types.SerializerCasing.html +1 -1
  211. package/docs/types/types.SimpleObjectSerializerType.html +1 -1
  212. package/docs/types/types.Snakeified.html +1 -1
  213. package/docs/types/types.StrictInterface.html +1 -1
  214. package/docs/types/types.UpdateableAssociationProperties.html +1 -1
  215. package/docs/types/types.UpdateableProperties.html +1 -1
  216. package/docs/types/types.ValidationType.html +1 -1
  217. package/docs/types/types.ViewModel.html +2 -2
  218. package/docs/types/types.ViewModelClass.html +1 -1
  219. package/docs/types/types.WeekdayName.html +1 -1
  220. package/docs/types/types.WhereStatementForDream.html +1 -1
  221. package/docs/types/types.WhereStatementForDreamClass.html +1 -1
  222. package/docs/variables/index.DreamConst.html +1 -1
  223. package/docs/variables/index.ops.html +1 -1
  224. package/docs/variables/openapi.openapiPrimitiveTypes.html +1 -1
  225. package/docs/variables/openapi.openapiShorthandPrimitiveTypes.html +1 -1
  226. package/docs/variables/system.DreamAppAllowedPackageManagersEnumValues.html +1 -1
  227. package/docs/variables/system.primaryKeyTypes.html +1 -1
  228. package/package.json +6 -3
  229. package/dist/cjs/src/db/helpers/syncDbTypesFiles.js +0 -41
  230. package/dist/cjs/src/helpers/cli/ASTKyselyCodegenEnhancer.js +0 -380
  231. package/dist/esm/src/db/helpers/syncDbTypesFiles.js +0 -41
  232. package/dist/esm/src/helpers/cli/ASTKyselyCodegenEnhancer.js +0 -380
  233. package/dist/types/src/db/helpers/syncDbTypesFiles.d.ts +0 -1
  234. package/dist/types/src/helpers/cli/ASTKyselyCodegenEnhancer.d.ts +0 -94
@@ -1,23 +1,24 @@
1
- import * as fs from 'node:fs/promises';
2
1
  import * as path from 'node:path';
3
- import ts from 'typescript';
4
2
  import dbTypesFilenameForConnection from '../../db/helpers/dbTypesFilenameForConnection.js';
5
3
  import dreamSchemaTypesFilenameForConnection from '../../db/helpers/dreamSchemaTypesFilenameForConnection.js';
6
4
  import DreamApp from '../../dream-app/index.js';
7
5
  import Query from '../../dream/Query.js';
8
6
  import { ExplicitForeignKeyRequired, InvalidComputedForeignKey, } from '../../errors/associations/InvalidComputedForeignKey.js';
9
7
  import FailedToIdentifyAssociation from '../../errors/schema-builder/FailedToIdentifyAssociation.js';
8
+ import camelize from '../camelize.js';
10
9
  import intersection from '../intersection.js';
11
10
  import sortBy from '../sortBy.js';
12
11
  import uniq from '../uniq.js';
13
12
  import ASTBuilder from './ASTBuilder.js';
13
+ import { dbTypesName, dbTypesReservedNames } from './dbTypesNaming.js';
14
14
  import resolveIgnoredColumns from './resolveIgnoredColumns.js';
15
+ import tableMatchesPattern from './tableMatchesPattern.js';
15
16
  /**
16
17
  * @internal
17
18
  *
18
19
  * This is a base class, which is inherited by the ASTSchemaBuilder and
19
- * the ASTKyselyCodegenEnhancer, both of which is responsible for building
20
- * up the output of the various type files consumed by dream internally.
20
+ * the ASTDbTypesBuilder, each of which builds one of the type files a
21
+ * connection's sync writes, from the same introspection of the connection.
21
22
  *
22
23
  * This base class is just a container for common methods used by both
23
24
  * classes. It requires a connectionName to be provided, unlike the underlying
@@ -27,9 +28,71 @@ import resolveIgnoredColumns from './resolveIgnoredColumns.js';
27
28
  export default class ASTConnectionBuilder extends ASTBuilder {
28
29
  connectionName;
29
30
  hasForeignKeyError = false;
30
- constructor(connectionName) {
31
+ introspection;
32
+ introspectionFrom;
33
+ /**
34
+ * @param connectionName - the connection whose type file the builder writes
35
+ * @param opts.introspectionFrom - another builder of the same connection,
36
+ * whose reading of it this builder takes instead of reading the connection
37
+ * again, so that a sync reads each connection once for both type files
38
+ */
39
+ constructor(connectionName, opts = {}) {
31
40
  super();
32
41
  this.connectionName = connectionName;
42
+ this.introspectionFrom = opts.introspectionFrom;
43
+ }
44
+ /**
45
+ * @internal
46
+ *
47
+ * the connection's tables, sorted by their key in the DB interface, and its
48
+ * enums, read through the query driver once, by this builder or by the one
49
+ * it takes its introspection from. The tables that `tableIncludePattern`
50
+ * leaves out, or `tableExcludePattern` names, are left out.
51
+ */
52
+ async introspectedDatabase() {
53
+ this.introspection ||=
54
+ this.introspectionFrom?.introspectedDatabase() ??
55
+ (async () => {
56
+ const dbDriverClass = Query.dbDriverClass(this.connectionName);
57
+ const database = await dbDriverClass.introspectDatabase(this.connectionName);
58
+ const credentials = DreamApp.getOrFail().dbCredentialsFor(this.connectionName);
59
+ const includePattern = credentials?.tableIncludePattern;
60
+ const excludePattern = credentials?.tableExcludePattern;
61
+ return {
62
+ ...database,
63
+ tables: database.tables
64
+ .filter(table => (!includePattern || tableMatchesPattern(table, includePattern)) &&
65
+ !(excludePattern && tableMatchesPattern(table, excludePattern)))
66
+ .sort((a, b) => this.tableKey(a).localeCompare(this.tableKey(b))),
67
+ };
68
+ })();
69
+ return await this.introspection;
70
+ }
71
+ /**
72
+ * @internal
73
+ *
74
+ * the table's key in the DB interface and in Dream's schema: its name, or
75
+ * `<schema>.<name>` outside the connection's default schema
76
+ */
77
+ tableKey(table) {
78
+ return table.inDefaultSchema ? table.name : `${table.schema}.${table.name}`;
79
+ }
80
+ /**
81
+ * @internal
82
+ *
83
+ * the TypeScript name of each enum the connection's tables use, keyed by
84
+ * the enum's database name (see dbTypesName), with a number added when it
85
+ * would repeat an earlier enum's name or a name types/db.ts reserves
86
+ */
87
+ async enumTypeNames() {
88
+ const database = await this.introspectedDatabase();
89
+ const usedEnumNames = new Set(database.tables.flatMap(table => table.columns.map(column => column.enumName).filter(name => !!name)));
90
+ const takenNames = new Set(dbTypesReservedNames(database.tables));
91
+ const typeNames = new Map();
92
+ for (const enumName of [...usedEnumNames].sort()) {
93
+ typeNames.set(enumName, dbTypesName(enumName, takenNames));
94
+ }
95
+ return typeNames;
33
96
  }
34
97
  /**
35
98
  * @internal
@@ -55,26 +118,6 @@ export default class ASTConnectionBuilder extends ASTBuilder {
55
118
  const dreamApp = DreamApp.getOrFail();
56
119
  return path.join(dreamApp.projectRoot, dreamApp.paths.types, dbTypesFilenameForConnection(this.connectionName));
57
120
  }
58
- /**
59
- * @internal
60
- *
61
- * returns the db source file for the given connectionName, injecting
62
- * the source file with the actual file contents, so that AST nodes
63
- * can be built through ingesting.
64
- */
65
- async getDbSourceFile() {
66
- const fileContent = await this.loadDbSyncFile();
67
- return ts.createSourceFile('./db.js', fileContent, ts.ScriptTarget.Latest, true);
68
- }
69
- /**
70
- * @internal
71
- *
72
- * reads the db source file for the given connection, returning the contents
73
- * as a raw string
74
- */
75
- async loadDbSyncFile() {
76
- return (await fs.readFile(this.dbPath())).toString();
77
- }
78
121
  /**
79
122
  * @internal
80
123
  *
@@ -82,53 +125,14 @@ export default class ASTConnectionBuilder extends ASTBuilder {
82
125
  * can be read and injected into AST nodes.
83
126
  */
84
127
  async getSchemaData() {
85
- const tables = await this.getTables();
128
+ const database = await this.introspectedDatabase();
129
+ const enumTypeNames = await this.enumTypeNames();
86
130
  const schemaData = {};
87
- for (const table of tables) {
88
- schemaData[table] = await this.tableData(table);
131
+ for (const table of database.tables) {
132
+ schemaData[this.tableKey(table)] = this.tableData(table, enumTypeNames);
89
133
  }
90
134
  return schemaData;
91
135
  }
92
- /**
93
- * @internal
94
- *
95
- * used by getSchemaData to build up all table data
96
- */
97
- async getTables() {
98
- const fileContents = await this.loadDbSyncFile();
99
- const tableLines = /export interface DB {([^}]*)}/.exec(fileContents)[1];
100
- if (tableLines === undefined)
101
- return [];
102
- const tables = tableLines
103
- .split('\n')
104
- .map(line => {
105
- const stingArray = line.split(':');
106
- const substring = stingArray[0];
107
- if (substring === undefined)
108
- return '';
109
- return substring.replace(/\s*/, '');
110
- })
111
- .filter(line => !!line);
112
- return tables;
113
- }
114
- /**
115
- * @internal
116
- *
117
- * finds all enums used by the app, and returns information
118
- * about those enums that can be used for type generating purpposes
119
- */
120
- async getAllEnumValueNames() {
121
- const schemaData = await this.getSchemaData();
122
- const enumValueNames = Object.values(schemaData)
123
- .map(tableData => Object.keys(tableData.columns)
124
- .filter(columnName => !!tableData.columns[columnName]?.enumValues)
125
- .map(columnName => ({
126
- enumValues: tableData.columns[columnName].enumValues,
127
- enumType: tableData.columns[columnName].enumType,
128
- })))
129
- .flat();
130
- return enumValueNames;
131
- }
132
136
  /**
133
137
  * @internal
134
138
  *
@@ -233,7 +237,8 @@ export default class ASTConnectionBuilder extends ASTBuilder {
233
237
  * retrieves the table data for an individual table.
234
238
  * Can be used to build up types
235
239
  */
236
- async tableData(tableName) {
240
+ tableData(table, enumTypeNames) {
241
+ const tableName = this.tableKey(table);
237
242
  const dreamApp = DreamApp.getOrFail();
238
243
  const models = Object.values(dreamApp.models).filter(model => model.table === tableName);
239
244
  const maybeModel = models[0];
@@ -266,7 +271,7 @@ may need to update the table getter in the corresponding Dream.
266
271
  default: uniq(models.flatMap(model => model['scopes'].default.map(scopeStatement => scopeStatement.method))),
267
272
  named: uniq(models.flatMap(model => model['scopes'].named.map(scopeStatement => scopeStatement.method))),
268
273
  },
269
- columns: this.withoutIgnoredColumns(await this.getColumnData(tableName, associationData), tableName),
274
+ columns: this.withoutIgnoredColumns(this.columnData(table, associationData, enumTypeNames), tableName),
270
275
  virtualColumns: uniq(models.flatMap(model => model['virtualAttributes'].map(prop => prop.property) || [])),
271
276
  associations: associationData,
272
277
  serializerKeys,
@@ -311,11 +316,28 @@ may need to update the table getter in the corresponding Dream.
311
316
  /**
312
317
  * @internal
313
318
  *
314
- * retrieves the column data for an individual table and association.
315
- * Can be used to build up types
319
+ * the columns of an introspected table, as Dream's schema records them,
320
+ * keyed by camelized column name
316
321
  */
317
- async getColumnData(tableName, allTableAssociationData) {
318
- const dbDriverClass = Query.dbDriverClass(this.connectionName);
319
- return await dbDriverClass.getColumnData(this.connectionName, tableName, allTableAssociationData);
322
+ columnData(table, allTableAssociationData, enumTypeNames) {
323
+ const columnData = {};
324
+ for (const column of table.columns) {
325
+ const enumType = column.enumName ? enumTypeNames.get(column.enumName) : null;
326
+ columnData[camelize(column.name)] = {
327
+ dbType: column.dbType,
328
+ valueType: column.valueType,
329
+ allowNull: column.allowNull,
330
+ enumType,
331
+ enumValues: enumType ? `${enumType}Values` : null,
332
+ isArray: column.isArray,
333
+ foreignKey: allTableAssociationData[column.name]?.foreignKey || null,
334
+ };
335
+ }
336
+ return Object.keys(columnData)
337
+ .sort()
338
+ .reduce((acc, key) => {
339
+ acc[key] = columnData[key];
340
+ return acc;
341
+ }, {});
320
342
  }
321
343
  }
@@ -0,0 +1,132 @@
1
+ import ts from 'typescript';
2
+ import { CliFileWriter } from '../../cli/CliFileWriter.js';
3
+ import camelize from '../camelize.js';
4
+ import { propertyName } from './ASTBuilder.js';
5
+ import ASTConnectionBuilder from './ASTConnectionBuilder.js';
6
+ import autogeneratedFileDisclaimer from './autoGeneratedFileDisclaimer.js';
7
+ import { dbTypesHelperNames, dbTypesName, dbTypesReservedNames, HELPER_TYPE_DECLARATIONS, PLAIN_ARRAY_VALUE_TYPES, } from './dbTypesNaming.js';
8
+ const f = ts.factory;
9
+ /**
10
+ * Writes a connection's types/db.ts (types/db.<connectionName>.ts for any
11
+ * connection but default) from its introspection: the Kysely `DB`
12
+ * interface, an interface for each table, each enum the tables use as a
13
+ * union of its values with a `<Enum>Values` const of them, and the column
14
+ * types those declare. Columns that the table's models ignore are left out,
15
+ * so that code still referring to one fails to compile.
16
+ */
17
+ export default class ASTDbTypesBuilder extends ASTConnectionBuilder {
18
+ async build() {
19
+ const database = await this.introspectedDatabase();
20
+ const enumTypeNames = await this.enumTypeNames();
21
+ const helperNames = dbTypesHelperNames(database.tables);
22
+ const takenNames = new Set([...dbTypesReservedNames(database.tables), ...enumTypeNames.values()]);
23
+ const tables = database.tables.map(table => ({
24
+ key: this.tableKey(table),
25
+ interfaceName: dbTypesName(this.tableKey(table), takenNames),
26
+ columns: this.columns(table, enumTypeNames),
27
+ }));
28
+ const enumValues = new Map(database.enums.map(databaseEnum => [databaseEnum.name, databaseEnum.values]));
29
+ const typeDeclarations = [
30
+ ...helperNames.map(name => ({ name, statements: [helperTypeDeclaration(name)] })),
31
+ ...[...enumTypeNames].map(([enumName, typeName]) => ({
32
+ name: typeName,
33
+ statements: enumDeclarations(typeName, [...(enumValues.get(enumName) ?? [])].sort((a, b) => a.localeCompare(b))),
34
+ })),
35
+ ];
36
+ const tableInterfaces = [...tables]
37
+ .sort((a, b) => a.interfaceName.localeCompare(b.interfaceName))
38
+ .map(table => f.createInterfaceDeclaration([f.createModifier(ts.SyntaxKind.ExportKeyword)], table.interfaceName, undefined, undefined, table.columns.map(column => f.createPropertySignature(undefined, propertyName(column.key), undefined, column.type))));
39
+ const dbMembers = tables.map(table => ({
40
+ name: propertyName(table.key),
41
+ type: f.createTypeReferenceNode(table.interfaceName),
42
+ }));
43
+ const statements = [
44
+ ...typeDeclarations
45
+ .sort((a, b) => a.name.localeCompare(b.name))
46
+ .flatMap(declaration => declaration.statements),
47
+ ...tableInterfaces,
48
+ f.createInterfaceDeclaration([f.createModifier(ts.SyntaxKind.ExportKeyword)], 'DB', undefined, undefined, dbMembers.map(member => f.createPropertySignature(undefined, member.name, undefined, member.type))),
49
+ f.createClassDeclaration([f.createModifier(ts.SyntaxKind.ExportKeyword)], 'DBClass', undefined, undefined, dbMembers.map(member => f.createPropertyDeclaration(undefined, member.name, undefined, member.type, undefined))),
50
+ ];
51
+ const sourceFile = ts.createSourceFile('', '', ts.ScriptTarget.Latest, false, ts.ScriptKind.TS);
52
+ const printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed, omitTrailingSemicolon: true });
53
+ const print = (node) => printer.printNode(ts.EmitHint.Unspecified, node, sourceFile);
54
+ const output = await this.prettier(`\
55
+ ${autogeneratedFileDisclaimer()}
56
+ ${this.imports(helperNames).map(print).join('\n')}
57
+
58
+ ${statements.map(print).join('\n\n')}
59
+ `);
60
+ await CliFileWriter.write(this.dbPath(), output);
61
+ }
62
+ /**
63
+ * @internal
64
+ *
65
+ * the table's columns, minus those its models ignore, sorted by name, each
66
+ * with its key (the camelized column name) and its type
67
+ */
68
+ columns(table, enumTypeNames) {
69
+ const ignoredColumns = this.ignoredColumnsForTable(this.tableKey(table));
70
+ return [...table.columns]
71
+ .sort((a, b) => a.name.localeCompare(b.name))
72
+ .map(column => ({ key: camelize(column.name), type: columnType(column, enumTypeNames) }))
73
+ .filter(column => !ignoredColumns.has(column.key));
74
+ }
75
+ /**
76
+ * @internal
77
+ *
78
+ * the file's imports: Dream's date and time classes, Kysely's ColumnType,
79
+ * and postgres-interval's type when a column is an interval
80
+ */
81
+ imports(helperNames) {
82
+ return [
83
+ ...this.dateAndDateTimeImports(),
84
+ typeImport('ColumnType', 'kysely'),
85
+ ...(helperNames.includes('Interval') ? [typeImport('IPostgresInterval', 'postgres-interval')] : []),
86
+ ];
87
+ }
88
+ }
89
+ /**
90
+ * The column's type in its table's interface: its value type (an array of
91
+ * them for an array column), `| null` when it allows null, all wrapped in
92
+ * `Generated<>` when an insert may leave it out.
93
+ */
94
+ function columnType(column, enumTypeNames) {
95
+ const valueType = f.createTypeReferenceNode(column.valueType === 'enum' ? enumTypeNames.get(column.enumName) : column.valueType);
96
+ let type = valueType;
97
+ if (column.isArray) {
98
+ type = PLAIN_ARRAY_VALUE_TYPES.includes(column.valueType)
99
+ ? f.createArrayTypeNode(valueType)
100
+ : f.createTypeReferenceNode('ArrayType', [valueType]);
101
+ }
102
+ if (column.allowNull)
103
+ type = f.createUnionTypeNode([type, f.createLiteralTypeNode(f.createNull())]);
104
+ if (column.hasDefault)
105
+ type = f.createTypeReferenceNode('Generated', [type]);
106
+ return type;
107
+ }
108
+ /**
109
+ * An enum's type, the union of its values (`never` when it has none), and
110
+ * its `<Enum>Values` const, which lists them.
111
+ */
112
+ function enumDeclarations(typeName, values) {
113
+ const exportModifier = f.createModifier(ts.SyntaxKind.ExportKeyword);
114
+ return [
115
+ f.createTypeAliasDeclaration([exportModifier], typeName, undefined, values.length
116
+ ? f.createUnionTypeNode(values.map(value => f.createLiteralTypeNode(f.createStringLiteral(value))))
117
+ : f.createKeywordTypeNode(ts.SyntaxKind.NeverKeyword)),
118
+ f.createVariableStatement([exportModifier], f.createVariableDeclarationList([
119
+ f.createVariableDeclaration(`${typeName}Values`, undefined, undefined, f.createAsExpression(f.createArrayLiteralExpression(values.map(value => f.createStringLiteral(value))), f.createKeywordTypeNode(ts.SyntaxKind.ConstKeyword))),
120
+ ], ts.NodeFlags.Const)),
121
+ ];
122
+ }
123
+ /**
124
+ * A type types/db.ts declares for its columns, parsed from its declaration,
125
+ * which is fixed rather than built from the database.
126
+ */
127
+ function helperTypeDeclaration(name) {
128
+ return ts.createSourceFile('', HELPER_TYPE_DECLARATIONS[name], ts.ScriptTarget.Latest, false, ts.ScriptKind.TS).statements[0];
129
+ }
130
+ function typeImport(name, moduleName) {
131
+ return f.createImportDeclaration(undefined, f.createImportClause(true, undefined, f.createNamedImports([f.createImportSpecifier(false, undefined, f.createIdentifier(name))])), f.createStringLiteral(moduleName));
132
+ }
@@ -1,8 +1,8 @@
1
1
  import ts from 'typescript';
2
2
  import { CliFileWriter } from '../../cli/CliFileWriter.js';
3
3
  import { DreamConst } from '../../dream/constants.js';
4
- import compact from '../compact.js';
5
4
  import uniq from '../uniq.js';
5
+ import { propertyName } from './ASTBuilder.js';
6
6
  import ASTConnectionBuilder from './ASTConnectionBuilder.js';
7
7
  import autogeneratedFileDisclaimer from './autoGeneratedFileDisclaimer.js';
8
8
  const f = ts.factory;
@@ -51,11 +51,10 @@ export default class ASTSchemaBuilder extends ASTConnectionBuilder {
51
51
  const importedVariables = [];
52
52
  let passthroughColumns = [];
53
53
  let allDefaultScopeNames = [];
54
- const dbSourceFile = await this.getDbSourceFile();
55
54
  const schemaObjectLiteral = f.createObjectLiteralExpression(Object.keys(schemaData).map(tableName => {
56
55
  const tableData = schemaData[tableName];
57
56
  allDefaultScopeNames = [...allDefaultScopeNames, ...tableData.scopes.default];
58
- return f.createPropertyAssignment(f.createIdentifier(tableName), f.createObjectLiteralExpression([
57
+ return f.createPropertyAssignment(propertyName(tableName), f.createObjectLiteralExpression([
59
58
  f.createPropertyAssignment(f.createIdentifier('serializerKeys'), f.createArrayLiteralExpression([...(tableData?.serializerKeys || [])].sort().map(key => f.createStringLiteral(key)))),
60
59
  f.createPropertyAssignment(f.createIdentifier('scopes'), f.createObjectLiteralExpression([
61
60
  f.createPropertyAssignment(f.createIdentifier('default'), f.createArrayLiteralExpression((tableData?.scopes.default).sort().map(key => f.createStringLiteral(key)))),
@@ -84,8 +83,8 @@ export default class ASTSchemaBuilder extends ASTConnectionBuilder {
84
83
  const enumValuesNode = columnData.enumType
85
84
  ? f.createIdentifier(columnData.enumType + 'Values')
86
85
  : f.createNull();
87
- const coercedType = this.getCoercedTypeForTableColumn(dbSourceFile, tableName, columnName, tableData, importedTypes);
88
- return f.createPropertyAssignment(f.createIdentifier(columnName), f.createObjectLiteralExpression([
86
+ const coercedType = this.coercedType(columnData, importedTypes);
87
+ return f.createPropertyAssignment(propertyName(columnName), f.createObjectLiteralExpression([
89
88
  f.createPropertyAssignment(f.createIdentifier('coercedType'), f.createAsExpression(f.createObjectLiteralExpression(), coercedType)),
90
89
  f.createPropertyAssignment(f.createIdentifier('enumType'), enumTypeNode
91
90
  ? f.createAsExpression(f.createObjectLiteralExpression(), enumTypeNode)
@@ -238,83 +237,40 @@ ${output}`;
238
237
  /**
239
238
  * @internal
240
239
  *
241
- * given a column and table, this method returns the coerced type representation
242
- * of whatever type was found in the db.ts file. In most cases, it will simply
243
- * return the same type as was found, but in some cases it will perform coercion
244
- * to provide consistent and useful types to the underlying application.
245
- *
246
- * Amongst other things, it will convert Numeric -> number, Int8 -> string, etc...
247
- * Timestamp will be carefully converted to either CalendarDate or DateTime, depending
248
- * on if the type set in the db is a date or datetime field.
240
+ * the type Dream gives the column's values: Int8 (bigint) values are
241
+ * strings, Numeric values numbers, and a Timestamp is a CalendarDate for a
242
+ * date column and a DateTime otherwise. Types declared in the db.ts file
243
+ * (Json and the like) are added to importedTypes.
249
244
  */
250
- getCoercedTypeForTableColumn(dbSourceFile, tableName, columnName, tableData, importedModules) {
251
- const columnData = tableData.columns[columnName];
252
- const tableNode = this.getTableInterfaceDeclaration(dbSourceFile, tableName);
253
- const propertyNode = this.getPropertyFromInterface(tableNode, columnName);
254
- const coercedTypes = this.coercedType(dbSourceFile, propertyNode, columnData.dbType, importedModules);
255
- return coercedTypes.length === 1 ? coercedTypes[0] : f.createUnionTypeNode(coercedTypes);
245
+ coercedType(columnData, importedTypes) {
246
+ const valueType = this.coercedValueType(columnData, importedTypes);
247
+ const type = columnData.isArray ? f.createArrayTypeNode(valueType) : valueType;
248
+ return columnData.allowNull
249
+ ? f.createUnionTypeNode([type, f.createLiteralTypeNode(f.createNull())])
250
+ : type;
256
251
  }
257
- /**
258
- * @internal
259
- *
260
- * used by the getCoercedTypeForTableColumn to get the specific type for a column
261
- * if no coercion is necessary, the original type node will be returned
262
- */
263
- coercedType(dbSourceFile, propertySignature, dbType, importedModules) {
264
- const extractedPropertyTypes = this.extractTypeNodesFromTypeOrUnion(propertySignature);
265
- const isDate = this.isDateDbType(dbType);
266
- const isTime = this.isTimeWithoutTimeZoneDbType(dbType);
267
- const isTimeTz = this.isTimeWithTimeZoneDbType(dbType);
268
- const types = compact(extractedPropertyTypes.map(typeNode => {
269
- const typeText = typeNode.getText(dbSourceFile);
270
- let defaultReturnNode = /^Generated/.test(typeText) ? this.getFirstGenericType(typeNode) : typeNode;
271
- const modifiedText = defaultReturnNode.getText(dbSourceFile);
272
- defaultReturnNode = /^ArrayType/.test(modifiedText)
273
- ? f.createArrayTypeNode(this.getFirstGenericType(defaultReturnNode))
274
- : defaultReturnNode;
275
- const sanitized = typeText
276
- .replace(/\s/g, '')
277
- .replace(/Generated<(.*)>/g, '$1')
278
- .replace(/ArrayType<(.*)>/g, '$1[]');
279
- if (sanitized === '')
280
- return null;
281
- switch (sanitized) {
282
- case 'Numeric':
283
- return f.createKeywordTypeNode(ts.SyntaxKind.NumberKeyword);
284
- case 'Numeric[]':
285
- return f.createArrayTypeNode(f.createKeywordTypeNode(ts.SyntaxKind.NumberKeyword));
286
- case 'Timestamp':
287
- return isDate ? f.createTypeReferenceNode('CalendarDate') : f.createTypeReferenceNode('DateTime');
288
- case 'Timestamp[]':
289
- return isDate
290
- ? f.createArrayTypeNode(f.createTypeReferenceNode('CalendarDate'))
291
- : f.createArrayTypeNode(f.createTypeReferenceNode('DateTime'));
292
- case 'string':
293
- // Kysely-codegen types TIME columns as string, we need to check dbType
294
- if (isTime)
295
- return f.createTypeReferenceNode('ClockTime');
296
- if (isTimeTz)
297
- return f.createTypeReferenceNode('ClockTimeTz');
298
- return defaultReturnNode;
299
- case 'string[]':
300
- // Kysely-codegen types TIME[] columns as string[], we need to check dbType
301
- if (isTime)
302
- return f.createArrayTypeNode(f.createTypeReferenceNode('ClockTime'));
303
- if (isTimeTz)
304
- return f.createArrayTypeNode(f.createTypeReferenceNode('ClockTimeTz'));
305
- return defaultReturnNode;
306
- case 'Int8':
307
- return f.createKeywordTypeNode(ts.SyntaxKind.StringKeyword);
308
- case 'Int8[]':
309
- return f.createArrayTypeNode(f.createKeywordTypeNode(ts.SyntaxKind.StringKeyword));
310
- case 'Json':
311
- case 'Json[]':
312
- importedModules.push('Json');
313
- return defaultReturnNode;
314
- default:
315
- return defaultReturnNode;
316
- }
317
- }));
318
- return types;
252
+ coercedValueType(columnData, importedTypes) {
253
+ switch (columnData.valueType) {
254
+ case 'string':
255
+ case 'Int8':
256
+ return f.createKeywordTypeNode(ts.SyntaxKind.StringKeyword);
257
+ case 'number':
258
+ case 'Numeric':
259
+ return f.createKeywordTypeNode(ts.SyntaxKind.NumberKeyword);
260
+ case 'boolean':
261
+ return f.createKeywordTypeNode(ts.SyntaxKind.BooleanKeyword);
262
+ case 'Timestamp':
263
+ return f.createTypeReferenceNode(this.isDateDbType(columnData.dbType) ? 'CalendarDate' : 'DateTime');
264
+ case 'enum':
265
+ return f.createTypeReferenceNode(columnData.enumType);
266
+ case 'Json':
267
+ case 'Interval':
268
+ case 'Point':
269
+ case 'Circle':
270
+ importedTypes.push(columnData.valueType);
271
+ return f.createTypeReferenceNode(columnData.valueType);
272
+ default:
273
+ return f.createTypeReferenceNode(columnData.valueType);
274
+ }
319
275
  }
320
276
  }
@@ -0,0 +1,90 @@
1
+ import pascalize from '../pascalize.js';
2
+ /**
3
+ * @internal
4
+ *
5
+ * The value types an array column lists in a plain array in types/db.ts. Any
6
+ * other is listed through `ArrayType`, which turns a `ColumnType` (such as
7
+ * `Int8`) into a `ColumnType` of arrays.
8
+ */
9
+ export const PLAIN_ARRAY_VALUE_TYPES = ['string', 'number', 'boolean', 'ClockTime', 'ClockTimeTz'];
10
+ /**
11
+ * @internal
12
+ *
13
+ * The declaration of each type that types/db.ts declares for its columns.
14
+ */
15
+ export const HELPER_TYPE_DECLARATIONS = {
16
+ ArrayType: 'export type ArrayType<T> = ArrayTypeImpl<T> extends (infer U)[] ? U[] : ArrayTypeImpl<T>',
17
+ ArrayTypeImpl: 'export type ArrayTypeImpl<T> = T extends ColumnType<infer S, infer I, infer U> ? ColumnType<S[], I[], U[]> : T[]',
18
+ Circle: 'export type Circle = { x: number; y: number; radius: number }',
19
+ Generated: 'export type Generated<T> = T extends ColumnType<infer S, infer I, infer U> ? ColumnType<S, I | undefined, U> : ColumnType<T, T | undefined, T>',
20
+ Int8: 'export type Int8 = ColumnType<string, bigint | number | string, bigint | number | string>',
21
+ Interval: 'export type Interval = ColumnType<IPostgresInterval, IPostgresInterval | number | string, IPostgresInterval | number | string>',
22
+ Json: 'export type Json = JsonValue',
23
+ JsonArray: 'export type JsonArray = JsonValue[]',
24
+ JsonObject: 'export type JsonObject = {\n [x: string]: JsonValue | undefined\n}',
25
+ JsonPrimitive: 'export type JsonPrimitive = boolean | number | string | null',
26
+ JsonValue: 'export type JsonValue = JsonArray | JsonObject | JsonPrimitive',
27
+ Numeric: 'export type Numeric = ColumnType<string, number | string, number | string>',
28
+ Point: 'export type Point = { x: number; y: number }',
29
+ Timestamp: 'export type Timestamp = ColumnType<DateTime | CalendarDate>',
30
+ };
31
+ /**
32
+ * @internal
33
+ *
34
+ * The types types/db.ts declares for the given tables' columns.
35
+ */
36
+ export function dbTypesHelperNames(tables) {
37
+ const names = new Set();
38
+ for (const column of tables.flatMap(table => table.columns)) {
39
+ if (column.hasDefault)
40
+ names.add('Generated');
41
+ if (column.isArray && !PLAIN_ARRAY_VALUE_TYPES.includes(column.valueType)) {
42
+ names.add('ArrayType').add('ArrayTypeImpl');
43
+ }
44
+ if (column.valueType === 'Json') {
45
+ names.add('Json').add('JsonArray').add('JsonObject').add('JsonPrimitive').add('JsonValue');
46
+ }
47
+ if (HELPER_TYPE_DECLARATIONS[column.valueType])
48
+ names.add(column.valueType);
49
+ }
50
+ return [...names].sort();
51
+ }
52
+ /**
53
+ * @internal
54
+ *
55
+ * The names that types/db.ts declares, imports or uses from JavaScript for
56
+ * the given tables, which no enum or table interface may take.
57
+ */
58
+ export function dbTypesReservedNames(tables) {
59
+ const valueTypes = new Set(tables.flatMap(table => table.columns.map(column => column.valueType)));
60
+ return [
61
+ 'CalendarDate',
62
+ 'ClockTime',
63
+ 'ClockTimeTz',
64
+ 'ColumnType',
65
+ 'DB',
66
+ 'DBClass',
67
+ 'DateTime',
68
+ ...dbTypesHelperNames(tables),
69
+ ...(valueTypes.has('Date') ? ['Date'] : []),
70
+ ...(valueTypes.has('Buffer') ? ['Buffer'] : []),
71
+ ...(valueTypes.has('Interval') ? ['IPostgresInterval'] : []),
72
+ ];
73
+ }
74
+ /**
75
+ * @internal
76
+ *
77
+ * The TypeScript name types/db.ts gives a table or enum: its name, with a
78
+ * schema's `.` as `_`, pascalized, and prefixed with `_` when it would start
79
+ * with a digit. A number is added when the name is in `takenNames`, which
80
+ * the chosen name joins.
81
+ */
82
+ export function dbTypesName(name, takenNames) {
83
+ const pascalized = pascalize(name.replace(/\./g, '_'));
84
+ const baseName = /^\d/.test(pascalized) ? `_${pascalized}` : pascalized;
85
+ let typeName = baseName;
86
+ for (let suffix = 2; takenNames.has(typeName); suffix++)
87
+ typeName = `${baseName}${suffix}`;
88
+ takenNames.add(typeName);
89
+ return typeName;
90
+ }
@@ -0,0 +1,21 @@
1
+ import { matchesGlob } from 'node:path';
2
+ /**
3
+ * @internal
4
+ *
5
+ * Whether a table matches a `tableIncludePattern` or `tableExcludePattern`:
6
+ * a glob in Node's `path.matchesGlob` syntax (e.g. `chalupas*`, `public.*`
7
+ * or `public.+(users|posts)`), compared without regard to case. A pattern
8
+ * that contains a `.` is matched against `<schema>.<name>`, and any other
9
+ * against the table's name alone. As with micromatch, a leading `!` (one that
10
+ * does not open an extglob `!(…)`) negates the pattern, and a backslash
11
+ * before a glob character such as `*` or `?` matches that character itself.
12
+ */
13
+ export default function tableMatchesPattern(table, pattern) {
14
+ if (/^!(?!\()/.test(pattern))
15
+ return !tableMatchesPattern(table, pattern.slice(1));
16
+ const subject = pattern.includes('.') ? `${table.schema ?? '*'}.${table.name}` : table.name;
17
+ // matchesGlob does not read a backslash as an escape, so an escaped
18
+ // character is matched through a class of that one character
19
+ const glob = pattern.replace(/\\(.)/g, '[$1]');
20
+ return matchesGlob(subject.toLowerCase(), glob.toLowerCase());
21
+ }
@@ -1,11 +1,3 @@
1
- export default function dataTypes() {
2
- // In the future, when we support multiple db drivers,
3
- // this will need to be updated
4
- return postgresDatatypes;
5
- }
6
- export function isPrimitiveDataType(type) {
7
- return dataTypes().includes(type.replace(/\[\]$/, ''));
8
- }
9
1
  export const postgresDatatypes = [
10
2
  'bigint',
11
3
  'bigserial',