pipework 0.5.0 → 0.6.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.
- package/dist/config/load.d.ts +3 -0
- package/dist/config/load.d.ts.map +1 -1
- package/dist/config/load.js +1 -0
- package/dist/config/load.js.map +1 -1
- package/dist/config/namespace.d.ts +3 -0
- package/dist/config/namespace.d.ts.map +1 -1
- package/dist/config/schema.d.ts +6 -0
- package/dist/config/schema.d.ts.map +1 -1
- package/dist/config/schema.js +3 -0
- package/dist/config/schema.js.map +1 -1
- package/dist/domain/define.d.ts +1 -1
- package/dist/domain/define.d.ts.map +1 -1
- package/dist/domain/define.js +37 -6
- package/dist/domain/define.js.map +1 -1
- package/dist/domain/field.d.ts.map +1 -1
- package/dist/domain/field.js +1 -0
- package/dist/domain/field.js.map +1 -1
- package/dist/domain/index.d.ts +2 -1
- package/dist/domain/index.d.ts.map +1 -1
- package/dist/domain/index.js +1 -0
- package/dist/domain/index.js.map +1 -1
- package/dist/domain/project-schema.d.ts.map +1 -1
- package/dist/domain/project-schema.js +4 -0
- package/dist/domain/project-schema.js.map +1 -1
- package/dist/domain/traits.d.ts +9 -0
- package/dist/domain/traits.d.ts.map +1 -0
- package/dist/domain/traits.js +48 -0
- package/dist/domain/traits.js.map +1 -0
- package/dist/domain/types.d.ts +12 -1
- package/dist/domain/types.d.ts.map +1 -1
- package/dist/drizzle/index.d.ts +3 -0
- package/dist/drizzle/index.d.ts.map +1 -0
- package/dist/drizzle/index.js +3 -0
- package/dist/drizzle/index.js.map +1 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/migrate/generate.d.ts.map +1 -1
- package/dist/migrate/generate.js +8 -1
- package/dist/migrate/generate.js.map +1 -1
- package/dist/migrate/index.d.ts +2 -0
- package/dist/migrate/index.d.ts.map +1 -1
- package/dist/migrate/index.js +2 -0
- package/dist/migrate/index.js.map +1 -1
- package/dist/migrate/post-process.d.ts +9 -0
- package/dist/migrate/post-process.d.ts.map +1 -0
- package/dist/migrate/post-process.js +60 -0
- package/dist/migrate/post-process.js.map +1 -0
- package/dist/migrate/rls-generate.d.ts +3 -0
- package/dist/migrate/rls-generate.d.ts.map +1 -0
- package/dist/migrate/rls-generate.js +28 -0
- package/dist/migrate/rls-generate.js.map +1 -0
- package/dist/resource/batch.d.ts +17 -0
- package/dist/resource/batch.d.ts.map +1 -0
- package/dist/resource/batch.js +47 -0
- package/dist/resource/batch.js.map +1 -0
- package/dist/resource/builder.d.ts +11 -0
- package/dist/resource/builder.d.ts.map +1 -0
- package/dist/resource/builder.js +12 -0
- package/dist/resource/builder.js.map +1 -0
- package/dist/resource/errors.d.ts +7 -0
- package/dist/resource/errors.d.ts.map +1 -0
- package/dist/resource/errors.js +9 -0
- package/dist/resource/errors.js.map +1 -0
- package/dist/resource/index.d.ts +9 -0
- package/dist/resource/index.d.ts.map +1 -0
- package/dist/resource/index.js +6 -0
- package/dist/resource/index.js.map +1 -0
- package/dist/resource/paginate.d.ts +13 -0
- package/dist/resource/paginate.d.ts.map +1 -0
- package/dist/resource/paginate.js +29 -0
- package/dist/resource/paginate.js.map +1 -0
- package/dist/resource/register.d.ts +16 -0
- package/dist/resource/register.d.ts.map +1 -0
- package/dist/resource/register.js +181 -0
- package/dist/resource/register.js.map +1 -0
- package/dist/resource/types.d.ts +69 -0
- package/dist/resource/types.d.ts.map +1 -0
- package/dist/resource/types.js +2 -0
- package/dist/resource/types.js.map +1 -0
- package/dist/temporal/definition-queries.d.ts +14 -0
- package/dist/temporal/definition-queries.d.ts.map +1 -0
- package/dist/temporal/definition-queries.js +45 -0
- package/dist/temporal/definition-queries.js.map +1 -0
- package/dist/temporal/index.d.ts +1 -0
- package/dist/temporal/index.d.ts.map +1 -1
- package/dist/temporal/index.js +1 -0
- package/dist/temporal/index.js.map +1 -1
- package/dist/temporal/namespace.d.ts +7 -0
- package/dist/temporal/namespace.d.ts.map +1 -1
- package/dist/temporal/namespace.js +7 -0
- package/dist/temporal/namespace.js.map +1 -1
- package/dist/tenant/rls.d.ts +1 -1
- package/dist/tenant/rls.d.ts.map +1 -1
- package/dist/tenant/rls.js +4 -2
- package/dist/tenant/rls.js.map +1 -1
- package/dist/trunk.d.ts +35 -0
- package/dist/trunk.d.ts.map +1 -0
- package/dist/trunk.js +102 -0
- package/dist/trunk.js.map +1 -0
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generate.js","sourceRoot":"","sources":["../../src/migrate/generate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AAC5E,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AACxC,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AACxC,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAA;AAEvC,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;
|
|
1
|
+
{"version":3,"file":"generate.js","sourceRoot":"","sources":["../../src/migrate/generate.ts"],"names":[],"mappings":"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"}
|
package/dist/migrate/index.d.ts
CHANGED
|
@@ -2,4 +2,6 @@ export { migrateAll, migrateOne, UnsafeMigrationError, type MigrateResult, type
|
|
|
2
2
|
export { checkMigrations, formatCheckResult, type MigrationCheckResult, type MigrationHazard, type Severity } from './check.js';
|
|
3
3
|
export { analyzeSQL } from './safety.js';
|
|
4
4
|
export { generateForDatabase, type GenerateResult } from './generate.js';
|
|
5
|
+
export { postProcessMigration } from './post-process.js';
|
|
6
|
+
export { generateRlsStatements } from './rls-generate.js';
|
|
5
7
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/migrate/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,oBAAoB,EAAE,KAAK,aAAa,EAAE,KAAK,cAAc,EAAE,MAAM,UAAU,CAAA;AAChH,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,KAAK,oBAAoB,EAAE,KAAK,eAAe,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,CAAA;AAC/H,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AACxC,OAAO,EAAE,mBAAmB,EAAE,KAAK,cAAc,EAAE,MAAM,eAAe,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/migrate/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,oBAAoB,EAAE,KAAK,aAAa,EAAE,KAAK,cAAc,EAAE,MAAM,UAAU,CAAA;AAChH,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,KAAK,oBAAoB,EAAE,KAAK,eAAe,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,CAAA;AAC/H,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AACxC,OAAO,EAAE,mBAAmB,EAAE,KAAK,cAAc,EAAE,MAAM,eAAe,CAAA;AACxE,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAA;AACxD,OAAO,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAA"}
|
package/dist/migrate/index.js
CHANGED
|
@@ -2,4 +2,6 @@ export { migrateAll, migrateOne, UnsafeMigrationError } from './run.js';
|
|
|
2
2
|
export { checkMigrations, formatCheckResult } from './check.js';
|
|
3
3
|
export { analyzeSQL } from './safety.js';
|
|
4
4
|
export { generateForDatabase } from './generate.js';
|
|
5
|
+
export { postProcessMigration } from './post-process.js';
|
|
6
|
+
export { generateRlsStatements } from './rls-generate.js';
|
|
5
7
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/migrate/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,oBAAoB,EAA2C,MAAM,UAAU,CAAA;AAChH,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAkE,MAAM,YAAY,CAAA;AAC/H,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AACxC,OAAO,EAAE,mBAAmB,EAAuB,MAAM,eAAe,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/migrate/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,oBAAoB,EAA2C,MAAM,UAAU,CAAA;AAChH,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAkE,MAAM,YAAY,CAAA;AAC/H,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AACxC,OAAO,EAAE,mBAAmB,EAAuB,MAAM,eAAe,CAAA;AACxE,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAA;AACxD,OAAO,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAA"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Transform unsafe drizzle-kit migration SQL into safe SQL.
|
|
3
|
+
*
|
|
4
|
+
* Two transforms are applied:
|
|
5
|
+
* 1. `CREATE INDEX` → `CREATE INDEX CONCURRENTLY` (with `-- pipework:no-transaction` pragma)
|
|
6
|
+
* 2. `ADD CONSTRAINT ... FOREIGN KEY` → appends `NOT VALID`, emits `VALIDATE CONSTRAINT`
|
|
7
|
+
*/
|
|
8
|
+
export declare function postProcessMigration(sql: string): string;
|
|
9
|
+
//# sourceMappingURL=post-process.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"post-process.d.ts","sourceRoot":"","sources":["../../src/migrate/post-process.ts"],"names":[],"mappings":"AAQA;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CA4DxD"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
const CREATE_INDEX_RE = /\bCREATE\s+(UNIQUE\s+)?INDEX\b(?!\s+CONCURRENTLY)/i;
|
|
2
|
+
const CONCURRENTLY_RE = /\bCONCURRENTLY\b/i;
|
|
3
|
+
const FK_RE = /\bADD\s+CONSTRAINT\b[^;]*\bFOREIGN\s+KEY\b(?![^;]*\bNOT\s+VALID\b)/i;
|
|
4
|
+
const ALTER_TABLE_NAME_RE = /\bALTER\s+TABLE\s+(?:ONLY\s+)?((?:"(?:[^"]+)"\.)*"(?:[^"]+)"|[^\s(]+(?:\.[^\s(]+)*)/i;
|
|
5
|
+
const ADD_CONSTRAINT_NAME_RE = /\bADD\s+CONSTRAINT\s+("(?:[^"]+)"|[^\s(]+)/i;
|
|
6
|
+
const NO_TRANSACTION_PRAGMA = '-- pipework:no-transaction';
|
|
7
|
+
/**
|
|
8
|
+
* Transform unsafe drizzle-kit migration SQL into safe SQL.
|
|
9
|
+
*
|
|
10
|
+
* Two transforms are applied:
|
|
11
|
+
* 1. `CREATE INDEX` → `CREATE INDEX CONCURRENTLY` (with `-- pipework:no-transaction` pragma)
|
|
12
|
+
* 2. `ADD CONSTRAINT ... FOREIGN KEY` → appends `NOT VALID`, emits `VALIDATE CONSTRAINT`
|
|
13
|
+
*/
|
|
14
|
+
export function postProcessMigration(sql) {
|
|
15
|
+
const parts = sql.split(';');
|
|
16
|
+
const trailing = parts[parts.length - 1];
|
|
17
|
+
const rawStatements = parts.slice(0, -1);
|
|
18
|
+
const outputStatements = [];
|
|
19
|
+
let hasConcurrently = false;
|
|
20
|
+
for (const raw of rawStatements) {
|
|
21
|
+
const trimmed = raw.trim();
|
|
22
|
+
if (trimmed.length === 0 || trimmed.startsWith('--')) {
|
|
23
|
+
outputStatements.push(raw);
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
if (CREATE_INDEX_RE.test(trimmed)) {
|
|
27
|
+
const rewritten = raw.replace(/\b(CREATE\s+(?:UNIQUE\s+)?)(INDEX)\b/i, '$1$2 CONCURRENTLY');
|
|
28
|
+
outputStatements.push(rewritten);
|
|
29
|
+
hasConcurrently = true;
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
if (CONCURRENTLY_RE.test(trimmed)) {
|
|
33
|
+
hasConcurrently = true;
|
|
34
|
+
}
|
|
35
|
+
if (FK_RE.test(trimmed)) {
|
|
36
|
+
const tableMatch = ALTER_TABLE_NAME_RE.exec(trimmed);
|
|
37
|
+
const constraintMatch = ADD_CONSTRAINT_NAME_RE.exec(trimmed);
|
|
38
|
+
if (tableMatch !== null && constraintMatch !== null) {
|
|
39
|
+
const tableName = tableMatch[1];
|
|
40
|
+
const constraintName = constraintMatch[1];
|
|
41
|
+
const withNotValid = raw.replace(/\s*$/, ' NOT VALID');
|
|
42
|
+
outputStatements.push(withNotValid);
|
|
43
|
+
outputStatements.push(`\nALTER TABLE ${tableName} VALIDATE CONSTRAINT ${constraintName}`);
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
outputStatements.push(raw);
|
|
48
|
+
}
|
|
49
|
+
let result = outputStatements.join(';') + ';';
|
|
50
|
+
if (trailing !== undefined && trailing.trim().length > 0) {
|
|
51
|
+
result += trailing;
|
|
52
|
+
}
|
|
53
|
+
if (hasConcurrently) {
|
|
54
|
+
result = result.startsWith(NO_TRANSACTION_PRAGMA)
|
|
55
|
+
? result
|
|
56
|
+
: `${NO_TRANSACTION_PRAGMA}\n${result}`;
|
|
57
|
+
}
|
|
58
|
+
return result;
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=post-process.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"post-process.js","sourceRoot":"","sources":["../../src/migrate/post-process.ts"],"names":[],"mappings":"AAAA,MAAM,eAAe,GAAG,oDAAoD,CAAA;AAC5E,MAAM,eAAe,GAAG,mBAAmB,CAAA;AAC3C,MAAM,KAAK,GAAG,qEAAqE,CAAA;AACnF,MAAM,mBAAmB,GAAG,sFAAsF,CAAA;AAClH,MAAM,sBAAsB,GAAG,6CAA6C,CAAA;AAE5E,MAAM,qBAAqB,GAAG,4BAA4B,CAAA;AAE1D;;;;;;GAMG;AACH,MAAM,UAAU,oBAAoB,CAAC,GAAW;IAC9C,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IAC5B,MAAM,QAAQ,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;IACxC,MAAM,aAAa,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;IAExC,MAAM,gBAAgB,GAAa,EAAE,CAAA;IACrC,IAAI,eAAe,GAAG,KAAK,CAAA;IAE3B,KAAK,MAAM,GAAG,IAAI,aAAa,EAAE,CAAC;QAChC,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,EAAE,CAAA;QAC1B,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,IAAI,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YACrD,gBAAgB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;YAC1B,SAAQ;QACV,CAAC;QAED,IAAI,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YAClC,MAAM,SAAS,GAAG,GAAG,CAAC,OAAO,CAC3B,uCAAuC,EACvC,mBAAmB,CACpB,CAAA;YACD,gBAAgB,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;YAChC,eAAe,GAAG,IAAI,CAAA;YACtB,SAAQ;QACV,CAAC;QAED,IAAI,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YAClC,eAAe,GAAG,IAAI,CAAA;QACxB,CAAC;QAED,IAAI,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YACxB,MAAM,UAAU,GAAG,mBAAmB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;YACpD,MAAM,eAAe,GAAG,sBAAsB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;YAE5D,IAAI,UAAU,KAAK,IAAI,IAAI,eAAe,KAAK,IAAI,EAAE,CAAC;gBACpD,MAAM,SAAS,GAAG,UAAU,CAAC,CAAC,CAAE,CAAA;gBAChC,MAAM,cAAc,GAAG,eAAe,CAAC,CAAC,CAAE,CAAA;gBAE1C,MAAM,YAAY,GAAG,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,YAAY,CAAC,CAAA;gBACtD,gBAAgB,CAAC,IAAI,CAAC,YAAY,CAAC,CAAA;gBACnC,gBAAgB,CAAC,IAAI,CAAC,iBAAiB,SAAS,wBAAwB,cAAc,EAAE,CAAC,CAAA;gBACzF,SAAQ;YACV,CAAC;QACH,CAAC;QAED,gBAAgB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IAC5B,CAAC;IAED,IAAI,MAAM,GAAG,gBAAgB,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,GAAG,CAAA;IAE7C,IAAI,QAAQ,KAAK,SAAS,IAAI,QAAQ,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACzD,MAAM,IAAI,QAAQ,CAAA;IACpB,CAAC;IAED,IAAI,eAAe,EAAE,CAAC;QACpB,MAAM,GAAG,MAAM,CAAC,UAAU,CAAC,qBAAqB,CAAC;YAC/C,CAAC,CAAC,MAAM;YACR,CAAC,CAAC,GAAG,qBAAqB,KAAK,MAAM,EAAE,CAAA;IAC3C,CAAC;IAED,OAAO,MAAM,CAAA;AACf,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rls-generate.d.ts","sourceRoot":"","sources":["../../src/migrate/rls-generate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AAM1D,wBAAgB,qBAAqB,CACnC,YAAY,EAAE,MAAM,EACpB,WAAW,EAAE,WAAW,CAAC,MAAM,EAAE,gBAAgB,CAAC,EAClD,UAAU,EAAE,MAAM,GACjB,MAAM,CA6BR"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { camelToSnake } from '../domain/naming.js';
|
|
2
|
+
import { tenantIsolationPolicy } from '../tenant/rls.js';
|
|
3
|
+
const CREATE_TABLE_RE = /CREATE\s+TABLE\s+(?:IF\s+NOT\s+EXISTS\s+)?(?:"([^"]+)"|([a-z_][a-z0-9_]*))/gi;
|
|
4
|
+
export function generateRlsStatements(migrationSql, definitions, sessionVar) {
|
|
5
|
+
const rlsBlocks = [];
|
|
6
|
+
let match;
|
|
7
|
+
while ((match = CREATE_TABLE_RE.exec(migrationSql)) !== null) {
|
|
8
|
+
const tableName = match[1] ?? match[2];
|
|
9
|
+
if (tableName === undefined)
|
|
10
|
+
continue;
|
|
11
|
+
const definition = definitions.get(tableName);
|
|
12
|
+
if (definition === undefined)
|
|
13
|
+
continue;
|
|
14
|
+
const tenantFieldKey = Object.keys(definition.fields).find((key) => definition.fields[key]._meta.tenant === true);
|
|
15
|
+
if (tenantFieldKey === undefined)
|
|
16
|
+
continue;
|
|
17
|
+
const columnName = camelToSnake(tenantFieldKey);
|
|
18
|
+
if (migrationSql.includes(`"${tableName}" ENABLE ROW LEVEL SECURITY`) ||
|
|
19
|
+
migrationSql.includes(`${tableName} ENABLE ROW LEVEL SECURITY`)) {
|
|
20
|
+
continue;
|
|
21
|
+
}
|
|
22
|
+
rlsBlocks.push(tenantIsolationPolicy(tableName, columnName, sessionVar));
|
|
23
|
+
}
|
|
24
|
+
if (rlsBlocks.length === 0)
|
|
25
|
+
return migrationSql;
|
|
26
|
+
return migrationSql + ';\n\n' + rlsBlocks.join(';\n\n');
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=rls-generate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rls-generate.js","sourceRoot":"","sources":["../../src/migrate/rls-generate.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAA;AAExD,MAAM,eAAe,GAAG,8EAA8E,CAAA;AAEtG,MAAM,UAAU,qBAAqB,CACnC,YAAoB,EACpB,WAAkD,EAClD,UAAkB;IAElB,MAAM,SAAS,GAAa,EAAE,CAAA;IAC9B,IAAI,KAA6B,CAAA;IAEjC,OAAO,CAAC,KAAK,GAAG,eAAe,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;QAC7D,MAAM,SAAS,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAA;QACtC,IAAI,SAAS,KAAK,SAAS;YAAE,SAAQ;QAErC,MAAM,UAAU,GAAG,WAAW,CAAC,GAAG,CAAC,SAAS,CAAC,CAAA;QAC7C,IAAI,UAAU,KAAK,SAAS;YAAE,SAAQ;QAEtC,MAAM,cAAc,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,IAAI,CACxD,CAAC,GAAG,EAAE,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC,GAAG,CAAE,CAAC,KAAK,CAAC,MAAM,KAAK,IAAI,CACvD,CAAA;QACD,IAAI,cAAc,KAAK,SAAS;YAAE,SAAQ;QAE1C,MAAM,UAAU,GAAG,YAAY,CAAC,cAAc,CAAC,CAAA;QAE/C,IAAI,YAAY,CAAC,QAAQ,CAAC,IAAI,SAAS,6BAA6B,CAAC;YACjE,YAAY,CAAC,QAAQ,CAAC,GAAG,SAAS,4BAA4B,CAAC,EAAE,CAAC;YACpE,SAAQ;QACV,CAAC;QAED,SAAS,CAAC,IAAI,CAAC,qBAAqB,CAAC,SAAS,EAAE,UAAU,EAAE,UAAU,CAAC,CAAC,CAAA;IAC1E,CAAC;IAED,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,YAAY,CAAA;IAE/C,OAAO,YAAY,GAAG,OAAO,GAAG,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;AACzD,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { PostgresJsDatabase } from 'drizzle-orm/postgres-js';
|
|
2
|
+
import type { PermissionMeta } from '../di/types.js';
|
|
3
|
+
export interface BatchTargets {
|
|
4
|
+
readonly ids?: string[];
|
|
5
|
+
readonly filters?: Record<string, unknown>;
|
|
6
|
+
}
|
|
7
|
+
export interface BatchAction<TAuth> {
|
|
8
|
+
readonly permission?: PermissionMeta;
|
|
9
|
+
readonly preview?: (db: PostgresJsDatabase, auth: TAuth, tenant: string | null, targets: BatchTargets) => Promise<unknown>;
|
|
10
|
+
readonly execute: (db: PostgresJsDatabase, auth: TAuth, tenant: string | null, targets: BatchTargets) => Promise<unknown>;
|
|
11
|
+
}
|
|
12
|
+
export interface BatchRequest {
|
|
13
|
+
readonly action: string;
|
|
14
|
+
readonly targets: BatchTargets;
|
|
15
|
+
}
|
|
16
|
+
export declare function validateBatchRequest(body: unknown, validActions: string[]): BatchRequest;
|
|
17
|
+
//# sourceMappingURL=batch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"batch.d.ts","sourceRoot":"","sources":["../../src/resource/batch.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AACjE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAGpD,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,CAAA;IACvB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAC3C;AAED,MAAM,WAAW,WAAW,CAAC,KAAK;IAChC,QAAQ,CAAC,UAAU,CAAC,EAAE,cAAc,CAAA;IACpC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,EAAE,kBAAkB,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,EAAE,OAAO,EAAE,YAAY,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;IAC1H,QAAQ,CAAC,OAAO,EAAE,CAAC,EAAE,EAAE,kBAAkB,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,EAAE,OAAO,EAAE,YAAY,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;CAC1H;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAA;CAC/B;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,GAAG,YAAY,CAkDxF"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { ValidationError } from '../errors/index.js';
|
|
2
|
+
export function validateBatchRequest(body, validActions) {
|
|
3
|
+
if (body === null || typeof body !== 'object') {
|
|
4
|
+
throw new ValidationError('Batch request body must be an object');
|
|
5
|
+
}
|
|
6
|
+
const obj = body;
|
|
7
|
+
const action = obj['action'];
|
|
8
|
+
if (typeof action !== 'string' || action.length === 0) {
|
|
9
|
+
throw new ValidationError({ action: ['action is required and must be a non-empty string'] });
|
|
10
|
+
}
|
|
11
|
+
if (!validActions.includes(action)) {
|
|
12
|
+
throw new ValidationError({
|
|
13
|
+
action: [`Unknown batch action "${action}". Valid actions: ${validActions.join(', ')}`],
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
const targets = obj['targets'];
|
|
17
|
+
if (targets === null || targets === undefined || typeof targets !== 'object') {
|
|
18
|
+
throw new ValidationError({ targets: ['targets is required and must be an object'] });
|
|
19
|
+
}
|
|
20
|
+
const t = targets;
|
|
21
|
+
const hasIds = Array.isArray(t['ids']);
|
|
22
|
+
const hasFilters = t['filters'] !== undefined && t['filters'] !== null && typeof t['filters'] === 'object';
|
|
23
|
+
if (!hasIds && !hasFilters) {
|
|
24
|
+
throw new ValidationError({ targets: ['targets must contain exactly one of "ids" or "filters"'] });
|
|
25
|
+
}
|
|
26
|
+
if (hasIds && hasFilters) {
|
|
27
|
+
throw new ValidationError({ targets: ['targets must contain exactly one of "ids" or "filters", not both'] });
|
|
28
|
+
}
|
|
29
|
+
if (hasIds) {
|
|
30
|
+
const ids = t['ids'];
|
|
31
|
+
if (ids.length === 0) {
|
|
32
|
+
throw new ValidationError({ 'targets.ids': ['ids array must not be empty'] });
|
|
33
|
+
}
|
|
34
|
+
for (const id of ids) {
|
|
35
|
+
if (typeof id !== 'string') {
|
|
36
|
+
throw new ValidationError({ 'targets.ids': ['all ids must be strings'] });
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return {
|
|
41
|
+
action,
|
|
42
|
+
targets: hasIds
|
|
43
|
+
? { ids: t['ids'] }
|
|
44
|
+
: { filters: t['filters'] },
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=batch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"batch.js","sourceRoot":"","sources":["../../src/resource/batch.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AAkBpD,MAAM,UAAU,oBAAoB,CAAC,IAAa,EAAE,YAAsB;IACxE,IAAI,IAAI,KAAK,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC9C,MAAM,IAAI,eAAe,CAAC,sCAAsC,CAAC,CAAA;IACnE,CAAC;IACD,MAAM,GAAG,GAAG,IAA+B,CAAA;IAE3C,MAAM,MAAM,GAAG,GAAG,CAAC,QAAQ,CAAC,CAAA;IAC5B,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtD,MAAM,IAAI,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC,mDAAmD,CAAC,EAAE,CAAC,CAAA;IAC9F,CAAC;IACD,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QACnC,MAAM,IAAI,eAAe,CAAC;YACxB,MAAM,EAAE,CAAC,yBAAyB,MAAM,qBAAqB,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;SACxF,CAAC,CAAA;IACJ,CAAC;IAED,MAAM,OAAO,GAAG,GAAG,CAAC,SAAS,CAAC,CAAA;IAC9B,IAAI,OAAO,KAAK,IAAI,IAAI,OAAO,KAAK,SAAS,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;QAC7E,MAAM,IAAI,eAAe,CAAC,EAAE,OAAO,EAAE,CAAC,2CAA2C,CAAC,EAAE,CAAC,CAAA;IACvF,CAAC;IACD,MAAM,CAAC,GAAG,OAAkC,CAAA;IAE5C,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAA;IACtC,MAAM,UAAU,GAAG,CAAC,CAAC,SAAS,CAAC,KAAK,SAAS,IAAI,CAAC,CAAC,SAAS,CAAC,KAAK,IAAI,IAAI,OAAO,CAAC,CAAC,SAAS,CAAC,KAAK,QAAQ,CAAA;IAE1G,IAAI,CAAC,MAAM,IAAI,CAAC,UAAU,EAAE,CAAC;QAC3B,MAAM,IAAI,eAAe,CAAC,EAAE,OAAO,EAAE,CAAC,wDAAwD,CAAC,EAAE,CAAC,CAAA;IACpG,CAAC;IACD,IAAI,MAAM,IAAI,UAAU,EAAE,CAAC;QACzB,MAAM,IAAI,eAAe,CAAC,EAAE,OAAO,EAAE,CAAC,kEAAkE,CAAC,EAAE,CAAC,CAAA;IAC9G,CAAC;IAED,IAAI,MAAM,EAAE,CAAC;QACX,MAAM,GAAG,GAAG,CAAC,CAAC,KAAK,CAAc,CAAA;QACjC,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACrB,MAAM,IAAI,eAAe,CAAC,EAAE,aAAa,EAAE,CAAC,6BAA6B,CAAC,EAAE,CAAC,CAAA;QAC/E,CAAC;QACD,KAAK,MAAM,EAAE,IAAI,GAAG,EAAE,CAAC;YACrB,IAAI,OAAO,EAAE,KAAK,QAAQ,EAAE,CAAC;gBAC3B,MAAM,IAAI,eAAe,CAAC,EAAE,aAAa,EAAE,CAAC,yBAAyB,CAAC,EAAE,CAAC,CAAA;YAC3E,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO;QACL,MAAM;QACN,OAAO,EAAE,MAAM;YACb,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,KAAK,CAAa,EAAE;YAC/B,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,SAAS,CAA4B,EAAE;KACzD,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ResourceOperations, Resource, PaginationConfig } from './types.js';
|
|
2
|
+
import type { AuthRequirement, PermissionMeta } from '../di/types.js';
|
|
3
|
+
interface ResourceBuilderState {
|
|
4
|
+
database: string;
|
|
5
|
+
authRequirement: AuthRequirement;
|
|
6
|
+
permission: PermissionMeta | null;
|
|
7
|
+
pagination: PaginationConfig | null;
|
|
8
|
+
}
|
|
9
|
+
export declare function buildResource<TAuth>(name: string, operations: ResourceOperations<TAuth>, state: ResourceBuilderState): Resource<TAuth>;
|
|
10
|
+
export { type ResourceBuilderState };
|
|
11
|
+
//# sourceMappingURL=builder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"builder.d.ts","sourceRoot":"","sources":["../../src/resource/builder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,QAAQ,EAAgB,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAC9F,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAErE,UAAU,oBAAoB;IAC5B,QAAQ,EAAE,MAAM,CAAA;IAChB,eAAe,EAAE,eAAe,CAAA;IAChC,UAAU,EAAE,cAAc,GAAG,IAAI,CAAA;IACjC,UAAU,EAAE,gBAAgB,GAAG,IAAI,CAAA;CACpC;AAED,wBAAgB,aAAa,CAAC,KAAK,EACjC,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,kBAAkB,CAAC,KAAK,CAAC,EACrC,KAAK,EAAE,oBAAoB,GAC1B,QAAQ,CAAC,KAAK,CAAC,CASjB;AAED,OAAO,EAAE,KAAK,oBAAoB,EAAE,CAAA"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export function buildResource(name, operations, state) {
|
|
2
|
+
const meta = {
|
|
3
|
+
name,
|
|
4
|
+
database: state.database,
|
|
5
|
+
authRequirement: state.authRequirement,
|
|
6
|
+
permission: state.permission,
|
|
7
|
+
pagination: state.pagination,
|
|
8
|
+
};
|
|
9
|
+
return { meta, operations };
|
|
10
|
+
}
|
|
11
|
+
export {};
|
|
12
|
+
//# sourceMappingURL=builder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"builder.js","sourceRoot":"","sources":["../../src/resource/builder.ts"],"names":[],"mappings":"AAUA,MAAM,UAAU,aAAa,CAC3B,IAAY,EACZ,UAAqC,EACrC,KAA2B;IAE3B,MAAM,IAAI,GAAiB;QACzB,IAAI;QACJ,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,eAAe,EAAE,KAAK,CAAC,eAAe;QACtC,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,UAAU,EAAE,KAAK,CAAC,UAAU;KAC7B,CAAA;IACD,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,CAAA;AAC7B,CAAC;AAED,OAAO,EAA6B,CAAA"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { TrunkError } from '../errors/base.js';
|
|
2
|
+
export declare class MethodNotAllowedError extends TrunkError {
|
|
3
|
+
readonly code: "METHOD_NOT_ALLOWED";
|
|
4
|
+
readonly httpStatus: 405;
|
|
5
|
+
constructor(method: string, resource: string);
|
|
6
|
+
}
|
|
7
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/resource/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAE9C,qBAAa,qBAAsB,SAAQ,UAAU;IACnD,QAAQ,CAAC,IAAI,EAAG,oBAAoB,CAAS;IAC7C,QAAQ,CAAC,UAAU,EAAG,GAAG,CAAS;gBAEtB,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;CAG7C"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { TrunkError } from '../errors/base.js';
|
|
2
|
+
export class MethodNotAllowedError extends TrunkError {
|
|
3
|
+
code = 'METHOD_NOT_ALLOWED';
|
|
4
|
+
httpStatus = 405;
|
|
5
|
+
constructor(method, resource) {
|
|
6
|
+
super(`${method} not supported on ${resource}`);
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/resource/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAE9C,MAAM,OAAO,qBAAsB,SAAQ,UAAU;IAC1C,IAAI,GAAG,oBAA6B,CAAA;IACpC,UAAU,GAAG,GAAY,CAAA;IAElC,YAAY,MAAc,EAAE,QAAgB;QAC1C,KAAK,CAAC,GAAG,MAAM,qBAAqB,QAAQ,EAAE,CAAC,CAAA;IACjD,CAAC;CACF"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export type { Resource, ResourceOperations, ResourceMeta, ResourceId, ResourceListOp, ResourceListPaginatedOp, ResourceListCursorOp, ResourceGetOp, ResourceCreateOp, ResourceUpdateOp, ResourceDeleteOp, PaginationConfig, PaginationParams, PaginatedResponse } from './types.js';
|
|
2
|
+
export { buildResource } from './builder.js';
|
|
3
|
+
export { registerResource } from './register.js';
|
|
4
|
+
export { MethodNotAllowedError } from './errors.js';
|
|
5
|
+
export { encodeCursor, decodeCursor, buildPage } from './paginate.js';
|
|
6
|
+
export type { PageResult, CursorPaginationParams } from './paginate.js';
|
|
7
|
+
export { validateBatchRequest } from './batch.js';
|
|
8
|
+
export type { BatchAction, BatchTargets, BatchRequest } from './batch.js';
|
|
9
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/resource/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,QAAQ,EAAE,kBAAkB,EAAE,YAAY,EAAE,UAAU,EAAE,cAAc,EAAE,uBAAuB,EAAE,oBAAoB,EAAE,aAAa,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AACnR,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAC5C,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AAChD,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAA;AACnD,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AACrE,YAAY,EAAE,UAAU,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAA;AACvE,OAAO,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAA;AACjD,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { buildResource } from './builder.js';
|
|
2
|
+
export { registerResource } from './register.js';
|
|
3
|
+
export { MethodNotAllowedError } from './errors.js';
|
|
4
|
+
export { encodeCursor, decodeCursor, buildPage } from './paginate.js';
|
|
5
|
+
export { validateBatchRequest } from './batch.js';
|
|
6
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/resource/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAC5C,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AAChD,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAA;AACnD,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AAErE,OAAO,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAA"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface PageResult<T> {
|
|
2
|
+
readonly items: T[];
|
|
3
|
+
readonly cursor: string | null;
|
|
4
|
+
readonly hasMore: boolean;
|
|
5
|
+
}
|
|
6
|
+
export interface CursorPaginationParams {
|
|
7
|
+
readonly cursor?: string;
|
|
8
|
+
readonly limit: number;
|
|
9
|
+
}
|
|
10
|
+
export declare function encodeCursor(values: readonly unknown[]): string;
|
|
11
|
+
export declare function decodeCursor(cursor: string): unknown[];
|
|
12
|
+
export declare function buildPage<T>(rows: readonly T[], limit: number, getCursor: (item: T) => string): PageResult<T>;
|
|
13
|
+
//# sourceMappingURL=paginate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paginate.d.ts","sourceRoot":"","sources":["../../src/resource/paginate.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,UAAU,CAAC,CAAC;IAC3B,QAAQ,CAAC,KAAK,EAAE,CAAC,EAAE,CAAA;IACnB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IAC9B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;CAC1B;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CACvB;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,SAAS,OAAO,EAAE,GAAG,MAAM,CAG/D;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,EAAE,CAYtD;AAED,wBAAgB,SAAS,CAAC,CAAC,EACzB,IAAI,EAAE,SAAS,CAAC,EAAE,EAClB,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,MAAM,GAC7B,UAAU,CAAC,CAAC,CAAC,CAOf"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { ValidationError } from '../errors/index.js';
|
|
2
|
+
export function encodeCursor(values) {
|
|
3
|
+
const json = JSON.stringify(values);
|
|
4
|
+
return Buffer.from(json).toString('base64url');
|
|
5
|
+
}
|
|
6
|
+
export function decodeCursor(cursor) {
|
|
7
|
+
try {
|
|
8
|
+
const json = Buffer.from(cursor, 'base64url').toString('utf-8');
|
|
9
|
+
const parsed = JSON.parse(json);
|
|
10
|
+
if (!Array.isArray(parsed)) {
|
|
11
|
+
throw new ValidationError('Invalid cursor: expected encoded array');
|
|
12
|
+
}
|
|
13
|
+
return parsed;
|
|
14
|
+
}
|
|
15
|
+
catch (err) {
|
|
16
|
+
if (err instanceof ValidationError)
|
|
17
|
+
throw err;
|
|
18
|
+
throw new ValidationError('Invalid cursor: malformed or tampered value');
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
export function buildPage(rows, limit, getCursor) {
|
|
22
|
+
const hasMore = rows.length > limit;
|
|
23
|
+
const items = hasMore ? rows.slice(0, limit) : [...rows];
|
|
24
|
+
const cursor = hasMore && items.length > 0
|
|
25
|
+
? encodeCursor([getCursor(items[items.length - 1])])
|
|
26
|
+
: null;
|
|
27
|
+
return { items, cursor, hasMore };
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=paginate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paginate.js","sourceRoot":"","sources":["../../src/resource/paginate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AAapD,MAAM,UAAU,YAAY,CAAC,MAA0B;IACrD,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAA;IACnC,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAA;AAChD,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,MAAc;IACzC,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAA;QAC/D,MAAM,MAAM,GAAY,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;QACxC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YAC3B,MAAM,IAAI,eAAe,CAAC,wCAAwC,CAAC,CAAA;QACrE,CAAC;QACD,OAAO,MAAM,CAAA;IACf,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,GAAG,YAAY,eAAe;YAAE,MAAM,GAAG,CAAA;QAC7C,MAAM,IAAI,eAAe,CAAC,6CAA6C,CAAC,CAAA;IAC1E,CAAC;AACH,CAAC;AAED,MAAM,UAAU,SAAS,CACvB,IAAkB,EAClB,KAAa,EACb,SAA8B;IAE9B,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,GAAG,KAAK,CAAA;IACnC,MAAM,KAAK,GAAG,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAA;IACxD,MAAM,MAAM,GAAG,OAAO,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;QACxC,CAAC,CAAC,YAAY,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAE,CAAC,CAAC,CAAC;QACrD,CAAC,CAAC,IAAI,CAAA;IACR,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,CAAA;AACnC,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { FastifyInstance } from 'fastify';
|
|
2
|
+
import type { TrunkInstance } from '../trunk.js';
|
|
3
|
+
import type { Resource } from './types.js';
|
|
4
|
+
import type { TenantConfig } from '../tenant/types.js';
|
|
5
|
+
import type { Rbac } from '../rbac/types.js';
|
|
6
|
+
import { type ContextOptions } from '../http/middleware.js';
|
|
7
|
+
interface RegisterOptions {
|
|
8
|
+
instance: TrunkInstance;
|
|
9
|
+
contextOptions: ContextOptions;
|
|
10
|
+
tenantConfig: TenantConfig | null;
|
|
11
|
+
rbac: Rbac | null;
|
|
12
|
+
txDatabases: string[] | null;
|
|
13
|
+
}
|
|
14
|
+
export declare function registerResource<TAuth>(app: FastifyInstance, resource: Resource<TAuth>, options: RegisterOptions): void;
|
|
15
|
+
export {};
|
|
16
|
+
//# sourceMappingURL=register.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"register.d.ts","sourceRoot":"","sources":["../../src/resource/register.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAgC,MAAM,SAAS,CAAA;AAC5E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAChD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAC1C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACtD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAA;AAC5C,OAAO,EAAgB,KAAK,cAAc,EAAE,MAAM,uBAAuB,CAAA;AAQzE,UAAU,eAAe;IACvB,QAAQ,EAAE,aAAa,CAAA;IACvB,cAAc,EAAE,cAAc,CAAA;IAC9B,YAAY,EAAE,YAAY,GAAG,IAAI,CAAA;IACjC,IAAI,EAAE,IAAI,GAAG,IAAI,CAAA;IACjB,WAAW,EAAE,MAAM,EAAE,GAAG,IAAI,CAAA;CAC7B;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EACpC,GAAG,EAAE,eAAe,EACpB,QAAQ,EAAE,QAAQ,CAAC,KAAK,CAAC,EACzB,OAAO,EAAE,eAAe,GACvB,IAAI,CAsLN"}
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import { buildContext } from '../http/middleware.js';
|
|
2
|
+
import { runInContext } from '../context/store.js';
|
|
3
|
+
import { TrunkError, NotFoundError } from '../errors/index.js';
|
|
4
|
+
import { buildErrorResponse, buildInternalErrorResponse } from '../http/response.js';
|
|
5
|
+
import { parse } from '../schema/parse.js';
|
|
6
|
+
import { MethodNotAllowedError } from './errors.js';
|
|
7
|
+
import { validateBatchRequest } from './batch.js';
|
|
8
|
+
export function registerResource(app, resource, options) {
|
|
9
|
+
const { name, database } = resource.meta;
|
|
10
|
+
const basePath = `/${name}`;
|
|
11
|
+
const itemPath = `/${name}/:id`;
|
|
12
|
+
const ops = resource.operations;
|
|
13
|
+
const handler = async (req, reply, fn) => {
|
|
14
|
+
try {
|
|
15
|
+
const ctx = await buildContext(req, options.contextOptions, resource.meta.authRequirement);
|
|
16
|
+
if (resource.meta.permission && options.rbac !== null) {
|
|
17
|
+
const { enforcePermission } = await import('../rbac/middleware.js');
|
|
18
|
+
const auth = ctx.auth;
|
|
19
|
+
if (auth !== null && ctx.tenant !== null) {
|
|
20
|
+
const userId = typeof auth['userId'] === 'string' ? auth['userId'] : null;
|
|
21
|
+
const authVersion = typeof auth['authVersion'] === 'number' ? auth['authVersion'] : 1;
|
|
22
|
+
if (userId !== null) {
|
|
23
|
+
const dbConfig = options.instance.config.database(database);
|
|
24
|
+
const conn = options.instance.pool.getOrCreate(dbConfig);
|
|
25
|
+
await enforcePermission(options.rbac, conn.drizzle, userId, ctx.tenant, authVersion, resource.meta.permission.resource, resource.meta.permission.action, resource.meta.permission.scope);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
const dbConfig = options.instance.config.database(database);
|
|
30
|
+
const conn = options.instance.pool.getOrCreate(dbConfig);
|
|
31
|
+
if (resource.meta.authRequirement !== 'none' && ctx.tenant === null) {
|
|
32
|
+
return reply.status(401).send(buildErrorResponse(new (await import('../errors/index.js')).UnauthorizedError('Tenant context required')));
|
|
33
|
+
}
|
|
34
|
+
const result = await runInContext(ctx, () => fn(conn.drizzle, ctx.auth, ctx.tenant));
|
|
35
|
+
if (result.body !== undefined) {
|
|
36
|
+
return reply.status(result.status).send(result.body);
|
|
37
|
+
}
|
|
38
|
+
return reply.status(result.status).send();
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
if (error instanceof TrunkError) {
|
|
42
|
+
return reply.status(error.httpStatus).send(buildErrorResponse(error));
|
|
43
|
+
}
|
|
44
|
+
req.log.error(error, 'Unhandled error in resource handler');
|
|
45
|
+
return reply.status(500).send(buildInternalErrorResponse());
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
// GET /resource — list
|
|
49
|
+
app.get(basePath, async (req, reply) => {
|
|
50
|
+
if (ops.listCursor !== undefined && resource.meta.pagination !== null) {
|
|
51
|
+
return handler(req, reply, async (db, auth, tenant) => {
|
|
52
|
+
const query = (req.query ?? {});
|
|
53
|
+
const pagination = resource.meta.pagination;
|
|
54
|
+
const rawLimit = query['limit'] !== undefined ? parseInt(query['limit'], 10) : pagination.defaultLimit;
|
|
55
|
+
const limit = Math.min(Math.max(1, Number.isNaN(rawLimit) ? pagination.defaultLimit : rawLimit), pagination.maxLimit);
|
|
56
|
+
const cursor = query['cursor'];
|
|
57
|
+
const result = await ops.listCursor(db, auth, tenant, cursor !== undefined ? { cursor, limit } : { limit });
|
|
58
|
+
return { status: 200, body: result };
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
if (ops.listPaginated !== undefined && resource.meta.pagination !== null) {
|
|
62
|
+
return handler(req, reply, async (db, auth, tenant) => {
|
|
63
|
+
const query = (req.query ?? {});
|
|
64
|
+
const pagination = resource.meta.pagination;
|
|
65
|
+
const rawLimit = query['limit'] !== undefined ? parseInt(query['limit'], 10) : pagination.defaultLimit;
|
|
66
|
+
const limit = Math.min(Math.max(1, Number.isNaN(rawLimit) ? pagination.defaultLimit : rawLimit), pagination.maxLimit);
|
|
67
|
+
const rawOffset = query['offset'] !== undefined ? parseInt(query['offset'], 10) : 0;
|
|
68
|
+
const offset = Math.max(0, Number.isNaN(rawOffset) ? 0 : rawOffset);
|
|
69
|
+
const result = await ops.listPaginated(db, auth, tenant, { limit, offset });
|
|
70
|
+
return {
|
|
71
|
+
status: 200,
|
|
72
|
+
body: {
|
|
73
|
+
data: result.data,
|
|
74
|
+
pagination: { limit, offset, total: result.total, hasMore: offset + result.data.length < result.total },
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
if (ops.list === undefined) {
|
|
80
|
+
return reply.status(405).send(buildErrorResponse(new MethodNotAllowedError('GET', name)));
|
|
81
|
+
}
|
|
82
|
+
return handler(req, reply, async (db, auth, tenant) => {
|
|
83
|
+
const result = await ops.list(db, auth, tenant);
|
|
84
|
+
return { status: 200, body: result };
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
// GET /resource/:id — get
|
|
88
|
+
app.get(itemPath, async (req, reply) => {
|
|
89
|
+
if (ops.get === undefined) {
|
|
90
|
+
return reply.status(405).send(buildErrorResponse(new MethodNotAllowedError('GET', name)));
|
|
91
|
+
}
|
|
92
|
+
return handler(req, reply, async (db, auth, tenant) => {
|
|
93
|
+
const id = req.params['id'];
|
|
94
|
+
const result = await ops.get(db, auth, tenant, id);
|
|
95
|
+
if (result === null || result === undefined) {
|
|
96
|
+
throw new NotFoundError(`${capitalize(singularize(name))} "${id}"`);
|
|
97
|
+
}
|
|
98
|
+
return { status: 200, body: result };
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
// POST /resource — create
|
|
102
|
+
app.post(basePath, async (req, reply) => {
|
|
103
|
+
if (ops.create === undefined) {
|
|
104
|
+
return reply.status(405).send(buildErrorResponse(new MethodNotAllowedError('POST', name)));
|
|
105
|
+
}
|
|
106
|
+
return handler(req, reply, async (db, auth, tenant) => {
|
|
107
|
+
let input = req.body;
|
|
108
|
+
if (ops.create.input !== undefined) {
|
|
109
|
+
input = parse(ops.create.input, req.body);
|
|
110
|
+
}
|
|
111
|
+
const result = await ops.create.handler(db, auth, tenant, input);
|
|
112
|
+
return { status: 201, body: result };
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
// PUT /resource/:id — update
|
|
116
|
+
app.put(itemPath, async (req, reply) => {
|
|
117
|
+
if (ops.update === undefined) {
|
|
118
|
+
return reply.status(405).send(buildErrorResponse(new MethodNotAllowedError('PUT', name)));
|
|
119
|
+
}
|
|
120
|
+
return handler(req, reply, async (db, auth, tenant) => {
|
|
121
|
+
const id = req.params['id'];
|
|
122
|
+
let input = req.body;
|
|
123
|
+
if (ops.update.input !== undefined) {
|
|
124
|
+
input = parse(ops.update.input, req.body);
|
|
125
|
+
}
|
|
126
|
+
const result = await ops.update.handler(db, auth, tenant, id, input);
|
|
127
|
+
if (result === null || result === undefined) {
|
|
128
|
+
throw new NotFoundError(`${capitalize(singularize(name))} "${id}"`);
|
|
129
|
+
}
|
|
130
|
+
return { status: 200, body: result };
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
// DELETE /resource/:id — delete
|
|
134
|
+
app.delete(itemPath, async (req, reply) => {
|
|
135
|
+
if (ops.delete === undefined) {
|
|
136
|
+
return reply.status(405).send(buildErrorResponse(new MethodNotAllowedError('DELETE', name)));
|
|
137
|
+
}
|
|
138
|
+
return handler(req, reply, async (db, auth, tenant) => {
|
|
139
|
+
const id = req.params['id'];
|
|
140
|
+
await ops.delete(db, auth, tenant, id);
|
|
141
|
+
return { status: 204 };
|
|
142
|
+
});
|
|
143
|
+
});
|
|
144
|
+
if (ops.batch !== undefined) {
|
|
145
|
+
const validActions = Object.keys(ops.batch);
|
|
146
|
+
// POST /resource/batch/preview — batch preview
|
|
147
|
+
app.post(`${basePath}/batch/preview`, async (req, reply) => {
|
|
148
|
+
return handler(req, reply, async (db, auth, tenant) => {
|
|
149
|
+
const { action, targets } = validateBatchRequest(req.body, validActions);
|
|
150
|
+
const batchAction = ops.batch[action];
|
|
151
|
+
if (batchAction.preview === undefined) {
|
|
152
|
+
throw new MethodNotAllowedError('POST', `${name}/batch/preview (action: ${action})`);
|
|
153
|
+
}
|
|
154
|
+
const result = await batchAction.preview(db, auth, tenant, targets);
|
|
155
|
+
return { status: 200, body: result };
|
|
156
|
+
});
|
|
157
|
+
});
|
|
158
|
+
// POST /resource/batch — batch execute
|
|
159
|
+
app.post(`${basePath}/batch`, async (req, reply) => {
|
|
160
|
+
return handler(req, reply, async (db, auth, tenant) => {
|
|
161
|
+
const { action, targets } = validateBatchRequest(req.body, validActions);
|
|
162
|
+
const batchAction = ops.batch[action];
|
|
163
|
+
const result = await batchAction.execute(db, auth, tenant, targets);
|
|
164
|
+
return { status: 200, body: result };
|
|
165
|
+
});
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
function capitalize(s) {
|
|
170
|
+
return s.charAt(0).toUpperCase() + s.slice(1);
|
|
171
|
+
}
|
|
172
|
+
function singularize(s) {
|
|
173
|
+
if (s.endsWith('ies'))
|
|
174
|
+
return s.slice(0, -3) + 'y';
|
|
175
|
+
if (s.endsWith('ses') || s.endsWith('xes'))
|
|
176
|
+
return s.slice(0, -2);
|
|
177
|
+
if (s.endsWith('s') && !s.endsWith('ss'))
|
|
178
|
+
return s.slice(0, -1);
|
|
179
|
+
return s;
|
|
180
|
+
}
|
|
181
|
+
//# sourceMappingURL=register.js.map
|