@apiagex/database 0.6.2
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 +25 -0
- package/dist/admin-permission-repository.d.ts +7 -0
- package/dist/admin-permission-repository.d.ts.map +1 -0
- package/dist/admin-permission-repository.js +74 -0
- package/dist/admin-permission-repository.type.d.ts +10 -0
- package/dist/admin-permission-repository.type.d.ts.map +1 -0
- package/dist/admin-permission-repository.type.js +1 -0
- package/dist/api-token-repository.d.ts +7 -0
- package/dist/api-token-repository.d.ts.map +1 -0
- package/dist/api-token-repository.js +80 -0
- package/dist/api-token-repository.type.d.ts +19 -0
- package/dist/api-token-repository.type.d.ts.map +1 -0
- package/dist/api-token-repository.type.js +1 -0
- package/dist/entry-query.d.ts +4 -0
- package/dist/entry-query.d.ts.map +1 -0
- package/dist/entry-query.js +61 -0
- package/dist/entry-repository.d.ts +8 -0
- package/dist/entry-repository.d.ts.map +1 -0
- package/dist/entry-repository.js +181 -0
- package/dist/entry-repository.type.d.ts +32 -0
- package/dist/entry-repository.type.d.ts.map +1 -0
- package/dist/entry-repository.type.js +1 -0
- package/dist/index.d.ts +29 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +15 -0
- package/dist/migrations-additive.d.ts +2 -0
- package/dist/migrations-additive.d.ts.map +1 -0
- package/dist/migrations-additive.js +71 -0
- package/dist/migrations.d.ts +5 -0
- package/dist/migrations.d.ts.map +1 -0
- package/dist/migrations.js +175 -0
- package/dist/permission-repository.d.ts +6 -0
- package/dist/permission-repository.d.ts.map +1 -0
- package/dist/permission-repository.js +80 -0
- package/dist/permission-repository.type.d.ts +11 -0
- package/dist/permission-repository.type.d.ts.map +1 -0
- package/dist/permission-repository.type.js +1 -0
- package/dist/realtime-repository.d.ts +12 -0
- package/dist/realtime-repository.d.ts.map +1 -0
- package/dist/realtime-repository.js +98 -0
- package/dist/realtime-repository.type.d.ts +33 -0
- package/dist/realtime-repository.type.d.ts.map +1 -0
- package/dist/realtime-repository.type.js +1 -0
- package/dist/realtime-session-repository.d.ts +5 -0
- package/dist/realtime-session-repository.d.ts.map +1 -0
- package/dist/realtime-session-repository.js +38 -0
- package/dist/realtime-session-repository.type.d.ts +21 -0
- package/dist/realtime-session-repository.type.d.ts.map +1 -0
- package/dist/realtime-session-repository.type.js +1 -0
- package/dist/relation-errors.d.ts +20 -0
- package/dist/relation-errors.d.ts.map +1 -0
- package/dist/relation-errors.js +30 -0
- package/dist/relation-helpers.d.ts +14 -0
- package/dist/relation-helpers.d.ts.map +1 -0
- package/dist/relation-helpers.js +21 -0
- package/dist/role-repository.d.ts +8 -0
- package/dist/role-repository.d.ts.map +1 -0
- package/dist/role-repository.js +66 -0
- package/dist/role-repository.type.d.ts +15 -0
- package/dist/role-repository.type.d.ts.map +1 -0
- package/dist/role-repository.type.js +1 -0
- package/dist/schema-repository.d.ts +9 -0
- package/dist/schema-repository.d.ts.map +1 -0
- package/dist/schema-repository.js +155 -0
- package/dist/schema-repository.type.d.ts +45 -0
- package/dist/schema-repository.type.d.ts.map +1 -0
- package/dist/schema-repository.type.js +1 -0
- package/dist/schema.type.d.ts +9 -0
- package/dist/schema.type.d.ts.map +1 -0
- package/dist/schema.type.js +1 -0
- package/dist/sqlite.d.ts +6 -0
- package/dist/sqlite.d.ts.map +1 -0
- package/dist/sqlite.js +40 -0
- package/dist/user-repository.d.ts +11 -0
- package/dist/user-repository.d.ts.map +1 -0
- package/dist/user-repository.js +56 -0
- package/dist/user-repository.type.d.ts +15 -0
- package/dist/user-repository.type.d.ts.map +1 -0
- package/dist/user-repository.type.js +1 -0
- package/dist/webhook-repository.d.ts +15 -0
- package/dist/webhook-repository.d.ts.map +1 -0
- package/dist/webhook-repository.js +136 -0
- package/dist/webhook-repository.type.d.ts +79 -0
- package/dist/webhook-repository.type.d.ts.map +1 -0
- package/dist/webhook-repository.type.js +1 -0
- package/package.json +43 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Aditya Gupta and contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Database Package
|
|
2
|
+
|
|
3
|
+
## English
|
|
4
|
+
|
|
5
|
+
This package owns the database adapter contract for Apiagex. It currently exposes placeholder adapters for SQLite, PostgreSQL, and MySQL, plus a selector that chooses the right adapter from config.
|
|
6
|
+
|
|
7
|
+
MVP note: the active SQLite repository now stores role metadata with `roleKind`. Admin roles are `owner`, `admin`, `schema-manager`, and `user-manager`; API roles are used for content API permissions. Admin permissions live in `admin_permissions`, content API permissions stay in `permissions`, content API tokens are stored hashed in `api_tokens`, and webhooks use `webhooks`, `webhook_events`, and `webhook_deliveries`.
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
import { selectDatabaseAdapter } from '@apiagex/database';
|
|
11
|
+
|
|
12
|
+
const adapter = selectDatabaseAdapter({ client: 'sqlite', file: './data/apiagex.db' });
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Hindi
|
|
16
|
+
|
|
17
|
+
Ye package Apiagex ke database adapter contract ka owner hai. Abhi isme SQLite, PostgreSQL, aur MySQL ke placeholder adapters aur config ke basis par adapter select karne wala helper hai.
|
|
18
|
+
|
|
19
|
+
MVP note: active SQLite repository ab `roleKind` metadata store karta hai. Admin roles `owner`, `admin`, `schema-manager`, aur `user-manager` hain; API roles content API permissions ke liye use hote hain. Admin permissions `admin_permissions` me rehte hain, content API permissions `permissions` me alag rehte hain, content API tokens `api_tokens` me hashed form me store hote hain, aur webhooks `webhooks`, `webhook_events`, plus `webhook_deliveries` use karte hain.
|
|
20
|
+
|
|
21
|
+
```ts
|
|
22
|
+
import { selectDatabaseAdapter } from '@apiagex/database';
|
|
23
|
+
|
|
24
|
+
const adapter = selectDatabaseAdapter({ client: 'sqlite', file: './data/apiagex.db' });
|
|
25
|
+
```
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { SqliteDatabase } from "./sqlite.js";
|
|
2
|
+
import type { AdminPermissionAction, AdminPermissionRecord, SetAdminPermissionInput } from "./admin-permission-repository.type.js";
|
|
3
|
+
export declare const adminPermissionActions: AdminPermissionAction[];
|
|
4
|
+
export declare function setAdminPermission(db: SqliteDatabase, input: SetAdminPermissionInput): AdminPermissionRecord;
|
|
5
|
+
export declare function listAdminRolePermissions(db: SqliteDatabase, roleId: string): AdminPermissionRecord[];
|
|
6
|
+
export declare function canAdminRoleAccess(db: SqliteDatabase, roleId: string, action: AdminPermissionAction): boolean;
|
|
7
|
+
//# sourceMappingURL=admin-permission-repository.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"admin-permission-repository.d.ts","sourceRoot":"","sources":["../src/admin-permission-repository.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,OAAO,KAAK,EACV,qBAAqB,EACrB,qBAAqB,EACrB,uBAAuB,EACxB,MAAM,uCAAuC,CAAC;AAI/C,eAAO,MAAM,sBAAsB,EAAE,qBAAqB,EAMzD,CAAC;AAEF,wBAAgB,kBAAkB,CAChC,EAAE,EAAE,cAAc,EAClB,KAAK,EAAE,uBAAuB,GAC7B,qBAAqB,CAevB;AAED,wBAAgB,wBAAwB,CACtC,EAAE,EAAE,cAAc,EAClB,MAAM,EAAE,MAAM,GACb,qBAAqB,EAAE,CAOzB;AAED,wBAAgB,kBAAkB,CAChC,EAAE,EAAE,cAAc,EAClB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,qBAAqB,GAC5B,OAAO,CAKT"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { getRoleById } from "./role-repository.js";
|
|
3
|
+
export const adminPermissionActions = [
|
|
4
|
+
"schemas",
|
|
5
|
+
"entries",
|
|
6
|
+
"apiRoles",
|
|
7
|
+
"apiUsers",
|
|
8
|
+
"settings",
|
|
9
|
+
];
|
|
10
|
+
export function setAdminPermission(db, input) {
|
|
11
|
+
validateAdminPermissionInput(db, input);
|
|
12
|
+
const existing = findAdminPermission(db, input.roleId, input.action);
|
|
13
|
+
if (existing) {
|
|
14
|
+
db.prepare("UPDATE admin_permissions SET allowed = ? WHERE id = ?").run(input.allowed ? 1 : 0, existing.id);
|
|
15
|
+
return requireAdminPermission(db, existing.id);
|
|
16
|
+
}
|
|
17
|
+
const id = randomUUID();
|
|
18
|
+
db.prepare("INSERT INTO admin_permissions (id, role_id, action, allowed) VALUES (?, ?, ?, ?)").run(id, input.roleId, input.action, input.allowed ? 1 : 0);
|
|
19
|
+
return requireAdminPermission(db, id);
|
|
20
|
+
}
|
|
21
|
+
export function listAdminRolePermissions(db, roleId) {
|
|
22
|
+
const role = getRoleById(db, roleId);
|
|
23
|
+
if (role?.isOwner)
|
|
24
|
+
return ownerPermissions(roleId);
|
|
25
|
+
const rows = db
|
|
26
|
+
.prepare(adminPermissionSelectSql("WHERE role_id = ? ORDER BY action ASC"))
|
|
27
|
+
.all(roleId);
|
|
28
|
+
return rows.map(rowToAdminPermission);
|
|
29
|
+
}
|
|
30
|
+
export function canAdminRoleAccess(db, roleId, action) {
|
|
31
|
+
const role = getRoleById(db, roleId);
|
|
32
|
+
if (!role || role.roleKind !== "admin")
|
|
33
|
+
return false;
|
|
34
|
+
if (role.isOwner)
|
|
35
|
+
return true;
|
|
36
|
+
return Boolean(findAdminPermission(db, roleId, action)?.allowed);
|
|
37
|
+
}
|
|
38
|
+
function validateAdminPermissionInput(db, input) {
|
|
39
|
+
if (!adminPermissionActions.includes(input.action))
|
|
40
|
+
throw new Error("ADMIN_PERMISSION_ACTION_INVALID");
|
|
41
|
+
const role = getRoleById(db, input.roleId);
|
|
42
|
+
if (!role)
|
|
43
|
+
throw new Error("ROLE_NOT_FOUND");
|
|
44
|
+
if (role.roleKind !== "admin")
|
|
45
|
+
throw new Error("ROLE_ADMIN_REQUIRED");
|
|
46
|
+
if (role.isOwner)
|
|
47
|
+
throw new Error("ROLE_OWNER_LOCKED");
|
|
48
|
+
}
|
|
49
|
+
function findAdminPermission(db, roleId, action) {
|
|
50
|
+
const row = db
|
|
51
|
+
.prepare(adminPermissionSelectSql("WHERE role_id = ? AND action = ?"))
|
|
52
|
+
.get(roleId, action);
|
|
53
|
+
return row ? rowToAdminPermission(row) : undefined;
|
|
54
|
+
}
|
|
55
|
+
function requireAdminPermission(db, id) {
|
|
56
|
+
const row = db.prepare(adminPermissionSelectSql("WHERE id = ?")).get(id);
|
|
57
|
+
if (!row)
|
|
58
|
+
throw new Error("ADMIN_PERMISSION_NOT_FOUND");
|
|
59
|
+
return rowToAdminPermission(row);
|
|
60
|
+
}
|
|
61
|
+
function ownerPermissions(roleId) {
|
|
62
|
+
return adminPermissionActions.map((action) => ({
|
|
63
|
+
id: `${roleId}:${action}`,
|
|
64
|
+
roleId,
|
|
65
|
+
action,
|
|
66
|
+
allowed: true,
|
|
67
|
+
}));
|
|
68
|
+
}
|
|
69
|
+
function rowToAdminPermission(row) {
|
|
70
|
+
return { id: row.id, roleId: row.roleId, action: row.action, allowed: Boolean(row.allowed) };
|
|
71
|
+
}
|
|
72
|
+
function adminPermissionSelectSql(suffix) {
|
|
73
|
+
return `SELECT id, role_id as roleId, action, allowed FROM admin_permissions ${suffix}`;
|
|
74
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export type AdminPermissionAction = "schemas" | "entries" | "apiRoles" | "apiUsers" | "settings";
|
|
2
|
+
export type SetAdminPermissionInput = {
|
|
3
|
+
roleId: string;
|
|
4
|
+
action: AdminPermissionAction;
|
|
5
|
+
allowed: boolean;
|
|
6
|
+
};
|
|
7
|
+
export type AdminPermissionRecord = SetAdminPermissionInput & {
|
|
8
|
+
id: string;
|
|
9
|
+
};
|
|
10
|
+
//# sourceMappingURL=admin-permission-repository.type.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"admin-permission-repository.type.d.ts","sourceRoot":"","sources":["../src/admin-permission-repository.type.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,qBAAqB,GAC7B,SAAS,GACT,SAAS,GACT,UAAU,GACV,UAAU,GACV,UAAU,CAAC;AAEf,MAAM,MAAM,uBAAuB,GAAG;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,qBAAqB,CAAC;IAC9B,OAAO,EAAE,OAAO,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG,uBAAuB,GAAG;IAC5D,EAAE,EAAE,MAAM,CAAC;CACZ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { SqliteDatabase } from "./sqlite.js";
|
|
2
|
+
import type { ApiTokenRecord, CreatedApiToken, CreateApiTokenInput } from "./api-token-repository.type.js";
|
|
3
|
+
export declare function createApiToken(db: SqliteDatabase, input: CreateApiTokenInput): CreatedApiToken;
|
|
4
|
+
export declare function listApiTokens(db: SqliteDatabase, roleId: string): ApiTokenRecord[];
|
|
5
|
+
export declare function revokeApiToken(db: SqliteDatabase, roleId: string, tokenId: string): ApiTokenRecord | undefined;
|
|
6
|
+
export declare function resolveApiToken(db: SqliteDatabase, token: string): ApiTokenRecord | undefined;
|
|
7
|
+
//# sourceMappingURL=api-token-repository.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-token-repository.d.ts","sourceRoot":"","sources":["../src/api-token-repository.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,OAAO,KAAK,EACV,cAAc,EACd,eAAe,EACf,mBAAmB,EACpB,MAAM,gCAAgC,CAAC;AAaxC,wBAAgB,cAAc,CAAC,EAAE,EAAE,cAAc,EAAE,KAAK,EAAE,mBAAmB,GAAG,eAAe,CAW9F;AAED,wBAAgB,aAAa,CAAC,EAAE,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,GAAG,cAAc,EAAE,CAMlF;AAED,wBAAgB,cAAc,CAC5B,EAAE,EAAE,cAAc,EAClB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,GACd,cAAc,GAAG,SAAS,CAM5B;AAED,wBAAgB,eAAe,CAAC,EAAE,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS,CAQ7F"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { createHash, randomBytes, randomUUID } from "node:crypto";
|
|
2
|
+
import { getRoleById } from "./role-repository.js";
|
|
3
|
+
export function createApiToken(db, input) {
|
|
4
|
+
requireApiRole(db, input.roleId);
|
|
5
|
+
const token = `agx_${randomBytes(32).toString("base64url")}`;
|
|
6
|
+
const id = randomUUID();
|
|
7
|
+
const now = new Date().toISOString();
|
|
8
|
+
db.prepare(`INSERT INTO api_tokens
|
|
9
|
+
(id, role_id, name, token_hash, token_prefix, created_at, last_used_at, revoked_at)
|
|
10
|
+
VALUES (?, ?, ?, ?, ?, ?, NULL, NULL)`).run(id, input.roleId, normalizeTokenName(input.name), hashToken(token), token.slice(0, 12), now);
|
|
11
|
+
return { token, tokenRecord: requireApiToken(db, id) };
|
|
12
|
+
}
|
|
13
|
+
export function listApiTokens(db, roleId) {
|
|
14
|
+
requireApiRole(db, roleId);
|
|
15
|
+
const rows = db
|
|
16
|
+
.prepare(tokenSelectSql("WHERE api_tokens.role_id = ? ORDER BY api_tokens.created_at DESC"))
|
|
17
|
+
.all(roleId);
|
|
18
|
+
return rows.map(rowToApiToken);
|
|
19
|
+
}
|
|
20
|
+
export function revokeApiToken(db, roleId, tokenId) {
|
|
21
|
+
requireApiRole(db, roleId);
|
|
22
|
+
const now = new Date().toISOString();
|
|
23
|
+
db.prepare("UPDATE api_tokens SET revoked_at = COALESCE(revoked_at, ?) WHERE id = ? AND role_id = ?")
|
|
24
|
+
.run(now, tokenId, roleId);
|
|
25
|
+
return getApiTokenById(db, tokenId, roleId);
|
|
26
|
+
}
|
|
27
|
+
export function resolveApiToken(db, token) {
|
|
28
|
+
const row = db
|
|
29
|
+
.prepare(tokenSelectSql("WHERE api_tokens.token_hash = ? AND api_tokens.revoked_at IS NULL AND roles.role_kind = 'api'"))
|
|
30
|
+
.get(hashToken(token));
|
|
31
|
+
if (!row)
|
|
32
|
+
return undefined;
|
|
33
|
+
db.prepare("UPDATE api_tokens SET last_used_at = ? WHERE id = ?")
|
|
34
|
+
.run(new Date().toISOString(), row.id);
|
|
35
|
+
return getApiTokenById(db, row.id);
|
|
36
|
+
}
|
|
37
|
+
function getApiTokenById(db, tokenId, roleId) {
|
|
38
|
+
const suffix = roleId ? "WHERE api_tokens.id = ? AND api_tokens.role_id = ?" : "WHERE api_tokens.id = ?";
|
|
39
|
+
const params = roleId ? [tokenId, roleId] : [tokenId];
|
|
40
|
+
const row = db.prepare(tokenSelectSql(suffix)).get(...params);
|
|
41
|
+
return row ? rowToApiToken(row) : undefined;
|
|
42
|
+
}
|
|
43
|
+
function requireApiToken(db, tokenId) {
|
|
44
|
+
const token = getApiTokenById(db, tokenId);
|
|
45
|
+
if (!token)
|
|
46
|
+
throw new Error("API_TOKEN_NOT_FOUND");
|
|
47
|
+
return token;
|
|
48
|
+
}
|
|
49
|
+
function requireApiRole(db, roleId) {
|
|
50
|
+
const role = getRoleById(db, roleId);
|
|
51
|
+
if (!role)
|
|
52
|
+
throw new Error("ROLE_NOT_FOUND");
|
|
53
|
+
if (role.roleKind !== "api")
|
|
54
|
+
throw new Error("ROLE_API_REQUIRED");
|
|
55
|
+
}
|
|
56
|
+
function normalizeTokenName(name) {
|
|
57
|
+
const normalized = name?.trim() || "API token";
|
|
58
|
+
if (normalized.length > 80)
|
|
59
|
+
throw new Error("API_TOKEN_NAME_TOO_LONG");
|
|
60
|
+
return normalized;
|
|
61
|
+
}
|
|
62
|
+
function hashToken(token) {
|
|
63
|
+
return createHash("sha256").update(token).digest("hex");
|
|
64
|
+
}
|
|
65
|
+
function rowToApiToken(row) {
|
|
66
|
+
return row;
|
|
67
|
+
}
|
|
68
|
+
function tokenSelectSql(suffix) {
|
|
69
|
+
return `SELECT api_tokens.id,
|
|
70
|
+
api_tokens.role_id as roleId,
|
|
71
|
+
roles.name as roleName,
|
|
72
|
+
api_tokens.name,
|
|
73
|
+
api_tokens.token_prefix as tokenPrefix,
|
|
74
|
+
api_tokens.created_at as createdAt,
|
|
75
|
+
api_tokens.last_used_at as lastUsedAt,
|
|
76
|
+
api_tokens.revoked_at as revokedAt
|
|
77
|
+
FROM api_tokens
|
|
78
|
+
JOIN roles ON roles.id = api_tokens.role_id
|
|
79
|
+
${suffix}`;
|
|
80
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export type ApiTokenRecord = {
|
|
2
|
+
id: string;
|
|
3
|
+
roleId: string;
|
|
4
|
+
roleName: string;
|
|
5
|
+
name: string;
|
|
6
|
+
tokenPrefix: string;
|
|
7
|
+
createdAt: string;
|
|
8
|
+
lastUsedAt: string | null;
|
|
9
|
+
revokedAt: string | null;
|
|
10
|
+
};
|
|
11
|
+
export type CreateApiTokenInput = {
|
|
12
|
+
roleId: string;
|
|
13
|
+
name?: string | undefined;
|
|
14
|
+
};
|
|
15
|
+
export type CreatedApiToken = {
|
|
16
|
+
token: string;
|
|
17
|
+
tokenRecord: ApiTokenRecord;
|
|
18
|
+
};
|
|
19
|
+
//# sourceMappingURL=api-token-repository.type.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-token-repository.type.d.ts","sourceRoot":"","sources":["../src/api-token-repository.type.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,cAAc,GAAG;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,cAAc,CAAC;CAC7B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { SqliteDatabase } from "./sqlite.js";
|
|
2
|
+
import type { EntryListOptions, EntryListResult } from "./entry-repository.type.js";
|
|
3
|
+
export declare function queryEntries(db: SqliteDatabase, schemaId: string, options?: EntryListOptions): EntryListResult;
|
|
4
|
+
//# sourceMappingURL=entry-query.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entry-query.d.ts","sourceRoot":"","sources":["../src/entry-query.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,OAAO,KAAK,EAEV,gBAAgB,EAChB,eAAe,EAEhB,MAAM,4BAA4B,CAAC;AAWpC,wBAAgB,YAAY,CAC1B,EAAE,EAAE,cAAc,EAClB,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,gBAAqB,GAC7B,eAAe,CAoBjB"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { getSchemaById } from "./schema-repository.js";
|
|
2
|
+
export function queryEntries(db, schemaId, options = {}) {
|
|
3
|
+
const schema = requireSchema(db, schemaId);
|
|
4
|
+
const limit = clampListLimit(options.limit);
|
|
5
|
+
const offset = Math.max(0, Math.floor(options.offset ?? 0));
|
|
6
|
+
const search = options.search?.trim() ?? "";
|
|
7
|
+
const selectedFields = validateSelectedFields(schema, options.fields);
|
|
8
|
+
const where = search ? "WHERE schema_id = ? AND (data_json LIKE ? OR id LIKE ?)" : "WHERE schema_id = ?";
|
|
9
|
+
const params = search ? [schemaId, `%${search}%`, `%${search}%`] : [schemaId];
|
|
10
|
+
const totalRow = db.prepare(`SELECT COUNT(*) as total FROM entries ${where}`).get(...params);
|
|
11
|
+
const rows = db.prepare(`${entrySelectSql(where)} ORDER BY created_at DESC LIMIT ? OFFSET ?`).all(...params, limit, offset);
|
|
12
|
+
return {
|
|
13
|
+
entries: rows.map((row) => projectEntry(rowToEntry(row), selectedFields)),
|
|
14
|
+
limit,
|
|
15
|
+
offset,
|
|
16
|
+
total: totalRow.total,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
function clampListLimit(value) {
|
|
20
|
+
if (value === undefined || !Number.isFinite(value))
|
|
21
|
+
return 50;
|
|
22
|
+
return Math.min(100, Math.max(1, Math.floor(value)));
|
|
23
|
+
}
|
|
24
|
+
function validateSelectedFields(schema, fields) {
|
|
25
|
+
const selected = fields?.map((field) => field.trim()).filter(Boolean);
|
|
26
|
+
if (!selected || selected.length === 0)
|
|
27
|
+
return undefined;
|
|
28
|
+
const allowed = new Set(schema.fields.map((field) => field.slug));
|
|
29
|
+
for (const field of selected) {
|
|
30
|
+
if (!allowed.has(field))
|
|
31
|
+
throw new Error("ENTRY_FIELD_UNKNOWN");
|
|
32
|
+
}
|
|
33
|
+
return [...new Set(selected)];
|
|
34
|
+
}
|
|
35
|
+
function projectEntry(entry, fields) {
|
|
36
|
+
if (!fields)
|
|
37
|
+
return entry;
|
|
38
|
+
const data = {};
|
|
39
|
+
for (const field of fields) {
|
|
40
|
+
data[field] = entry.data[field];
|
|
41
|
+
}
|
|
42
|
+
return { ...entry, data };
|
|
43
|
+
}
|
|
44
|
+
function requireSchema(db, schemaId) {
|
|
45
|
+
const schema = getSchemaById(db, schemaId);
|
|
46
|
+
if (!schema)
|
|
47
|
+
throw new Error("SCHEMA_NOT_FOUND");
|
|
48
|
+
return schema;
|
|
49
|
+
}
|
|
50
|
+
function rowToEntry(row) {
|
|
51
|
+
return {
|
|
52
|
+
id: row.id,
|
|
53
|
+
schemaId: row.schemaId,
|
|
54
|
+
data: JSON.parse(row.dataJson),
|
|
55
|
+
createdAt: row.createdAt,
|
|
56
|
+
updatedAt: row.updatedAt,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
function entrySelectSql(where) {
|
|
60
|
+
return `SELECT id, schema_id as schemaId, data_json as dataJson, created_at as createdAt, updated_at as updatedAt FROM entries ${where}`;
|
|
61
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { SqliteDatabase } from "./sqlite.js";
|
|
2
|
+
import type { CreateEntryInput, EntryRecord, UpdateEntryInput } from "./entry-repository.type.js";
|
|
3
|
+
export declare function createEntry(db: SqliteDatabase, input: CreateEntryInput): EntryRecord;
|
|
4
|
+
export declare function listEntries(db: SqliteDatabase, schemaId: string): EntryRecord[];
|
|
5
|
+
export declare function getEntryById(db: SqliteDatabase, id: string): EntryRecord | undefined;
|
|
6
|
+
export declare function updateEntry(db: SqliteDatabase, id: string, input: UpdateEntryInput): EntryRecord;
|
|
7
|
+
export declare function deleteEntry(db: SqliteDatabase, id: string): void;
|
|
8
|
+
//# sourceMappingURL=entry-repository.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entry-repository.d.ts","sourceRoot":"","sources":["../src/entry-repository.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,OAAO,KAAK,EAAE,gBAAgB,EAAa,WAAW,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAK7G,wBAAgB,WAAW,CAAC,EAAE,EAAE,cAAc,EAAE,KAAK,EAAE,gBAAgB,GAAG,WAAW,CAUpF;AAED,wBAAgB,WAAW,CAAC,EAAE,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,GAAG,WAAW,EAAE,CAQ/E;AAED,wBAAgB,YAAY,CAAC,EAAE,EAAE,cAAc,EAAE,EAAE,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,CAGpF;AAED,wBAAgB,WAAW,CAAC,EAAE,EAAE,cAAc,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,gBAAgB,GAAG,WAAW,CAYhG;AAED,wBAAgB,WAAW,CAAC,EAAE,EAAE,cAAc,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI,CAIhE"}
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { relationEntryReferenced, relationOneToOneConflict, relationTargetEntryInvalid, relationValueShapeInvalid, } from "./relation-errors.js";
|
|
3
|
+
import { entryDataReferences, listEntryDataRows, parseEntryData, relationTypeOf, } from "./relation-helpers.js";
|
|
4
|
+
import { getSchemaById } from "./schema-repository.js";
|
|
5
|
+
export function createEntry(db, input) {
|
|
6
|
+
const schema = requireSchema(db, input.schemaId);
|
|
7
|
+
validateEntryData(db, schema, input.data);
|
|
8
|
+
const normalizedData = normalizeEntryData(schema, input.data);
|
|
9
|
+
const id = randomUUID();
|
|
10
|
+
const now = new Date().toISOString();
|
|
11
|
+
db.prepare("INSERT INTO entries (id, schema_id, data_json, created_at, updated_at) VALUES (?, ?, ?, ?, ?)").run(id, input.schemaId, JSON.stringify(normalizedData), now, now);
|
|
12
|
+
return requireEntry(db, id);
|
|
13
|
+
}
|
|
14
|
+
export function listEntries(db, schemaId) {
|
|
15
|
+
requireSchema(db, schemaId);
|
|
16
|
+
const rows = db
|
|
17
|
+
.prepare("SELECT id, schema_id as schemaId, data_json as dataJson, created_at as createdAt, updated_at as updatedAt FROM entries WHERE schema_id = ? ORDER BY created_at ASC")
|
|
18
|
+
.all(schemaId);
|
|
19
|
+
return rows.map(rowToEntry);
|
|
20
|
+
}
|
|
21
|
+
export function getEntryById(db, id) {
|
|
22
|
+
const row = db.prepare(entrySelectSql("WHERE id = ?")).get(id);
|
|
23
|
+
return row ? rowToEntry(row) : undefined;
|
|
24
|
+
}
|
|
25
|
+
export function updateEntry(db, id, input) {
|
|
26
|
+
const current = requireEntry(db, id);
|
|
27
|
+
const schema = requireSchema(db, current.schemaId);
|
|
28
|
+
validateEntryData(db, schema, input.data, id);
|
|
29
|
+
const normalizedData = normalizeEntryData(schema, input.data);
|
|
30
|
+
const now = new Date().toISOString();
|
|
31
|
+
db.prepare("UPDATE entries SET data_json = ?, updated_at = ? WHERE id = ?").run(JSON.stringify(normalizedData), now, id);
|
|
32
|
+
return requireEntry(db, id);
|
|
33
|
+
}
|
|
34
|
+
export function deleteEntry(db, id) {
|
|
35
|
+
assertEntryNotReferenced(db, id);
|
|
36
|
+
const result = db.prepare("DELETE FROM entries WHERE id = ?").run(id);
|
|
37
|
+
if (result.changes === 0)
|
|
38
|
+
throw new Error("ENTRY_NOT_FOUND");
|
|
39
|
+
}
|
|
40
|
+
function assertEntryNotReferenced(db, entryId) {
|
|
41
|
+
const rows = listEntryDataRows(db);
|
|
42
|
+
for (const row of rows) {
|
|
43
|
+
if (row.id === entryId)
|
|
44
|
+
continue;
|
|
45
|
+
if (entryDataReferences(parseEntryData(row.dataJson), entryId)) {
|
|
46
|
+
throw new Error(relationEntryReferenced(entryId));
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
function validateEntryData(db, schema, data, currentEntryId) {
|
|
51
|
+
if (!isRecord(data))
|
|
52
|
+
throw new Error("ENTRY_DATA_INVALID");
|
|
53
|
+
const fieldSlugs = new Set(schema.fields.map((field) => field.slug));
|
|
54
|
+
for (const key of Object.keys(data)) {
|
|
55
|
+
if (!fieldSlugs.has(key))
|
|
56
|
+
throw new Error("ENTRY_FIELD_UNKNOWN");
|
|
57
|
+
}
|
|
58
|
+
for (const field of schema.fields) {
|
|
59
|
+
const value = data[field.slug];
|
|
60
|
+
if (field.required && isMissing(value)) {
|
|
61
|
+
throw new Error(`ENTRY_FIELD_REQUIRED:${field.slug}`);
|
|
62
|
+
}
|
|
63
|
+
if (!isMissing(value)) {
|
|
64
|
+
validateFieldValue(db, schema, field, value, currentEntryId);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
function validateFieldValue(db, schema, field, value, currentEntryId) {
|
|
69
|
+
if (field.type === "text" || field.type === "longText" || field.type === "media") {
|
|
70
|
+
assertType(field, typeof value === "string");
|
|
71
|
+
}
|
|
72
|
+
else if (field.type === "number") {
|
|
73
|
+
assertType(field, typeof value === "number" && Number.isFinite(value));
|
|
74
|
+
}
|
|
75
|
+
else if (field.type === "boolean") {
|
|
76
|
+
assertType(field, typeof value === "boolean");
|
|
77
|
+
}
|
|
78
|
+
else if (field.type === "date") {
|
|
79
|
+
assertType(field, typeof value === "string" && !Number.isNaN(Date.parse(value)));
|
|
80
|
+
}
|
|
81
|
+
else if (field.type === "relation") {
|
|
82
|
+
assertRelation(db, schema, field, value, currentEntryId);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
function assertRelation(db, schema, field, value, currentEntryId) {
|
|
86
|
+
const relationType = relationTypeOf(field);
|
|
87
|
+
if (relationType === "oneToMany" || relationType === "manyToMany") {
|
|
88
|
+
assertMultiRelation(db, field, value);
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
if (typeof value !== "string") {
|
|
92
|
+
throw new Error(relationValueShapeInvalid(field.slug));
|
|
93
|
+
}
|
|
94
|
+
const target = getEntryById(db, String(value));
|
|
95
|
+
if (!target || target.schemaId !== field.relationSchemaId) {
|
|
96
|
+
throw new Error(relationTargetEntryInvalid(field.slug));
|
|
97
|
+
}
|
|
98
|
+
if (relationType === "oneToOne") {
|
|
99
|
+
assertOneToOneAvailable(db, schema, field, value, currentEntryId);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
function assertMultiRelation(db, field, value) {
|
|
103
|
+
if (!Array.isArray(value)) {
|
|
104
|
+
throw new Error(relationValueShapeInvalid(field.slug));
|
|
105
|
+
}
|
|
106
|
+
if (field.required && value.length === 0) {
|
|
107
|
+
throw new Error(`ENTRY_FIELD_REQUIRED:${field.slug}`);
|
|
108
|
+
}
|
|
109
|
+
const seen = new Set();
|
|
110
|
+
for (const targetEntryId of value) {
|
|
111
|
+
if (typeof targetEntryId !== "string") {
|
|
112
|
+
throw new Error(relationValueShapeInvalid(field.slug));
|
|
113
|
+
}
|
|
114
|
+
if (seen.has(targetEntryId))
|
|
115
|
+
continue;
|
|
116
|
+
seen.add(targetEntryId);
|
|
117
|
+
const target = getEntryById(db, targetEntryId);
|
|
118
|
+
if (!target || target.schemaId !== field.relationSchemaId) {
|
|
119
|
+
throw new Error(relationTargetEntryInvalid(field.slug));
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
function normalizeEntryData(schema, data) {
|
|
124
|
+
const normalized = { ...data };
|
|
125
|
+
for (const field of schema.fields) {
|
|
126
|
+
if (field.type !== "relation")
|
|
127
|
+
continue;
|
|
128
|
+
const value = normalized[field.slug];
|
|
129
|
+
if (isMissing(value))
|
|
130
|
+
continue;
|
|
131
|
+
const relationType = relationTypeOf(field);
|
|
132
|
+
if (relationType === "oneToMany" || relationType === "manyToMany") {
|
|
133
|
+
normalized[field.slug] = Array.isArray(value) ? [...new Set(value)] : value;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return normalized;
|
|
137
|
+
}
|
|
138
|
+
function assertOneToOneAvailable(db, schema, field, targetEntryId, currentEntryId) {
|
|
139
|
+
const rows = listEntryDataRows(db, "WHERE schema_id = ?", [schema.id]);
|
|
140
|
+
for (const row of rows) {
|
|
141
|
+
if (row.id === currentEntryId)
|
|
142
|
+
continue;
|
|
143
|
+
const data = parseEntryData(row.dataJson);
|
|
144
|
+
if (data[field.slug] === targetEntryId)
|
|
145
|
+
throw new Error(relationOneToOneConflict(field.slug));
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
function assertType(field, valid) {
|
|
149
|
+
if (!valid)
|
|
150
|
+
throw new Error(`ENTRY_FIELD_TYPE_INVALID:${field.slug}`);
|
|
151
|
+
}
|
|
152
|
+
function isMissing(value) {
|
|
153
|
+
return value === undefined || value === null || value === "";
|
|
154
|
+
}
|
|
155
|
+
function isRecord(value) {
|
|
156
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
157
|
+
}
|
|
158
|
+
function requireSchema(db, schemaId) {
|
|
159
|
+
const schema = getSchemaById(db, schemaId);
|
|
160
|
+
if (!schema)
|
|
161
|
+
throw new Error("SCHEMA_NOT_FOUND");
|
|
162
|
+
return schema;
|
|
163
|
+
}
|
|
164
|
+
function requireEntry(db, id) {
|
|
165
|
+
const entry = getEntryById(db, id);
|
|
166
|
+
if (!entry)
|
|
167
|
+
throw new Error("ENTRY_NOT_FOUND");
|
|
168
|
+
return entry;
|
|
169
|
+
}
|
|
170
|
+
function rowToEntry(row) {
|
|
171
|
+
return {
|
|
172
|
+
id: row.id,
|
|
173
|
+
schemaId: row.schemaId,
|
|
174
|
+
data: JSON.parse(row.dataJson),
|
|
175
|
+
createdAt: row.createdAt,
|
|
176
|
+
updatedAt: row.updatedAt,
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
function entrySelectSql(where) {
|
|
180
|
+
return `SELECT id, schema_id as schemaId, data_json as dataJson, created_at as createdAt, updated_at as updatedAt FROM entries ${where}`;
|
|
181
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export type SingleRelationEntryValue = string | null;
|
|
2
|
+
export type MultiRelationEntryValue = string[];
|
|
3
|
+
export type RelationEntryValue = SingleRelationEntryValue | MultiRelationEntryValue;
|
|
4
|
+
export type EntryFieldValue = boolean | number | string | null | Record<string, unknown> | unknown[] | RelationEntryValue;
|
|
5
|
+
export type EntryData = Record<string, EntryFieldValue | undefined>;
|
|
6
|
+
export type CreateEntryInput = {
|
|
7
|
+
schemaId: string;
|
|
8
|
+
data: EntryData;
|
|
9
|
+
};
|
|
10
|
+
export type UpdateEntryInput = {
|
|
11
|
+
data: EntryData;
|
|
12
|
+
};
|
|
13
|
+
export type EntryListOptions = {
|
|
14
|
+
fields?: string[];
|
|
15
|
+
limit?: number;
|
|
16
|
+
offset?: number;
|
|
17
|
+
search?: string;
|
|
18
|
+
};
|
|
19
|
+
export type EntryListResult = {
|
|
20
|
+
entries: EntryRecord[];
|
|
21
|
+
limit: number;
|
|
22
|
+
offset: number;
|
|
23
|
+
total: number;
|
|
24
|
+
};
|
|
25
|
+
export type EntryRecord = {
|
|
26
|
+
id: string;
|
|
27
|
+
schemaId: string;
|
|
28
|
+
data: EntryData;
|
|
29
|
+
createdAt: string;
|
|
30
|
+
updatedAt: string;
|
|
31
|
+
};
|
|
32
|
+
//# sourceMappingURL=entry-repository.type.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entry-repository.type.d.ts","sourceRoot":"","sources":["../src/entry-repository.type.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,wBAAwB,GAAG,MAAM,GAAG,IAAI,CAAC;AAErD,MAAM,MAAM,uBAAuB,GAAG,MAAM,EAAE,CAAC;AAE/C,MAAM,MAAM,kBAAkB,GAAG,wBAAwB,GAAG,uBAAuB,CAAC;AAEpF,MAAM,MAAM,eAAe,GACvB,OAAO,GACP,MAAM,GACN,MAAM,GACN,IAAI,GACJ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACvB,OAAO,EAAE,GACT,kBAAkB,CAAC;AAEvB,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,eAAe,GAAG,SAAS,CAAC,CAAC;AAEpE,MAAM,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,SAAS,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,EAAE,SAAS,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,SAAS,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export { MVP_FOUNDATION_SQL, MVP_MIGRATION_ID, MVP_TABLES, } from "./migrations.js";
|
|
2
|
+
export { listMvpTables, migrateMvpDatabase, openSqliteDatabase, } from "./sqlite.js";
|
|
3
|
+
export { createEntry, deleteEntry, getEntryById, listEntries, updateEntry, } from "./entry-repository.js";
|
|
4
|
+
export { queryEntries } from "./entry-query.js";
|
|
5
|
+
export { createAdminRole, createRole, getRoleById, listAdminRoles, listRoles, } from "./role-repository.js";
|
|
6
|
+
export { createApiToken, listApiTokens, resolveApiToken, revokeApiToken, } from "./api-token-repository.js";
|
|
7
|
+
export { consumeRealtimeSession, createRealtimeSession, } from "./realtime-session-repository.js";
|
|
8
|
+
export { countWebhookDeliveryAttempts, createWebhook, deleteWebhook, enqueueWebhookEvent, hasSuccessfulWebhookDelivery, listMatchingWebhooks, listPendingWebhookEvents, listWebhookDeliveries, listWebhooks, recordWebhookDelivery, updateWebhook, updateWebhookEventStatus, } from "./webhook-repository.js";
|
|
9
|
+
export { getRealtimeConfig, isRealtimeEventEnabled, listRealtimeEventsAfter, listRealtimeConfigs, listRealtimeSettings, listRecentRealtimeEvents, pruneRealtimeEvents, recordRealtimeEvent, setRealtimeConfig, } from "./realtime-repository.js";
|
|
10
|
+
export { adminPermissionActions, canAdminRoleAccess, listAdminRolePermissions, setAdminPermission, } from "./admin-permission-repository.js";
|
|
11
|
+
export { canRoleAccess, listRolePermissions, setPermission, } from "./permission-repository.js";
|
|
12
|
+
export { createUser, getUserById, getUserPasswordHashByEmail, listUsers, } from "./user-repository.js";
|
|
13
|
+
export { createSchema, deleteSchema, getSchemaById, getSchemaBySlug, listSchemas, updateSchema, } from "./schema-repository.js";
|
|
14
|
+
export { relationEntryReferenced, relationFieldUpdateUnsafe, relationOneToOneConflict, relationSchemaReferenced, relationErrors, relationTargetEntryInvalid, relationValueShapeInvalid, } from "./relation-errors.js";
|
|
15
|
+
export { entryDataReferences, listEntryDataRows, parseEntryData, relationTypeOf, schemaEntriesUseField, } from "./relation-helpers.js";
|
|
16
|
+
export type { MvpTableName, MigrationRecord, TableInfoRow } from "./schema.type.js";
|
|
17
|
+
export type { CreateEntryInput, EntryData, EntryFieldValue, EntryListOptions, EntryListResult, EntryRecord, MultiRelationEntryValue, RelationEntryValue, SingleRelationEntryValue, UpdateEntryInput, } from "./entry-repository.type.js";
|
|
18
|
+
export type { CreateRoleInput, RoleKind, RoleRecord } from "./role-repository.type.js";
|
|
19
|
+
export type { ApiTokenRecord, CreatedApiToken, CreateApiTokenInput, } from "./api-token-repository.type.js";
|
|
20
|
+
export type { CreatedRealtimeSession, CreateRealtimeSessionInput, RealtimeSessionRecord, } from "./realtime-session-repository.type.js";
|
|
21
|
+
export type { EnqueueWebhookEventInput, RecordWebhookDeliveryInput, WebhookDeliveryRecord, WebhookDeliveryStatus, WebhookDraft, WebhookEventRecord, WebhookEventStatus, WebhookEventType, WebhookPayload, WebhookRecord, WebhookSecretRecord, } from "./webhook-repository.type.js";
|
|
22
|
+
export type { RealtimeConfigRecord, RealtimeEventRecord, RealtimeEventType, RecordRealtimeEventInput, SetRealtimeConfigInput, } from "./realtime-repository.type.js";
|
|
23
|
+
export type { AdminPermissionAction, AdminPermissionRecord, SetAdminPermissionInput, } from "./admin-permission-repository.type.js";
|
|
24
|
+
export type { PermissionAction, PermissionRecord, SetPermissionInput, } from "./permission-repository.type.js";
|
|
25
|
+
export type { CreateUserInput, UserRecord } from "./user-repository.type.js";
|
|
26
|
+
export type { CreateFieldInput, CreateSchemaInput, FieldRecord, FieldType, MultiRelationValue, RelationFieldContract, RelationType, RelationValue, SchemaRecord, SingleRelationValue, UpdateSchemaInput, } from "./schema-repository.type.js";
|
|
27
|
+
export type { RelationErrorCode } from "./relation-errors.js";
|
|
28
|
+
export type { SqliteDatabase } from "./sqlite.js";
|
|
29
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export { MVP_FOUNDATION_SQL, MVP_MIGRATION_ID, MVP_TABLES, } from "./migrations.js";
|
|
2
|
+
export { listMvpTables, migrateMvpDatabase, openSqliteDatabase, } from "./sqlite.js";
|
|
3
|
+
export { createEntry, deleteEntry, getEntryById, listEntries, updateEntry, } from "./entry-repository.js";
|
|
4
|
+
export { queryEntries } from "./entry-query.js";
|
|
5
|
+
export { createAdminRole, createRole, getRoleById, listAdminRoles, listRoles, } from "./role-repository.js";
|
|
6
|
+
export { createApiToken, listApiTokens, resolveApiToken, revokeApiToken, } from "./api-token-repository.js";
|
|
7
|
+
export { consumeRealtimeSession, createRealtimeSession, } from "./realtime-session-repository.js";
|
|
8
|
+
export { countWebhookDeliveryAttempts, createWebhook, deleteWebhook, enqueueWebhookEvent, hasSuccessfulWebhookDelivery, listMatchingWebhooks, listPendingWebhookEvents, listWebhookDeliveries, listWebhooks, recordWebhookDelivery, updateWebhook, updateWebhookEventStatus, } from "./webhook-repository.js";
|
|
9
|
+
export { getRealtimeConfig, isRealtimeEventEnabled, listRealtimeEventsAfter, listRealtimeConfigs, listRealtimeSettings, listRecentRealtimeEvents, pruneRealtimeEvents, recordRealtimeEvent, setRealtimeConfig, } from "./realtime-repository.js";
|
|
10
|
+
export { adminPermissionActions, canAdminRoleAccess, listAdminRolePermissions, setAdminPermission, } from "./admin-permission-repository.js";
|
|
11
|
+
export { canRoleAccess, listRolePermissions, setPermission, } from "./permission-repository.js";
|
|
12
|
+
export { createUser, getUserById, getUserPasswordHashByEmail, listUsers, } from "./user-repository.js";
|
|
13
|
+
export { createSchema, deleteSchema, getSchemaById, getSchemaBySlug, listSchemas, updateSchema, } from "./schema-repository.js";
|
|
14
|
+
export { relationEntryReferenced, relationFieldUpdateUnsafe, relationOneToOneConflict, relationSchemaReferenced, relationErrors, relationTargetEntryInvalid, relationValueShapeInvalid, } from "./relation-errors.js";
|
|
15
|
+
export { entryDataReferences, listEntryDataRows, parseEntryData, relationTypeOf, schemaEntriesUseField, } from "./relation-helpers.js";
|