@sigitex/outlaw 1.0.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 (58) hide show
  1. package/LICENSE +7 -0
  2. package/README.md +9 -0
  3. package/package.json +52 -0
  4. package/src/api/DatabaseTable.ts +51 -0
  5. package/src/api/DatabaseView.ts +22 -0
  6. package/src/api/api.types.ts +200 -0
  7. package/src/api/createDatabase.ts +24 -0
  8. package/src/api/index.ts +4 -0
  9. package/src/bun/bun.ts +27 -0
  10. package/src/bun/index.ts +1 -0
  11. package/src/cloudflare/cloudflare.ts +18 -0
  12. package/src/cloudflare/index.ts +1 -0
  13. package/src/console.ts +14 -0
  14. package/src/cowboyMigration/Compare.ts +97 -0
  15. package/src/cowboyMigration/CowboyConnection.ts +57 -0
  16. package/src/cowboyMigration/CowboyMigrator.ts +437 -0
  17. package/src/cowboyMigration/CowboySeeder.ts +245 -0
  18. package/src/cowboyMigration/cowboyMigration.types.ts +29 -0
  19. package/src/cowboyMigration/createSchemaHacker.ts +28 -0
  20. package/src/cowboyMigration/index.ts +3 -0
  21. package/src/crypto.d.ts +9 -0
  22. package/src/framework/Format.ts +31 -0
  23. package/src/framework/definitions.d.ts +4 -0
  24. package/src/framework/index.ts +1 -0
  25. package/src/index.ts +10 -0
  26. package/src/queryBuilder/DeleteBuilder.ts +40 -0
  27. package/src/queryBuilder/InsertBuilder.ts +31 -0
  28. package/src/queryBuilder/Mappings.ts +55 -0
  29. package/src/queryBuilder/SelectBuilder.ts +39 -0
  30. package/src/queryBuilder/SelectQueryBuilder.ts +93 -0
  31. package/src/queryBuilder/UpdateBuilder.ts +44 -0
  32. package/src/queryBuilder/addWhereClause.ts +35 -0
  33. package/src/queryBuilder/index.ts +7 -0
  34. package/src/queryBuilder/operators.ts +35 -0
  35. package/src/queryBuilder/queryBuilders.types.ts +105 -0
  36. package/src/queryGenerator/Clause.ts +79 -0
  37. package/src/queryGenerator/generateDelete.ts +18 -0
  38. package/src/queryGenerator/generateInsert.ts +29 -0
  39. package/src/queryGenerator/generateSelect.ts +89 -0
  40. package/src/queryGenerator/generateUpdate.ts +29 -0
  41. package/src/queryGenerator/index.ts +4 -0
  42. package/src/reflection/Reflector.ts +47 -0
  43. package/src/reflection/index.ts +2 -0
  44. package/src/reflection/reflection.types.ts +12 -0
  45. package/src/schemaBuilder/Mapping.ts +44 -0
  46. package/src/schemaBuilder/columnBuilders.ts +67 -0
  47. package/src/schemaBuilder/createFixture.ts +112 -0
  48. package/src/schemaBuilder/createIndex.ts +33 -0
  49. package/src/schemaBuilder/createSchema.ts +23 -0
  50. package/src/schemaBuilder/createTable.ts +80 -0
  51. package/src/schemaBuilder/createView.ts +21 -0
  52. package/src/schemaBuilder/index.ts +9 -0
  53. package/src/schemaBuilder/metadata.ts +73 -0
  54. package/src/schemaBuilder/schemaBuilder.types.ts +139 -0
  55. package/src/schemaGenerator/generateCreateIndex.ts +18 -0
  56. package/src/schemaGenerator/generateCreateTable.ts +68 -0
  57. package/src/schemaGenerator/generateCreateView.ts +13 -0
  58. package/src/schemaGenerator/index.ts +3 -0
@@ -0,0 +1,139 @@
1
+ // oxlint-disable typescript/no-explicit-any
2
+ import type { CheckExpression, ColumnData, ColumnRef, IndexData, TableData, ViewData } from "./metadata"
3
+ import type { Mapping } from "./Mapping"
4
+
5
+ export type SchemaMembers = {
6
+ readonly [key: string]: AnyBuildTable | BuildView<any> | BuildIndex
7
+ }
8
+
9
+ export type TablesOf<M extends SchemaMembers> = {
10
+ [K in keyof M as M[K] extends AnyBuildTable ? K : never]: M[K]
11
+ }
12
+
13
+ export type ViewsOf<M extends SchemaMembers> = {
14
+ [K in keyof M as M[K] extends BuildView<any> ? K : never]: M[K]
15
+ }
16
+
17
+ export type IndexesOf<M extends SchemaMembers> = {
18
+ [K in keyof M as M[K] extends BuildIndex ? K : never]: M[K]
19
+ }
20
+
21
+ export type Schema<M extends SchemaMembers> = {
22
+ readonly tables: TablesOf<M>
23
+ readonly views: ViewsOf<M>
24
+ readonly indexes: IndexesOf<M>
25
+ }
26
+
27
+ export type ColumnNames<Columns> = { readonly [K in keyof Columns]: string }
28
+
29
+ export type BuildColumns = {
30
+ readonly [columnName: string]: BuildColumn<any, any>
31
+ }
32
+
33
+ export type InferColumn<BC> = BC extends BuildColumn<infer Type, infer Defined>
34
+ ? "notNull" extends Defined
35
+ ? Type
36
+ : "primaryKey" extends Defined
37
+ ? Type
38
+ : Type | null
39
+ : never
40
+
41
+ export type InferTable<BT> = BT extends BuildTable<infer Columns>
42
+ ? { [K in keyof Columns]: InferColumn<Columns[K]> }
43
+ : never
44
+
45
+ export type RefBy = {
46
+ readonly _tag: "RefBy"
47
+ readonly table: AnyBuildTable
48
+ readonly column: string
49
+ readonly value: unknown
50
+ }
51
+
52
+ type BuildTableDSL<DefineColumns> = {
53
+ readonly $kind: "table"
54
+ primaryKey: (...columns: (keyof DefineColumns)[]) => BuildTable<DefineColumns>
55
+ unique: (...columns: (keyof DefineColumns)[]) => BuildTable<DefineColumns>
56
+ check: (expression: string | ((columns: ColumnNames<DefineColumns>, table: TableData) => string)) => BuildTable<DefineColumns>
57
+ select(all: "*"): SchemaSelect<DefineColumns, DefineColumns>
58
+ select<C extends keyof DefineColumns>(...columns: C[]): SchemaSelect<Pick<DefineColumns, C>, DefineColumns>
59
+ readonly by: {
60
+ readonly [K in keyof DefineColumns]: (
61
+ value: InferColumn<DefineColumns[K]>,
62
+ ) => RefBy
63
+ }
64
+ readonly $meta: TableData
65
+ readonly infer: InferTable<BuildTable<DefineColumns>>
66
+ }
67
+
68
+ export type BuildTable<DefineColumns> = BuildTableDSL<DefineColumns> & {
69
+ readonly [K in keyof DefineColumns]: ColumnRef
70
+ }
71
+
72
+ export type AnyBuildTable = {
73
+ readonly $kind: "table"
74
+ readonly $meta: TableData
75
+ readonly [key: string]: unknown
76
+ }
77
+
78
+ // oxlint-disable-next-line no-unused-vars
79
+ export type BuildView<SelectColumns = unknown> = {
80
+ readonly $kind: "view"
81
+ readonly $meta: ViewData
82
+ readonly $tableData: TableData
83
+ }
84
+
85
+ export type BuildIndex = {
86
+ readonly $kind: "index"
87
+ readonly $meta: IndexData
88
+ }
89
+
90
+ /** Schema-level select builder — tracks column types without requiring a connection. */
91
+ export type SchemaSelect<SelectColumns, Columns> = {
92
+ where<Column extends keyof Columns>(column: Column, value: unknown): SchemaSelect<SelectColumns, Columns>
93
+ where<Column extends keyof Columns>(column: Column, operator: string): SchemaSelect<SelectColumns, Columns>
94
+ where<Column extends keyof Columns>(column: Column, operator: string, value: unknown): SchemaSelect<SelectColumns, Columns>
95
+ orderBy(sorts: [keyof Columns, "asc" | "desc"][]): SchemaSelect<SelectColumns, Columns>
96
+ limit(n: number): SchemaSelect<SelectColumns, Columns>
97
+ offset(n: number): SchemaSelect<SelectColumns, Columns>
98
+ join<JC>(table: BuildTable<JC>): SchemaSelect<SelectColumns & JC, Columns & JC>
99
+ leftJoin<JC>(table: BuildTable<JC>): SchemaSelect<SelectColumns & JC, Columns & JC>
100
+ on(left: ColumnRef, operator: string, right: ColumnRef): SchemaSelect<SelectColumns, Columns>
101
+ }
102
+
103
+ export type BuildColumn<Type, Defined extends string> = Omit<
104
+ {
105
+ readonly notNull: BuildColumn<Type, Defined | "notNull">
106
+ readonly primaryKey: BuildColumn<Type, Defined | "primaryKey"> &
107
+ BuildPrimaryKey<Type, Defined | "primaryKey">
108
+ readonly default: (sql: string) => BuildColumn<Type, Defined | "default">
109
+ readonly unique: BuildColumn<Type, Defined | "unique">
110
+ readonly check: (expression: CheckExpression) => BuildColumn<Type, Defined | "check">
111
+ readonly foreignKey: BuildForeignKey<Type, Defined>
112
+ readonly map: BuildColumnMap<Type, Defined>
113
+ },
114
+ Defined
115
+ >
116
+
117
+ export type BuildColumnInner = BuildColumn<any, never> & {
118
+ $meta: Partial<ColumnData>
119
+ }
120
+
121
+ export type BuildPrimaryKey<Type, Defined extends string> = {
122
+ readonly autoincrement: BuildColumn<Type, Defined>
123
+ }
124
+
125
+ export type BuildForeignKey<Type, Defined extends string> = {
126
+ readonly references: (
127
+ ref: ColumnRef,
128
+ ) => BuildColumn<Type, Defined | "foreignKey">
129
+ }
130
+
131
+ export type BuildColumnMap<Type, Defined extends string> = {
132
+ readonly boolean: BuildColumn<boolean, Defined | "map">
133
+ readonly timestamp: BuildColumn<Date, Defined | "map">
134
+ readonly date: BuildColumn<Date, Defined | "map">
135
+ readonly json: <T>() => BuildColumn<T, Defined | "map">
136
+ } & {
137
+ <To>(mapping: Mapping<Type, To>): BuildColumn<To, Defined | "map">
138
+ <To>(): BuildColumn<To, Defined | "map">
139
+ }
@@ -0,0 +1,18 @@
1
+ import { join, newline, print } from "@sigitex/print"
2
+ import { Format } from "../framework"
3
+ import type { IndexData } from "../schemaBuilder"
4
+
5
+ export function generateCreateIndex(index: IndexData) {
6
+ return print([
7
+ "create ",
8
+ index.unique && "unique ",
9
+ "index ",
10
+ Format.name(index.name),
11
+ " on ",
12
+ Format.name(index.table),
13
+ " (",
14
+ join(", ", index.columns, Format.name),
15
+ ");",
16
+ newline,
17
+ ])
18
+ }
@@ -0,0 +1,68 @@
1
+ import { indent, newline, print } from "@sigitex/print"
2
+ import { Format } from "../framework"
3
+ import type { CheckExpression, ColumnData, TableData } from "../schemaBuilder"
4
+
5
+ export function generateCreateTable(table: TableData) {
6
+ const columnNames = Object.fromEntries(table.columns.map(c => [c.name, c.name]))
7
+ return print([
8
+ "create table ",
9
+ Format.name(table.name),
10
+ " (",
11
+ indent(
12
+ table.columns.map((column, c) => [
13
+ c > 0 && [",", newline],
14
+ Format.name(column.name),
15
+ " ",
16
+ column.datatype,
17
+ column.primaryKey && [
18
+ " primary key",
19
+ column.primaryKey.autoincrement && " autoincrement",
20
+ ],
21
+ column.notNull && " not null",
22
+ column.unique && " unique",
23
+ column.default && [" default ", column.default],
24
+ column.check && [" check(", resolveColumnCheck(column.check, column), ")"],
25
+ ]),
26
+ table.columns
27
+ .filter(({ foreignKey }) => foreignKey)
28
+ .map((column) => [
29
+ ",",
30
+ newline,
31
+ "foreign key (",
32
+ Format.name(column.name),
33
+ ") references ",
34
+ Format.name(column.foreignKey?.table),
35
+ " (",
36
+ Format.name(column.foreignKey?.column),
37
+ ")",
38
+ ]),
39
+ table.constraints.map((constraint) => [
40
+ ",",
41
+ newline,
42
+ constraint.type === "primaryKey" && "primary key",
43
+ constraint.type === "unique" && "unique",
44
+ (constraint.type === "primaryKey" || constraint.type === "unique") && [
45
+ " (",
46
+ constraint.columns.map((fkColumn, c) => [
47
+ c > 0 && ", ",
48
+ Format.name(fkColumn),
49
+ ]),
50
+ ")",
51
+ ],
52
+ constraint.type === "check" && [
53
+ "check(",
54
+ typeof constraint.expression === "function"
55
+ ? constraint.expression(columnNames, table)
56
+ : constraint.expression,
57
+ ")",
58
+ ],
59
+ ]),
60
+ ),
61
+ ");",
62
+ newline,
63
+ ])
64
+ }
65
+
66
+ function resolveColumnCheck(check: CheckExpression, column: ColumnData): string {
67
+ return typeof check === "function" ? check(column.name, column) : check
68
+ }
@@ -0,0 +1,13 @@
1
+ import { newline, print } from "@sigitex/print"
2
+ import { Format } from "../framework"
3
+ import type { ViewData } from "../schemaBuilder"
4
+
5
+ export function generateCreateView(view: ViewData) {
6
+ return print([
7
+ "create view ",
8
+ Format.name(view.name),
9
+ " as ",
10
+ view.sql,
11
+ newline,
12
+ ])
13
+ }
@@ -0,0 +1,3 @@
1
+ export * from "./generateCreateTable"
2
+ export * from "./generateCreateIndex"
3
+ export * from "./generateCreateView"