elysia-rack 0.1.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.
- package/LICENSE +21 -0
- package/README.md +241 -0
- package/dist/Dashboard-xpstr7fr.js +172 -0
- package/dist/Panel-fbp3wrsw.js +738 -0
- package/dist/index-37x76zdn.js +4 -0
- package/dist/index-zc7rgvmm.js +13 -0
- package/dist/panel-app.js +1 -0
- package/dist/panel-theme.js +1 -0
- package/dist/panel.css +1 -0
- package/dist/rack/adapter.d.ts +5 -0
- package/dist/rack/adapters/drizzle.d.ts +2 -0
- package/dist/rack/adapters/index.d.ts +59 -0
- package/dist/rack/adapters/prisma.d.ts +2 -0
- package/dist/rack/authorization.d.ts +23 -0
- package/dist/rack/idempotency.d.ts +9 -0
- package/dist/rack/index.d.ts +40 -0
- package/dist/rack/index.js +1362 -0
- package/dist/rack/models/drizzle.d.ts +4 -0
- package/dist/rack/models/index.d.ts +24 -0
- package/dist/rack/models/prisma.d.ts +4 -0
- package/dist/rack/openapi.d.ts +6 -0
- package/dist/rack/page.d.ts +33 -0
- package/dist/rack/query.d.ts +22 -0
- package/dist/rack/registry.d.ts +20 -0
- package/dist/rack/types/authorization.d.ts +16 -0
- package/dist/rack/types/idempotency.d.ts +46 -0
- package/dist/rack/types/index.d.ts +89 -0
- package/dist/rack/types/metadata.d.ts +36 -0
- package/dist/rack/types/openapi.d.ts +22 -0
- package/dist/rack/types/operations.d.ts +14 -0
- package/dist/rack/types/page.d.ts +41 -0
- package/dist/rack/types/query.d.ts +30 -0
- package/dist/rack/types/validation.d.ts +19 -0
- package/dist/react/index.d.ts +64 -0
- package/dist/react/index.js +126 -0
- package/dist/react/page/Dashboard.d.ts +7 -0
- package/dist/react/page/Panel.d.ts +36 -0
- package/dist/react/page/client/panel.d.ts +1 -0
- package/dist/react/page/client/theme.d.ts +1 -0
- package/dist/react/page/components/Breadcrumb.d.ts +7 -0
- package/dist/react/page/components/DataTable.d.ts +10 -0
- package/dist/react/page/components/Masthead.d.ts +7 -0
- package/dist/react/page/components/Pagination.d.ts +10 -0
- package/dist/react/page/components/Sidebar.d.ts +16 -0
- package/dist/react/page/components/Toolbar.d.ts +7 -0
- package/dist/react/page/components/href.d.ts +10 -0
- package/dist/react/page/components/panelForm.d.ts +9 -0
- package/dist/react/render.d.ts +2 -0
- package/dist/react/types.d.ts +16 -0
- package/package.json +89 -0
|
@@ -0,0 +1,1362 @@
|
|
|
1
|
+
import {
|
|
2
|
+
clearRacks,
|
|
3
|
+
listRacks,
|
|
4
|
+
registerRack
|
|
5
|
+
} from "../index-zc7rgvmm.js";
|
|
6
|
+
import"../index-37x76zdn.js";
|
|
7
|
+
|
|
8
|
+
// src/rack/index.ts
|
|
9
|
+
import Elysia, { status as status2 } from "elysia";
|
|
10
|
+
|
|
11
|
+
// src/rack/adapter.ts
|
|
12
|
+
function resolveAdapter(model) {
|
|
13
|
+
return "drizzle" in model && model.drizzle !== undefined ? "drizzle" : "prisma";
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// node_modules/drizzle-orm/entity.js
|
|
17
|
+
var entityKind = Symbol.for("drizzle:entityKind");
|
|
18
|
+
var hasOwnEntityKind = Symbol.for("drizzle:hasOwnEntityKind");
|
|
19
|
+
function is(value, type) {
|
|
20
|
+
if (!value || typeof value !== "object") {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
if (value instanceof type) {
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
26
|
+
if (!Object.prototype.hasOwnProperty.call(type, entityKind)) {
|
|
27
|
+
throw new Error(`Class "${type.name ?? "<unknown>"}" doesn't look like a Drizzle entity. If this is incorrect and the class is provided by Drizzle, please report this as a bug.`);
|
|
28
|
+
}
|
|
29
|
+
let cls = Object.getPrototypeOf(value).constructor;
|
|
30
|
+
if (cls) {
|
|
31
|
+
while (cls) {
|
|
32
|
+
if (entityKind in cls && cls[entityKind] === type[entityKind]) {
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
35
|
+
cls = Object.getPrototypeOf(cls);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// node_modules/drizzle-orm/column.js
|
|
42
|
+
class Column {
|
|
43
|
+
constructor(table, config) {
|
|
44
|
+
this.table = table;
|
|
45
|
+
this.config = config;
|
|
46
|
+
this.name = config.name;
|
|
47
|
+
this.keyAsName = config.keyAsName;
|
|
48
|
+
this.notNull = config.notNull;
|
|
49
|
+
this.default = config.default;
|
|
50
|
+
this.defaultFn = config.defaultFn;
|
|
51
|
+
this.onUpdateFn = config.onUpdateFn;
|
|
52
|
+
this.hasDefault = config.hasDefault;
|
|
53
|
+
this.primary = config.primaryKey;
|
|
54
|
+
this.isUnique = config.isUnique;
|
|
55
|
+
this.uniqueName = config.uniqueName;
|
|
56
|
+
this.uniqueType = config.uniqueType;
|
|
57
|
+
this.dataType = config.dataType;
|
|
58
|
+
this.columnType = config.columnType;
|
|
59
|
+
this.generated = config.generated;
|
|
60
|
+
this.generatedIdentity = config.generatedIdentity;
|
|
61
|
+
}
|
|
62
|
+
static [entityKind] = "Column";
|
|
63
|
+
name;
|
|
64
|
+
keyAsName;
|
|
65
|
+
primary;
|
|
66
|
+
notNull;
|
|
67
|
+
default;
|
|
68
|
+
defaultFn;
|
|
69
|
+
onUpdateFn;
|
|
70
|
+
hasDefault;
|
|
71
|
+
isUnique;
|
|
72
|
+
uniqueName;
|
|
73
|
+
uniqueType;
|
|
74
|
+
dataType;
|
|
75
|
+
columnType;
|
|
76
|
+
enumValues = undefined;
|
|
77
|
+
generated = undefined;
|
|
78
|
+
generatedIdentity = undefined;
|
|
79
|
+
config;
|
|
80
|
+
mapFromDriverValue(value) {
|
|
81
|
+
return value;
|
|
82
|
+
}
|
|
83
|
+
mapToDriverValue(value) {
|
|
84
|
+
return value;
|
|
85
|
+
}
|
|
86
|
+
shouldDisableInsert() {
|
|
87
|
+
return this.config.generated !== undefined && this.config.generated.type !== "byDefault";
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// node_modules/drizzle-orm/table.utils.js
|
|
92
|
+
var TableName = Symbol.for("drizzle:Name");
|
|
93
|
+
|
|
94
|
+
// node_modules/drizzle-orm/tracing-utils.js
|
|
95
|
+
function iife(fn, ...args) {
|
|
96
|
+
return fn(...args);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// node_modules/drizzle-orm/pg-core/unique-constraint.js
|
|
100
|
+
function uniqueKeyName(table, columns) {
|
|
101
|
+
return `${table[TableName]}_${columns.join("_")}_unique`;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// node_modules/drizzle-orm/pg-core/columns/common.js
|
|
105
|
+
class PgColumn extends Column {
|
|
106
|
+
constructor(table, config) {
|
|
107
|
+
if (!config.uniqueName) {
|
|
108
|
+
config.uniqueName = uniqueKeyName(table, [config.name]);
|
|
109
|
+
}
|
|
110
|
+
super(table, config);
|
|
111
|
+
this.table = table;
|
|
112
|
+
}
|
|
113
|
+
static [entityKind] = "PgColumn";
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
class ExtraConfigColumn extends PgColumn {
|
|
117
|
+
static [entityKind] = "ExtraConfigColumn";
|
|
118
|
+
getSQLType() {
|
|
119
|
+
return this.getSQLType();
|
|
120
|
+
}
|
|
121
|
+
indexConfig = {
|
|
122
|
+
order: this.config.order ?? "asc",
|
|
123
|
+
nulls: this.config.nulls ?? "last",
|
|
124
|
+
opClass: this.config.opClass
|
|
125
|
+
};
|
|
126
|
+
defaultConfig = {
|
|
127
|
+
order: "asc",
|
|
128
|
+
nulls: "last",
|
|
129
|
+
opClass: undefined
|
|
130
|
+
};
|
|
131
|
+
asc() {
|
|
132
|
+
this.indexConfig.order = "asc";
|
|
133
|
+
return this;
|
|
134
|
+
}
|
|
135
|
+
desc() {
|
|
136
|
+
this.indexConfig.order = "desc";
|
|
137
|
+
return this;
|
|
138
|
+
}
|
|
139
|
+
nullsFirst() {
|
|
140
|
+
this.indexConfig.nulls = "first";
|
|
141
|
+
return this;
|
|
142
|
+
}
|
|
143
|
+
nullsLast() {
|
|
144
|
+
this.indexConfig.nulls = "last";
|
|
145
|
+
return this;
|
|
146
|
+
}
|
|
147
|
+
op(opClass) {
|
|
148
|
+
this.indexConfig.opClass = opClass;
|
|
149
|
+
return this;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// node_modules/drizzle-orm/pg-core/columns/enum.js
|
|
154
|
+
class PgEnumObjectColumn extends PgColumn {
|
|
155
|
+
static [entityKind] = "PgEnumObjectColumn";
|
|
156
|
+
enum;
|
|
157
|
+
enumValues = this.config.enum.enumValues;
|
|
158
|
+
constructor(table, config) {
|
|
159
|
+
super(table, config);
|
|
160
|
+
this.enum = config.enum;
|
|
161
|
+
}
|
|
162
|
+
getSQLType() {
|
|
163
|
+
return this.enum.enumName;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
var isPgEnumSym = Symbol.for("drizzle:isPgEnum");
|
|
167
|
+
function isPgEnum(obj) {
|
|
168
|
+
return !!obj && typeof obj === "function" && isPgEnumSym in obj && obj[isPgEnumSym] === true;
|
|
169
|
+
}
|
|
170
|
+
class PgEnumColumn extends PgColumn {
|
|
171
|
+
static [entityKind] = "PgEnumColumn";
|
|
172
|
+
enum = this.config.enum;
|
|
173
|
+
enumValues = this.config.enum.enumValues;
|
|
174
|
+
constructor(table, config) {
|
|
175
|
+
super(table, config);
|
|
176
|
+
this.enum = config.enum;
|
|
177
|
+
}
|
|
178
|
+
getSQLType() {
|
|
179
|
+
return this.enum.enumName;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// node_modules/drizzle-orm/subquery.js
|
|
184
|
+
class Subquery {
|
|
185
|
+
static [entityKind] = "Subquery";
|
|
186
|
+
constructor(sql, fields, alias, isWith = false, usedTables = []) {
|
|
187
|
+
this._ = {
|
|
188
|
+
brand: "Subquery",
|
|
189
|
+
sql,
|
|
190
|
+
selectedFields: fields,
|
|
191
|
+
alias,
|
|
192
|
+
isWith,
|
|
193
|
+
usedTables
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// node_modules/drizzle-orm/version.js
|
|
199
|
+
var version = "0.45.2";
|
|
200
|
+
|
|
201
|
+
// node_modules/drizzle-orm/tracing.js
|
|
202
|
+
var otel;
|
|
203
|
+
var rawTracer;
|
|
204
|
+
var tracer = {
|
|
205
|
+
startActiveSpan(name, fn) {
|
|
206
|
+
if (!otel) {
|
|
207
|
+
return fn();
|
|
208
|
+
}
|
|
209
|
+
if (!rawTracer) {
|
|
210
|
+
rawTracer = otel.trace.getTracer("drizzle-orm", version);
|
|
211
|
+
}
|
|
212
|
+
return iife((otel2, rawTracer2) => rawTracer2.startActiveSpan(name, (span) => {
|
|
213
|
+
try {
|
|
214
|
+
return fn(span);
|
|
215
|
+
} catch (e) {
|
|
216
|
+
span.setStatus({
|
|
217
|
+
code: otel2.SpanStatusCode.ERROR,
|
|
218
|
+
message: e instanceof Error ? e.message : "Unknown error"
|
|
219
|
+
});
|
|
220
|
+
throw e;
|
|
221
|
+
} finally {
|
|
222
|
+
span.end();
|
|
223
|
+
}
|
|
224
|
+
}), otel, rawTracer);
|
|
225
|
+
}
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
// node_modules/drizzle-orm/view-common.js
|
|
229
|
+
var ViewBaseConfig = Symbol.for("drizzle:ViewBaseConfig");
|
|
230
|
+
|
|
231
|
+
// node_modules/drizzle-orm/table.js
|
|
232
|
+
var Schema = Symbol.for("drizzle:Schema");
|
|
233
|
+
var Columns = Symbol.for("drizzle:Columns");
|
|
234
|
+
var ExtraConfigColumns = Symbol.for("drizzle:ExtraConfigColumns");
|
|
235
|
+
var OriginalName = Symbol.for("drizzle:OriginalName");
|
|
236
|
+
var BaseName = Symbol.for("drizzle:BaseName");
|
|
237
|
+
var IsAlias = Symbol.for("drizzle:IsAlias");
|
|
238
|
+
var ExtraConfigBuilder = Symbol.for("drizzle:ExtraConfigBuilder");
|
|
239
|
+
var IsDrizzleTable = Symbol.for("drizzle:IsDrizzleTable");
|
|
240
|
+
|
|
241
|
+
class Table {
|
|
242
|
+
static [entityKind] = "Table";
|
|
243
|
+
static Symbol = {
|
|
244
|
+
Name: TableName,
|
|
245
|
+
Schema,
|
|
246
|
+
OriginalName,
|
|
247
|
+
Columns,
|
|
248
|
+
ExtraConfigColumns,
|
|
249
|
+
BaseName,
|
|
250
|
+
IsAlias,
|
|
251
|
+
ExtraConfigBuilder
|
|
252
|
+
};
|
|
253
|
+
[TableName];
|
|
254
|
+
[OriginalName];
|
|
255
|
+
[Schema];
|
|
256
|
+
[Columns];
|
|
257
|
+
[ExtraConfigColumns];
|
|
258
|
+
[BaseName];
|
|
259
|
+
[IsAlias] = false;
|
|
260
|
+
[IsDrizzleTable] = true;
|
|
261
|
+
[ExtraConfigBuilder] = undefined;
|
|
262
|
+
constructor(name, schema, baseName) {
|
|
263
|
+
this[TableName] = this[OriginalName] = name;
|
|
264
|
+
this[Schema] = schema;
|
|
265
|
+
this[BaseName] = baseName;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// node_modules/drizzle-orm/sql/sql.js
|
|
270
|
+
function isSQLWrapper(value) {
|
|
271
|
+
return value !== null && value !== undefined && typeof value.getSQL === "function";
|
|
272
|
+
}
|
|
273
|
+
function mergeQueries(queries) {
|
|
274
|
+
const result = { sql: "", params: [] };
|
|
275
|
+
for (const query of queries) {
|
|
276
|
+
result.sql += query.sql;
|
|
277
|
+
result.params.push(...query.params);
|
|
278
|
+
if (query.typings?.length) {
|
|
279
|
+
if (!result.typings) {
|
|
280
|
+
result.typings = [];
|
|
281
|
+
}
|
|
282
|
+
result.typings.push(...query.typings);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
return result;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
class StringChunk {
|
|
289
|
+
static [entityKind] = "StringChunk";
|
|
290
|
+
value;
|
|
291
|
+
constructor(value) {
|
|
292
|
+
this.value = Array.isArray(value) ? value : [value];
|
|
293
|
+
}
|
|
294
|
+
getSQL() {
|
|
295
|
+
return new SQL([this]);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
class SQL {
|
|
300
|
+
constructor(queryChunks) {
|
|
301
|
+
this.queryChunks = queryChunks;
|
|
302
|
+
for (const chunk of queryChunks) {
|
|
303
|
+
if (is(chunk, Table)) {
|
|
304
|
+
const schemaName = chunk[Table.Symbol.Schema];
|
|
305
|
+
this.usedTables.push(schemaName === undefined ? chunk[Table.Symbol.Name] : schemaName + "." + chunk[Table.Symbol.Name]);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
static [entityKind] = "SQL";
|
|
310
|
+
decoder = noopDecoder;
|
|
311
|
+
shouldInlineParams = false;
|
|
312
|
+
usedTables = [];
|
|
313
|
+
append(query) {
|
|
314
|
+
this.queryChunks.push(...query.queryChunks);
|
|
315
|
+
return this;
|
|
316
|
+
}
|
|
317
|
+
toQuery(config) {
|
|
318
|
+
return tracer.startActiveSpan("drizzle.buildSQL", (span) => {
|
|
319
|
+
const query = this.buildQueryFromSourceParams(this.queryChunks, config);
|
|
320
|
+
span?.setAttributes({
|
|
321
|
+
"drizzle.query.text": query.sql,
|
|
322
|
+
"drizzle.query.params": JSON.stringify(query.params)
|
|
323
|
+
});
|
|
324
|
+
return query;
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
buildQueryFromSourceParams(chunks, _config) {
|
|
328
|
+
const config = Object.assign({}, _config, {
|
|
329
|
+
inlineParams: _config.inlineParams || this.shouldInlineParams,
|
|
330
|
+
paramStartIndex: _config.paramStartIndex || { value: 0 }
|
|
331
|
+
});
|
|
332
|
+
const {
|
|
333
|
+
casing,
|
|
334
|
+
escapeName,
|
|
335
|
+
escapeParam,
|
|
336
|
+
prepareTyping,
|
|
337
|
+
inlineParams,
|
|
338
|
+
paramStartIndex
|
|
339
|
+
} = config;
|
|
340
|
+
return mergeQueries(chunks.map((chunk) => {
|
|
341
|
+
if (is(chunk, StringChunk)) {
|
|
342
|
+
return { sql: chunk.value.join(""), params: [] };
|
|
343
|
+
}
|
|
344
|
+
if (is(chunk, Name)) {
|
|
345
|
+
return { sql: escapeName(chunk.value), params: [] };
|
|
346
|
+
}
|
|
347
|
+
if (chunk === undefined) {
|
|
348
|
+
return { sql: "", params: [] };
|
|
349
|
+
}
|
|
350
|
+
if (Array.isArray(chunk)) {
|
|
351
|
+
const result = [new StringChunk("(")];
|
|
352
|
+
for (const [i, p] of chunk.entries()) {
|
|
353
|
+
result.push(p);
|
|
354
|
+
if (i < chunk.length - 1) {
|
|
355
|
+
result.push(new StringChunk(", "));
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
result.push(new StringChunk(")"));
|
|
359
|
+
return this.buildQueryFromSourceParams(result, config);
|
|
360
|
+
}
|
|
361
|
+
if (is(chunk, SQL)) {
|
|
362
|
+
return this.buildQueryFromSourceParams(chunk.queryChunks, {
|
|
363
|
+
...config,
|
|
364
|
+
inlineParams: inlineParams || chunk.shouldInlineParams
|
|
365
|
+
});
|
|
366
|
+
}
|
|
367
|
+
if (is(chunk, Table)) {
|
|
368
|
+
const schemaName = chunk[Table.Symbol.Schema];
|
|
369
|
+
const tableName = chunk[Table.Symbol.Name];
|
|
370
|
+
return {
|
|
371
|
+
sql: schemaName === undefined || chunk[IsAlias] ? escapeName(tableName) : escapeName(schemaName) + "." + escapeName(tableName),
|
|
372
|
+
params: []
|
|
373
|
+
};
|
|
374
|
+
}
|
|
375
|
+
if (is(chunk, Column)) {
|
|
376
|
+
const columnName = casing.getColumnCasing(chunk);
|
|
377
|
+
if (_config.invokeSource === "indexes") {
|
|
378
|
+
return { sql: escapeName(columnName), params: [] };
|
|
379
|
+
}
|
|
380
|
+
const schemaName = chunk.table[Table.Symbol.Schema];
|
|
381
|
+
return {
|
|
382
|
+
sql: chunk.table[IsAlias] || schemaName === undefined ? escapeName(chunk.table[Table.Symbol.Name]) + "." + escapeName(columnName) : escapeName(schemaName) + "." + escapeName(chunk.table[Table.Symbol.Name]) + "." + escapeName(columnName),
|
|
383
|
+
params: []
|
|
384
|
+
};
|
|
385
|
+
}
|
|
386
|
+
if (is(chunk, View)) {
|
|
387
|
+
const schemaName = chunk[ViewBaseConfig].schema;
|
|
388
|
+
const viewName = chunk[ViewBaseConfig].name;
|
|
389
|
+
return {
|
|
390
|
+
sql: schemaName === undefined || chunk[ViewBaseConfig].isAlias ? escapeName(viewName) : escapeName(schemaName) + "." + escapeName(viewName),
|
|
391
|
+
params: []
|
|
392
|
+
};
|
|
393
|
+
}
|
|
394
|
+
if (is(chunk, Param)) {
|
|
395
|
+
if (is(chunk.value, Placeholder)) {
|
|
396
|
+
return { sql: escapeParam(paramStartIndex.value++, chunk), params: [chunk], typings: ["none"] };
|
|
397
|
+
}
|
|
398
|
+
const mappedValue = chunk.value === null ? null : chunk.encoder.mapToDriverValue(chunk.value);
|
|
399
|
+
if (is(mappedValue, SQL)) {
|
|
400
|
+
return this.buildQueryFromSourceParams([mappedValue], config);
|
|
401
|
+
}
|
|
402
|
+
if (inlineParams) {
|
|
403
|
+
return { sql: this.mapInlineParam(mappedValue, config), params: [] };
|
|
404
|
+
}
|
|
405
|
+
let typings = ["none"];
|
|
406
|
+
if (prepareTyping) {
|
|
407
|
+
typings = [prepareTyping(chunk.encoder)];
|
|
408
|
+
}
|
|
409
|
+
return { sql: escapeParam(paramStartIndex.value++, mappedValue), params: [mappedValue], typings };
|
|
410
|
+
}
|
|
411
|
+
if (is(chunk, Placeholder)) {
|
|
412
|
+
return { sql: escapeParam(paramStartIndex.value++, chunk), params: [chunk], typings: ["none"] };
|
|
413
|
+
}
|
|
414
|
+
if (is(chunk, SQL.Aliased) && chunk.fieldAlias !== undefined) {
|
|
415
|
+
return { sql: escapeName(chunk.fieldAlias), params: [] };
|
|
416
|
+
}
|
|
417
|
+
if (is(chunk, Subquery)) {
|
|
418
|
+
if (chunk._.isWith) {
|
|
419
|
+
return { sql: escapeName(chunk._.alias), params: [] };
|
|
420
|
+
}
|
|
421
|
+
return this.buildQueryFromSourceParams([
|
|
422
|
+
new StringChunk("("),
|
|
423
|
+
chunk._.sql,
|
|
424
|
+
new StringChunk(") "),
|
|
425
|
+
new Name(chunk._.alias)
|
|
426
|
+
], config);
|
|
427
|
+
}
|
|
428
|
+
if (isPgEnum(chunk)) {
|
|
429
|
+
if (chunk.schema) {
|
|
430
|
+
return { sql: escapeName(chunk.schema) + "." + escapeName(chunk.enumName), params: [] };
|
|
431
|
+
}
|
|
432
|
+
return { sql: escapeName(chunk.enumName), params: [] };
|
|
433
|
+
}
|
|
434
|
+
if (isSQLWrapper(chunk)) {
|
|
435
|
+
if (chunk.shouldOmitSQLParens?.()) {
|
|
436
|
+
return this.buildQueryFromSourceParams([chunk.getSQL()], config);
|
|
437
|
+
}
|
|
438
|
+
return this.buildQueryFromSourceParams([
|
|
439
|
+
new StringChunk("("),
|
|
440
|
+
chunk.getSQL(),
|
|
441
|
+
new StringChunk(")")
|
|
442
|
+
], config);
|
|
443
|
+
}
|
|
444
|
+
if (inlineParams) {
|
|
445
|
+
return { sql: this.mapInlineParam(chunk, config), params: [] };
|
|
446
|
+
}
|
|
447
|
+
return { sql: escapeParam(paramStartIndex.value++, chunk), params: [chunk], typings: ["none"] };
|
|
448
|
+
}));
|
|
449
|
+
}
|
|
450
|
+
mapInlineParam(chunk, { escapeString }) {
|
|
451
|
+
if (chunk === null) {
|
|
452
|
+
return "null";
|
|
453
|
+
}
|
|
454
|
+
if (typeof chunk === "number" || typeof chunk === "boolean") {
|
|
455
|
+
return chunk.toString();
|
|
456
|
+
}
|
|
457
|
+
if (typeof chunk === "string") {
|
|
458
|
+
return escapeString(chunk);
|
|
459
|
+
}
|
|
460
|
+
if (typeof chunk === "object") {
|
|
461
|
+
const mappedValueAsString = chunk.toString();
|
|
462
|
+
if (mappedValueAsString === "[object Object]") {
|
|
463
|
+
return escapeString(JSON.stringify(chunk));
|
|
464
|
+
}
|
|
465
|
+
return escapeString(mappedValueAsString);
|
|
466
|
+
}
|
|
467
|
+
throw new Error("Unexpected param value: " + chunk);
|
|
468
|
+
}
|
|
469
|
+
getSQL() {
|
|
470
|
+
return this;
|
|
471
|
+
}
|
|
472
|
+
as(alias) {
|
|
473
|
+
if (alias === undefined) {
|
|
474
|
+
return this;
|
|
475
|
+
}
|
|
476
|
+
return new SQL.Aliased(this, alias);
|
|
477
|
+
}
|
|
478
|
+
mapWith(decoder) {
|
|
479
|
+
this.decoder = typeof decoder === "function" ? { mapFromDriverValue: decoder } : decoder;
|
|
480
|
+
return this;
|
|
481
|
+
}
|
|
482
|
+
inlineParams() {
|
|
483
|
+
this.shouldInlineParams = true;
|
|
484
|
+
return this;
|
|
485
|
+
}
|
|
486
|
+
if(condition) {
|
|
487
|
+
return condition ? this : undefined;
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
class Name {
|
|
492
|
+
constructor(value) {
|
|
493
|
+
this.value = value;
|
|
494
|
+
}
|
|
495
|
+
static [entityKind] = "Name";
|
|
496
|
+
brand;
|
|
497
|
+
getSQL() {
|
|
498
|
+
return new SQL([this]);
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
function isDriverValueEncoder(value) {
|
|
502
|
+
return typeof value === "object" && value !== null && "mapToDriverValue" in value && typeof value.mapToDriverValue === "function";
|
|
503
|
+
}
|
|
504
|
+
var noopDecoder = {
|
|
505
|
+
mapFromDriverValue: (value) => value
|
|
506
|
+
};
|
|
507
|
+
var noopEncoder = {
|
|
508
|
+
mapToDriverValue: (value) => value
|
|
509
|
+
};
|
|
510
|
+
var noopMapper = {
|
|
511
|
+
...noopDecoder,
|
|
512
|
+
...noopEncoder
|
|
513
|
+
};
|
|
514
|
+
|
|
515
|
+
class Param {
|
|
516
|
+
constructor(value, encoder = noopEncoder) {
|
|
517
|
+
this.value = value;
|
|
518
|
+
this.encoder = encoder;
|
|
519
|
+
}
|
|
520
|
+
static [entityKind] = "Param";
|
|
521
|
+
brand;
|
|
522
|
+
getSQL() {
|
|
523
|
+
return new SQL([this]);
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
function sql(strings, ...params) {
|
|
527
|
+
const queryChunks = [];
|
|
528
|
+
if (params.length > 0 || strings.length > 0 && strings[0] !== "") {
|
|
529
|
+
queryChunks.push(new StringChunk(strings[0]));
|
|
530
|
+
}
|
|
531
|
+
for (const [paramIndex, param2] of params.entries()) {
|
|
532
|
+
queryChunks.push(param2, new StringChunk(strings[paramIndex + 1]));
|
|
533
|
+
}
|
|
534
|
+
return new SQL(queryChunks);
|
|
535
|
+
}
|
|
536
|
+
((sql2) => {
|
|
537
|
+
function empty() {
|
|
538
|
+
return new SQL([]);
|
|
539
|
+
}
|
|
540
|
+
sql2.empty = empty;
|
|
541
|
+
function fromList(list) {
|
|
542
|
+
return new SQL(list);
|
|
543
|
+
}
|
|
544
|
+
sql2.fromList = fromList;
|
|
545
|
+
function raw(str) {
|
|
546
|
+
return new SQL([new StringChunk(str)]);
|
|
547
|
+
}
|
|
548
|
+
sql2.raw = raw;
|
|
549
|
+
function join(chunks, separator) {
|
|
550
|
+
const result = [];
|
|
551
|
+
for (const [i, chunk] of chunks.entries()) {
|
|
552
|
+
if (i > 0 && separator !== undefined) {
|
|
553
|
+
result.push(separator);
|
|
554
|
+
}
|
|
555
|
+
result.push(chunk);
|
|
556
|
+
}
|
|
557
|
+
return new SQL(result);
|
|
558
|
+
}
|
|
559
|
+
sql2.join = join;
|
|
560
|
+
function identifier(value) {
|
|
561
|
+
return new Name(value);
|
|
562
|
+
}
|
|
563
|
+
sql2.identifier = identifier;
|
|
564
|
+
function placeholder2(name2) {
|
|
565
|
+
return new Placeholder(name2);
|
|
566
|
+
}
|
|
567
|
+
sql2.placeholder = placeholder2;
|
|
568
|
+
function param2(value, encoder) {
|
|
569
|
+
return new Param(value, encoder);
|
|
570
|
+
}
|
|
571
|
+
sql2.param = param2;
|
|
572
|
+
})(sql || (sql = {}));
|
|
573
|
+
((SQL2) => {
|
|
574
|
+
|
|
575
|
+
class Aliased {
|
|
576
|
+
constructor(sql2, fieldAlias) {
|
|
577
|
+
this.sql = sql2;
|
|
578
|
+
this.fieldAlias = fieldAlias;
|
|
579
|
+
}
|
|
580
|
+
static [entityKind] = "SQL.Aliased";
|
|
581
|
+
isSelectionField = false;
|
|
582
|
+
getSQL() {
|
|
583
|
+
return this.sql;
|
|
584
|
+
}
|
|
585
|
+
clone() {
|
|
586
|
+
return new Aliased(this.sql, this.fieldAlias);
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
SQL2.Aliased = Aliased;
|
|
590
|
+
})(SQL || (SQL = {}));
|
|
591
|
+
|
|
592
|
+
class Placeholder {
|
|
593
|
+
constructor(name2) {
|
|
594
|
+
this.name = name2;
|
|
595
|
+
}
|
|
596
|
+
static [entityKind] = "Placeholder";
|
|
597
|
+
getSQL() {
|
|
598
|
+
return new SQL([this]);
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
var IsDrizzleView = Symbol.for("drizzle:IsDrizzleView");
|
|
602
|
+
|
|
603
|
+
class View {
|
|
604
|
+
static [entityKind] = "View";
|
|
605
|
+
[ViewBaseConfig];
|
|
606
|
+
[IsDrizzleView] = true;
|
|
607
|
+
constructor({ name: name2, schema, selectedFields, query }) {
|
|
608
|
+
this[ViewBaseConfig] = {
|
|
609
|
+
name: name2,
|
|
610
|
+
originalName: name2,
|
|
611
|
+
schema,
|
|
612
|
+
selectedFields,
|
|
613
|
+
query,
|
|
614
|
+
isExisting: !query,
|
|
615
|
+
isAlias: false
|
|
616
|
+
};
|
|
617
|
+
}
|
|
618
|
+
getSQL() {
|
|
619
|
+
return new SQL([this]);
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
Column.prototype.getSQL = function() {
|
|
623
|
+
return new SQL([this]);
|
|
624
|
+
};
|
|
625
|
+
Table.prototype.getSQL = function() {
|
|
626
|
+
return new SQL([this]);
|
|
627
|
+
};
|
|
628
|
+
Subquery.prototype.getSQL = function() {
|
|
629
|
+
return new SQL([this]);
|
|
630
|
+
};
|
|
631
|
+
|
|
632
|
+
// node_modules/drizzle-orm/sql/expressions/conditions.js
|
|
633
|
+
function bindIfParam(value, column) {
|
|
634
|
+
if (isDriverValueEncoder(column) && !isSQLWrapper(value) && !is(value, Param) && !is(value, Placeholder) && !is(value, Column) && !is(value, Table) && !is(value, View)) {
|
|
635
|
+
return new Param(value, column);
|
|
636
|
+
}
|
|
637
|
+
return value;
|
|
638
|
+
}
|
|
639
|
+
var eq = (left, right) => {
|
|
640
|
+
return sql`${left} = ${bindIfParam(right, left)}`;
|
|
641
|
+
};
|
|
642
|
+
function and(...unfilteredConditions) {
|
|
643
|
+
const conditions = unfilteredConditions.filter((c) => c !== undefined);
|
|
644
|
+
if (conditions.length === 0) {
|
|
645
|
+
return;
|
|
646
|
+
}
|
|
647
|
+
if (conditions.length === 1) {
|
|
648
|
+
return new SQL(conditions);
|
|
649
|
+
}
|
|
650
|
+
return new SQL([
|
|
651
|
+
new StringChunk("("),
|
|
652
|
+
sql.join(conditions, new StringChunk(" and ")),
|
|
653
|
+
new StringChunk(")")
|
|
654
|
+
]);
|
|
655
|
+
}
|
|
656
|
+
function or(...unfilteredConditions) {
|
|
657
|
+
const conditions = unfilteredConditions.filter((c) => c !== undefined);
|
|
658
|
+
if (conditions.length === 0) {
|
|
659
|
+
return;
|
|
660
|
+
}
|
|
661
|
+
if (conditions.length === 1) {
|
|
662
|
+
return new SQL(conditions);
|
|
663
|
+
}
|
|
664
|
+
return new SQL([
|
|
665
|
+
new StringChunk("("),
|
|
666
|
+
sql.join(conditions, new StringChunk(" or ")),
|
|
667
|
+
new StringChunk(")")
|
|
668
|
+
]);
|
|
669
|
+
}
|
|
670
|
+
function inArray(column, values) {
|
|
671
|
+
if (Array.isArray(values)) {
|
|
672
|
+
if (values.length === 0) {
|
|
673
|
+
return sql`false`;
|
|
674
|
+
}
|
|
675
|
+
return sql`${column} in ${values.map((v) => bindIfParam(v, column))}`;
|
|
676
|
+
}
|
|
677
|
+
return sql`${column} in ${bindIfParam(values, column)}`;
|
|
678
|
+
}
|
|
679
|
+
function isNull(value) {
|
|
680
|
+
return sql`${value} is null`;
|
|
681
|
+
}
|
|
682
|
+
function like(column, value) {
|
|
683
|
+
return sql`${column} like ${value}`;
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
// node_modules/drizzle-orm/sql/expressions/select.js
|
|
687
|
+
function asc(column) {
|
|
688
|
+
return sql`${column} asc`;
|
|
689
|
+
}
|
|
690
|
+
function desc(column) {
|
|
691
|
+
return sql`${column} desc`;
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
// node_modules/drizzle-orm/sql/functions/aggregate.js
|
|
695
|
+
function count(expression) {
|
|
696
|
+
return sql`count(${expression || sql.raw("*")})`.mapWith(Number);
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
// src/rack/adapters/drizzle.ts
|
|
700
|
+
function tableOf(model) {
|
|
701
|
+
return model.drizzle.table;
|
|
702
|
+
}
|
|
703
|
+
function dbOf(model) {
|
|
704
|
+
return model.drizzle.db;
|
|
705
|
+
}
|
|
706
|
+
function escapeLike(value) {
|
|
707
|
+
return value.replace(/[\\%_]/g, (m) => `\\${m}`);
|
|
708
|
+
}
|
|
709
|
+
function fieldKind(columnType, dataType, enumValues) {
|
|
710
|
+
if (enumValues && enumValues.length > 0)
|
|
711
|
+
return "enum";
|
|
712
|
+
if (columnType && /serial|smallint|integer|bigint|int8/i.test(columnType))
|
|
713
|
+
return "integer";
|
|
714
|
+
if (columnType && /numeric|decimal|real|double|float/i.test(columnType))
|
|
715
|
+
return "number";
|
|
716
|
+
if (dataType === "boolean")
|
|
717
|
+
return "boolean";
|
|
718
|
+
if (dataType === "date")
|
|
719
|
+
return "date";
|
|
720
|
+
if (dataType === "json")
|
|
721
|
+
return "json";
|
|
722
|
+
if (dataType === "bigint" || dataType === "number")
|
|
723
|
+
return "integer";
|
|
724
|
+
return "text";
|
|
725
|
+
}
|
|
726
|
+
function isAutoIncrement(col, columnType) {
|
|
727
|
+
if (columnType && /serial/i.test(columnType))
|
|
728
|
+
return true;
|
|
729
|
+
if (col.generated !== undefined && col.generated !== null)
|
|
730
|
+
return true;
|
|
731
|
+
if (col.primary && columnType && /sqliteinteger/i.test(columnType))
|
|
732
|
+
return true;
|
|
733
|
+
return false;
|
|
734
|
+
}
|
|
735
|
+
function resolvableId(table, primaryKey, id) {
|
|
736
|
+
const col = table?.[primaryKey];
|
|
737
|
+
const columnType = col?.columnType ?? col?.dataType;
|
|
738
|
+
const value = coerceIdValue(id, columnType);
|
|
739
|
+
if (col && isNumericColumn(columnType) && typeof value !== "number")
|
|
740
|
+
return null;
|
|
741
|
+
return value;
|
|
742
|
+
}
|
|
743
|
+
function aliveCondition(table, opts, withSoftDelete) {
|
|
744
|
+
if (!withSoftDelete)
|
|
745
|
+
return;
|
|
746
|
+
const col = table[opts.deletedAtField ?? "deletedAt"];
|
|
747
|
+
return col ? isNull(col) : undefined;
|
|
748
|
+
}
|
|
749
|
+
function whereFor(table, query, opts, withSoftDelete) {
|
|
750
|
+
const conds = [];
|
|
751
|
+
const alive = aliveCondition(table, opts, withSoftDelete);
|
|
752
|
+
if (alive)
|
|
753
|
+
conds.push(alive);
|
|
754
|
+
for (const [key, value] of Object.entries(query.filters)) {
|
|
755
|
+
const col = table[key];
|
|
756
|
+
if (!col)
|
|
757
|
+
continue;
|
|
758
|
+
conds.push(Array.isArray(value) ? inArray(col, value) : eq(col, value));
|
|
759
|
+
}
|
|
760
|
+
if (query.search && query.search.fields.length > 0) {
|
|
761
|
+
const pattern = `%${escapeLike(query.search.value)}%`;
|
|
762
|
+
const ors = query.search.fields.map((f) => table[f] ? like(table[f], pattern) : undefined).filter((c) => c !== undefined);
|
|
763
|
+
if (ors.length > 0)
|
|
764
|
+
conds.push(or(...ors));
|
|
765
|
+
}
|
|
766
|
+
return conds.length > 0 ? and(...conds) : undefined;
|
|
767
|
+
}
|
|
768
|
+
function orderFor(table, query) {
|
|
769
|
+
if (!query.sort)
|
|
770
|
+
return;
|
|
771
|
+
const col = table[query.sort.field];
|
|
772
|
+
if (!col)
|
|
773
|
+
return;
|
|
774
|
+
return query.sort.direction === "desc" ? desc(col) : asc(col);
|
|
775
|
+
}
|
|
776
|
+
async function firstRow(promise) {
|
|
777
|
+
const rows = await promise;
|
|
778
|
+
return Array.isArray(rows) ? rows[0] ?? null : null;
|
|
779
|
+
}
|
|
780
|
+
async function applyUpdate(db, table, cond, body) {
|
|
781
|
+
return firstRow(db.update(table).set(body).where(cond).returning());
|
|
782
|
+
}
|
|
783
|
+
async function findByKey(db, table, opts, key) {
|
|
784
|
+
const cond = eq(table[opts.primaryKey], key);
|
|
785
|
+
const alive = aliveCondition(table, opts, opts.softDelete ?? false);
|
|
786
|
+
return firstRow(db.select().from(table).where(alive ? and(cond, alive) : cond).limit(1));
|
|
787
|
+
}
|
|
788
|
+
function isEmptyBody(body) {
|
|
789
|
+
return typeof body === "object" && body !== null && Object.keys(body).length === 0;
|
|
790
|
+
}
|
|
791
|
+
var drizzleAdapter = {
|
|
792
|
+
name: "drizzle",
|
|
793
|
+
describe(model) {
|
|
794
|
+
const table = tableOf(model);
|
|
795
|
+
const out = [];
|
|
796
|
+
for (const [name, col] of Object.entries(table)) {
|
|
797
|
+
if (!(col instanceof Column))
|
|
798
|
+
continue;
|
|
799
|
+
const column = col;
|
|
800
|
+
const columnType = typeof column["columnType"] === "string" ? column["columnType"] : undefined;
|
|
801
|
+
const dataType = typeof column["dataType"] === "string" ? column["dataType"] : undefined;
|
|
802
|
+
const enumValues = Array.isArray(column["enumValues"]) ? [...column["enumValues"]] : undefined;
|
|
803
|
+
out.push({
|
|
804
|
+
name,
|
|
805
|
+
kind: fieldKind(columnType, dataType, enumValues),
|
|
806
|
+
primary: column["primary"] === true,
|
|
807
|
+
autoIncrement: isAutoIncrement(column, columnType),
|
|
808
|
+
nullable: column["notNull"] !== true,
|
|
809
|
+
...enumValues ? { enumValues } : {}
|
|
810
|
+
});
|
|
811
|
+
}
|
|
812
|
+
return out;
|
|
813
|
+
},
|
|
814
|
+
async list(model, query, opts) {
|
|
815
|
+
const db = dbOf(model);
|
|
816
|
+
const table = tableOf(model);
|
|
817
|
+
const where = whereFor(table, query, opts, opts.softDelete ?? false);
|
|
818
|
+
const order = orderFor(table, query);
|
|
819
|
+
let select = db.select().from(table);
|
|
820
|
+
if (where)
|
|
821
|
+
select = select.where(where);
|
|
822
|
+
if (order)
|
|
823
|
+
select = select.orderBy(order);
|
|
824
|
+
const data = await select.limit(query.limit).offset((query.page - 1) * query.limit);
|
|
825
|
+
let counted = db.select({ n: count() }).from(table);
|
|
826
|
+
if (where)
|
|
827
|
+
counted = counted.where(where);
|
|
828
|
+
const totalRows = await counted;
|
|
829
|
+
return { data, total: totalRows[0]?.n ?? 0 };
|
|
830
|
+
},
|
|
831
|
+
async detail(model, id, opts) {
|
|
832
|
+
const db = dbOf(model);
|
|
833
|
+
const table = tableOf(model);
|
|
834
|
+
const key = resolvableId(table, opts.primaryKey, id);
|
|
835
|
+
if (key === null)
|
|
836
|
+
return null;
|
|
837
|
+
return findByKey(db, table, opts, key);
|
|
838
|
+
},
|
|
839
|
+
async create(model, body, opts) {
|
|
840
|
+
const db = dbOf(model);
|
|
841
|
+
const table = tableOf(model);
|
|
842
|
+
if (opts.returning === false) {
|
|
843
|
+
await db.insert(table).values(body);
|
|
844
|
+
return;
|
|
845
|
+
}
|
|
846
|
+
return firstRow(db.insert(table).values(body).returning());
|
|
847
|
+
},
|
|
848
|
+
async replace(model, id, body, opts) {
|
|
849
|
+
const db = dbOf(model);
|
|
850
|
+
const table = tableOf(model);
|
|
851
|
+
const key = resolvableId(table, opts.primaryKey, id);
|
|
852
|
+
if (key === null)
|
|
853
|
+
return null;
|
|
854
|
+
if (isEmptyBody(body))
|
|
855
|
+
return findByKey(db, table, opts, key);
|
|
856
|
+
const row = await applyUpdate(db, table, eq(table[opts.primaryKey], key), body);
|
|
857
|
+
if (row === null)
|
|
858
|
+
return null;
|
|
859
|
+
return opts.returning === false ? undefined : row;
|
|
860
|
+
},
|
|
861
|
+
async update(model, id, body, opts) {
|
|
862
|
+
const db = dbOf(model);
|
|
863
|
+
const table = tableOf(model);
|
|
864
|
+
const key = resolvableId(table, opts.primaryKey, id);
|
|
865
|
+
if (key === null)
|
|
866
|
+
return null;
|
|
867
|
+
if (isEmptyBody(body))
|
|
868
|
+
return findByKey(db, table, opts, key);
|
|
869
|
+
const row = await applyUpdate(db, table, eq(table[opts.primaryKey], key), body);
|
|
870
|
+
if (row === null)
|
|
871
|
+
return null;
|
|
872
|
+
return opts.returning === false ? undefined : row;
|
|
873
|
+
},
|
|
874
|
+
async remove(model, id, opts) {
|
|
875
|
+
const db = dbOf(model);
|
|
876
|
+
const table = tableOf(model);
|
|
877
|
+
const key = resolvableId(table, opts.primaryKey, id);
|
|
878
|
+
if (key === null)
|
|
879
|
+
return null;
|
|
880
|
+
const cond = eq(table[opts.primaryKey], key);
|
|
881
|
+
const row = await firstRow(opts.softDelete ? db.update(table).set({ [opts.deletedAtField ?? "deletedAt"]: new Date }).where(cond).returning() : db.delete(table).where(cond).returning());
|
|
882
|
+
if (row === null)
|
|
883
|
+
return null;
|
|
884
|
+
return opts.returning === false ? undefined : row;
|
|
885
|
+
}
|
|
886
|
+
};
|
|
887
|
+
|
|
888
|
+
// src/rack/adapters/prisma.ts
|
|
889
|
+
function delegateOf(model) {
|
|
890
|
+
return model.prisma.model;
|
|
891
|
+
}
|
|
892
|
+
function deletedAtFilter(opts) {
|
|
893
|
+
return opts.softDelete ? { [opts.deletedAtField ?? "deletedAt"]: null } : {};
|
|
894
|
+
}
|
|
895
|
+
function whereFor2(query, opts) {
|
|
896
|
+
const where = {
|
|
897
|
+
...deletedAtFilter(opts)
|
|
898
|
+
};
|
|
899
|
+
for (const [key, value] of Object.entries(query.filters)) {
|
|
900
|
+
where[key] = Array.isArray(value) ? { in: value } : value;
|
|
901
|
+
}
|
|
902
|
+
if (query.search && query.search.fields.length > 0) {
|
|
903
|
+
where["OR"] = query.search.fields.map((field) => ({
|
|
904
|
+
[field]: { contains: query.search.value, mode: "insensitive" }
|
|
905
|
+
}));
|
|
906
|
+
}
|
|
907
|
+
return where;
|
|
908
|
+
}
|
|
909
|
+
function isNotFound(error) {
|
|
910
|
+
return typeof error === "object" && error !== null && error.code === "P2025";
|
|
911
|
+
}
|
|
912
|
+
async function applyUpdate2(delegate, primaryKey, id, body, returning) {
|
|
913
|
+
try {
|
|
914
|
+
const row = await delegate.update({
|
|
915
|
+
where: { [primaryKey]: coerceIdValue(id) },
|
|
916
|
+
data: body
|
|
917
|
+
});
|
|
918
|
+
return returning === false ? undefined : row;
|
|
919
|
+
} catch (error) {
|
|
920
|
+
if (isNotFound(error))
|
|
921
|
+
return null;
|
|
922
|
+
throw error;
|
|
923
|
+
}
|
|
924
|
+
}
|
|
925
|
+
var prismaAdapter = {
|
|
926
|
+
name: "prisma",
|
|
927
|
+
describe() {
|
|
928
|
+
return [];
|
|
929
|
+
},
|
|
930
|
+
async list(model, query, opts) {
|
|
931
|
+
const delegate = delegateOf(model);
|
|
932
|
+
const where = whereFor2(query, opts);
|
|
933
|
+
const [data, total] = await Promise.all([
|
|
934
|
+
delegate.findMany({
|
|
935
|
+
where,
|
|
936
|
+
...query.sort ? { orderBy: { [query.sort.field]: query.sort.direction } } : {},
|
|
937
|
+
skip: (query.page - 1) * query.limit,
|
|
938
|
+
take: query.limit
|
|
939
|
+
}),
|
|
940
|
+
delegate.count({ where })
|
|
941
|
+
]);
|
|
942
|
+
return { data, total };
|
|
943
|
+
},
|
|
944
|
+
async detail(model, id, opts) {
|
|
945
|
+
const delegate = delegateOf(model);
|
|
946
|
+
return delegate.findFirst({
|
|
947
|
+
where: {
|
|
948
|
+
[opts.primaryKey]: coerceIdValue(id),
|
|
949
|
+
...deletedAtFilter(opts)
|
|
950
|
+
}
|
|
951
|
+
});
|
|
952
|
+
},
|
|
953
|
+
async create(model, body, opts) {
|
|
954
|
+
const delegate = delegateOf(model);
|
|
955
|
+
const row = await delegate.create({ data: body });
|
|
956
|
+
return opts.returning === false ? undefined : row;
|
|
957
|
+
},
|
|
958
|
+
async replace(model, id, body, opts) {
|
|
959
|
+
return applyUpdate2(delegateOf(model), opts.primaryKey, id, body, opts.returning);
|
|
960
|
+
},
|
|
961
|
+
async update(model, id, body, opts) {
|
|
962
|
+
return applyUpdate2(delegateOf(model), opts.primaryKey, id, body, opts.returning);
|
|
963
|
+
},
|
|
964
|
+
async remove(model, id, opts) {
|
|
965
|
+
const delegate = delegateOf(model);
|
|
966
|
+
const where = { [opts.primaryKey]: coerceIdValue(id) };
|
|
967
|
+
try {
|
|
968
|
+
const row = opts.softDelete ? await delegate.update({
|
|
969
|
+
where,
|
|
970
|
+
data: { [opts.deletedAtField ?? "deletedAt"]: new Date }
|
|
971
|
+
}) : await delegate.delete({ where });
|
|
972
|
+
return opts.returning === false ? undefined : row;
|
|
973
|
+
} catch (error) {
|
|
974
|
+
if (isNotFound(error))
|
|
975
|
+
return null;
|
|
976
|
+
throw error;
|
|
977
|
+
}
|
|
978
|
+
}
|
|
979
|
+
};
|
|
980
|
+
|
|
981
|
+
// src/rack/adapters/index.ts
|
|
982
|
+
function getAdapter(model) {
|
|
983
|
+
return "drizzle" in model && model.drizzle !== undefined ? drizzleAdapter : prismaAdapter;
|
|
984
|
+
}
|
|
985
|
+
function isNumericColumn(columnType) {
|
|
986
|
+
return columnType === undefined || /serial|smallint|integer|bigint|int8|^(number|bigint)$/i.test(columnType);
|
|
987
|
+
}
|
|
988
|
+
function coerceIdValue(id, columnType) {
|
|
989
|
+
if (!isNumericColumn(columnType))
|
|
990
|
+
return id;
|
|
991
|
+
if (id.trim() === "")
|
|
992
|
+
return id;
|
|
993
|
+
const n = Number(id);
|
|
994
|
+
return Number.isNaN(n) ? id : n;
|
|
995
|
+
}
|
|
996
|
+
|
|
997
|
+
// src/rack/authorization.ts
|
|
998
|
+
import { status } from "elysia";
|
|
999
|
+
async function authorize(operation, rule, ctx) {
|
|
1000
|
+
const forbidden = (extra) => status(403, {
|
|
1001
|
+
error: "Forbidden",
|
|
1002
|
+
operation,
|
|
1003
|
+
...extra ?? {}
|
|
1004
|
+
});
|
|
1005
|
+
if (rule === undefined || rule === true)
|
|
1006
|
+
return null;
|
|
1007
|
+
if (rule === false)
|
|
1008
|
+
return forbidden();
|
|
1009
|
+
if (typeof rule === "string") {
|
|
1010
|
+
const fromContext = Array.isArray(ctx.permissions) ? ctx.permissions : Array.isArray(ctx.store?.["permissions"]) ? ctx.store?.["permissions"] : null;
|
|
1011
|
+
if (fromContext !== null)
|
|
1012
|
+
return fromContext.includes(rule) ? null : forbidden({ requiredPermission: rule });
|
|
1013
|
+
const header = ctx.request.headers.get("x-permissions");
|
|
1014
|
+
if (typeof header === "string" && header.length > 0) {
|
|
1015
|
+
const granted = header.split(",").map((s) => s.trim());
|
|
1016
|
+
return granted.includes(rule) ? null : forbidden({ requiredPermission: rule });
|
|
1017
|
+
}
|
|
1018
|
+
return null;
|
|
1019
|
+
}
|
|
1020
|
+
const allowed = await rule({
|
|
1021
|
+
operation,
|
|
1022
|
+
request: ctx.request,
|
|
1023
|
+
id: ctx.id,
|
|
1024
|
+
resource: ctx.resource
|
|
1025
|
+
});
|
|
1026
|
+
return allowed ? null : forbidden();
|
|
1027
|
+
}
|
|
1028
|
+
|
|
1029
|
+
// src/rack/idempotency.ts
|
|
1030
|
+
function createMemoryIdempotencyStore(maxEntries = 1000) {
|
|
1031
|
+
const entries = new Map;
|
|
1032
|
+
return {
|
|
1033
|
+
get(key) {
|
|
1034
|
+
const entry = entries.get(key);
|
|
1035
|
+
if (entry === undefined)
|
|
1036
|
+
return;
|
|
1037
|
+
if (Date.now() >= entry.expiresAt) {
|
|
1038
|
+
entries.delete(key);
|
|
1039
|
+
return;
|
|
1040
|
+
}
|
|
1041
|
+
return entry.record;
|
|
1042
|
+
},
|
|
1043
|
+
set(key, record, ttlSeconds = 86400) {
|
|
1044
|
+
if (entries.size >= maxEntries && !entries.has(key)) {
|
|
1045
|
+
const oldest = entries.keys().next();
|
|
1046
|
+
if (!oldest.done)
|
|
1047
|
+
entries.delete(oldest.value);
|
|
1048
|
+
}
|
|
1049
|
+
entries.set(key, {
|
|
1050
|
+
record,
|
|
1051
|
+
expiresAt: Date.now() + ttlSeconds * 1000
|
|
1052
|
+
});
|
|
1053
|
+
}
|
|
1054
|
+
};
|
|
1055
|
+
}
|
|
1056
|
+
|
|
1057
|
+
// src/rack/openapi.ts
|
|
1058
|
+
function detailFor(options, operation) {
|
|
1059
|
+
const baseTags = options.openapi?.tags ?? (options.metadata?.label !== undefined ? [options.metadata.label] : options.metadata?.id !== undefined ? [options.metadata.id] : undefined);
|
|
1060
|
+
const baseDescription = options.openapi?.description;
|
|
1061
|
+
const over = options.openapi?.operations?.[operation];
|
|
1062
|
+
const detail = {};
|
|
1063
|
+
const tags = over?.tags ?? baseTags;
|
|
1064
|
+
if (tags !== undefined)
|
|
1065
|
+
detail["tags"] = [...tags];
|
|
1066
|
+
const description = over?.description ?? baseDescription;
|
|
1067
|
+
if (description !== undefined)
|
|
1068
|
+
detail["description"] = description;
|
|
1069
|
+
if (over?.summary !== undefined)
|
|
1070
|
+
detail["summary"] = over.summary;
|
|
1071
|
+
if (over?.operationId !== undefined)
|
|
1072
|
+
detail["operationId"] = over.operationId;
|
|
1073
|
+
if (over?.deprecated !== undefined)
|
|
1074
|
+
detail["deprecated"] = over.deprecated;
|
|
1075
|
+
return detail;
|
|
1076
|
+
}
|
|
1077
|
+
|
|
1078
|
+
// src/rack/page.ts
|
|
1079
|
+
var PANEL_PAGE_KEY = "@elysia-panel/react";
|
|
1080
|
+
function panelPage(path, props) {
|
|
1081
|
+
return {
|
|
1082
|
+
[Symbol.for(PANEL_PAGE_KEY)]: true,
|
|
1083
|
+
path,
|
|
1084
|
+
props
|
|
1085
|
+
};
|
|
1086
|
+
}
|
|
1087
|
+
|
|
1088
|
+
// src/rack/query.ts
|
|
1089
|
+
function parseListQuery(raw, queryOptions) {
|
|
1090
|
+
const pagination = queryOptions?.pagination ?? {};
|
|
1091
|
+
const max = pagination.max ?? 100;
|
|
1092
|
+
const fallbackLimit = pagination.default ?? 20;
|
|
1093
|
+
const limit = Math.min(Math.max(Number(raw["limit"] ?? raw["perPage"] ?? fallbackLimit) || 1, 1), Math.max(max, 1));
|
|
1094
|
+
const page = Math.max(Number(raw["page"] ?? 1) || 1, 1);
|
|
1095
|
+
const search = typeof raw["search"] === "string" && raw["search"].length > 0 ? {
|
|
1096
|
+
value: raw["search"],
|
|
1097
|
+
fields: queryOptions?.searchable ?? []
|
|
1098
|
+
} : undefined;
|
|
1099
|
+
const requestedSort = typeof raw["sort"] === "string" && raw["sort"].length > 0 ? raw["sort"] : undefined;
|
|
1100
|
+
const requestedDirection = raw["order"] === "asc" || raw["order"] === "desc" ? raw["order"] : raw["direction"] === "asc" || raw["direction"] === "desc" ? raw["direction"] : undefined;
|
|
1101
|
+
const sortField = requestedSort !== undefined && (queryOptions?.sortable === undefined || queryOptions.sortable.includes(requestedSort)) ? requestedSort : queryOptions?.defaultSort?.field;
|
|
1102
|
+
const sort = sortField !== undefined ? {
|
|
1103
|
+
field: sortField,
|
|
1104
|
+
direction: requestedDirection ?? queryOptions?.defaultSort?.direction ?? "asc"
|
|
1105
|
+
} : undefined;
|
|
1106
|
+
const reserved = new Set([
|
|
1107
|
+
"search",
|
|
1108
|
+
"sort",
|
|
1109
|
+
"order",
|
|
1110
|
+
"direction",
|
|
1111
|
+
"page",
|
|
1112
|
+
"limit",
|
|
1113
|
+
"perPage"
|
|
1114
|
+
]);
|
|
1115
|
+
const filters = {};
|
|
1116
|
+
for (const [key, value] of Object.entries(raw)) {
|
|
1117
|
+
if (reserved.has(key))
|
|
1118
|
+
continue;
|
|
1119
|
+
if (queryOptions?.filterable !== undefined && !queryOptions.filterable.includes(key))
|
|
1120
|
+
continue;
|
|
1121
|
+
filters[key] = value;
|
|
1122
|
+
}
|
|
1123
|
+
return { search, filters, sort, page, limit };
|
|
1124
|
+
}
|
|
1125
|
+
|
|
1126
|
+
// src/rack/index.ts
|
|
1127
|
+
var DEFAULT_OPERATIONS = {
|
|
1128
|
+
list: true,
|
|
1129
|
+
detail: true,
|
|
1130
|
+
create: true,
|
|
1131
|
+
replace: true,
|
|
1132
|
+
update: true,
|
|
1133
|
+
delete: true
|
|
1134
|
+
};
|
|
1135
|
+
function rack(path, options) {
|
|
1136
|
+
const operations = { ...DEFAULT_OPERATIONS, ...options.operations };
|
|
1137
|
+
const primaryKey = options.settings?.primaryKey ?? "id";
|
|
1138
|
+
const itemPath = `/:${primaryKey}`;
|
|
1139
|
+
const resource = options.metadata?.id ?? path;
|
|
1140
|
+
const adapter = resolveAdapter(options.model);
|
|
1141
|
+
registerRack({
|
|
1142
|
+
path,
|
|
1143
|
+
metadata: { ...options.metadata, id: resource },
|
|
1144
|
+
operations
|
|
1145
|
+
});
|
|
1146
|
+
const dataAdapter = getAdapter(options.model);
|
|
1147
|
+
const adapterOpts = {
|
|
1148
|
+
primaryKey,
|
|
1149
|
+
deletedAtField: options.settings?.deletedAtField,
|
|
1150
|
+
returning: options.settings?.returning,
|
|
1151
|
+
softDelete: options.settings?.softDelete
|
|
1152
|
+
};
|
|
1153
|
+
const app = new Elysia({ name: `rack:${path}`, prefix: path });
|
|
1154
|
+
const notFound = (operation, id) => status2(404, { error: "Not Found", operation, id });
|
|
1155
|
+
const envelope = (operation) => ({
|
|
1156
|
+
resource,
|
|
1157
|
+
operation,
|
|
1158
|
+
adapter,
|
|
1159
|
+
...options.metadata !== undefined ? { metadata: options.metadata } : {}
|
|
1160
|
+
});
|
|
1161
|
+
const authContext = (context, operation) => ({
|
|
1162
|
+
request: context.request,
|
|
1163
|
+
id: context.params?.[primaryKey] !== undefined ? String(context.params[primaryKey]) : undefined,
|
|
1164
|
+
resource: options.model,
|
|
1165
|
+
permissions: context.permissions,
|
|
1166
|
+
store: context.store
|
|
1167
|
+
});
|
|
1168
|
+
const maybeBody = (schema) => schema !== undefined ? { body: schema } : {};
|
|
1169
|
+
const maybeParams = () => options.validation?.params !== undefined ? { params: options.validation.params } : {};
|
|
1170
|
+
if (operations.list && options.page?.enabled !== false)
|
|
1171
|
+
app.get("/", async (context) => {
|
|
1172
|
+
const denied = await authorize("list", options.authorization?.list, authContext(context, "list"));
|
|
1173
|
+
if (denied)
|
|
1174
|
+
return denied;
|
|
1175
|
+
return panelPage(options.page?.path ?? "/panel", {
|
|
1176
|
+
resource,
|
|
1177
|
+
metadata: options.metadata,
|
|
1178
|
+
query: options.query,
|
|
1179
|
+
operations,
|
|
1180
|
+
primaryKey,
|
|
1181
|
+
params: { ...context.query ?? {} },
|
|
1182
|
+
queryUrl: `${path.replace(/\/$/, "")}/data`,
|
|
1183
|
+
fields: dataAdapter.describe(options.model),
|
|
1184
|
+
deletedAtField: options.settings?.deletedAtField ?? "deletedAt",
|
|
1185
|
+
load: (input) => dataAdapter.list(options.model, parseListQuery(input, options.query), adapterOpts).then(({ data, total }) => ({ data, total }))
|
|
1186
|
+
});
|
|
1187
|
+
}, { detail: detailFor(options, "list") });
|
|
1188
|
+
if (operations.list)
|
|
1189
|
+
app.route("QUERY", "/data", async (context) => {
|
|
1190
|
+
const denied = await authorize("list", options.authorization?.list, authContext(context, "list"));
|
|
1191
|
+
if (denied)
|
|
1192
|
+
return denied;
|
|
1193
|
+
const body = typeof context.body === "object" && context.body !== null ? context.body : {};
|
|
1194
|
+
const parsed = parseListQuery({ ...context.query ?? {}, ...body }, options.query);
|
|
1195
|
+
const result = await dataAdapter.list(options.model, parsed, adapterOpts);
|
|
1196
|
+
return {
|
|
1197
|
+
...envelope("list"),
|
|
1198
|
+
via: "QUERY",
|
|
1199
|
+
query: parsed,
|
|
1200
|
+
data: result.data,
|
|
1201
|
+
total: result.total
|
|
1202
|
+
};
|
|
1203
|
+
}, {
|
|
1204
|
+
...maybeBody(options.validation?.query),
|
|
1205
|
+
detail: detailFor(options, "list")
|
|
1206
|
+
});
|
|
1207
|
+
if (operations.create) {
|
|
1208
|
+
const idem = options.idempotency;
|
|
1209
|
+
const idemStore = idem?.enabled !== false ? idem?.store ?? createMemoryIdempotencyStore() : undefined;
|
|
1210
|
+
const idemHeader = idem?.header ?? "Idempotency-Key";
|
|
1211
|
+
const idemRequired = idem?.required ?? true;
|
|
1212
|
+
const idemTtl = idem?.ttl ?? 86400;
|
|
1213
|
+
const idemInflight = new Map;
|
|
1214
|
+
const buildCreatedBody = (context, row) => ({
|
|
1215
|
+
...envelope("create"),
|
|
1216
|
+
...row !== undefined ? { data: row } : {},
|
|
1217
|
+
...options.settings?.returning !== undefined ? { returning: options.settings.returning } : {}
|
|
1218
|
+
});
|
|
1219
|
+
const replay = (context, record) => {
|
|
1220
|
+
(context.set.headers ??= {})["Idempotent-Replayed"] = "true";
|
|
1221
|
+
return status2(record.status, record.body);
|
|
1222
|
+
};
|
|
1223
|
+
app.post("/", async (context) => {
|
|
1224
|
+
const denied = await authorize("create", options.authorization?.create, authContext(context, "create"));
|
|
1225
|
+
if (denied)
|
|
1226
|
+
return denied;
|
|
1227
|
+
if (idemStore !== undefined) {
|
|
1228
|
+
const clientKey = context.request.headers.get(idemHeader);
|
|
1229
|
+
if (!clientKey) {
|
|
1230
|
+
if (idemRequired)
|
|
1231
|
+
return status2(400, {
|
|
1232
|
+
error: `${idemHeader} header is required`,
|
|
1233
|
+
operation: "create"
|
|
1234
|
+
});
|
|
1235
|
+
} else {
|
|
1236
|
+
const scoped = `${resource}::${clientKey}`;
|
|
1237
|
+
const stored = await idemStore.get(scoped);
|
|
1238
|
+
if (stored !== undefined)
|
|
1239
|
+
return replay(context, stored);
|
|
1240
|
+
let pending = idemInflight.get(scoped);
|
|
1241
|
+
if (pending === undefined) {
|
|
1242
|
+
pending = (async () => {
|
|
1243
|
+
const row2 = await dataAdapter.create(options.model, context.body, adapterOpts);
|
|
1244
|
+
const record = {
|
|
1245
|
+
status: 201,
|
|
1246
|
+
body: buildCreatedBody(context, row2)
|
|
1247
|
+
};
|
|
1248
|
+
await idemStore.set(scoped, record, idemTtl);
|
|
1249
|
+
return record;
|
|
1250
|
+
})();
|
|
1251
|
+
idemInflight.set(scoped, pending);
|
|
1252
|
+
try {
|
|
1253
|
+
return status2(201, (await pending).body);
|
|
1254
|
+
} finally {
|
|
1255
|
+
idemInflight.delete(scoped);
|
|
1256
|
+
}
|
|
1257
|
+
}
|
|
1258
|
+
return replay(context, await pending);
|
|
1259
|
+
}
|
|
1260
|
+
}
|
|
1261
|
+
const row = await dataAdapter.create(options.model, context.body, adapterOpts);
|
|
1262
|
+
return status2(201, buildCreatedBody(context, row));
|
|
1263
|
+
}, {
|
|
1264
|
+
...maybeBody(options.validation?.create),
|
|
1265
|
+
detail: detailFor(options, "create")
|
|
1266
|
+
});
|
|
1267
|
+
}
|
|
1268
|
+
if (operations.detail)
|
|
1269
|
+
app.route("QUERY", `/data${itemPath}`, async (context) => {
|
|
1270
|
+
const denied = await authorize("detail", options.authorization?.detail, authContext(context, "detail"));
|
|
1271
|
+
if (denied)
|
|
1272
|
+
return denied;
|
|
1273
|
+
const id = String(context.params[primaryKey]);
|
|
1274
|
+
const row = await dataAdapter.detail(options.model, id, adapterOpts);
|
|
1275
|
+
if (row == null)
|
|
1276
|
+
return notFound("detail", id);
|
|
1277
|
+
return {
|
|
1278
|
+
...envelope("detail"),
|
|
1279
|
+
id,
|
|
1280
|
+
data: row
|
|
1281
|
+
};
|
|
1282
|
+
}, {
|
|
1283
|
+
...maybeParams(),
|
|
1284
|
+
detail: detailFor(options, "detail")
|
|
1285
|
+
});
|
|
1286
|
+
if (operations.replace)
|
|
1287
|
+
app.put(itemPath, async (context) => {
|
|
1288
|
+
const denied = await authorize("replace", options.authorization?.replace, authContext(context, "replace"));
|
|
1289
|
+
if (denied)
|
|
1290
|
+
return denied;
|
|
1291
|
+
const id = String(context.params[primaryKey]);
|
|
1292
|
+
const row = await dataAdapter.replace(options.model, id, context.body, adapterOpts);
|
|
1293
|
+
if (row == null)
|
|
1294
|
+
return notFound("replace", id);
|
|
1295
|
+
return {
|
|
1296
|
+
...envelope("replace"),
|
|
1297
|
+
id,
|
|
1298
|
+
...row !== undefined ? { data: row } : {},
|
|
1299
|
+
...options.settings?.returning !== undefined ? { returning: options.settings.returning } : {}
|
|
1300
|
+
};
|
|
1301
|
+
}, {
|
|
1302
|
+
...maybeBody(options.validation?.replace),
|
|
1303
|
+
...maybeParams(),
|
|
1304
|
+
detail: detailFor(options, "replace")
|
|
1305
|
+
});
|
|
1306
|
+
if (operations.update)
|
|
1307
|
+
app.patch(itemPath, async (context) => {
|
|
1308
|
+
const denied = await authorize("update", options.authorization?.update, authContext(context, "update"));
|
|
1309
|
+
if (denied)
|
|
1310
|
+
return denied;
|
|
1311
|
+
const id = String(context.params[primaryKey]);
|
|
1312
|
+
const row = await dataAdapter.update(options.model, id, context.body, adapterOpts);
|
|
1313
|
+
if (row == null)
|
|
1314
|
+
return notFound("update", id);
|
|
1315
|
+
return {
|
|
1316
|
+
...envelope("update"),
|
|
1317
|
+
id,
|
|
1318
|
+
...row !== undefined ? { data: row } : {},
|
|
1319
|
+
...options.settings?.returning !== undefined ? { returning: options.settings.returning } : {}
|
|
1320
|
+
};
|
|
1321
|
+
}, {
|
|
1322
|
+
...maybeBody(options.validation?.update),
|
|
1323
|
+
...maybeParams(),
|
|
1324
|
+
detail: detailFor(options, "update")
|
|
1325
|
+
});
|
|
1326
|
+
if (operations.delete)
|
|
1327
|
+
app.delete(itemPath, async (context) => {
|
|
1328
|
+
const denied = await authorize("delete", options.authorization?.delete, authContext(context, "delete"));
|
|
1329
|
+
if (denied)
|
|
1330
|
+
return denied;
|
|
1331
|
+
const id = String(context.params[primaryKey]);
|
|
1332
|
+
const row = await dataAdapter.remove(options.model, id, adapterOpts);
|
|
1333
|
+
if (row == null)
|
|
1334
|
+
return notFound("delete", id);
|
|
1335
|
+
return {
|
|
1336
|
+
...envelope("delete"),
|
|
1337
|
+
id,
|
|
1338
|
+
...row !== undefined ? { data: row } : {},
|
|
1339
|
+
...options.settings?.softDelete !== undefined ? { softDelete: options.settings.softDelete } : {}
|
|
1340
|
+
};
|
|
1341
|
+
}, {
|
|
1342
|
+
...maybeParams(),
|
|
1343
|
+
detail: detailFor(options, "delete")
|
|
1344
|
+
});
|
|
1345
|
+
return app;
|
|
1346
|
+
}
|
|
1347
|
+
export {
|
|
1348
|
+
resolveAdapter,
|
|
1349
|
+
registerRack,
|
|
1350
|
+
rack,
|
|
1351
|
+
prismaAdapter,
|
|
1352
|
+
parseListQuery,
|
|
1353
|
+
panelPage,
|
|
1354
|
+
listRacks,
|
|
1355
|
+
getAdapter,
|
|
1356
|
+
drizzleAdapter,
|
|
1357
|
+
detailFor,
|
|
1358
|
+
createMemoryIdempotencyStore,
|
|
1359
|
+
clearRacks,
|
|
1360
|
+
authorize,
|
|
1361
|
+
PANEL_PAGE_KEY
|
|
1362
|
+
};
|