@headless-lms/adapter-db 0.1.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/LICENSE +21 -0
- package/dist/_virtual/_rolldown/runtime.js +13 -0
- package/dist/client.d.ts +17 -0
- package/dist/client.js +11 -0
- package/dist/client.js.map +1 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.js +22 -0
- package/dist/migrate.d.ts +7 -0
- package/dist/migrate.js +27 -0
- package/dist/migrate.js.map +1 -0
- package/dist/repositories/assets.d.ts +17 -0
- package/dist/repositories/assets.js +90 -0
- package/dist/repositories/assets.js.map +1 -0
- package/dist/repositories/automations.d.ts +30 -0
- package/dist/repositories/automations.js +165 -0
- package/dist/repositories/automations.js.map +1 -0
- package/dist/repositories/content.d.ts +52 -0
- package/dist/repositories/content.js +350 -0
- package/dist/repositories/content.js.map +1 -0
- package/dist/repositories/credentials.d.ts +25 -0
- package/dist/repositories/credentials.js +86 -0
- package/dist/repositories/credentials.js.map +1 -0
- package/dist/repositories/dashboard.d.ts +14 -0
- package/dist/repositories/dashboard.js +55 -0
- package/dist/repositories/dashboard.js.map +1 -0
- package/dist/repositories/discussion.d.ts +31 -0
- package/dist/repositories/discussion.js +201 -0
- package/dist/repositories/discussion.js.map +1 -0
- package/dist/repositories/entitlements.d.ts +23 -0
- package/dist/repositories/entitlements.js +129 -0
- package/dist/repositories/entitlements.js.map +1 -0
- package/dist/repositories/identity.d.ts +17 -0
- package/dist/repositories/identity.js +44 -0
- package/dist/repositories/identity.js.map +1 -0
- package/dist/repositories/integrations.d.ts +18 -0
- package/dist/repositories/integrations.js +65 -0
- package/dist/repositories/integrations.js.map +1 -0
- package/dist/repositories/learn.d.ts +19 -0
- package/dist/repositories/learn.js +54 -0
- package/dist/repositories/learn.js.map +1 -0
- package/dist/repositories/members.d.ts +16 -0
- package/dist/repositories/members.js +116 -0
- package/dist/repositories/members.js.map +1 -0
- package/dist/repositories/org-user-profile.d.ts +92 -0
- package/dist/repositories/org-user-profile.js +16 -0
- package/dist/repositories/org-user-profile.js.map +1 -0
- package/dist/repositories/organizations.d.ts +33 -0
- package/dist/repositories/organizations.js +198 -0
- package/dist/repositories/organizations.js.map +1 -0
- package/dist/repositories/outbox.d.ts +24 -0
- package/dist/repositories/outbox.js +56 -0
- package/dist/repositories/outbox.js.map +1 -0
- package/dist/repositories/pg-errors.d.ts +11 -0
- package/dist/repositories/pg-errors.js +15 -0
- package/dist/repositories/pg-errors.js.map +1 -0
- package/dist/repositories/progress.d.ts +18 -0
- package/dist/repositories/progress.js +59 -0
- package/dist/repositories/progress.js.map +1 -0
- package/dist/repositories/settings.d.ts +22 -0
- package/dist/repositories/settings.js +73 -0
- package/dist/repositories/settings.js.map +1 -0
- package/dist/repositories/students.d.ts +15 -0
- package/dist/repositories/students.js +83 -0
- package/dist/repositories/students.js.map +1 -0
- package/dist/schema/assets.d.ts +181 -0
- package/dist/schema/assets.js +24 -0
- package/dist/schema/assets.js.map +1 -0
- package/dist/schema/automations.d.ts +364 -0
- package/dist/schema/automations.js +42 -0
- package/dist/schema/automations.js.map +1 -0
- package/dist/schema/better-auth.d.ts +2311 -0
- package/dist/schema/better-auth.js +156 -0
- package/dist/schema/better-auth.js.map +1 -0
- package/dist/schema/content.d.ts +966 -0
- package/dist/schema/content.js +163 -0
- package/dist/schema/content.js.map +1 -0
- package/dist/schema/credentials.d.ts +113 -0
- package/dist/schema/credentials.js +15 -0
- package/dist/schema/credentials.js.map +1 -0
- package/dist/schema/discussion.d.ts +399 -0
- package/dist/schema/discussion.js +89 -0
- package/dist/schema/discussion.js.map +1 -0
- package/dist/schema/drift.d.ts +9 -0
- package/dist/schema/drift.js +1 -0
- package/dist/schema/entitlements.d.ts +147 -0
- package/dist/schema/entitlements.js +30 -0
- package/dist/schema/entitlements.js.map +1 -0
- package/dist/schema/identity.d.ts +130 -0
- package/dist/schema/identity.js +16 -0
- package/dist/schema/identity.js.map +1 -0
- package/dist/schema/index.d.ts +18 -0
- package/dist/schema/index.js +43 -0
- package/dist/schema/index.js.map +1 -0
- package/dist/schema/integrations.d.ts +149 -0
- package/dist/schema/integrations.js +25 -0
- package/dist/schema/integrations.js.map +1 -0
- package/dist/schema/organizations.d.ts +416 -0
- package/dist/schema/organizations.js +58 -0
- package/dist/schema/organizations.js.map +1 -0
- package/dist/schema/outbox.d.ts +166 -0
- package/dist/schema/outbox.js +19 -0
- package/dist/schema/outbox.js.map +1 -0
- package/dist/schema/progress.d.ts +166 -0
- package/dist/schema/progress.js +30 -0
- package/dist/schema/progress.js.map +1 -0
- package/dist/schema/settings.d.ts +115 -0
- package/dist/schema/settings.js +19 -0
- package/dist/schema/settings.js.map +1 -0
- package/dist/unit-of-work.d.ts +13 -0
- package/dist/unit-of-work.js +16 -0
- package/dist/unit-of-work.js.map +1 -0
- package/drizzle/0000_baseline.sql +526 -0
- package/drizzle/meta/0000_snapshot.json +3925 -0
- package/drizzle/meta/_journal.json +13 -0
- package/package.json +56 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 mdwt
|
|
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.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
//#region \0rolldown/runtime.js
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __exportAll = (all, no_symbols) => {
|
|
4
|
+
let target = {};
|
|
5
|
+
for (var name in all) __defProp(target, name, {
|
|
6
|
+
get: all[name],
|
|
7
|
+
enumerable: true
|
|
8
|
+
});
|
|
9
|
+
if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
|
|
10
|
+
return target;
|
|
11
|
+
};
|
|
12
|
+
//#endregion
|
|
13
|
+
export { __exportAll };
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { index_d_exports } from "./schema/index.js";
|
|
2
|
+
import { NodePgDatabase } from "drizzle-orm/node-postgres";
|
|
3
|
+
//#region src/client.d.ts
|
|
4
|
+
/** Transaction executor — the same query surface as the root db.
|
|
5
|
+
* (Promoted from the structure.ts repository's local alias.) */
|
|
6
|
+
type Tx = Parameters<Parameters<NodePgDatabase['transaction']>[0]>[0];
|
|
7
|
+
/** What a Drizzle repository executes against: the root db OR a transaction
|
|
8
|
+
* handle — tx-bound repo instances are how DrizzleUnitOfWork guarantees no
|
|
9
|
+
* statement escapes the transaction. */
|
|
10
|
+
type DbExecutor = NodePgDatabase | Tx;
|
|
11
|
+
type Db = ReturnType<typeof createDb>;
|
|
12
|
+
declare function createDb(connectionString: string): NodePgDatabase<Record<string, never>> & {
|
|
13
|
+
$client: import("pg").Pool;
|
|
14
|
+
};
|
|
15
|
+
//#endregion
|
|
16
|
+
export { Db, DbExecutor, Tx, createDb, index_d_exports as schema };
|
|
17
|
+
//# sourceMappingURL=client.d.ts.map
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { schema_exports } from "./schema/index.js";
|
|
2
|
+
import { drizzle } from "drizzle-orm/node-postgres";
|
|
3
|
+
import pg from "pg";
|
|
4
|
+
//#region src/client.ts
|
|
5
|
+
function createDb(connectionString) {
|
|
6
|
+
return drizzle(new pg.Pool({ connectionString }));
|
|
7
|
+
}
|
|
8
|
+
//#endregion
|
|
9
|
+
export { createDb, schema_exports as schema };
|
|
10
|
+
|
|
11
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","names":[],"sources":["../src/client.ts"],"sourcesContent":["// Drizzle client + connection. Owns connection pooling (Drizzle does not).\nimport { drizzle, type NodePgDatabase } from 'drizzle-orm/node-postgres';\nimport pg from 'pg';\n\n/** Transaction executor — the same query surface as the root db.\n * (Promoted from the structure.ts repository's local alias.) */\nexport type Tx = Parameters<Parameters<NodePgDatabase['transaction']>[0]>[0];\n\n/** What a Drizzle repository executes against: the root db OR a transaction\n * handle — tx-bound repo instances are how DrizzleUnitOfWork guarantees no\n * statement escapes the transaction. */\nexport type DbExecutor = NodePgDatabase | Tx;\n\n// Centralized schema — re-exported so the db adapter is the single source for tables.\nexport * as schema from './schema/index.js';\n\nexport type Db = ReturnType<typeof createDb>;\n\nexport function createDb(connectionString: string) {\n const pool = new pg.Pool({ connectionString });\n return drizzle(pool);\n}\n"],"mappings":";;;;AAkBA,SAAgB,SAAS,kBAA0B;CAEjD,OAAO,QAAQ,IADE,GAAG,KAAK,EAAE,iBAAiB,CAC1B,CAAC;AACrB"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { index_d_exports } from "./schema/index.js";
|
|
2
|
+
import { Db, createDb } from "./client.js";
|
|
3
|
+
import { DrizzleUnitOfWork } from "./unit-of-work.js";
|
|
4
|
+
import { migrationsFolder, runMigrations } from "./migrate.js";
|
|
5
|
+
import { DrizzleAssetsRepository } from "./repositories/assets.js";
|
|
6
|
+
import { DrizzleAutomationRunsRepository, DrizzleAutomationsRepository } from "./repositories/automations.js";
|
|
7
|
+
import { DrizzleContentRepository } from "./repositories/content.js";
|
|
8
|
+
import { DrizzleCredentialStore, decryptSecret, encryptSecret } from "./repositories/credentials.js";
|
|
9
|
+
import { DrizzleDashboardRepository } from "./repositories/dashboard.js";
|
|
10
|
+
import { DrizzleDiscussionRepository } from "./repositories/discussion.js";
|
|
11
|
+
import { DrizzleEntitlementsRepository } from "./repositories/entitlements.js";
|
|
12
|
+
import { DrizzleIdentityRepository } from "./repositories/identity.js";
|
|
13
|
+
import { DrizzleConnectionsRepository } from "./repositories/integrations.js";
|
|
14
|
+
import { DrizzleLearnRepository } from "./repositories/learn.js";
|
|
15
|
+
import { DrizzleMembersRepository } from "./repositories/members.js";
|
|
16
|
+
import { orgUserProfileColumns } from "./repositories/org-user-profile.js";
|
|
17
|
+
import { DrizzleOrganizationsRepository } from "./repositories/organizations.js";
|
|
18
|
+
import { DrizzleOutboxAppender, DrizzleOutboxStore, OUTBOX_MAX_ATTEMPTS } from "./repositories/outbox.js";
|
|
19
|
+
import { DrizzleProgressRepository } from "./repositories/progress.js";
|
|
20
|
+
import { DrizzleSettingsRepository, deepMerge } from "./repositories/settings.js";
|
|
21
|
+
import { DrizzleStudentsRepository } from "./repositories/students.js";
|
|
22
|
+
export { type Db, DrizzleAssetsRepository, DrizzleAutomationRunsRepository, DrizzleAutomationsRepository, DrizzleConnectionsRepository, DrizzleContentRepository, DrizzleCredentialStore, DrizzleDashboardRepository, DrizzleDiscussionRepository, DrizzleEntitlementsRepository, DrizzleIdentityRepository, DrizzleLearnRepository, DrizzleMembersRepository, DrizzleOrganizationsRepository, DrizzleOutboxAppender, DrizzleOutboxStore, DrizzleProgressRepository, DrizzleSettingsRepository, DrizzleStudentsRepository, DrizzleUnitOfWork, OUTBOX_MAX_ATTEMPTS, createDb, decryptSecret, deepMerge, encryptSecret, migrationsFolder, orgUserProfileColumns, runMigrations, index_d_exports as schema };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { schema_exports } from "./schema/index.js";
|
|
2
|
+
import { createDb } from "./client.js";
|
|
3
|
+
import { DrizzleUnitOfWork } from "./unit-of-work.js";
|
|
4
|
+
import { migrationsFolder, runMigrations } from "./migrate.js";
|
|
5
|
+
import { DrizzleAssetsRepository } from "./repositories/assets.js";
|
|
6
|
+
import { DrizzleAutomationRunsRepository, DrizzleAutomationsRepository } from "./repositories/automations.js";
|
|
7
|
+
import { DrizzleContentRepository } from "./repositories/content.js";
|
|
8
|
+
import { DrizzleCredentialStore, decryptSecret, encryptSecret } from "./repositories/credentials.js";
|
|
9
|
+
import { DrizzleDashboardRepository } from "./repositories/dashboard.js";
|
|
10
|
+
import { orgUserProfileColumns } from "./repositories/org-user-profile.js";
|
|
11
|
+
import { DrizzleDiscussionRepository } from "./repositories/discussion.js";
|
|
12
|
+
import { DrizzleEntitlementsRepository } from "./repositories/entitlements.js";
|
|
13
|
+
import { DrizzleIdentityRepository } from "./repositories/identity.js";
|
|
14
|
+
import { DrizzleConnectionsRepository } from "./repositories/integrations.js";
|
|
15
|
+
import { DrizzleLearnRepository } from "./repositories/learn.js";
|
|
16
|
+
import { DrizzleMembersRepository } from "./repositories/members.js";
|
|
17
|
+
import { DrizzleOrganizationsRepository } from "./repositories/organizations.js";
|
|
18
|
+
import { DrizzleOutboxAppender, DrizzleOutboxStore, OUTBOX_MAX_ATTEMPTS } from "./repositories/outbox.js";
|
|
19
|
+
import { DrizzleProgressRepository } from "./repositories/progress.js";
|
|
20
|
+
import { DrizzleSettingsRepository, deepMerge } from "./repositories/settings.js";
|
|
21
|
+
import { DrizzleStudentsRepository } from "./repositories/students.js";
|
|
22
|
+
export { DrizzleAssetsRepository, DrizzleAutomationRunsRepository, DrizzleAutomationsRepository, DrizzleConnectionsRepository, DrizzleContentRepository, DrizzleCredentialStore, DrizzleDashboardRepository, DrizzleDiscussionRepository, DrizzleEntitlementsRepository, DrizzleIdentityRepository, DrizzleLearnRepository, DrizzleMembersRepository, DrizzleOrganizationsRepository, DrizzleOutboxAppender, DrizzleOutboxStore, DrizzleProgressRepository, DrizzleSettingsRepository, DrizzleStudentsRepository, DrizzleUnitOfWork, OUTBOX_MAX_ATTEMPTS, createDb, decryptSecret, deepMerge, encryptSecret, migrationsFolder, orgUserProfileColumns, runMigrations, schema_exports as schema };
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
//#region src/migrate.d.ts
|
|
2
|
+
/** drizzle/ sits at the package root: ../drizzle from src/ AND dist/. */
|
|
3
|
+
declare function migrationsFolder(): string;
|
|
4
|
+
declare function runMigrations(databaseUrl: string): Promise<void>;
|
|
5
|
+
//#endregion
|
|
6
|
+
export { migrationsFolder, runMigrations };
|
|
7
|
+
//# sourceMappingURL=migrate.d.ts.map
|
package/dist/migrate.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { drizzle } from "drizzle-orm/node-postgres";
|
|
2
|
+
import pg from "pg";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
import { migrate } from "drizzle-orm/node-postgres/migrator";
|
|
5
|
+
//#region src/migrate.ts
|
|
6
|
+
/** drizzle/ sits at the package root: ../drizzle from src/ AND dist/. */
|
|
7
|
+
function migrationsFolder() {
|
|
8
|
+
return fileURLToPath(new URL("../drizzle/", import.meta.url));
|
|
9
|
+
}
|
|
10
|
+
async function runMigrations(databaseUrl) {
|
|
11
|
+
if (!databaseUrl) throw new Error("DATABASE_URL is not set. Put it in your .env (e.g. postgres://postgres:postgres@localhost:8005/headless_lms) and re-run.");
|
|
12
|
+
const pool = new pg.Pool({
|
|
13
|
+
connectionString: databaseUrl,
|
|
14
|
+
max: 1
|
|
15
|
+
});
|
|
16
|
+
try {
|
|
17
|
+
await migrate(drizzle(pool), { migrationsFolder: migrationsFolder() });
|
|
18
|
+
} catch (err) {
|
|
19
|
+
throw new Error(`Migration failed against ${databaseUrl.replace(/\/\/.*@/, "//***@")}: ${err instanceof Error ? err.message : String(err)}`, { cause: err });
|
|
20
|
+
} finally {
|
|
21
|
+
await pool.end();
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
//#endregion
|
|
25
|
+
export { migrationsFolder, runMigrations };
|
|
26
|
+
|
|
27
|
+
//# sourceMappingURL=migrate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migrate.js","names":[],"sources":["../src/migrate.ts"],"sourcesContent":["// Runs the drizzle migrations shipped inside this package against the\n// installation's database. Fails loudly and legibly — this is the first\n// command every new installation runs.\nimport { fileURLToPath } from 'node:url';\nimport pg from 'pg';\nimport { drizzle } from 'drizzle-orm/node-postgres';\nimport { migrate } from 'drizzle-orm/node-postgres/migrator';\n\n/** drizzle/ sits at the package root: ../drizzle from src/ AND dist/. */\nexport function migrationsFolder(): string {\n return fileURLToPath(new URL('../drizzle/', import.meta.url));\n}\n\nexport async function runMigrations(databaseUrl: string): Promise<void> {\n if (!databaseUrl) {\n throw new Error(\n 'DATABASE_URL is not set. Put it in your .env (e.g. postgres://postgres:postgres@localhost:8005/headless_lms) and re-run.',\n );\n }\n const pool = new pg.Pool({ connectionString: databaseUrl, max: 1 });\n try {\n await migrate(drizzle(pool), { migrationsFolder: migrationsFolder() });\n } catch (err) {\n throw new Error(\n `Migration failed against ${databaseUrl.replace(/\\/\\/.*@/, '//***@')}: ${err instanceof Error ? err.message : String(err)}`,\n { cause: err },\n );\n } finally {\n await pool.end();\n }\n}\n"],"mappings":";;;;;;AASA,SAAgB,mBAA2B;CACzC,OAAO,cAAc,IAAI,IAAI,eAAe,OAAO,KAAK,GAAG,CAAC;AAC9D;AAEA,eAAsB,cAAc,aAAoC;CACtE,IAAI,CAAC,aACH,MAAM,IAAI,MACR,0HACF;CAEF,MAAM,OAAO,IAAI,GAAG,KAAK;EAAE,kBAAkB;EAAa,KAAK;CAAE,CAAC;CAClE,IAAI;EACF,MAAM,QAAQ,QAAQ,IAAI,GAAG,EAAE,kBAAkB,iBAAiB,EAAE,CAAC;CACvE,SAAS,KAAK;EACZ,MAAM,IAAI,MACR,4BAA4B,YAAY,QAAQ,WAAW,QAAQ,EAAE,IAAI,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,KACxH,EAAE,OAAO,IAAI,CACf;CACF,UAAU;EACR,MAAM,KAAK,IAAI;CACjB;AACF"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { DbExecutor } from "../client.js";
|
|
2
|
+
import { AssetsRepository } from "@headless-lms/core/assets";
|
|
3
|
+
import { Asset, AssetsQuery, Logger, Page } from "@headless-lms/core/types";
|
|
4
|
+
//#region src/repositories/assets.d.ts
|
|
5
|
+
declare class DrizzleAssetsRepository implements AssetsRepository {
|
|
6
|
+
private readonly db;
|
|
7
|
+
private readonly logger;
|
|
8
|
+
constructor(db: DbExecutor, logger?: Logger);
|
|
9
|
+
insert(orgId: string, asset: Asset): Promise<Asset>;
|
|
10
|
+
list(orgId: string, query: AssetsQuery): Promise<Page<Asset>>;
|
|
11
|
+
findById(orgId: string, id: string): Promise<Asset | null>;
|
|
12
|
+
update(id: string, patch: Partial<Pick<Asset, 'size' | 'contentType' | 'status'>>): Promise<Asset | null>;
|
|
13
|
+
delete(id: string): Promise<boolean>;
|
|
14
|
+
}
|
|
15
|
+
//#endregion
|
|
16
|
+
export { DrizzleAssetsRepository };
|
|
17
|
+
//# sourceMappingURL=assets.d.ts.map
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { assets } from "../schema/assets.js";
|
|
2
|
+
import { and, asc, desc, eq, ilike, sql } from "drizzle-orm";
|
|
3
|
+
import { noopLogger } from "@headless-lms/core/shared/logger";
|
|
4
|
+
//#region src/repositories/assets.ts
|
|
5
|
+
function toAsset(row) {
|
|
6
|
+
return {
|
|
7
|
+
orgId: row.orgId,
|
|
8
|
+
id: row.id,
|
|
9
|
+
key: row.key,
|
|
10
|
+
kind: row.kind,
|
|
11
|
+
filename: row.filename,
|
|
12
|
+
contentType: row.contentType,
|
|
13
|
+
size: row.size,
|
|
14
|
+
status: row.status,
|
|
15
|
+
uploadedBy: row.uploadedBy,
|
|
16
|
+
createdAt: row.createdAt
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
const SORT_COLUMNS = {
|
|
20
|
+
filename: assets.filename,
|
|
21
|
+
size: assets.size,
|
|
22
|
+
createdAt: assets.createdAt
|
|
23
|
+
};
|
|
24
|
+
var DrizzleAssetsRepository = class {
|
|
25
|
+
db;
|
|
26
|
+
logger;
|
|
27
|
+
constructor(db, logger = noopLogger) {
|
|
28
|
+
this.db = db;
|
|
29
|
+
this.logger = logger;
|
|
30
|
+
}
|
|
31
|
+
async insert(orgId, asset) {
|
|
32
|
+
if (asset.orgId !== orgId) throw new Error("asset org mismatch");
|
|
33
|
+
const [row] = await this.db.insert(assets).values({
|
|
34
|
+
id: asset.id,
|
|
35
|
+
orgId: asset.orgId,
|
|
36
|
+
key: asset.key,
|
|
37
|
+
kind: asset.kind,
|
|
38
|
+
filename: asset.filename,
|
|
39
|
+
contentType: asset.contentType,
|
|
40
|
+
size: asset.size,
|
|
41
|
+
status: asset.status,
|
|
42
|
+
uploadedBy: asset.uploadedBy,
|
|
43
|
+
createdAt: new Date(asset.createdAt)
|
|
44
|
+
}).returning();
|
|
45
|
+
if (!row) throw new Error("failed to insert asset");
|
|
46
|
+
return toAsset(row);
|
|
47
|
+
}
|
|
48
|
+
async list(orgId, query) {
|
|
49
|
+
const filters = [eq(assets.orgId, orgId)];
|
|
50
|
+
if (query.kind) filters.push(eq(assets.kind, query.kind));
|
|
51
|
+
const q = query.search?.trim();
|
|
52
|
+
if (q) filters.push(ilike(assets.filename, `%${q}%`));
|
|
53
|
+
const where = and(...filters);
|
|
54
|
+
const orderBy = (() => {
|
|
55
|
+
if (!query.sort) return desc(assets.createdAt);
|
|
56
|
+
const descending = query.sort.startsWith("-");
|
|
57
|
+
const field = descending ? query.sort.slice(1) : query.sort;
|
|
58
|
+
const col = SORT_COLUMNS[field] ?? assets.createdAt;
|
|
59
|
+
return descending ? desc(col) : asc(col);
|
|
60
|
+
})();
|
|
61
|
+
const offset = (query.page - 1) * query.pageSize;
|
|
62
|
+
const rows = await this.db.select().from(assets).where(where).orderBy(orderBy).limit(query.pageSize).offset(offset);
|
|
63
|
+
const counted = await this.db.select({ value: sql`count(*)::int` }).from(assets).where(where);
|
|
64
|
+
return {
|
|
65
|
+
rows: rows.map(toAsset),
|
|
66
|
+
total: counted[0]?.value ?? 0,
|
|
67
|
+
page: query.page,
|
|
68
|
+
pageSize: query.pageSize
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
async findById(orgId, id) {
|
|
72
|
+
const [row] = await this.db.select().from(assets).where(and(eq(assets.orgId, orgId), eq(assets.id, id))).limit(1);
|
|
73
|
+
return row ? toAsset(row) : null;
|
|
74
|
+
}
|
|
75
|
+
async update(id, patch) {
|
|
76
|
+
const [row] = await this.db.update(assets).set({
|
|
77
|
+
...patch.size !== void 0 ? { size: patch.size } : {},
|
|
78
|
+
...patch.contentType !== void 0 ? { contentType: patch.contentType } : {},
|
|
79
|
+
...patch.status !== void 0 ? { status: patch.status } : {}
|
|
80
|
+
}).where(eq(assets.id, id)).returning();
|
|
81
|
+
return row ? toAsset(row) : null;
|
|
82
|
+
}
|
|
83
|
+
async delete(id) {
|
|
84
|
+
return (await this.db.delete(assets).where(eq(assets.id, id)).returning({ id: assets.id })).length > 0;
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
//#endregion
|
|
88
|
+
export { DrizzleAssetsRepository };
|
|
89
|
+
|
|
90
|
+
//# sourceMappingURL=assets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"assets.js","names":[],"sources":["../../src/repositories/assets.ts"],"sourcesContent":["// assets — Drizzle repository (implements the core outbound port).\nimport { and, eq, ilike, sql, asc, desc, type SQL } from 'drizzle-orm';\nimport type { AssetsRepository } from '@headless-lms/core/assets';\nimport type {\n Asset,\n AssetKind,\n AssetStatus,\n AssetsQuery,\n Logger,\n Page,\n} from '@headless-lms/core/types';\nimport { assets } from '../schema/assets.js';\nimport { noopLogger } from '@headless-lms/core/shared/logger';\nimport type { DbExecutor } from '../client.js';\n\ntype Row = typeof assets.$inferSelect;\n\nfunction toAsset(row: Row): Asset {\n return {\n orgId: row.orgId,\n id: row.id,\n key: row.key,\n kind: row.kind as AssetKind,\n filename: row.filename,\n contentType: row.contentType,\n size: row.size,\n status: row.status as AssetStatus,\n uploadedBy: row.uploadedBy,\n createdAt: row.createdAt,\n };\n}\n\n// Whitelisted sort columns; anything else falls back to newest-first.\nconst SORT_COLUMNS = {\n filename: assets.filename,\n size: assets.size,\n createdAt: assets.createdAt,\n} as const;\n\nexport class DrizzleAssetsRepository implements AssetsRepository {\n constructor(\n private readonly db: DbExecutor,\n private readonly logger: Logger = noopLogger,\n ) {}\n\n async insert(orgId: string, asset: Asset): Promise<Asset> {\n if (asset.orgId !== orgId) {\n throw new Error('asset org mismatch');\n }\n const [row] = await this.db\n .insert(assets)\n .values({\n id: asset.id,\n orgId: asset.orgId,\n key: asset.key,\n kind: asset.kind,\n filename: asset.filename,\n contentType: asset.contentType,\n size: asset.size,\n status: asset.status,\n uploadedBy: asset.uploadedBy,\n createdAt: new Date(asset.createdAt),\n })\n .returning();\n if (!row) {\n throw new Error('failed to insert asset');\n }\n return toAsset(row);\n }\n\n async list(orgId: string, query: AssetsQuery): Promise<Page<Asset>> {\n const filters: (SQL | undefined)[] = [eq(assets.orgId, orgId)];\n if (query.kind) {\n filters.push(eq(assets.kind, query.kind));\n }\n const q = query.search?.trim();\n if (q) {\n filters.push(ilike(assets.filename, `%${q}%`));\n }\n const where = and(...filters);\n\n const orderBy = (() => {\n if (!query.sort) {\n return desc(assets.createdAt);\n }\n const descending = query.sort.startsWith('-');\n const field = descending ? query.sort.slice(1) : query.sort;\n const col = SORT_COLUMNS[field as keyof typeof SORT_COLUMNS] ?? assets.createdAt;\n return descending ? desc(col) : asc(col);\n })();\n\n const offset = (query.page - 1) * query.pageSize;\n const rows = await this.db\n .select()\n .from(assets)\n .where(where)\n .orderBy(orderBy)\n .limit(query.pageSize)\n .offset(offset);\n\n const counted = await this.db\n .select({ value: sql<number>`count(*)::int` })\n .from(assets)\n .where(where);\n\n return {\n rows: rows.map(toAsset),\n total: counted[0]?.value ?? 0,\n page: query.page,\n pageSize: query.pageSize,\n };\n }\n\n async findById(orgId: string, id: string): Promise<Asset | null> {\n const [row] = await this.db\n .select()\n .from(assets)\n .where(and(eq(assets.orgId, orgId), eq(assets.id, id)))\n .limit(1);\n return row ? toAsset(row) : null;\n }\n\n async update(\n id: string,\n patch: Partial<Pick<Asset, 'size' | 'contentType' | 'status'>>,\n ): Promise<Asset | null> {\n const [row] = await this.db\n .update(assets)\n .set({\n ...(patch.size !== undefined ? { size: patch.size } : {}),\n ...(patch.contentType !== undefined ? { contentType: patch.contentType } : {}),\n ...(patch.status !== undefined ? { status: patch.status } : {}),\n })\n .where(eq(assets.id, id))\n .returning();\n return row ? toAsset(row) : null;\n }\n\n async delete(id: string): Promise<boolean> {\n const deleted = await this.db\n .delete(assets)\n .where(eq(assets.id, id))\n .returning({ id: assets.id });\n return deleted.length > 0;\n }\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { DbExecutor } from "../client.js";
|
|
2
|
+
import { Logger } from "@headless-lms/core/shared/ports";
|
|
3
|
+
import { Automation, AutomationRun, AutomationRunsQuery, AutomationRunsRepository, AutomationsRepository, CreateAutomationInput, NewAutomationRun, Page, UpdateAutomationInput } from "@headless-lms/core/automations";
|
|
4
|
+
//#region src/repositories/automations.d.ts
|
|
5
|
+
declare class DrizzleAutomationsRepository implements AutomationsRepository {
|
|
6
|
+
private readonly db;
|
|
7
|
+
private readonly logger;
|
|
8
|
+
constructor(db: DbExecutor, logger?: Logger);
|
|
9
|
+
insert(orgId: string, input: CreateAutomationInput): Promise<Automation>;
|
|
10
|
+
update(orgId: string, id: string, patch: UpdateAutomationInput): Promise<Automation | null>;
|
|
11
|
+
delete(orgId: string, id: string): Promise<Automation | null>;
|
|
12
|
+
findById(orgId: string, id: string): Promise<Automation | null>;
|
|
13
|
+
listByOrg(orgId: string): Promise<Automation[]>;
|
|
14
|
+
listByTrigger(orgId: string, trigger: string): Promise<Automation[]>;
|
|
15
|
+
}
|
|
16
|
+
declare class DrizzleAutomationRunsRepository implements AutomationRunsRepository {
|
|
17
|
+
private readonly db;
|
|
18
|
+
private readonly logger;
|
|
19
|
+
constructor(db: DbExecutor, logger?: Logger);
|
|
20
|
+
insert(orgId: string, run: NewAutomationRun): Promise<AutomationRun | null>;
|
|
21
|
+
recordOutcome(orgId: string, id: string, outcome: {
|
|
22
|
+
status: AutomationRun['status'];
|
|
23
|
+
actionResults: AutomationRun['actionResults'];
|
|
24
|
+
finishedAt: Date;
|
|
25
|
+
}): Promise<AutomationRun | null>;
|
|
26
|
+
list(orgId: string, automationId: string, query: AutomationRunsQuery): Promise<Page<AutomationRun>>;
|
|
27
|
+
}
|
|
28
|
+
//#endregion
|
|
29
|
+
export { DrizzleAutomationRunsRepository, DrizzleAutomationsRepository };
|
|
30
|
+
//# sourceMappingURL=automations.d.ts.map
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import { automationRuns, automations } from "../schema/automations.js";
|
|
2
|
+
import "../schema/index.js";
|
|
3
|
+
import { and, asc, desc, eq, sql } from "drizzle-orm";
|
|
4
|
+
import { noopLogger } from "@headless-lms/core/shared/logger";
|
|
5
|
+
//#region src/repositories/automations.ts
|
|
6
|
+
const automationSelection = {
|
|
7
|
+
orgId: automations.orgId,
|
|
8
|
+
id: automations.id,
|
|
9
|
+
name: automations.name,
|
|
10
|
+
description: automations.description,
|
|
11
|
+
trigger: automations.trigger,
|
|
12
|
+
actions: automations.actions,
|
|
13
|
+
enabled: automations.enabled,
|
|
14
|
+
createdAt: automations.createdAt,
|
|
15
|
+
updatedAt: automations.updatedAt
|
|
16
|
+
};
|
|
17
|
+
function toAutomation(row) {
|
|
18
|
+
return {
|
|
19
|
+
orgId: row.orgId,
|
|
20
|
+
id: row.id,
|
|
21
|
+
name: row.name,
|
|
22
|
+
description: row.description,
|
|
23
|
+
trigger: row.trigger,
|
|
24
|
+
actions: row.actions,
|
|
25
|
+
enabled: row.enabled,
|
|
26
|
+
createdAt: row.createdAt,
|
|
27
|
+
updatedAt: row.updatedAt
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
var DrizzleAutomationsRepository = class {
|
|
31
|
+
db;
|
|
32
|
+
logger;
|
|
33
|
+
constructor(db, logger = noopLogger) {
|
|
34
|
+
this.db = db;
|
|
35
|
+
this.logger = logger;
|
|
36
|
+
}
|
|
37
|
+
async insert(orgId, input) {
|
|
38
|
+
const [inserted] = await this.db.insert(automations).values({
|
|
39
|
+
orgId,
|
|
40
|
+
name: input.name,
|
|
41
|
+
description: input.description,
|
|
42
|
+
trigger: input.trigger,
|
|
43
|
+
actions: input.actions
|
|
44
|
+
}).returning({ id: automations.id });
|
|
45
|
+
if (!inserted) throw new Error("failed to insert automation");
|
|
46
|
+
const created = await this.findById(orgId, inserted.id);
|
|
47
|
+
if (!created) throw new Error("failed to load created automation");
|
|
48
|
+
return created;
|
|
49
|
+
}
|
|
50
|
+
async update(orgId, id, patch) {
|
|
51
|
+
const set = { updatedAt: /* @__PURE__ */ new Date() };
|
|
52
|
+
if (patch.name !== void 0) set.name = patch.name;
|
|
53
|
+
if (patch.description !== void 0) set.description = patch.description;
|
|
54
|
+
if (patch.trigger !== void 0) set.trigger = patch.trigger;
|
|
55
|
+
if (patch.actions !== void 0) set.actions = patch.actions;
|
|
56
|
+
if (patch.enabled !== void 0) set.enabled = patch.enabled;
|
|
57
|
+
const [updated] = await this.db.update(automations).set(set).where(and(eq(automations.orgId, orgId), eq(automations.id, id))).returning({ id: automations.id });
|
|
58
|
+
if (!updated) return null;
|
|
59
|
+
return this.findById(orgId, id);
|
|
60
|
+
}
|
|
61
|
+
async delete(orgId, id) {
|
|
62
|
+
const [deleted] = await this.db.delete(automations).where(and(eq(automations.orgId, orgId), eq(automations.id, id))).returning(automationSelection);
|
|
63
|
+
return deleted ? toAutomation(deleted) : null;
|
|
64
|
+
}
|
|
65
|
+
async findById(orgId, id) {
|
|
66
|
+
const [row] = await this.db.select(automationSelection).from(automations).where(and(eq(automations.orgId, orgId), eq(automations.id, id))).limit(1);
|
|
67
|
+
return row ? toAutomation(row) : null;
|
|
68
|
+
}
|
|
69
|
+
async listByOrg(orgId) {
|
|
70
|
+
return (await this.db.select(automationSelection).from(automations).where(eq(automations.orgId, orgId)).orderBy(desc(automations.createdAt))).map(toAutomation);
|
|
71
|
+
}
|
|
72
|
+
async listByTrigger(orgId, trigger) {
|
|
73
|
+
return (await this.db.select(automationSelection).from(automations).where(and(eq(automations.orgId, orgId), eq(automations.trigger, trigger))).orderBy(desc(automations.createdAt))).map(toAutomation);
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
const runSelection = {
|
|
77
|
+
id: automationRuns.id,
|
|
78
|
+
orgId: automationRuns.orgId,
|
|
79
|
+
automationId: automationRuns.automationId,
|
|
80
|
+
trigger: automationRuns.trigger,
|
|
81
|
+
eventId: automationRuns.eventId,
|
|
82
|
+
event: automationRuns.event,
|
|
83
|
+
status: automationRuns.status,
|
|
84
|
+
actionResults: automationRuns.actionResults,
|
|
85
|
+
startedAt: automationRuns.startedAt,
|
|
86
|
+
finishedAt: automationRuns.finishedAt
|
|
87
|
+
};
|
|
88
|
+
function toAutomationRun(row) {
|
|
89
|
+
return {
|
|
90
|
+
id: row.id,
|
|
91
|
+
orgId: row.orgId,
|
|
92
|
+
automationId: row.automationId,
|
|
93
|
+
trigger: row.trigger,
|
|
94
|
+
eventId: row.eventId,
|
|
95
|
+
event: row.event,
|
|
96
|
+
status: row.status,
|
|
97
|
+
actionResults: row.actionResults,
|
|
98
|
+
startedAt: row.startedAt,
|
|
99
|
+
finishedAt: row.finishedAt
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
const sortColumns = {
|
|
103
|
+
startedAt: automationRuns.startedAt,
|
|
104
|
+
finishedAt: automationRuns.finishedAt,
|
|
105
|
+
status: automationRuns.status
|
|
106
|
+
};
|
|
107
|
+
var DrizzleAutomationRunsRepository = class {
|
|
108
|
+
db;
|
|
109
|
+
logger;
|
|
110
|
+
constructor(db, logger = noopLogger) {
|
|
111
|
+
this.db = db;
|
|
112
|
+
this.logger = logger;
|
|
113
|
+
}
|
|
114
|
+
async insert(orgId, run) {
|
|
115
|
+
const [inserted] = await this.db.insert(automationRuns).values({
|
|
116
|
+
orgId,
|
|
117
|
+
automationId: run.automationId,
|
|
118
|
+
trigger: run.trigger,
|
|
119
|
+
eventId: run.event.id,
|
|
120
|
+
event: run.event,
|
|
121
|
+
status: run.status,
|
|
122
|
+
actionResults: run.actionResults,
|
|
123
|
+
startedAt: run.startedAt,
|
|
124
|
+
finishedAt: run.finishedAt
|
|
125
|
+
}).onConflictDoNothing({ target: [
|
|
126
|
+
automationRuns.orgId,
|
|
127
|
+
automationRuns.automationId,
|
|
128
|
+
automationRuns.eventId
|
|
129
|
+
] }).returning(runSelection);
|
|
130
|
+
return inserted ? toAutomationRun(inserted) : null;
|
|
131
|
+
}
|
|
132
|
+
async recordOutcome(orgId, id, outcome) {
|
|
133
|
+
const [updated] = await this.db.update(automationRuns).set({
|
|
134
|
+
status: outcome.status,
|
|
135
|
+
actionResults: outcome.actionResults,
|
|
136
|
+
finishedAt: outcome.finishedAt
|
|
137
|
+
}).where(and(eq(automationRuns.orgId, orgId), eq(automationRuns.id, id))).returning(runSelection);
|
|
138
|
+
return updated ? toAutomationRun(updated) : null;
|
|
139
|
+
}
|
|
140
|
+
async list(orgId, automationId, query) {
|
|
141
|
+
const conditions = [eq(automationRuns.orgId, orgId), eq(automationRuns.automationId, automationId)];
|
|
142
|
+
if (query.status) conditions.push(eq(automationRuns.status, query.status));
|
|
143
|
+
const where = and(...conditions);
|
|
144
|
+
let orderBy;
|
|
145
|
+
if (query.sort) {
|
|
146
|
+
const isDesc = query.sort.startsWith("-");
|
|
147
|
+
const field = isDesc ? query.sort.slice(1) : query.sort;
|
|
148
|
+
const col = sortColumns[field] ?? automationRuns.startedAt;
|
|
149
|
+
orderBy = isDesc ? desc(col) : asc(col);
|
|
150
|
+
} else orderBy = desc(automationRuns.startedAt);
|
|
151
|
+
const offset = (query.page - 1) * query.pageSize;
|
|
152
|
+
const rows = await this.db.select(runSelection).from(automationRuns).where(where).orderBy(orderBy).limit(query.pageSize).offset(offset);
|
|
153
|
+
const [{ total } = { total: 0 }] = await this.db.select({ total: sql`cast(count(*) as int)` }).from(automationRuns).where(where);
|
|
154
|
+
return {
|
|
155
|
+
rows: rows.map(toAutomationRun),
|
|
156
|
+
total,
|
|
157
|
+
page: query.page,
|
|
158
|
+
pageSize: query.pageSize
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
};
|
|
162
|
+
//#endregion
|
|
163
|
+
export { DrizzleAutomationRunsRepository, DrizzleAutomationsRepository };
|
|
164
|
+
|
|
165
|
+
//# sourceMappingURL=automations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"automations.js","names":[],"sources":["../../src/repositories/automations.ts"],"sourcesContent":["// automations — Drizzle repositories (implement the core outbound ports).\n// Org-scoped: every method takes the domain `organizations.id` and constrains\n// its queries to that tenant. `Automation`/`AutomationRun` carry no `orgId`\n// column of their own in the domain type (mirrors the `Entitlement` shape) —\n// `AutomationRun` is the one exception, since it's the run's own `orgId`\n// field the service reads back off `handle`'s event.\nimport { and, asc, desc, eq, sql, type SQL } from 'drizzle-orm';\nimport type { DbExecutor } from '../client.js';\nimport type {\n Automation,\n AutomationRun,\n AutomationRunsQuery,\n AutomationRunsRepository,\n AutomationsRepository,\n CreateAutomationInput,\n NewAutomationRun,\n Page,\n UpdateAutomationInput,\n} from '@headless-lms/core/automations';\nimport { automations, automationRuns } from '../schema/index.js';\nimport type { Logger } from '@headless-lms/core/shared/ports';\nimport { noopLogger } from '@headless-lms/core/shared/logger';\n\nconst automationSelection = {\n orgId: automations.orgId,\n id: automations.id,\n name: automations.name,\n description: automations.description,\n trigger: automations.trigger,\n actions: automations.actions,\n enabled: automations.enabled,\n createdAt: automations.createdAt,\n updatedAt: automations.updatedAt,\n};\n\ninterface AutomationRow {\n orgId: string;\n id: string;\n name: string;\n description: string | null;\n trigger: string;\n actions: Automation['actions'];\n enabled: boolean;\n createdAt: Date;\n updatedAt: Date;\n}\n\nfunction toAutomation(row: AutomationRow): Automation {\n return {\n orgId: row.orgId,\n id: row.id,\n name: row.name,\n description: row.description,\n trigger: row.trigger,\n actions: row.actions,\n enabled: row.enabled,\n createdAt: row.createdAt,\n updatedAt: row.updatedAt,\n };\n}\n\nexport class DrizzleAutomationsRepository implements AutomationsRepository {\n constructor(\n private readonly db: DbExecutor,\n private readonly logger: Logger = noopLogger,\n ) {}\n\n async insert(orgId: string, input: CreateAutomationInput): Promise<Automation> {\n const [inserted] = await this.db\n .insert(automations)\n .values({\n orgId,\n name: input.name,\n description: input.description,\n trigger: input.trigger,\n actions: input.actions,\n })\n .returning({ id: automations.id });\n if (!inserted) {\n throw new Error('failed to insert automation');\n }\n const created = await this.findById(orgId, inserted.id);\n if (!created) {\n throw new Error('failed to load created automation');\n }\n return created;\n }\n\n async update(orgId: string, id: string, patch: UpdateAutomationInput): Promise<Automation | null> {\n const set: Record<string, unknown> = { updatedAt: new Date() };\n if (patch.name !== undefined) {\n set.name = patch.name;\n }\n if (patch.description !== undefined) {\n set.description = patch.description;\n }\n if (patch.trigger !== undefined) {\n set.trigger = patch.trigger;\n }\n if (patch.actions !== undefined) {\n set.actions = patch.actions;\n }\n if (patch.enabled !== undefined) {\n set.enabled = patch.enabled;\n }\n\n const [updated] = await this.db\n .update(automations)\n .set(set)\n .where(and(eq(automations.orgId, orgId), eq(automations.id, id)))\n .returning({ id: automations.id });\n if (!updated) {\n return null;\n }\n return this.findById(orgId, id);\n }\n\n async delete(orgId: string, id: string): Promise<Automation | null> {\n const [deleted] = await this.db\n .delete(automations)\n .where(and(eq(automations.orgId, orgId), eq(automations.id, id)))\n .returning(automationSelection);\n return deleted ? toAutomation(deleted) : null;\n }\n\n async findById(orgId: string, id: string): Promise<Automation | null> {\n const [row] = await this.db\n .select(automationSelection)\n .from(automations)\n .where(and(eq(automations.orgId, orgId), eq(automations.id, id)))\n .limit(1);\n return row ? toAutomation(row) : null;\n }\n\n async listByOrg(orgId: string): Promise<Automation[]> {\n const rows = await this.db\n .select(automationSelection)\n .from(automations)\n .where(eq(automations.orgId, orgId))\n .orderBy(desc(automations.createdAt));\n return rows.map(toAutomation);\n }\n\n async listByTrigger(orgId: string, trigger: string): Promise<Automation[]> {\n const rows = await this.db\n .select(automationSelection)\n .from(automations)\n .where(and(eq(automations.orgId, orgId), eq(automations.trigger, trigger)))\n .orderBy(desc(automations.createdAt));\n return rows.map(toAutomation);\n }\n}\n\nconst runSelection = {\n id: automationRuns.id,\n orgId: automationRuns.orgId,\n automationId: automationRuns.automationId,\n trigger: automationRuns.trigger,\n eventId: automationRuns.eventId,\n event: automationRuns.event,\n status: automationRuns.status,\n actionResults: automationRuns.actionResults,\n startedAt: automationRuns.startedAt,\n finishedAt: automationRuns.finishedAt,\n};\n\ninterface RunRow {\n id: string;\n orgId: string;\n automationId: string;\n trigger: string;\n eventId: string;\n event: AutomationRun['event'];\n status: AutomationRun['status'];\n actionResults: AutomationRun['actionResults'];\n startedAt: Date;\n finishedAt: Date | null;\n}\n\nfunction toAutomationRun(row: RunRow): AutomationRun {\n return {\n id: row.id,\n orgId: row.orgId,\n automationId: row.automationId,\n trigger: row.trigger,\n eventId: row.eventId,\n event: row.event,\n status: row.status,\n actionResults: row.actionResults,\n startedAt: row.startedAt,\n finishedAt: row.finishedAt,\n };\n}\n\n// Sortable columns by the client-facing field name. `-field` = desc.\nconst sortColumns = {\n startedAt: automationRuns.startedAt,\n finishedAt: automationRuns.finishedAt,\n status: automationRuns.status,\n} as const;\n\nexport class DrizzleAutomationRunsRepository implements AutomationRunsRepository {\n constructor(\n private readonly db: DbExecutor,\n private readonly logger: Logger = noopLogger,\n ) {}\n\n async insert(orgId: string, run: NewAutomationRun): Promise<AutomationRun | null> {\n const [inserted] = await this.db\n .insert(automationRuns)\n .values({\n orgId,\n automationId: run.automationId,\n trigger: run.trigger,\n eventId: run.event.id,\n event: run.event,\n status: run.status,\n actionResults: run.actionResults,\n startedAt: run.startedAt,\n finishedAt: run.finishedAt,\n })\n // A redelivered trigger event hits the unique (org, automation, event) index; no row comes back.\n .onConflictDoNothing({\n target: [automationRuns.orgId, automationRuns.automationId, automationRuns.eventId],\n })\n .returning(runSelection);\n return inserted ? toAutomationRun(inserted) : null;\n }\n\n async recordOutcome(\n orgId: string,\n id: string,\n outcome: {\n status: AutomationRun['status'];\n actionResults: AutomationRun['actionResults'];\n finishedAt: Date;\n },\n ): Promise<AutomationRun | null> {\n const [updated] = await this.db\n .update(automationRuns)\n .set({\n status: outcome.status,\n actionResults: outcome.actionResults,\n finishedAt: outcome.finishedAt,\n })\n .where(and(eq(automationRuns.orgId, orgId), eq(automationRuns.id, id)))\n .returning(runSelection);\n return updated ? toAutomationRun(updated) : null;\n }\n\n async list(orgId: string, automationId: string, query: AutomationRunsQuery): Promise<Page<AutomationRun>> {\n const conditions: SQL[] = [\n eq(automationRuns.orgId, orgId),\n eq(automationRuns.automationId, automationId),\n ];\n if (query.status) {\n conditions.push(eq(automationRuns.status, query.status));\n }\n const where = and(...conditions);\n\n // Sort: `-field` for descending; default to most-recently started first.\n let orderBy: SQL;\n if (query.sort) {\n const isDesc = query.sort.startsWith('-');\n const field = (isDesc ? query.sort.slice(1) : query.sort) as keyof typeof sortColumns;\n const col = sortColumns[field] ?? automationRuns.startedAt;\n orderBy = isDesc ? desc(col) : asc(col);\n } else {\n orderBy = desc(automationRuns.startedAt);\n }\n\n const offset = (query.page - 1) * query.pageSize;\n\n const rows = await this.db\n .select(runSelection)\n .from(automationRuns)\n .where(where)\n .orderBy(orderBy)\n .limit(query.pageSize)\n .offset(offset);\n\n const [{ total } = { total: 0 }] = await this.db\n .select({ total: sql<number>`cast(count(*) as int)` })\n .from(automationRuns)\n .where(where);\n\n return {\n rows: rows.map(toAutomationRun),\n total,\n page: query.page,\n pageSize: query.pageSize,\n };\n }\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { DbExecutor } from "../client.js";
|
|
2
|
+
import { Logger } from "@headless-lms/core/shared/ports";
|
|
3
|
+
import { Activity, AddDownloadAssetInput, ContentRepository, Course, CreateCourseInput, CreateDownloadInput, Download, DownloadAsset, ListCoursesQuery, ListDownloadsQuery, Module, Page, SaveActivityInput, UpdateCourseInput, UpdateDownloadInput } from "@headless-lms/core/content";
|
|
4
|
+
//#region src/repositories/content.d.ts
|
|
5
|
+
declare class DrizzleContentRepository implements ContentRepository {
|
|
6
|
+
private readonly db;
|
|
7
|
+
private readonly logger;
|
|
8
|
+
constructor(db: DbExecutor, logger?: Logger);
|
|
9
|
+
/** On the root db this opens a transaction; tx-bound (ContentUnitOfWork) it
|
|
10
|
+
* nests as a savepoint inside the surrounding transaction. */
|
|
11
|
+
private tx;
|
|
12
|
+
list(orgId: string, query: ListCoursesQuery): Promise<Page<Course>>;
|
|
13
|
+
findById(orgId: string, id: string): Promise<Course | null>;
|
|
14
|
+
create(orgId: string, input: CreateCourseInput, slug: string): Promise<Course>;
|
|
15
|
+
update(orgId: string, id: string, patch: UpdateCourseInput): Promise<Course | null>;
|
|
16
|
+
delete(orgId: string, id: string): Promise<boolean>;
|
|
17
|
+
listForCourse(orgId: string, courseId: string): Promise<Module[]>;
|
|
18
|
+
listActivitiesForCourse(orgId: string, courseId: string): Promise<Activity[]>;
|
|
19
|
+
findActivity(orgId: string, activityId: string): Promise<Activity | null>;
|
|
20
|
+
findModule(orgId: string, moduleId: string): Promise<Module | null>;
|
|
21
|
+
/** The course's full ordered module list. */
|
|
22
|
+
private listModules;
|
|
23
|
+
/** Assert the module belongs to the org + course; throw otherwise. */
|
|
24
|
+
private assertModule;
|
|
25
|
+
/** Replace an activity's ordered asset links with `assetIds`. */
|
|
26
|
+
private replaceActivityAssets;
|
|
27
|
+
createModule(orgId: string, courseId: string, title: string): Promise<Module[]>;
|
|
28
|
+
updateModule(orgId: string, courseId: string, moduleId: string, title: string): Promise<Module[]>;
|
|
29
|
+
deleteModule(orgId: string, courseId: string, moduleId: string): Promise<Module[]>;
|
|
30
|
+
reorderModules(orgId: string, courseId: string, orderedIds: string[]): Promise<Module[]>;
|
|
31
|
+
reorderActivities(orgId: string, courseId: string, moduleId: string, orderedIds: string[]): Promise<Module[]>;
|
|
32
|
+
saveActivity(orgId: string, courseId: string, moduleId: string, input: SaveActivityInput, activityId?: string): Promise<{
|
|
33
|
+
modules: Module[];
|
|
34
|
+
activity: Activity;
|
|
35
|
+
}>;
|
|
36
|
+
deleteActivity(orgId: string, courseId: string, moduleId: string, activityId: string): Promise<Module[]>;
|
|
37
|
+
listDownloads(orgId: string, query: ListDownloadsQuery): Promise<Page<Download>>;
|
|
38
|
+
getDownload(orgId: string, id: string): Promise<Download | null>;
|
|
39
|
+
createDownload(orgId: string, input: CreateDownloadInput, slug: string): Promise<Download>;
|
|
40
|
+
updateDownload(orgId: string, id: string, patch: UpdateDownloadInput): Promise<Download | null>;
|
|
41
|
+
deleteDownload(orgId: string, id: string): Promise<boolean>;
|
|
42
|
+
listDownloadAssets(orgId: string, downloadId: string): Promise<DownloadAsset[]>;
|
|
43
|
+
/** Assert the download exists in the org; throw otherwise. */
|
|
44
|
+
private assertDownload;
|
|
45
|
+
addDownloadAsset(orgId: string, downloadId: string, input: AddDownloadAssetInput): Promise<DownloadAsset[]>;
|
|
46
|
+
removeDownloadAsset(orgId: string, downloadId: string, assetId: string): Promise<DownloadAsset[]>;
|
|
47
|
+
renameDownloadAsset(orgId: string, downloadId: string, assetId: string, displayName: string | null): Promise<DownloadAsset[]>;
|
|
48
|
+
reorderDownloadAssets(orgId: string, downloadId: string, assetIds: string[]): Promise<DownloadAsset[]>;
|
|
49
|
+
}
|
|
50
|
+
//#endregion
|
|
51
|
+
export { DrizzleContentRepository };
|
|
52
|
+
//# sourceMappingURL=content.d.ts.map
|