@c9up/atlas 0.1.19 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (250) hide show
  1. package/README.md +63 -14
  2. package/db.darwin-arm64.node +0 -0
  3. package/db.darwin-x64.node +0 -0
  4. package/db.linux-arm64-gnu.node +0 -0
  5. package/db.linux-x64-gnu.node +0 -0
  6. package/db.win32-x64-msvc.node +0 -0
  7. package/dist/AtlasProvider.d.ts +66 -7
  8. package/dist/AtlasProvider.d.ts.map +1 -1
  9. package/dist/AtlasProvider.js +205 -39
  10. package/dist/AtlasProvider.js.map +1 -1
  11. package/dist/BaseEntity.d.ts +181 -5
  12. package/dist/BaseEntity.d.ts.map +1 -1
  13. package/dist/BaseEntity.js +339 -33
  14. package/dist/BaseEntity.js.map +1 -1
  15. package/dist/BaseModel.d.ts +127 -0
  16. package/dist/BaseModel.d.ts.map +1 -0
  17. package/dist/BaseModel.js +250 -0
  18. package/dist/BaseModel.js.map +1 -0
  19. package/dist/BaseRepository.d.ts +81 -15
  20. package/dist/BaseRepository.d.ts.map +1 -1
  21. package/dist/BaseRepository.js +1433 -387
  22. package/dist/BaseRepository.js.map +1 -1
  23. package/dist/ConnectionManager.d.ts +106 -0
  24. package/dist/ConnectionManager.d.ts.map +1 -0
  25. package/dist/ConnectionManager.js +228 -0
  26. package/dist/ConnectionManager.js.map +1 -0
  27. package/dist/ModelQuery.d.ts +577 -41
  28. package/dist/ModelQuery.d.ts.map +1 -1
  29. package/dist/ModelQuery.js +2188 -291
  30. package/dist/ModelQuery.js.map +1 -1
  31. package/dist/Transaction.d.ts +71 -1
  32. package/dist/Transaction.d.ts.map +1 -1
  33. package/dist/Transaction.js +138 -24
  34. package/dist/Transaction.js.map +1 -1
  35. package/dist/adapters/NapiDbAdapter.d.ts +44 -4
  36. package/dist/adapters/NapiDbAdapter.d.ts.map +1 -1
  37. package/dist/adapters/NapiDbAdapter.js +131 -13
  38. package/dist/adapters/NapiDbAdapter.js.map +1 -1
  39. package/dist/console/contract.d.ts +62 -0
  40. package/dist/console/contract.d.ts.map +1 -0
  41. package/dist/console/contract.js +38 -0
  42. package/dist/console/contract.js.map +1 -0
  43. package/dist/console/factoryCommands.d.ts +23 -0
  44. package/dist/console/factoryCommands.d.ts.map +1 -0
  45. package/dist/console/factoryCommands.js +62 -0
  46. package/dist/console/factoryCommands.js.map +1 -0
  47. package/dist/console/migrationCommands.d.ts +78 -0
  48. package/dist/console/migrationCommands.d.ts.map +1 -0
  49. package/dist/console/migrationCommands.js +327 -0
  50. package/dist/console/migrationCommands.js.map +1 -0
  51. package/dist/console/schemaCheckCommand.d.ts +11 -17
  52. package/dist/console/schemaCheckCommand.d.ts.map +1 -1
  53. package/dist/console/schemaCheckCommand.js +21 -15
  54. package/dist/console/schemaCheckCommand.js.map +1 -1
  55. package/dist/console/schemaDumpCommand.d.ts +30 -0
  56. package/dist/console/schemaDumpCommand.d.ts.map +1 -0
  57. package/dist/console/schemaDumpCommand.js +69 -0
  58. package/dist/console/schemaDumpCommand.js.map +1 -0
  59. package/dist/console/schemaGenerateCommand.d.ts +100 -0
  60. package/dist/console/schemaGenerateCommand.d.ts.map +1 -0
  61. package/dist/console/schemaGenerateCommand.js +246 -0
  62. package/dist/console/schemaGenerateCommand.js.map +1 -0
  63. package/dist/console/seederCommands.d.ts +46 -0
  64. package/dist/console/seederCommands.d.ts.map +1 -0
  65. package/dist/console/seederCommands.js +136 -0
  66. package/dist/console/seederCommands.js.map +1 -0
  67. package/dist/decorators/entity.d.ts +50 -8
  68. package/dist/decorators/entity.d.ts.map +1 -1
  69. package/dist/decorators/entity.js +42 -2
  70. package/dist/decorators/entity.js.map +1 -1
  71. package/dist/decorators/hooks.d.ts +3 -3
  72. package/dist/decorators/hooks.d.ts.map +1 -1
  73. package/dist/decorators/hooks.js.map +1 -1
  74. package/dist/events.d.ts +69 -0
  75. package/dist/events.d.ts.map +1 -0
  76. package/dist/events.js +82 -0
  77. package/dist/events.js.map +1 -0
  78. package/dist/factories.d.ts +8 -0
  79. package/dist/factories.d.ts.map +1 -0
  80. package/dist/factories.js +8 -0
  81. package/dist/factories.js.map +1 -0
  82. package/dist/index.d.ts +15 -5
  83. package/dist/index.d.ts.map +1 -1
  84. package/dist/index.js +14 -3
  85. package/dist/index.js.map +1 -1
  86. package/dist/lucid-schema.d.ts +15 -0
  87. package/dist/lucid-schema.d.ts.map +1 -0
  88. package/dist/lucid-schema.js +16 -0
  89. package/dist/lucid-schema.js.map +1 -0
  90. package/dist/metadata-keys.d.ts +3 -2
  91. package/dist/metadata-keys.d.ts.map +1 -1
  92. package/dist/naming/NamingStrategy.d.ts +7 -0
  93. package/dist/naming/NamingStrategy.d.ts.map +1 -1
  94. package/dist/naming/NamingStrategy.js +16 -0
  95. package/dist/naming/NamingStrategy.js.map +1 -1
  96. package/dist/orm.d.ts +14 -0
  97. package/dist/orm.d.ts.map +1 -0
  98. package/dist/orm.js +14 -0
  99. package/dist/orm.js.map +1 -0
  100. package/dist/query/DatabaseQueryBuilder.d.ts +557 -0
  101. package/dist/query/DatabaseQueryBuilder.d.ts.map +1 -0
  102. package/dist/query/DatabaseQueryBuilder.js +1798 -0
  103. package/dist/query/DatabaseQueryBuilder.js.map +1 -0
  104. package/dist/query/DmlBuilder.d.ts +62 -0
  105. package/dist/query/DmlBuilder.d.ts.map +1 -0
  106. package/dist/query/DmlBuilder.js +84 -0
  107. package/dist/query/DmlBuilder.js.map +1 -0
  108. package/dist/query/QueryBuilder.d.ts +5 -0
  109. package/dist/query/QueryBuilder.d.ts.map +1 -1
  110. package/dist/query/QueryBuilder.js +7 -0
  111. package/dist/query/QueryBuilder.js.map +1 -1
  112. package/dist/query/RawQueryBuilder.d.ts +47 -0
  113. package/dist/query/RawQueryBuilder.d.ts.map +1 -0
  114. package/dist/query/RawQueryBuilder.js +138 -0
  115. package/dist/query/RawQueryBuilder.js.map +1 -0
  116. package/dist/query/interpolate.d.ts +45 -0
  117. package/dist/query/interpolate.d.ts.map +1 -0
  118. package/dist/query/interpolate.js +51 -0
  119. package/dist/query/interpolate.js.map +1 -0
  120. package/dist/query/native.d.ts +8 -0
  121. package/dist/query/native.d.ts.map +1 -1
  122. package/dist/query/native.js +14 -0
  123. package/dist/query/native.js.map +1 -1
  124. package/dist/query/operators.d.ts +4 -0
  125. package/dist/query/operators.d.ts.map +1 -0
  126. package/dist/query/operators.js +27 -0
  127. package/dist/query/operators.js.map +1 -0
  128. package/dist/schema/Migration.d.ts +50 -3
  129. package/dist/schema/Migration.d.ts.map +1 -1
  130. package/dist/schema/Migration.js +60 -24
  131. package/dist/schema/Migration.js.map +1 -1
  132. package/dist/schema/MigrationRunner.d.ts +95 -34
  133. package/dist/schema/MigrationRunner.d.ts.map +1 -1
  134. package/dist/schema/MigrationRunner.js +523 -68
  135. package/dist/schema/MigrationRunner.js.map +1 -1
  136. package/dist/schema/Schema.d.ts +114 -0
  137. package/dist/schema/Schema.d.ts.map +1 -1
  138. package/dist/schema/Schema.js +272 -3
  139. package/dist/schema/Schema.js.map +1 -1
  140. package/dist/schema/SchemaDumper.d.ts +121 -0
  141. package/dist/schema/SchemaDumper.d.ts.map +1 -0
  142. package/dist/schema/SchemaDumper.js +365 -0
  143. package/dist/schema/SchemaDumper.js.map +1 -0
  144. package/dist/schema/Seeder.d.ts +13 -0
  145. package/dist/schema/Seeder.d.ts.map +1 -1
  146. package/dist/schema/Seeder.js +28 -5
  147. package/dist/schema/Seeder.js.map +1 -1
  148. package/dist/schema/TableBuilder.d.ts +274 -16
  149. package/dist/schema/TableBuilder.d.ts.map +1 -1
  150. package/dist/schema/TableBuilder.js +656 -52
  151. package/dist/schema/TableBuilder.js.map +1 -1
  152. package/dist/schema/catalog.d.ts +71 -0
  153. package/dist/schema/catalog.d.ts.map +1 -0
  154. package/dist/schema/catalog.js +158 -0
  155. package/dist/schema/catalog.js.map +1 -0
  156. package/dist/schema/introspect.d.ts +1 -1
  157. package/dist/schema/introspect.d.ts.map +1 -1
  158. package/dist/schema/introspect.js +26 -11
  159. package/dist/schema/introspect.js.map +1 -1
  160. package/dist/schema/types.d.ts +150 -1
  161. package/dist/schema/types.d.ts.map +1 -1
  162. package/dist/schema/types.js +11 -0
  163. package/dist/schema/types.js.map +1 -1
  164. package/dist/seeders.d.ts +7 -0
  165. package/dist/seeders.d.ts.map +1 -0
  166. package/dist/seeders.js +7 -0
  167. package/dist/seeders.js.map +1 -0
  168. package/dist/services/db.d.ts +122 -5
  169. package/dist/services/db.d.ts.map +1 -1
  170. package/dist/services/db.js +187 -14
  171. package/dist/services/db.js.map +1 -1
  172. package/dist/testing/DatabaseCleanup.d.ts +33 -7
  173. package/dist/testing/DatabaseCleanup.d.ts.map +1 -1
  174. package/dist/testing/DatabaseCleanup.js +54 -24
  175. package/dist/testing/DatabaseCleanup.js.map +1 -1
  176. package/dist/testing/DbAssertions.d.ts +48 -0
  177. package/dist/testing/DbAssertions.d.ts.map +1 -0
  178. package/dist/testing/DbAssertions.js +80 -0
  179. package/dist/testing/DbAssertions.js.map +1 -0
  180. package/dist/testing/Factory.d.ts +166 -15
  181. package/dist/testing/Factory.d.ts.map +1 -1
  182. package/dist/testing/Factory.js +497 -23
  183. package/dist/testing/Factory.js.map +1 -1
  184. package/dist/testing/TestUtils.d.ts +49 -0
  185. package/dist/testing/TestUtils.d.ts.map +1 -0
  186. package/dist/testing/TestUtils.js +79 -0
  187. package/dist/testing/TestUtils.js.map +1 -0
  188. package/dist/testing/index.d.ts +3 -1
  189. package/dist/testing/index.d.ts.map +1 -1
  190. package/dist/testing/index.js +3 -1
  191. package/dist/testing/index.js.map +1 -1
  192. package/dist/types/relations.d.ts +31 -0
  193. package/dist/types/relations.d.ts.map +1 -0
  194. package/dist/types/relations.js +20 -0
  195. package/dist/types/relations.js.map +1 -0
  196. package/index.darwin-arm64.node +0 -0
  197. package/index.darwin-x64.node +0 -0
  198. package/index.linux-arm64-gnu.node +0 -0
  199. package/index.linux-x64-gnu.node +0 -0
  200. package/index.win32-x64-msvc.node +0 -0
  201. package/package.json +32 -2
  202. package/scripts/guard-publish.mjs +15 -0
  203. package/src/AtlasProvider.ts +305 -52
  204. package/src/BaseEntity.ts +460 -41
  205. package/src/BaseModel.ts +461 -0
  206. package/src/BaseRepository.ts +1710 -421
  207. package/src/ConnectionManager.ts +298 -0
  208. package/src/ModelQuery.ts +2998 -335
  209. package/src/Transaction.ts +227 -30
  210. package/src/adapters/NapiDbAdapter.ts +224 -17
  211. package/src/console/contract.ts +96 -0
  212. package/src/console/factoryCommands.ts +73 -0
  213. package/src/console/migrationCommands.ts +448 -0
  214. package/src/console/schemaCheckCommand.ts +26 -22
  215. package/src/console/schemaDumpCommand.ts +96 -0
  216. package/src/console/schemaGenerateCommand.ts +380 -0
  217. package/src/console/seederCommands.ts +174 -0
  218. package/src/decorators/entity.ts +71 -8
  219. package/src/decorators/hooks.ts +5 -3
  220. package/src/events.ts +117 -0
  221. package/src/factories.ts +10 -0
  222. package/src/index.ts +69 -3
  223. package/src/lucid-schema.ts +22 -0
  224. package/src/metadata-keys.ts +3 -2
  225. package/src/naming/NamingStrategy.ts +23 -0
  226. package/src/orm.ts +13 -0
  227. package/src/query/DatabaseQueryBuilder.ts +2724 -0
  228. package/src/query/DmlBuilder.ts +131 -0
  229. package/src/query/QueryBuilder.ts +8 -0
  230. package/src/query/RawQueryBuilder.ts +173 -0
  231. package/src/query/interpolate.ts +73 -0
  232. package/src/query/native.ts +29 -0
  233. package/src/query/operators.ts +27 -0
  234. package/src/schema/Migration.ts +71 -3
  235. package/src/schema/MigrationRunner.ts +676 -69
  236. package/src/schema/Schema.ts +359 -3
  237. package/src/schema/SchemaDumper.ts +518 -0
  238. package/src/schema/Seeder.ts +47 -10
  239. package/src/schema/TableBuilder.ts +783 -52
  240. package/src/schema/catalog.ts +236 -0
  241. package/src/schema/introspect.ts +26 -9
  242. package/src/schema/types.ts +137 -2
  243. package/src/seeders.ts +16 -0
  244. package/src/services/db.ts +361 -21
  245. package/src/testing/DatabaseCleanup.ts +78 -25
  246. package/src/testing/DbAssertions.ts +127 -0
  247. package/src/testing/Factory.ts +837 -40
  248. package/src/testing/TestUtils.ts +123 -0
  249. package/src/testing/index.ts +12 -1
  250. package/src/types/relations.ts +43 -0
@@ -12,32 +12,246 @@ import {
12
12
  compileStatementNative,
13
13
  getAtlasDialect,
14
14
  } from "../query/native.js";
15
+ import {
16
+ type CatalogConnection,
17
+ columnExists,
18
+ tableExists,
19
+ } from "./catalog.js";
15
20
  import { TableBuilder } from "./TableBuilder.js";
16
21
 
17
22
  export class Schema {
18
23
  #dialect: AtlasDialect;
19
24
  #statements: string[] = [];
25
+ #connection?: CatalogConnection;
26
+ #schemaName?: string;
20
27
 
21
28
  constructor(dialect: AtlasDialect = getAtlasDialect()) {
22
29
  this.#dialect = dialect;
23
30
  }
24
31
 
32
+ /**
33
+ * Qualify subsequent table names with `name` (Adonis Lucid/Knex
34
+ * `withSchema`), e.g. `withSchema('reporting').createTable('t', …)` targets
35
+ * `"reporting"."t"`. Applies to every table-taking method until changed; the
36
+ * Rust compiler quotes each dotted segment. Chainable.
37
+ */
38
+ withSchema(name: string): this {
39
+ this.#schemaName = name;
40
+ return this;
41
+ }
42
+
43
+ /** Prefix a table name with the active schema, if one was set. */
44
+ #qualify(table: string): string {
45
+ return this.#schemaName ? `${this.#schemaName}.${table}` : table;
46
+ }
47
+
48
+ /**
49
+ * Attach a live connection so the async introspection helpers
50
+ * ({@link hasTable}/{@link hasColumn}) can query the catalog. The migration
51
+ * runner calls this before running a migration's `up`/`down`.
52
+ */
53
+ bindConnection(connection: CatalogConnection): void {
54
+ this.#connection = connection;
55
+ }
56
+
57
+ /**
58
+ * Does this table exist right now? (Adonis Lucid/Knex `hasTable`.) Runs a
59
+ * live catalog query, so it reflects migrations already applied — but NOT
60
+ * statements this same migration has only buffered (they run after `up`).
61
+ * Requires a bound connection (present inside a migration).
62
+ */
63
+ async hasTable(name: string): Promise<boolean> {
64
+ return tableExists(
65
+ this.#requireConnection("hasTable"),
66
+ this.#dialect,
67
+ name,
68
+ );
69
+ }
70
+
71
+ /** Does this column exist on this table right now? (Adonis Lucid/Knex `hasColumn`.) */
72
+ async hasColumn(table: string, column: string): Promise<boolean> {
73
+ return columnExists(
74
+ this.#requireConnection("hasColumn"),
75
+ this.#dialect,
76
+ table,
77
+ column,
78
+ );
79
+ }
80
+
81
+ #requireConnection(method: string): CatalogConnection {
82
+ if (!this.#connection) {
83
+ throw new Error(
84
+ `E_NO_CONNECTION: schema.${method}() needs a live connection — it is available inside a migration, not on a standalone Schema.`,
85
+ );
86
+ }
87
+ return this.#connection;
88
+ }
89
+
25
90
  createTable(name: string, callback: (table: TableBuilder) => void): this {
26
- const builder = new TableBuilder(name);
91
+ const builder = new TableBuilder(this.#qualify(name));
27
92
  callback(builder);
28
93
  this.#statements.push(...builder.toStatements(this.#dialect));
29
94
  return this;
30
95
  }
31
96
 
97
+ /** `CREATE TABLE IF NOT EXISTS` (Lucid/Knex `createTableIfNotExists`). */
98
+ createTableIfNotExists(
99
+ name: string,
100
+ callback: (table: TableBuilder) => void,
101
+ ): this {
102
+ const builder = new TableBuilder(this.#qualify(name));
103
+ callback(builder);
104
+ this.#statements.push(
105
+ ...builder.toStatements(this.#dialect, { ifNotExists: true }),
106
+ );
107
+ return this;
108
+ }
109
+
110
+ /**
111
+ * `ALTER TABLE` (Lucid/Knex `alterTable`, also spelled `table()`). Inside
112
+ * the callback a column-type method adds a column, `.alter()` changes one,
113
+ * and `dropColumn` / `renameColumn` / `setNullable` / `dropNullable` do
114
+ * what they say. Operations compile in call order.
115
+ */
116
+ alterTable(name: string, callback: (table: TableBuilder) => void): this {
117
+ const builder = new TableBuilder(this.#qualify(name), "alter");
118
+ callback(builder);
119
+ // An empty callback is a caller bug, not an empty statement list: the
120
+ // Rust compiler rejects a no-op ALTER, so short-circuit with a clearer error.
121
+ if (
122
+ builder.getOperations().length === 0 &&
123
+ builder.getIndexes().length === 0
124
+ ) {
125
+ throw new Error(
126
+ `E_ALTER_EMPTY: schema.alterTable('${name}') declared no operations`,
127
+ );
128
+ }
129
+ this.#statements.push(...builder.toStatements(this.#dialect));
130
+ return this;
131
+ }
132
+
133
+ /** Alias of {@link alterTable} (Lucid/Knex `table()`). */
134
+ table(name: string, callback: (table: TableBuilder) => void): this {
135
+ return this.alterTable(name, callback);
136
+ }
137
+
138
+ /** `ALTER TABLE old RENAME TO new` (Lucid/Knex `renameTable`). */
139
+ renameTable(from: string, to: string): this {
140
+ const { statements } = compileStatementNative(
141
+ {
142
+ kind: "renameTable",
143
+ table: this.#qualify(from),
144
+ to: this.#qualify(to),
145
+ },
146
+ this.#dialect,
147
+ );
148
+ this.#statements.push(...statements);
149
+ return this;
150
+ }
151
+
152
+ /** `DROP TABLE` — errors if the table is missing (Adonis Lucid/Knex `dropTable`). */
32
153
  dropTable(name: string): this {
33
154
  const { statements } = compileStatementNative(
34
- { kind: "dropTable", table: name, ifExists: true },
155
+ { kind: "dropTable", table: this.#qualify(name), ifExists: false },
35
156
  this.#dialect,
36
157
  );
37
158
  this.#statements.push(...statements);
38
159
  return this;
39
160
  }
40
161
 
162
+ /** `DROP TABLE IF EXISTS` — a no-op when missing (Lucid/Knex `dropTableIfExists`). */
163
+ dropTableIfExists(name: string): this {
164
+ const { statements } = compileStatementNative(
165
+ { kind: "dropTable", table: this.#qualify(name), ifExists: true },
166
+ this.#dialect,
167
+ );
168
+ this.#statements.push(...statements);
169
+ return this;
170
+ }
171
+
172
+ /**
173
+ * `CREATE SCHEMA` (Lucid/Knex `createSchema`). Postgres and MySQL (where a
174
+ * schema is a database); rejected on SQLite, which has no schemas.
175
+ */
176
+ createSchema(name: string): this {
177
+ return this.#schemaStmt({ kind: "createSchema", name, ifNotExists: false });
178
+ }
179
+
180
+ /** `CREATE SCHEMA IF NOT EXISTS` (Lucid/Knex `createSchemaIfNotExists`). */
181
+ createSchemaIfNotExists(name: string): this {
182
+ return this.#schemaStmt({ kind: "createSchema", name, ifNotExists: true });
183
+ }
184
+
185
+ /** `DROP SCHEMA [CASCADE]` (Lucid/Knex `dropSchema`). CASCADE is Postgres-only. */
186
+ dropSchema(name: string, cascade = false): this {
187
+ return this.#schemaStmt({
188
+ kind: "dropSchema",
189
+ name,
190
+ ifExists: false,
191
+ cascade,
192
+ });
193
+ }
194
+
195
+ /** `DROP SCHEMA IF EXISTS [CASCADE]` (Lucid/Knex `dropSchemaIfExists`). */
196
+ dropSchemaIfExists(name: string, cascade = false): this {
197
+ return this.#schemaStmt({
198
+ kind: "dropSchema",
199
+ name,
200
+ ifExists: true,
201
+ cascade,
202
+ });
203
+ }
204
+
205
+ /** Compile a schema-level DDL spec and queue it. */
206
+ #schemaStmt(spec: object): this {
207
+ const { statements } = compileStatementNative(spec, this.#dialect);
208
+ this.#statements.push(...statements);
209
+ return this;
210
+ }
211
+
212
+ /**
213
+ * `CREATE TABLE new LIKE old` (Lucid/Knex `createTableLike`) — copy a table's
214
+ * structure. Postgres copies everything (`INCLUDING ALL`), MySQL uses `LIKE`,
215
+ * SQLite copies COLUMNS ONLY (`AS SELECT … WHERE 0` — no constraints/indexes,
216
+ * the same limitation Knex documents).
217
+ */
218
+ createTableLike(
219
+ name: string,
220
+ likeTable: string,
221
+ callback?: (table: TableBuilder) => void,
222
+ ): this {
223
+ this.#schemaStmt({
224
+ kind: "createTableLike",
225
+ table: this.#qualify(name),
226
+ likeTable: this.#qualify(likeTable),
227
+ ifNotExists: false,
228
+ });
229
+ // Lucid's optional callback adds columns to the copied table — emit them as
230
+ // a follow-up ALTER TABLE (the copy exists by the time it runs).
231
+ if (callback) this.alterTable(name, callback);
232
+ return this;
233
+ }
234
+
235
+ /**
236
+ * `ALTER VIEW` (Lucid/Knex `alterView`) — rename a view's columns via the
237
+ * callback (`view.column('id').rename('user_id')`). Postgres only: MySQL/SQLite
238
+ * can't rename view columns in place, so drop and re-create the view there.
239
+ */
240
+ alterView(name: string, callback: (view: AlterViewBuilder) => void): this {
241
+ const builder = new AlterViewBuilder();
242
+ callback(builder);
243
+ return this.#schemaStmt({
244
+ kind: "alterView",
245
+ view: this.#qualify(name),
246
+ renames: builder.renames,
247
+ });
248
+ }
249
+
250
+ /** Alias of {@link alterView} (Lucid/Knex `view`). */
251
+ view(name: string, callback: (view: AlterViewBuilder) => void): this {
252
+ return this.alterView(name, callback);
253
+ }
254
+
41
255
  createIndex(
42
256
  table: string,
43
257
  columns: string | string[],
@@ -47,7 +261,13 @@ export class Schema {
47
261
  const cols = Array.isArray(columns) ? columns : [columns];
48
262
  const indexName = name ?? `idx_${table}_${cols.join("_")}`;
49
263
  const { statements } = compileStatementNative(
50
- { kind: "createIndex", table, name: indexName, columns: cols, unique },
264
+ {
265
+ kind: "createIndex",
266
+ table: this.#qualify(table),
267
+ name: indexName,
268
+ columns: cols,
269
+ unique,
270
+ },
51
271
  this.#dialect,
52
272
  );
53
273
  this.#statements.push(...statements);
@@ -63,6 +283,125 @@ export class Schema {
63
283
  return this;
64
284
  }
65
285
 
286
+ /**
287
+ * `CREATE VIEW name [(cols)] AS <select>` (Lucid/Knex `createView`). The
288
+ * `select` is raw, developer-authored SQL — same trust level as {@link raw} —
289
+ * embedded verbatim; the view name and column list are validated + quoted by
290
+ * the Rust compiler.
291
+ */
292
+ createView(
293
+ name: string,
294
+ select: string,
295
+ options: { columns?: string[] } = {},
296
+ ): this {
297
+ return this.#pushView(name, select, options);
298
+ }
299
+
300
+ /** `CREATE OR REPLACE VIEW` (Lucid/Knex `createViewOrReplace`). Rejected on SQLite. */
301
+ createViewOrReplace(
302
+ name: string,
303
+ select: string,
304
+ options: { columns?: string[] } = {},
305
+ ): this {
306
+ return this.#pushView(name, select, { ...options, orReplace: true });
307
+ }
308
+
309
+ /** `CREATE MATERIALIZED VIEW` (Lucid/Knex `createMaterializedView`). Postgres-only. */
310
+ createMaterializedView(
311
+ name: string,
312
+ select: string,
313
+ options: { columns?: string[] } = {},
314
+ ): this {
315
+ return this.#pushView(name, select, { ...options, materialized: true });
316
+ }
317
+
318
+ /** `DROP VIEW` — errors if missing (Lucid/Knex `dropView`). */
319
+ dropView(name: string): this {
320
+ return this.#schemaStmt({
321
+ kind: "dropView",
322
+ name: this.#qualify(name),
323
+ ifExists: false,
324
+ });
325
+ }
326
+
327
+ /** `DROP VIEW IF EXISTS` — a no-op when missing (Lucid/Knex `dropViewIfExists`). */
328
+ dropViewIfExists(name: string): this {
329
+ return this.#schemaStmt({
330
+ kind: "dropView",
331
+ name: this.#qualify(name),
332
+ ifExists: true,
333
+ });
334
+ }
335
+
336
+ /** `DROP MATERIALIZED VIEW` (Lucid/Knex). Postgres-only. */
337
+ dropMaterializedView(name: string): this {
338
+ return this.#schemaStmt({
339
+ kind: "dropView",
340
+ name: this.#qualify(name),
341
+ ifExists: false,
342
+ materialized: true,
343
+ });
344
+ }
345
+
346
+ /** `DROP MATERIALIZED VIEW IF EXISTS` (Lucid/Knex). Postgres-only. */
347
+ dropMaterializedViewIfExists(name: string): this {
348
+ return this.#schemaStmt({
349
+ kind: "dropView",
350
+ name: this.#qualify(name),
351
+ ifExists: true,
352
+ materialized: true,
353
+ });
354
+ }
355
+
356
+ /**
357
+ * Rename a view (Lucid/Knex `renameView`). Postgres `ALTER VIEW … RENAME TO`,
358
+ * MySQL `RENAME TABLE`; SQLite can't rename a view (drop and re-create).
359
+ */
360
+ renameView(from: string, to: string): this {
361
+ return this.#schemaStmt({
362
+ kind: "renameView",
363
+ from: this.#qualify(from),
364
+ to: this.#qualify(to),
365
+ materialized: false,
366
+ });
367
+ }
368
+
369
+ /**
370
+ * `REFRESH MATERIALIZED VIEW [CONCURRENTLY]` (Lucid/Knex
371
+ * `refreshMaterializedView`). Postgres-only.
372
+ */
373
+ refreshMaterializedView(name: string, concurrently = false): this {
374
+ return this.#schemaStmt({
375
+ kind: "refreshMaterializedView",
376
+ name: this.#qualify(name),
377
+ concurrently,
378
+ });
379
+ }
380
+
381
+ #pushView(
382
+ name: string,
383
+ select: string,
384
+ options: {
385
+ columns?: string[];
386
+ orReplace?: boolean;
387
+ materialized?: boolean;
388
+ },
389
+ ): this {
390
+ const { statements } = compileStatementNative(
391
+ {
392
+ kind: "createView",
393
+ name: this.#qualify(name),
394
+ select,
395
+ orReplace: options.orReplace ?? false,
396
+ materialized: options.materialized ?? false,
397
+ columns: options.columns ?? null,
398
+ },
399
+ this.#dialect,
400
+ );
401
+ this.#statements.push(...statements);
402
+ return this;
403
+ }
404
+
66
405
  raw(sql: string): this {
67
406
  this.#statements.push(sql);
68
407
  return this;
@@ -76,3 +415,20 @@ export class Schema {
76
415
  return [...this.#statements];
77
416
  }
78
417
  }
418
+
419
+ /**
420
+ * Callback builder for {@link Schema.alterView} — collects column renames
421
+ * (Adonis Lucid `view.column('id').rename('user_id')`).
422
+ */
423
+ export class AlterViewBuilder {
424
+ readonly renames: Array<{ from: string; to: string }> = [];
425
+
426
+ /** Target a view column; `.rename(to)` queues its rename. */
427
+ column(name: string): { rename(to: string): void } {
428
+ return {
429
+ rename: (to: string): void => {
430
+ this.renames.push({ from: name, to });
431
+ },
432
+ };
433
+ }
434
+ }