@apiagex/database 0.6.4 → 0.8.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/README.md +10 -6
- package/dist/admin-permission-repository.d.ts +4 -4
- package/dist/admin-permission-repository.d.ts.map +1 -1
- package/dist/admin-permission-repository.js +19 -17
- package/dist/api-token-repository.d.ts +5 -5
- package/dist/api-token-repository.d.ts.map +1 -1
- package/dist/api-token-repository.js +19 -20
- package/dist/database-adapter.type.d.ts +18 -0
- package/dist/database-adapter.type.d.ts.map +1 -0
- package/dist/database-adapter.type.js +1 -0
- package/dist/entry-query.d.ts +2 -2
- package/dist/entry-query.d.ts.map +1 -1
- package/dist/entry-query.js +8 -7
- package/dist/entry-repository.d.ts +6 -6
- package/dist/entry-repository.d.ts.map +1 -1
- package/dist/entry-repository.js +46 -56
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/mysql-adapter.d.ts +17 -0
- package/dist/mysql-adapter.d.ts.map +1 -0
- package/dist/mysql-adapter.js +63 -0
- package/dist/permission-repository.d.ts +4 -4
- package/dist/permission-repository.d.ts.map +1 -1
- package/dist/permission-repository.js +24 -38
- package/dist/postgres-adapter.d.ts +17 -0
- package/dist/postgres-adapter.d.ts.map +1 -0
- package/dist/postgres-adapter.js +61 -0
- package/dist/provider-migrations.d.ts +14 -0
- package/dist/provider-migrations.d.ts.map +1 -0
- package/dist/provider-migrations.js +198 -0
- package/dist/realtime-repository.d.ts +11 -11
- package/dist/realtime-repository.d.ts.map +1 -1
- package/dist/realtime-repository.js +37 -27
- package/dist/realtime-session-repository.d.ts +3 -3
- package/dist/realtime-session-repository.d.ts.map +1 -1
- package/dist/realtime-session-repository.js +11 -11
- package/dist/relation-helpers.d.ts +3 -3
- package/dist/relation-helpers.d.ts.map +1 -1
- package/dist/relation-helpers.js +4 -6
- package/dist/role-repository.d.ts +6 -6
- package/dist/role-repository.d.ts.map +1 -1
- package/dist/role-repository.js +17 -24
- package/dist/schema-repository.d.ts +7 -7
- package/dist/schema-repository.d.ts.map +1 -1
- package/dist/schema-repository.js +63 -88
- package/dist/sqlite-adapter.d.ts +15 -0
- package/dist/sqlite-adapter.d.ts.map +1 -0
- package/dist/sqlite-adapter.js +48 -0
- package/dist/user-repository.d.ts +8 -6
- package/dist/user-repository.d.ts.map +1 -1
- package/dist/user-repository.js +17 -27
- package/dist/webhook-repository.d.ts +13 -13
- package/dist/webhook-repository.d.ts.map +1 -1
- package/dist/webhook-repository.js +47 -43
- package/package.json +6 -3
package/README.md
CHANGED
|
@@ -2,24 +2,28 @@
|
|
|
2
2
|
|
|
3
3
|
## English
|
|
4
4
|
|
|
5
|
-
This package owns the database adapter contract for Apiagex.
|
|
5
|
+
This package owns the database adapter contract for Apiagex. SQLite is backed by `better-sqlite3` and remains the default local database. PostgreSQL is available through `pg` when `APIAGEX_DATABASE_PROVIDER=postgres` and `APIAGEX_DATABASE_URL` is set. MySQL is available through `mysql2` when `APIAGEX_DATABASE_PROVIDER=mysql` and `APIAGEX_DATABASE_URL` is set.
|
|
6
6
|
|
|
7
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
8
|
|
|
9
9
|
```ts
|
|
10
|
-
import {
|
|
10
|
+
import { openMigratedSqliteAdapter, openMySqlAdapter, openPostgresAdapter } from '@apiagex/database';
|
|
11
11
|
|
|
12
|
-
const
|
|
12
|
+
const sqlite = openMigratedSqliteAdapter('./data/apiagex.db');
|
|
13
|
+
const postgres = await openPostgresAdapter(process.env.APIAGEX_DATABASE_URL);
|
|
14
|
+
const mysql = await openMySqlAdapter(process.env.APIAGEX_DATABASE_URL);
|
|
13
15
|
```
|
|
14
16
|
|
|
15
17
|
## Hindi
|
|
16
18
|
|
|
17
|
-
Ye package Apiagex ke database adapter contract ka owner hai.
|
|
19
|
+
Ye package Apiagex ke database adapter contract ka owner hai. SQLite default hai aur `better-sqlite3` par chalta hai. PostgreSQL `pg` driver ke through real runtime provider hai jab `APIAGEX_DATABASE_PROVIDER=postgres` aur `APIAGEX_DATABASE_URL` set ho. MySQL `mysql2` driver ke through real runtime provider hai jab `APIAGEX_DATABASE_PROVIDER=mysql` aur `APIAGEX_DATABASE_URL` set ho.
|
|
18
20
|
|
|
19
21
|
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
22
|
|
|
21
23
|
```ts
|
|
22
|
-
import {
|
|
24
|
+
import { openMigratedSqliteAdapter, openMySqlAdapter, openPostgresAdapter } from '@apiagex/database';
|
|
23
25
|
|
|
24
|
-
const
|
|
26
|
+
const sqlite = openMigratedSqliteAdapter('./data/apiagex.db');
|
|
27
|
+
const postgres = await openPostgresAdapter(process.env.APIAGEX_DATABASE_URL);
|
|
28
|
+
const mysql = await openMySqlAdapter(process.env.APIAGEX_DATABASE_URL);
|
|
25
29
|
```
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ApiagexDatabase } from "./database-adapter.type.js";
|
|
2
2
|
import type { AdminPermissionAction, AdminPermissionRecord, SetAdminPermissionInput } from "./admin-permission-repository.type.js";
|
|
3
3
|
export declare const adminPermissionActions: AdminPermissionAction[];
|
|
4
|
-
export declare function setAdminPermission(db:
|
|
5
|
-
export declare function listAdminRolePermissions(db:
|
|
6
|
-
export declare function canAdminRoleAccess(db:
|
|
4
|
+
export declare function setAdminPermission(db: ApiagexDatabase, input: SetAdminPermissionInput): Promise<AdminPermissionRecord>;
|
|
5
|
+
export declare function listAdminRolePermissions(db: ApiagexDatabase, roleId: string): Promise<AdminPermissionRecord[]>;
|
|
6
|
+
export declare function canAdminRoleAccess(db: ApiagexDatabase, roleId: string, action: AdminPermissionAction): Promise<boolean>;
|
|
7
7
|
//# sourceMappingURL=admin-permission-repository.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"admin-permission-repository.d.ts","sourceRoot":"","sources":["../src/admin-permission-repository.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"admin-permission-repository.d.ts","sourceRoot":"","sources":["../src/admin-permission-repository.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAClE,OAAO,KAAK,EACV,qBAAqB,EACrB,qBAAqB,EACrB,uBAAuB,EACxB,MAAM,uCAAuC,CAAC;AAK/C,eAAO,MAAM,sBAAsB,EAAE,qBAAqB,EAMzD,CAAC;AAEF,wBAAsB,kBAAkB,CACtC,EAAE,EAAE,eAAe,EACnB,KAAK,EAAE,uBAAuB,GAC7B,OAAO,CAAC,qBAAqB,CAAC,CAYhC;AAED,wBAAsB,wBAAwB,CAC5C,EAAE,EAAE,eAAe,EACnB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,qBAAqB,EAAE,CAAC,CAOlC;AAED,wBAAsB,kBAAkB,CACtC,EAAE,EAAE,eAAe,EACnB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,qBAAqB,GAC5B,OAAO,CAAC,OAAO,CAAC,CAKlB"}
|
|
@@ -7,38 +7,40 @@ export const adminPermissionActions = [
|
|
|
7
7
|
"apiUsers",
|
|
8
8
|
"settings",
|
|
9
9
|
];
|
|
10
|
-
export function setAdminPermission(db, input) {
|
|
11
|
-
validateAdminPermissionInput(db, input);
|
|
12
|
-
const existing = findAdminPermission(db, input.roleId, input.action);
|
|
10
|
+
export async function setAdminPermission(db, input) {
|
|
11
|
+
await validateAdminPermissionInput(db, input);
|
|
12
|
+
const existing = await findAdminPermission(db, input.roleId, input.action);
|
|
13
13
|
if (existing) {
|
|
14
|
-
db.prepare("UPDATE admin_permissions SET allowed = ? WHERE id = ?")
|
|
14
|
+
await db.prepare("UPDATE admin_permissions SET allowed = ? WHERE id = ?")
|
|
15
|
+
.run(input.allowed ? 1 : 0, existing.id);
|
|
15
16
|
return requireAdminPermission(db, existing.id);
|
|
16
17
|
}
|
|
17
18
|
const id = randomUUID();
|
|
18
|
-
db.prepare("INSERT INTO admin_permissions (id, role_id, action, allowed) VALUES (?, ?, ?, ?)")
|
|
19
|
+
await db.prepare("INSERT INTO admin_permissions (id, role_id, action, allowed) VALUES (?, ?, ?, ?)")
|
|
20
|
+
.run(id, input.roleId, input.action, input.allowed ? 1 : 0);
|
|
19
21
|
return requireAdminPermission(db, id);
|
|
20
22
|
}
|
|
21
|
-
export function listAdminRolePermissions(db, roleId) {
|
|
22
|
-
const role = getRoleById(db, roleId);
|
|
23
|
+
export async function listAdminRolePermissions(db, roleId) {
|
|
24
|
+
const role = await getRoleById(db, roleId);
|
|
23
25
|
if (role?.isOwner)
|
|
24
26
|
return ownerPermissions(roleId);
|
|
25
|
-
const rows = db
|
|
27
|
+
const rows = await db
|
|
26
28
|
.prepare(adminPermissionSelectSql("WHERE role_id = ? ORDER BY action ASC"))
|
|
27
29
|
.all(roleId);
|
|
28
30
|
return rows.map(rowToAdminPermission);
|
|
29
31
|
}
|
|
30
|
-
export function canAdminRoleAccess(db, roleId, action) {
|
|
31
|
-
const role = getRoleById(db, roleId);
|
|
32
|
+
export async function canAdminRoleAccess(db, roleId, action) {
|
|
33
|
+
const role = await getRoleById(db, roleId);
|
|
32
34
|
if (!role || role.roleKind !== "admin")
|
|
33
35
|
return false;
|
|
34
36
|
if (role.isOwner)
|
|
35
37
|
return true;
|
|
36
|
-
return Boolean(findAdminPermission(db, roleId, action)?.allowed);
|
|
38
|
+
return Boolean((await findAdminPermission(db, roleId, action))?.allowed);
|
|
37
39
|
}
|
|
38
|
-
function validateAdminPermissionInput(db, input) {
|
|
40
|
+
async function validateAdminPermissionInput(db, input) {
|
|
39
41
|
if (!adminPermissionActions.includes(input.action))
|
|
40
42
|
throw new Error("ADMIN_PERMISSION_ACTION_INVALID");
|
|
41
|
-
const role = getRoleById(db, input.roleId);
|
|
43
|
+
const role = await getRoleById(db, input.roleId);
|
|
42
44
|
if (!role)
|
|
43
45
|
throw new Error("ROLE_NOT_FOUND");
|
|
44
46
|
if (role.roleKind !== "admin")
|
|
@@ -46,14 +48,14 @@ function validateAdminPermissionInput(db, input) {
|
|
|
46
48
|
if (role.isOwner)
|
|
47
49
|
throw new Error("ROLE_OWNER_LOCKED");
|
|
48
50
|
}
|
|
49
|
-
function findAdminPermission(db, roleId, action) {
|
|
50
|
-
const row = db
|
|
51
|
+
async function findAdminPermission(db, roleId, action) {
|
|
52
|
+
const row = await db
|
|
51
53
|
.prepare(adminPermissionSelectSql("WHERE role_id = ? AND action = ?"))
|
|
52
54
|
.get(roleId, action);
|
|
53
55
|
return row ? rowToAdminPermission(row) : undefined;
|
|
54
56
|
}
|
|
55
|
-
function requireAdminPermission(db, id) {
|
|
56
|
-
const row = db.prepare(adminPermissionSelectSql("WHERE id = ?")).get(id);
|
|
57
|
+
async function requireAdminPermission(db, id) {
|
|
58
|
+
const row = await db.prepare(adminPermissionSelectSql("WHERE id = ?")).get(id);
|
|
57
59
|
if (!row)
|
|
58
60
|
throw new Error("ADMIN_PERMISSION_NOT_FOUND");
|
|
59
61
|
return rowToAdminPermission(row);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ApiagexDatabase } from "./database-adapter.type.js";
|
|
2
2
|
import type { ApiTokenRecord, CreatedApiToken, CreateApiTokenInput } from "./api-token-repository.type.js";
|
|
3
|
-
export declare function createApiToken(db:
|
|
4
|
-
export declare function listApiTokens(db:
|
|
5
|
-
export declare function revokeApiToken(db:
|
|
6
|
-
export declare function resolveApiToken(db:
|
|
3
|
+
export declare function createApiToken(db: ApiagexDatabase, input: CreateApiTokenInput): Promise<CreatedApiToken>;
|
|
4
|
+
export declare function listApiTokens(db: ApiagexDatabase, roleId: string): Promise<ApiTokenRecord[]>;
|
|
5
|
+
export declare function revokeApiToken(db: ApiagexDatabase, roleId: string, tokenId: string): Promise<ApiTokenRecord | undefined>;
|
|
6
|
+
export declare function resolveApiToken(db: ApiagexDatabase, token: string): Promise<ApiTokenRecord | undefined>;
|
|
7
7
|
//# sourceMappingURL=api-token-repository.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api-token-repository.d.ts","sourceRoot":"","sources":["../src/api-token-repository.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"api-token-repository.d.ts","sourceRoot":"","sources":["../src/api-token-repository.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAsB,MAAM,4BAA4B,CAAC;AACtF,OAAO,KAAK,EACV,cAAc,EACd,eAAe,EACf,mBAAmB,EACpB,MAAM,gCAAgC,CAAC;AAcxC,wBAAsB,cAAc,CAAC,EAAE,EAAE,eAAe,EAAE,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,eAAe,CAAC,CAW9G;AAED,wBAAsB,aAAa,CAAC,EAAE,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CAMlG;AAED,wBAAsB,cAAc,CAClC,EAAE,EAAE,eAAe,EACnB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,cAAc,GAAG,SAAS,CAAC,CAMrC;AAED,wBAAsB,eAAe,CAAC,EAAE,EAAE,eAAe,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,SAAS,CAAC,CAO7G"}
|
|
@@ -1,53 +1,52 @@
|
|
|
1
1
|
import { createHash, randomBytes, randomUUID } from "node:crypto";
|
|
2
2
|
import { getRoleById } from "./role-repository.js";
|
|
3
|
-
export function createApiToken(db, input) {
|
|
4
|
-
requireApiRole(db, input.roleId);
|
|
3
|
+
export async function createApiToken(db, input) {
|
|
4
|
+
await requireApiRole(db, input.roleId);
|
|
5
5
|
const token = `agx_${randomBytes(32).toString("base64url")}`;
|
|
6
6
|
const id = randomUUID();
|
|
7
7
|
const now = new Date().toISOString();
|
|
8
|
-
db.prepare(`INSERT INTO api_tokens
|
|
8
|
+
await db.prepare(`INSERT INTO api_tokens
|
|
9
9
|
(id, role_id, name, token_hash, token_prefix, created_at, last_used_at, revoked_at)
|
|
10
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) };
|
|
11
|
+
return { token, tokenRecord: await requireApiToken(db, id) };
|
|
12
12
|
}
|
|
13
|
-
export function listApiTokens(db, roleId) {
|
|
14
|
-
requireApiRole(db, roleId);
|
|
15
|
-
const rows = db
|
|
13
|
+
export async function listApiTokens(db, roleId) {
|
|
14
|
+
await requireApiRole(db, roleId);
|
|
15
|
+
const rows = await db
|
|
16
16
|
.prepare(tokenSelectSql("WHERE api_tokens.role_id = ? ORDER BY api_tokens.created_at DESC"))
|
|
17
17
|
.all(roleId);
|
|
18
18
|
return rows.map(rowToApiToken);
|
|
19
19
|
}
|
|
20
|
-
export function revokeApiToken(db, roleId, tokenId) {
|
|
21
|
-
requireApiRole(db, roleId);
|
|
20
|
+
export async function revokeApiToken(db, roleId, tokenId) {
|
|
21
|
+
await requireApiRole(db, roleId);
|
|
22
22
|
const now = new Date().toISOString();
|
|
23
|
-
db.prepare("UPDATE api_tokens SET revoked_at = COALESCE(revoked_at, ?) WHERE id = ? AND role_id = ?")
|
|
23
|
+
await db.prepare("UPDATE api_tokens SET revoked_at = COALESCE(revoked_at, ?) WHERE id = ? AND role_id = ?")
|
|
24
24
|
.run(now, tokenId, roleId);
|
|
25
25
|
return getApiTokenById(db, tokenId, roleId);
|
|
26
26
|
}
|
|
27
|
-
export function resolveApiToken(db, token) {
|
|
28
|
-
const row = db
|
|
27
|
+
export async function resolveApiToken(db, token) {
|
|
28
|
+
const row = await db
|
|
29
29
|
.prepare(tokenSelectSql("WHERE api_tokens.token_hash = ? AND api_tokens.revoked_at IS NULL AND roles.role_kind = 'api'"))
|
|
30
30
|
.get(hashToken(token));
|
|
31
31
|
if (!row)
|
|
32
32
|
return undefined;
|
|
33
|
-
db.prepare("UPDATE api_tokens SET last_used_at = ? WHERE id = ?")
|
|
34
|
-
.run(new Date().toISOString(), row.id);
|
|
33
|
+
await db.prepare("UPDATE api_tokens SET last_used_at = ? WHERE id = ?").run(new Date().toISOString(), row.id);
|
|
35
34
|
return getApiTokenById(db, row.id);
|
|
36
35
|
}
|
|
37
|
-
function getApiTokenById(db, tokenId, roleId) {
|
|
36
|
+
async function getApiTokenById(db, tokenId, roleId) {
|
|
38
37
|
const suffix = roleId ? "WHERE api_tokens.id = ? AND api_tokens.role_id = ?" : "WHERE api_tokens.id = ?";
|
|
39
38
|
const params = roleId ? [tokenId, roleId] : [tokenId];
|
|
40
|
-
const row = db.prepare(tokenSelectSql(suffix)).get(...params);
|
|
39
|
+
const row = await db.prepare(tokenSelectSql(suffix)).get(...params);
|
|
41
40
|
return row ? rowToApiToken(row) : undefined;
|
|
42
41
|
}
|
|
43
|
-
function requireApiToken(db, tokenId) {
|
|
44
|
-
const token = getApiTokenById(db, tokenId);
|
|
42
|
+
async function requireApiToken(db, tokenId) {
|
|
43
|
+
const token = await getApiTokenById(db, tokenId);
|
|
45
44
|
if (!token)
|
|
46
45
|
throw new Error("API_TOKEN_NOT_FOUND");
|
|
47
46
|
return token;
|
|
48
47
|
}
|
|
49
|
-
function requireApiRole(db, roleId) {
|
|
50
|
-
const role = getRoleById(db, roleId);
|
|
48
|
+
async function requireApiRole(db, roleId) {
|
|
49
|
+
const role = await getRoleById(db, roleId);
|
|
51
50
|
if (!role)
|
|
52
51
|
throw new Error("ROLE_NOT_FOUND");
|
|
53
52
|
if (role.roleKind !== "api")
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export type DatabaseProvider = "sqlite" | "postgres" | "mysql";
|
|
2
|
+
export type DatabaseQueryParam = string | number | boolean | null | Buffer;
|
|
3
|
+
export type DatabaseRunResult = {
|
|
4
|
+
changes: number;
|
|
5
|
+
};
|
|
6
|
+
export type DatabaseStatement = {
|
|
7
|
+
get<TRecord = unknown>(...params: DatabaseQueryParam[]): Promise<TRecord | undefined>;
|
|
8
|
+
all<TRecord = unknown>(...params: DatabaseQueryParam[]): Promise<TRecord[]>;
|
|
9
|
+
run(...params: DatabaseQueryParam[]): Promise<DatabaseRunResult>;
|
|
10
|
+
};
|
|
11
|
+
export type ApiagexDatabase = {
|
|
12
|
+
provider: DatabaseProvider;
|
|
13
|
+
exec(sql: string): Promise<void>;
|
|
14
|
+
prepare(sql: string): DatabaseStatement;
|
|
15
|
+
transaction<TResult>(callback: () => Promise<TResult>): Promise<TResult>;
|
|
16
|
+
close(): Promise<void>;
|
|
17
|
+
};
|
|
18
|
+
//# sourceMappingURL=database-adapter.type.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"database-adapter.type.d.ts","sourceRoot":"","sources":["../src/database-adapter.type.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,gBAAgB,GAAG,QAAQ,GAAG,UAAU,GAAG,OAAO,CAAC;AAE/D,MAAM,MAAM,kBAAkB,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,MAAM,CAAC;AAE3E,MAAM,MAAM,iBAAiB,GAAG;IAC9B,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,GAAG,CAAC,OAAO,GAAG,OAAO,EAAE,GAAG,MAAM,EAAE,kBAAkB,EAAE,GAAG,OAAO,CAAC,OAAO,GAAG,SAAS,CAAC,CAAC;IACtF,GAAG,CAAC,OAAO,GAAG,OAAO,EAAE,GAAG,MAAM,EAAE,kBAAkB,EAAE,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;IAC5E,GAAG,CAAC,GAAG,MAAM,EAAE,kBAAkB,EAAE,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;CAClE,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACjC,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,iBAAiB,CAAC;IACxC,WAAW,CAAC,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACzE,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/entry-query.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ApiagexDatabase } from "./database-adapter.type.js";
|
|
2
2
|
import type { EntryListOptions, EntryListResult } from "./entry-repository.type.js";
|
|
3
|
-
export declare function queryEntries(db:
|
|
3
|
+
export declare function queryEntries(db: ApiagexDatabase, schemaId: string, options?: EntryListOptions): Promise<EntryListResult>;
|
|
4
4
|
//# sourceMappingURL=entry-query.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entry-query.d.ts","sourceRoot":"","sources":["../src/entry-query.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"entry-query.d.ts","sourceRoot":"","sources":["../src/entry-query.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAsB,MAAM,4BAA4B,CAAC;AACtF,OAAO,KAAK,EAEV,gBAAgB,EAChB,eAAe,EAEhB,MAAM,4BAA4B,CAAC;AAYpC,wBAAsB,YAAY,CAChC,EAAE,EAAE,eAAe,EACnB,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,gBAAqB,GAC7B,OAAO,CAAC,eAAe,CAAC,CAiB1B"}
|
package/dist/entry-query.js
CHANGED
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
import { getSchemaById } from "./schema-repository.js";
|
|
2
|
-
export function queryEntries(db, schemaId, options = {}) {
|
|
3
|
-
const schema = requireSchema(db, schemaId);
|
|
2
|
+
export async function queryEntries(db, schemaId, options = {}) {
|
|
3
|
+
const schema = await requireSchema(db, schemaId);
|
|
4
4
|
const limit = clampListLimit(options.limit);
|
|
5
5
|
const offset = Math.max(0, Math.floor(options.offset ?? 0));
|
|
6
6
|
const search = options.search?.trim() ?? "";
|
|
7
7
|
const selectedFields = validateSelectedFields(schema, options.fields);
|
|
8
8
|
const where = search ? "WHERE schema_id = ? AND (data_json LIKE ? OR id LIKE ?)" : "WHERE schema_id = ?";
|
|
9
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 ?`)
|
|
10
|
+
const totalRow = await db.prepare(`SELECT COUNT(*) as total FROM entries ${where}`).get(...params);
|
|
11
|
+
const rows = await db.prepare(`${entrySelectSql(where)} ORDER BY created_at DESC LIMIT ? OFFSET ?`)
|
|
12
|
+
.all(...params, limit, offset);
|
|
12
13
|
return {
|
|
13
14
|
entries: rows.map((row) => projectEntry(rowToEntry(row), selectedFields)),
|
|
14
15
|
limit,
|
|
15
16
|
offset,
|
|
16
|
-
total: totalRow
|
|
17
|
+
total: totalRow?.total ?? 0,
|
|
17
18
|
};
|
|
18
19
|
}
|
|
19
20
|
function clampListLimit(value) {
|
|
@@ -41,8 +42,8 @@ function projectEntry(entry, fields) {
|
|
|
41
42
|
}
|
|
42
43
|
return { ...entry, data };
|
|
43
44
|
}
|
|
44
|
-
function requireSchema(db, schemaId) {
|
|
45
|
-
const schema = getSchemaById(db, schemaId);
|
|
45
|
+
async function requireSchema(db, schemaId) {
|
|
46
|
+
const schema = await getSchemaById(db, schemaId);
|
|
46
47
|
if (!schema)
|
|
47
48
|
throw new Error("SCHEMA_NOT_FOUND");
|
|
48
49
|
return schema;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ApiagexDatabase } from "./database-adapter.type.js";
|
|
2
2
|
import type { CreateEntryInput, EntryRecord, UpdateEntryInput } from "./entry-repository.type.js";
|
|
3
|
-
export declare function createEntry(db:
|
|
4
|
-
export declare function listEntries(db:
|
|
5
|
-
export declare function getEntryById(db:
|
|
6
|
-
export declare function updateEntry(db:
|
|
7
|
-
export declare function deleteEntry(db:
|
|
3
|
+
export declare function createEntry(db: ApiagexDatabase, input: CreateEntryInput): Promise<EntryRecord>;
|
|
4
|
+
export declare function listEntries(db: ApiagexDatabase, schemaId: string): Promise<EntryRecord[]>;
|
|
5
|
+
export declare function getEntryById(db: ApiagexDatabase, id: string): Promise<EntryRecord | undefined>;
|
|
6
|
+
export declare function updateEntry(db: ApiagexDatabase, id: string, input: UpdateEntryInput): Promise<EntryRecord>;
|
|
7
|
+
export declare function deleteEntry(db: ApiagexDatabase, id: string): Promise<void>;
|
|
8
8
|
//# sourceMappingURL=entry-repository.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entry-repository.d.ts","sourceRoot":"","sources":["../src/entry-repository.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"entry-repository.d.ts","sourceRoot":"","sources":["../src/entry-repository.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAClE,OAAO,KAAK,EAAE,gBAAgB,EAAa,WAAW,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAkB7G,wBAAsB,WAAW,CAAC,EAAE,EAAE,eAAe,EAAE,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,WAAW,CAAC,CAUpG;AAED,wBAAsB,WAAW,CAAC,EAAE,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,CAQ/F;AAED,wBAAsB,YAAY,CAAC,EAAE,EAAE,eAAe,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC,CAGpG;AAED,wBAAsB,WAAW,CAC/B,EAAE,EAAE,eAAe,EACnB,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,gBAAgB,GACtB,OAAO,CAAC,WAAW,CAAC,CAQtB;AAED,wBAAsB,WAAW,CAAC,EAAE,EAAE,eAAe,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAIhF"}
|
package/dist/entry-repository.js
CHANGED
|
@@ -2,52 +2,51 @@ import { randomUUID } from "node:crypto";
|
|
|
2
2
|
import { relationEntryReferenced, relationOneToOneConflict, relationTargetEntryInvalid, relationValueShapeInvalid, } from "./relation-errors.js";
|
|
3
3
|
import { entryDataReferences, listEntryDataRows, parseEntryData, relationTypeOf, } from "./relation-helpers.js";
|
|
4
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);
|
|
5
|
+
export async function createEntry(db, input) {
|
|
6
|
+
const schema = await requireSchema(db, input.schemaId);
|
|
7
|
+
await validateEntryData(db, schema, input.data);
|
|
8
8
|
const normalizedData = normalizeEntryData(schema, input.data);
|
|
9
9
|
const id = randomUUID();
|
|
10
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);
|
|
11
|
+
await 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
12
|
return requireEntry(db, id);
|
|
13
13
|
}
|
|
14
|
-
export function listEntries(db, schemaId) {
|
|
15
|
-
requireSchema(db, schemaId);
|
|
16
|
-
const rows = db
|
|
14
|
+
export async function listEntries(db, schemaId) {
|
|
15
|
+
await requireSchema(db, schemaId);
|
|
16
|
+
const rows = await db
|
|
17
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
18
|
.all(schemaId);
|
|
19
19
|
return rows.map(rowToEntry);
|
|
20
20
|
}
|
|
21
|
-
export function getEntryById(db, id) {
|
|
22
|
-
const row = db.prepare(entrySelectSql("WHERE id = ?")).get(id);
|
|
21
|
+
export async function getEntryById(db, id) {
|
|
22
|
+
const row = await db.prepare(entrySelectSql("WHERE id = ?")).get(id);
|
|
23
23
|
return row ? rowToEntry(row) : undefined;
|
|
24
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);
|
|
25
|
+
export async function updateEntry(db, id, input) {
|
|
26
|
+
const current = await requireEntry(db, id);
|
|
27
|
+
const schema = await requireSchema(db, current.schemaId);
|
|
28
|
+
await validateEntryData(db, schema, input.data, id);
|
|
29
29
|
const normalizedData = normalizeEntryData(schema, input.data);
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
await db.prepare("UPDATE entries SET data_json = ?, updated_at = ? WHERE id = ?")
|
|
31
|
+
.run(JSON.stringify(normalizedData), new Date().toISOString(), id);
|
|
32
32
|
return requireEntry(db, id);
|
|
33
33
|
}
|
|
34
|
-
export function deleteEntry(db, id) {
|
|
35
|
-
assertEntryNotReferenced(db, id);
|
|
36
|
-
const result = db.prepare("DELETE FROM entries WHERE id = ?").run(id);
|
|
34
|
+
export async function deleteEntry(db, id) {
|
|
35
|
+
await assertEntryNotReferenced(db, id);
|
|
36
|
+
const result = await db.prepare("DELETE FROM entries WHERE id = ?").run(id);
|
|
37
37
|
if (result.changes === 0)
|
|
38
38
|
throw new Error("ENTRY_NOT_FOUND");
|
|
39
39
|
}
|
|
40
|
-
function assertEntryNotReferenced(db, entryId) {
|
|
41
|
-
const rows = listEntryDataRows(db);
|
|
40
|
+
async function assertEntryNotReferenced(db, entryId) {
|
|
41
|
+
const rows = await listEntryDataRows(db);
|
|
42
42
|
for (const row of rows) {
|
|
43
43
|
if (row.id === entryId)
|
|
44
44
|
continue;
|
|
45
|
-
if (entryDataReferences(parseEntryData(row.dataJson), entryId))
|
|
45
|
+
if (entryDataReferences(parseEntryData(row.dataJson), entryId))
|
|
46
46
|
throw new Error(relationEntryReferenced(entryId));
|
|
47
|
-
}
|
|
48
47
|
}
|
|
49
48
|
}
|
|
50
|
-
function validateEntryData(db, schema, data, currentEntryId) {
|
|
49
|
+
async function validateEntryData(db, schema, data, currentEntryId) {
|
|
51
50
|
if (!isRecord(data))
|
|
52
51
|
throw new Error("ENTRY_DATA_INVALID");
|
|
53
52
|
const fieldSlugs = new Set(schema.fields.map((field) => field.slug));
|
|
@@ -57,15 +56,13 @@ function validateEntryData(db, schema, data, currentEntryId) {
|
|
|
57
56
|
}
|
|
58
57
|
for (const field of schema.fields) {
|
|
59
58
|
const value = data[field.slug];
|
|
60
|
-
if (field.required && isMissing(value))
|
|
59
|
+
if (field.required && isMissing(value))
|
|
61
60
|
throw new Error(`ENTRY_FIELD_REQUIRED:${field.slug}`);
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
validateFieldValue(db, schema, field, value, currentEntryId);
|
|
65
|
-
}
|
|
61
|
+
if (!isMissing(value))
|
|
62
|
+
await validateFieldValue(db, schema, field, value, currentEntryId);
|
|
66
63
|
}
|
|
67
64
|
}
|
|
68
|
-
function validateFieldValue(db, schema, field, value, currentEntryId) {
|
|
65
|
+
async function validateFieldValue(db, schema, field, value, currentEntryId) {
|
|
69
66
|
if (field.type === "text" || field.type === "longText" || field.type === "media") {
|
|
70
67
|
assertType(field, typeof value === "string");
|
|
71
68
|
}
|
|
@@ -79,45 +76,38 @@ function validateFieldValue(db, schema, field, value, currentEntryId) {
|
|
|
79
76
|
assertType(field, typeof value === "string" && !Number.isNaN(Date.parse(value)));
|
|
80
77
|
}
|
|
81
78
|
else if (field.type === "relation") {
|
|
82
|
-
assertRelation(db, schema, field, value, currentEntryId);
|
|
79
|
+
await assertRelation(db, schema, field, value, currentEntryId);
|
|
83
80
|
}
|
|
84
81
|
}
|
|
85
|
-
function assertRelation(db, schema, field, value, currentEntryId) {
|
|
82
|
+
async function assertRelation(db, schema, field, value, currentEntryId) {
|
|
86
83
|
const relationType = relationTypeOf(field);
|
|
87
84
|
if (relationType === "oneToMany" || relationType === "manyToMany") {
|
|
88
|
-
assertMultiRelation(db, field, value);
|
|
85
|
+
await assertMultiRelation(db, field, value);
|
|
89
86
|
return;
|
|
90
87
|
}
|
|
91
|
-
if (typeof value !== "string")
|
|
88
|
+
if (typeof value !== "string")
|
|
92
89
|
throw new Error(relationValueShapeInvalid(field.slug));
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
if (!target || target.schemaId !== field.relationSchemaId) {
|
|
90
|
+
const target = await getEntryById(db, String(value));
|
|
91
|
+
if (!target || target.schemaId !== field.relationSchemaId)
|
|
96
92
|
throw new Error(relationTargetEntryInvalid(field.slug));
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
assertOneToOneAvailable(db, schema, field, value, currentEntryId);
|
|
100
|
-
}
|
|
93
|
+
if (relationType === "oneToOne")
|
|
94
|
+
await assertOneToOneAvailable(db, schema, field, value, currentEntryId);
|
|
101
95
|
}
|
|
102
|
-
function assertMultiRelation(db, field, value) {
|
|
103
|
-
if (!Array.isArray(value))
|
|
96
|
+
async function assertMultiRelation(db, field, value) {
|
|
97
|
+
if (!Array.isArray(value))
|
|
104
98
|
throw new Error(relationValueShapeInvalid(field.slug));
|
|
105
|
-
|
|
106
|
-
if (field.required && value.length === 0) {
|
|
99
|
+
if (field.required && value.length === 0)
|
|
107
100
|
throw new Error(`ENTRY_FIELD_REQUIRED:${field.slug}`);
|
|
108
|
-
}
|
|
109
101
|
const seen = new Set();
|
|
110
102
|
for (const targetEntryId of value) {
|
|
111
|
-
if (typeof targetEntryId !== "string")
|
|
103
|
+
if (typeof targetEntryId !== "string")
|
|
112
104
|
throw new Error(relationValueShapeInvalid(field.slug));
|
|
113
|
-
}
|
|
114
105
|
if (seen.has(targetEntryId))
|
|
115
106
|
continue;
|
|
116
107
|
seen.add(targetEntryId);
|
|
117
|
-
const target = getEntryById(db, targetEntryId);
|
|
118
|
-
if (!target || target.schemaId !== field.relationSchemaId)
|
|
108
|
+
const target = await getEntryById(db, targetEntryId);
|
|
109
|
+
if (!target || target.schemaId !== field.relationSchemaId)
|
|
119
110
|
throw new Error(relationTargetEntryInvalid(field.slug));
|
|
120
|
-
}
|
|
121
111
|
}
|
|
122
112
|
}
|
|
123
113
|
function normalizeEntryData(schema, data) {
|
|
@@ -135,8 +125,8 @@ function normalizeEntryData(schema, data) {
|
|
|
135
125
|
}
|
|
136
126
|
return normalized;
|
|
137
127
|
}
|
|
138
|
-
function assertOneToOneAvailable(db, schema, field, targetEntryId, currentEntryId) {
|
|
139
|
-
const rows = listEntryDataRows(db, "WHERE schema_id = ?", [schema.id]);
|
|
128
|
+
async function assertOneToOneAvailable(db, schema, field, targetEntryId, currentEntryId) {
|
|
129
|
+
const rows = await listEntryDataRows(db, "WHERE schema_id = ?", [schema.id]);
|
|
140
130
|
for (const row of rows) {
|
|
141
131
|
if (row.id === currentEntryId)
|
|
142
132
|
continue;
|
|
@@ -155,14 +145,14 @@ function isMissing(value) {
|
|
|
155
145
|
function isRecord(value) {
|
|
156
146
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
157
147
|
}
|
|
158
|
-
function requireSchema(db, schemaId) {
|
|
159
|
-
const schema = getSchemaById(db, schemaId);
|
|
148
|
+
async function requireSchema(db, schemaId) {
|
|
149
|
+
const schema = await getSchemaById(db, schemaId);
|
|
160
150
|
if (!schema)
|
|
161
151
|
throw new Error("SCHEMA_NOT_FOUND");
|
|
162
152
|
return schema;
|
|
163
153
|
}
|
|
164
|
-
function requireEntry(db, id) {
|
|
165
|
-
const entry = getEntryById(db, id);
|
|
154
|
+
async function requireEntry(db, id) {
|
|
155
|
+
const entry = await getEntryById(db, id);
|
|
166
156
|
if (!entry)
|
|
167
157
|
throw new Error("ENTRY_NOT_FOUND");
|
|
168
158
|
return entry;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
export { MVP_FOUNDATION_SQL, MVP_MIGRATION_ID, MVP_TABLES, } from "./migrations.js";
|
|
2
|
+
export { getProviderFoundationMigration, migrateProviderFoundation, MYSQL_FOUNDATION_SQL, POSTGRES_FOUNDATION_SQL, providerFoundationSql, } from "./provider-migrations.js";
|
|
3
|
+
export { convertPostgresPlaceholders, openPostgresAdapter, PostgresApiagexDatabase, } from "./postgres-adapter.js";
|
|
4
|
+
export type { PostgresAdapterOptions } from "./postgres-adapter.js";
|
|
5
|
+
export { openMySqlAdapter, MySqlApiagexDatabase, splitMySqlStatements, } from "./mysql-adapter.js";
|
|
6
|
+
export type { MySqlAdapterOptions } from "./mysql-adapter.js";
|
|
2
7
|
export { listMvpTables, migrateMvpDatabase, openSqliteDatabase, } from "./sqlite.js";
|
|
8
|
+
export { openMigratedSqliteAdapter, openSqliteAdapter, SqliteApiagexDatabase, wrapSqliteDatabase, } from "./sqlite-adapter.js";
|
|
3
9
|
export { createEntry, deleteEntry, getEntryById, listEntries, updateEntry, } from "./entry-repository.js";
|
|
4
10
|
export { queryEntries } from "./entry-query.js";
|
|
5
11
|
export { createAdminRole, createRole, getRoleById, listAdminRoles, listRoles, } from "./role-repository.js";
|
|
@@ -14,6 +20,8 @@ export { createSchema, deleteSchema, getSchemaById, getSchemaBySlug, listSchemas
|
|
|
14
20
|
export { relationEntryReferenced, relationFieldUpdateUnsafe, relationOneToOneConflict, relationSchemaReferenced, relationErrors, relationTargetEntryInvalid, relationValueShapeInvalid, } from "./relation-errors.js";
|
|
15
21
|
export { entryDataReferences, listEntryDataRows, parseEntryData, relationTypeOf, schemaEntriesUseField, } from "./relation-helpers.js";
|
|
16
22
|
export type { MvpTableName, MigrationRecord, TableInfoRow } from "./schema.type.js";
|
|
23
|
+
export type { ProviderFoundationMigration } from "./provider-migrations.js";
|
|
24
|
+
export type { ApiagexDatabase, DatabaseProvider, DatabaseQueryParam, DatabaseRunResult, DatabaseStatement, } from "./database-adapter.type.js";
|
|
17
25
|
export type { CreateEntryInput, EntryData, EntryFieldValue, EntryListOptions, EntryListResult, EntryRecord, MultiRelationEntryValue, RelationEntryValue, SingleRelationEntryValue, UpdateEntryInput, } from "./entry-repository.type.js";
|
|
18
26
|
export type { CreateRoleInput, RoleKind, RoleRecord } from "./role-repository.type.js";
|
|
19
27
|
export type { ApiTokenRecord, CreatedApiToken, CreateApiTokenInput, } from "./api-token-repository.type.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
export { MVP_FOUNDATION_SQL, MVP_MIGRATION_ID, MVP_TABLES, } from "./migrations.js";
|
|
2
|
+
export { getProviderFoundationMigration, migrateProviderFoundation, MYSQL_FOUNDATION_SQL, POSTGRES_FOUNDATION_SQL, providerFoundationSql, } from "./provider-migrations.js";
|
|
3
|
+
export { convertPostgresPlaceholders, openPostgresAdapter, PostgresApiagexDatabase, } from "./postgres-adapter.js";
|
|
4
|
+
export { openMySqlAdapter, MySqlApiagexDatabase, splitMySqlStatements, } from "./mysql-adapter.js";
|
|
2
5
|
export { listMvpTables, migrateMvpDatabase, openSqliteDatabase, } from "./sqlite.js";
|
|
6
|
+
export { openMigratedSqliteAdapter, openSqliteAdapter, SqliteApiagexDatabase, wrapSqliteDatabase, } from "./sqlite-adapter.js";
|
|
3
7
|
export { createEntry, deleteEntry, getEntryById, listEntries, updateEntry, } from "./entry-repository.js";
|
|
4
8
|
export { queryEntries } from "./entry-query.js";
|
|
5
9
|
export { createAdminRole, createRole, getRoleById, listAdminRoles, listRoles, } from "./role-repository.js";
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import mysql from "mysql2/promise";
|
|
2
|
+
import type { ApiagexDatabase, DatabaseStatement } from "./database-adapter.type.js";
|
|
3
|
+
export type MySqlAdapterOptions = {
|
|
4
|
+
migrate?: boolean;
|
|
5
|
+
};
|
|
6
|
+
export declare class MySqlApiagexDatabase implements ApiagexDatabase {
|
|
7
|
+
private readonly connection;
|
|
8
|
+
readonly provider = "mysql";
|
|
9
|
+
constructor(connection: mysql.Connection);
|
|
10
|
+
exec(sql: string): Promise<void>;
|
|
11
|
+
prepare(sql: string): DatabaseStatement;
|
|
12
|
+
transaction<TResult>(callback: () => Promise<TResult>): Promise<TResult>;
|
|
13
|
+
close(): Promise<void>;
|
|
14
|
+
}
|
|
15
|
+
export declare function openMySqlAdapter(connectionString: string | undefined, options?: MySqlAdapterOptions): Promise<ApiagexDatabase>;
|
|
16
|
+
export declare function splitMySqlStatements(sql: string): string[];
|
|
17
|
+
//# sourceMappingURL=mysql-adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mysql-adapter.d.ts","sourceRoot":"","sources":["../src/mysql-adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,gBAAgB,CAAC;AACnC,OAAO,KAAK,EAAE,eAAe,EAAyC,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAG5H,MAAM,MAAM,mBAAmB,GAAG;IAChC,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AAEF,qBAAa,oBAAqB,YAAW,eAAe;IAG9C,OAAO,CAAC,QAAQ,CAAC,UAAU;IAFvC,QAAQ,CAAC,QAAQ,WAAW;gBAEC,UAAU,EAAE,KAAK,CAAC,UAAU;IAEnD,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAMtC,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,iBAAiB;IAiBjC,WAAW,CAAC,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC;IAYxE,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAG7B;AAED,wBAAsB,gBAAgB,CACpC,gBAAgB,EAAE,MAAM,GAAG,SAAS,EACpC,OAAO,GAAE,mBAAwB,GAChC,OAAO,CAAC,eAAe,CAAC,CAM1B;AAED,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAK1D"}
|