-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsqlite.ts
More file actions
138 lines (124 loc) · 3.26 KB
/
Copy pathsqlite.ts
File metadata and controls
138 lines (124 loc) · 3.26 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
import { FinalResult } from "../types/helpers";
const column = Symbol("column");
const primaryKeyColumn = Symbol("primaryKeyColumn");
const tableDefinition = Symbol("tableDefinition");
export const ids = {
column,
primaryKeyColumn,
tableDefinition,
} as const;
export type ColumnStorageType = "INTEGER" | "REAL" | "TEXT" | "BLOB";
export function Column(name: string, storageType: ColumnStorageType) {
return Object.freeze({
type: ids.column,
name,
storageType,
nullable: true,
} as const);
}
export function NotNull(column: ReturnType<typeof Column>) {
return Object.freeze({
type: ids.column,
name: column.name,
storageType: column.storageType,
nullable: false,
} as const);
}
export function PrimaryKey(column: ReturnType<typeof Column>) {
return Object.freeze({
type: ids.primaryKeyColumn,
name: column.name,
storageType: column.storageType,
} as const);
}
type ColumnsComponent<Result> = () => Generator<
ReturnType<typeof Column | typeof NotNull | typeof PrimaryKey>,
Result,
void
>;
export function Table<ColumnsResult>(
name: string,
columns: ColumnsComponent<ColumnsResult>
) {
return Object.freeze({
type: ids.tableDefinition,
name,
columns,
ifNotExists: false,
} as const);
}
export function IfNotExists<ColumnsResult>(
table: Readonly<{
type: typeof tableDefinition;
name: string;
columns: ColumnsComponent<ColumnsResult>;
ifNotExists: false;
}>
) {
return Object.freeze({
...table,
ifNotExists: true,
} as const);
}
export function createTableStatement(
tableDefinition: ReturnType<typeof Table | typeof IfNotExists>
) {
const { name, columns, ifNotExists } = tableDefinition;
return [
`CREATE TABLE `,
ifNotExists ? `IF NOT EXISTS ` : "",
`${name}(\n\t`,
Array.from(
function* () {
for (const message of columns()) {
if (message.type === ids.column) {
if (message.nullable) {
yield `${message.name} ${message.storageType}`;
} else {
yield `${message.name} ${message.storageType} NOT NULL`;
}
} else if (message.type === ids.primaryKeyColumn) {
yield `${message.name} ${message.storageType} PRIMARY KEY`;
}
}
}.call(null)
).join(",\n\t"),
"\n);",
].join("");
}
export function createInsertStatement<
ColumnsResult extends Record<string, number | string | Uint8Array>
>(
tableDefinition: Readonly<{
name: string;
columns: ColumnsComponent<ColumnsResult>;
}>,
values: Partial<ColumnsResult>
) {
const { name } = tableDefinition;
const valuesMap = new Map(Object.entries(values));
return [
`INSERT INTO `,
`${name}(`,
Array.from(valuesMap.keys()).join(", "),
`) VALUES (`,
Array.from(valuesMap.keys(), (key) => `:${key}`).join(", "),
`);`,
].join("");
}
export function createInsertArgs<
ColumnsResult extends Record<string, number | string | Uint8Array>
>(
tableDefinition: Readonly<{
name: string;
columns: ColumnsComponent<ColumnsResult>;
}>,
values: Partial<ColumnsResult>
) {
return [
createInsertStatement(tableDefinition, values),
Object.fromEntries(
Array.from(Object.entries(values), ([key, value]) => [`:${key}`, value])
),
];
}