bopodev-db 0.1.26 → 0.1.27

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.
@@ -1,5 +1,5 @@
1
1
 
2
2
  
3
- > bopodev-db@0.1.26 build /Users/danielkrusenstrahle/Documents/Projects/Monorepo/bopohq/packages/db
3
+ > bopodev-db@0.1.27 build /Users/danielkrusenstrahle/Documents/Projects/Monorepo/bopohq/packages/db
4
4
  > tsc -p tsconfig.json --emitDeclarationOnly
5
5
 
@@ -1,4 +1,4 @@
1
1
 
2
- > bopodev-db@0.1.24 typecheck /Users/danielkrusenstrahle/Documents/Projects/Monorepo/bopohq/packages/db
2
+ > bopodev-db@0.1.26 typecheck /Users/danielkrusenstrahle/Documents/Projects/Monorepo/bopohq/packages/db
3
3
  > tsc -p tsconfig.json --noEmit
4
4
 
package/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # `packages/db`
2
+
3
+ Database schema and repository layer for Bopo, backed by Drizzle + PGlite.
4
+
5
+ ## Responsibilities
6
+
7
+ - Define schema models and migrations/bootstrap behavior.
8
+ - Expose repository functions used by API services/routes.
9
+ - Provide typed DB access primitives for shared business logic.
10
+
11
+ ## Usage
12
+
13
+ Primary consumer is `apps/api`.
14
+
15
+ ## Commands
16
+
17
+ - `pnpm --filter bopodev-db build`
18
+ - `pnpm --filter bopodev-db typecheck`
19
+
20
+ ## Notes
21
+
22
+ - Default DB path is managed by app/runtime config; see configuration docs before overriding.
23
+ - API startup bootstraps DB and registers built-in plugins/templates.
24
+
25
+ ## Related Docs
26
+
27
+ - `docs/developer/architecture.md`
28
+ - `docs/developer/configuration-reference.md`
29
+ - `docs/operations/deployment.md`
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  export * from "./bootstrap";
2
2
  export * from "./client";
3
+ export { resolveDefaultDbPath, resolveBopoInstanceRoot } from "./default-paths";
3
4
  export * from "./repositories";
4
5
  export * from "./schema";
@@ -326,6 +326,23 @@ export declare function listIssues(db: BopoDb, companyId: string, projectId?: st
326
326
  createdAt: Date;
327
327
  updatedAt: Date;
328
328
  }[]>;
329
+ export declare function getIssue(db: BopoDb, companyId: string, issueId: string): Promise<{
330
+ id: string;
331
+ companyId: string;
332
+ projectId: string;
333
+ parentIssueId: string | null;
334
+ title: string;
335
+ body: string | null;
336
+ status: string;
337
+ priority: string;
338
+ assigneeAgentId: string | null;
339
+ labelsJson: string;
340
+ tagsJson: string;
341
+ isClaimed: boolean;
342
+ claimedByHeartbeatRunId: string | null;
343
+ createdAt: Date;
344
+ updatedAt: Date;
345
+ } | null>;
329
346
  export declare function createIssue(db: BopoDb, input: {
330
347
  companyId: string;
331
348
  projectId: string;
@@ -1433,39 +1450,3 @@ export declare function createTemplateInstall(db: BopoDb, input: {
1433
1450
  templateVersionId: string | null;
1434
1451
  summaryJson: string;
1435
1452
  } | null>;
1436
- export declare function listModelPricing(db: BopoDb, companyId: string): Promise<{
1437
- companyId: string;
1438
- providerType: string;
1439
- modelId: string;
1440
- displayName: string | null;
1441
- inputUsdPer1M: string;
1442
- outputUsdPer1M: string;
1443
- currency: string;
1444
- updatedAt: Date;
1445
- updatedBy: string | null;
1446
- }[]>;
1447
- export declare function getModelPricing(db: BopoDb, input: {
1448
- companyId: string;
1449
- providerType: string;
1450
- modelId: string;
1451
- }): Promise<{
1452
- companyId: string;
1453
- providerType: string;
1454
- modelId: string;
1455
- displayName: string | null;
1456
- inputUsdPer1M: string;
1457
- outputUsdPer1M: string;
1458
- currency: string;
1459
- updatedAt: Date;
1460
- updatedBy: string | null;
1461
- } | null>;
1462
- export declare function upsertModelPricing(db: BopoDb, input: {
1463
- companyId: string;
1464
- providerType: string;
1465
- modelId: string;
1466
- displayName?: string | null;
1467
- inputUsdPer1M?: string | null;
1468
- outputUsdPer1M?: string | null;
1469
- currency?: string | null;
1470
- updatedBy?: string | null;
1471
- }): Promise<void>;
package/dist/schema.d.ts CHANGED
@@ -4038,166 +4038,6 @@ export declare const templateInstalls: import("drizzle-orm/pg-core").PgTableWith
4038
4038
  };
4039
4039
  dialect: "pg";
4040
4040
  }>;
4041
- export declare const modelPricing: import("drizzle-orm/pg-core").PgTableWithColumns<{
4042
- name: "model_pricing";
4043
- schema: undefined;
4044
- columns: {
4045
- companyId: import("drizzle-orm/pg-core").PgColumn<{
4046
- name: "company_id";
4047
- tableName: "model_pricing";
4048
- dataType: "string";
4049
- columnType: "PgText";
4050
- data: string;
4051
- driverParam: string;
4052
- notNull: true;
4053
- hasDefault: false;
4054
- isPrimaryKey: false;
4055
- isAutoincrement: false;
4056
- hasRuntimeDefault: false;
4057
- enumValues: [string, ...string[]];
4058
- baseColumn: never;
4059
- identity: undefined;
4060
- generated: undefined;
4061
- }, {}, {}>;
4062
- providerType: import("drizzle-orm/pg-core").PgColumn<{
4063
- name: "provider_type";
4064
- tableName: "model_pricing";
4065
- dataType: "string";
4066
- columnType: "PgText";
4067
- data: string;
4068
- driverParam: string;
4069
- notNull: true;
4070
- hasDefault: false;
4071
- isPrimaryKey: false;
4072
- isAutoincrement: false;
4073
- hasRuntimeDefault: false;
4074
- enumValues: [string, ...string[]];
4075
- baseColumn: never;
4076
- identity: undefined;
4077
- generated: undefined;
4078
- }, {}, {}>;
4079
- modelId: import("drizzle-orm/pg-core").PgColumn<{
4080
- name: "model_id";
4081
- tableName: "model_pricing";
4082
- dataType: "string";
4083
- columnType: "PgText";
4084
- data: string;
4085
- driverParam: string;
4086
- notNull: true;
4087
- hasDefault: false;
4088
- isPrimaryKey: false;
4089
- isAutoincrement: false;
4090
- hasRuntimeDefault: false;
4091
- enumValues: [string, ...string[]];
4092
- baseColumn: never;
4093
- identity: undefined;
4094
- generated: undefined;
4095
- }, {}, {}>;
4096
- displayName: import("drizzle-orm/pg-core").PgColumn<{
4097
- name: "display_name";
4098
- tableName: "model_pricing";
4099
- dataType: "string";
4100
- columnType: "PgText";
4101
- data: string;
4102
- driverParam: string;
4103
- notNull: false;
4104
- hasDefault: false;
4105
- isPrimaryKey: false;
4106
- isAutoincrement: false;
4107
- hasRuntimeDefault: false;
4108
- enumValues: [string, ...string[]];
4109
- baseColumn: never;
4110
- identity: undefined;
4111
- generated: undefined;
4112
- }, {}, {}>;
4113
- inputUsdPer1M: import("drizzle-orm/pg-core").PgColumn<{
4114
- name: "input_usd_per_1m";
4115
- tableName: "model_pricing";
4116
- dataType: "string";
4117
- columnType: "PgNumeric";
4118
- data: string;
4119
- driverParam: string;
4120
- notNull: true;
4121
- hasDefault: true;
4122
- isPrimaryKey: false;
4123
- isAutoincrement: false;
4124
- hasRuntimeDefault: false;
4125
- enumValues: undefined;
4126
- baseColumn: never;
4127
- identity: undefined;
4128
- generated: undefined;
4129
- }, {}, {}>;
4130
- outputUsdPer1M: import("drizzle-orm/pg-core").PgColumn<{
4131
- name: "output_usd_per_1m";
4132
- tableName: "model_pricing";
4133
- dataType: "string";
4134
- columnType: "PgNumeric";
4135
- data: string;
4136
- driverParam: string;
4137
- notNull: true;
4138
- hasDefault: true;
4139
- isPrimaryKey: false;
4140
- isAutoincrement: false;
4141
- hasRuntimeDefault: false;
4142
- enumValues: undefined;
4143
- baseColumn: never;
4144
- identity: undefined;
4145
- generated: undefined;
4146
- }, {}, {}>;
4147
- currency: import("drizzle-orm/pg-core").PgColumn<{
4148
- name: "currency";
4149
- tableName: "model_pricing";
4150
- dataType: "string";
4151
- columnType: "PgText";
4152
- data: string;
4153
- driverParam: string;
4154
- notNull: true;
4155
- hasDefault: true;
4156
- isPrimaryKey: false;
4157
- isAutoincrement: false;
4158
- hasRuntimeDefault: false;
4159
- enumValues: [string, ...string[]];
4160
- baseColumn: never;
4161
- identity: undefined;
4162
- generated: undefined;
4163
- }, {}, {}>;
4164
- updatedAt: import("drizzle-orm/pg-core").PgColumn<{
4165
- name: "updated_at";
4166
- tableName: "model_pricing";
4167
- dataType: "date";
4168
- columnType: "PgTimestamp";
4169
- data: Date;
4170
- driverParam: string;
4171
- notNull: true;
4172
- hasDefault: true;
4173
- isPrimaryKey: false;
4174
- isAutoincrement: false;
4175
- hasRuntimeDefault: false;
4176
- enumValues: undefined;
4177
- baseColumn: never;
4178
- identity: undefined;
4179
- generated: undefined;
4180
- }, {}, {}>;
4181
- updatedBy: import("drizzle-orm/pg-core").PgColumn<{
4182
- name: "updated_by";
4183
- tableName: "model_pricing";
4184
- dataType: "string";
4185
- columnType: "PgText";
4186
- data: string;
4187
- driverParam: string;
4188
- notNull: false;
4189
- hasDefault: false;
4190
- isPrimaryKey: false;
4191
- isAutoincrement: false;
4192
- hasRuntimeDefault: false;
4193
- enumValues: [string, ...string[]];
4194
- baseColumn: never;
4195
- identity: undefined;
4196
- generated: undefined;
4197
- }, {}, {}>;
4198
- };
4199
- dialect: "pg";
4200
- }>;
4201
4041
  export declare const pluginConfigs: import("drizzle-orm/pg-core").PgTableWithColumns<{
4202
4042
  name: "plugin_configs";
4203
4043
  schema: undefined;
@@ -8760,166 +8600,6 @@ export declare const schema: {
8760
8600
  };
8761
8601
  dialect: "pg";
8762
8602
  }>;
8763
- modelPricing: import("drizzle-orm/pg-core").PgTableWithColumns<{
8764
- name: "model_pricing";
8765
- schema: undefined;
8766
- columns: {
8767
- companyId: import("drizzle-orm/pg-core").PgColumn<{
8768
- name: "company_id";
8769
- tableName: "model_pricing";
8770
- dataType: "string";
8771
- columnType: "PgText";
8772
- data: string;
8773
- driverParam: string;
8774
- notNull: true;
8775
- hasDefault: false;
8776
- isPrimaryKey: false;
8777
- isAutoincrement: false;
8778
- hasRuntimeDefault: false;
8779
- enumValues: [string, ...string[]];
8780
- baseColumn: never;
8781
- identity: undefined;
8782
- generated: undefined;
8783
- }, {}, {}>;
8784
- providerType: import("drizzle-orm/pg-core").PgColumn<{
8785
- name: "provider_type";
8786
- tableName: "model_pricing";
8787
- dataType: "string";
8788
- columnType: "PgText";
8789
- data: string;
8790
- driverParam: string;
8791
- notNull: true;
8792
- hasDefault: false;
8793
- isPrimaryKey: false;
8794
- isAutoincrement: false;
8795
- hasRuntimeDefault: false;
8796
- enumValues: [string, ...string[]];
8797
- baseColumn: never;
8798
- identity: undefined;
8799
- generated: undefined;
8800
- }, {}, {}>;
8801
- modelId: import("drizzle-orm/pg-core").PgColumn<{
8802
- name: "model_id";
8803
- tableName: "model_pricing";
8804
- dataType: "string";
8805
- columnType: "PgText";
8806
- data: string;
8807
- driverParam: string;
8808
- notNull: true;
8809
- hasDefault: false;
8810
- isPrimaryKey: false;
8811
- isAutoincrement: false;
8812
- hasRuntimeDefault: false;
8813
- enumValues: [string, ...string[]];
8814
- baseColumn: never;
8815
- identity: undefined;
8816
- generated: undefined;
8817
- }, {}, {}>;
8818
- displayName: import("drizzle-orm/pg-core").PgColumn<{
8819
- name: "display_name";
8820
- tableName: "model_pricing";
8821
- dataType: "string";
8822
- columnType: "PgText";
8823
- data: string;
8824
- driverParam: string;
8825
- notNull: false;
8826
- hasDefault: false;
8827
- isPrimaryKey: false;
8828
- isAutoincrement: false;
8829
- hasRuntimeDefault: false;
8830
- enumValues: [string, ...string[]];
8831
- baseColumn: never;
8832
- identity: undefined;
8833
- generated: undefined;
8834
- }, {}, {}>;
8835
- inputUsdPer1M: import("drizzle-orm/pg-core").PgColumn<{
8836
- name: "input_usd_per_1m";
8837
- tableName: "model_pricing";
8838
- dataType: "string";
8839
- columnType: "PgNumeric";
8840
- data: string;
8841
- driverParam: string;
8842
- notNull: true;
8843
- hasDefault: true;
8844
- isPrimaryKey: false;
8845
- isAutoincrement: false;
8846
- hasRuntimeDefault: false;
8847
- enumValues: undefined;
8848
- baseColumn: never;
8849
- identity: undefined;
8850
- generated: undefined;
8851
- }, {}, {}>;
8852
- outputUsdPer1M: import("drizzle-orm/pg-core").PgColumn<{
8853
- name: "output_usd_per_1m";
8854
- tableName: "model_pricing";
8855
- dataType: "string";
8856
- columnType: "PgNumeric";
8857
- data: string;
8858
- driverParam: string;
8859
- notNull: true;
8860
- hasDefault: true;
8861
- isPrimaryKey: false;
8862
- isAutoincrement: false;
8863
- hasRuntimeDefault: false;
8864
- enumValues: undefined;
8865
- baseColumn: never;
8866
- identity: undefined;
8867
- generated: undefined;
8868
- }, {}, {}>;
8869
- currency: import("drizzle-orm/pg-core").PgColumn<{
8870
- name: "currency";
8871
- tableName: "model_pricing";
8872
- dataType: "string";
8873
- columnType: "PgText";
8874
- data: string;
8875
- driverParam: string;
8876
- notNull: true;
8877
- hasDefault: true;
8878
- isPrimaryKey: false;
8879
- isAutoincrement: false;
8880
- hasRuntimeDefault: false;
8881
- enumValues: [string, ...string[]];
8882
- baseColumn: never;
8883
- identity: undefined;
8884
- generated: undefined;
8885
- }, {}, {}>;
8886
- updatedAt: import("drizzle-orm/pg-core").PgColumn<{
8887
- name: "updated_at";
8888
- tableName: "model_pricing";
8889
- dataType: "date";
8890
- columnType: "PgTimestamp";
8891
- data: Date;
8892
- driverParam: string;
8893
- notNull: true;
8894
- hasDefault: true;
8895
- isPrimaryKey: false;
8896
- isAutoincrement: false;
8897
- hasRuntimeDefault: false;
8898
- enumValues: undefined;
8899
- baseColumn: never;
8900
- identity: undefined;
8901
- generated: undefined;
8902
- }, {}, {}>;
8903
- updatedBy: import("drizzle-orm/pg-core").PgColumn<{
8904
- name: "updated_by";
8905
- tableName: "model_pricing";
8906
- dataType: "string";
8907
- columnType: "PgText";
8908
- data: string;
8909
- driverParam: string;
8910
- notNull: false;
8911
- hasDefault: false;
8912
- isPrimaryKey: false;
8913
- isAutoincrement: false;
8914
- hasRuntimeDefault: false;
8915
- enumValues: [string, ...string[]];
8916
- baseColumn: never;
8917
- identity: undefined;
8918
- generated: undefined;
8919
- }, {}, {}>;
8920
- };
8921
- dialect: "pg";
8922
- }>;
8923
8603
  agentIssueLabels: import("drizzle-orm/pg-core").PgTableWithColumns<{
8924
8604
  name: "agent_issue_labels";
8925
8605
  schema: undefined;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bopodev-db",
3
- "version": "0.1.26",
3
+ "version": "0.1.27",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "main": "src/index.ts",
package/src/bootstrap.ts CHANGED
@@ -412,18 +412,7 @@ export async function bootstrapDatabase(dbPath?: string) {
412
412
  ADD COLUMN IF NOT EXISTS usd_cost_status TEXT;
413
413
  `);
414
414
  await db.execute(sql`
415
- CREATE TABLE IF NOT EXISTS model_pricing (
416
- company_id TEXT NOT NULL REFERENCES companies(id) ON DELETE CASCADE,
417
- provider_type TEXT NOT NULL,
418
- model_id TEXT NOT NULL,
419
- display_name TEXT,
420
- input_usd_per_1m NUMERIC(12, 6) NOT NULL DEFAULT 0,
421
- output_usd_per_1m NUMERIC(12, 6) NOT NULL DEFAULT 0,
422
- currency TEXT NOT NULL DEFAULT 'USD',
423
- updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
424
- updated_by TEXT,
425
- PRIMARY KEY (company_id, provider_type, model_id)
426
- );
415
+ DROP TABLE IF EXISTS model_pricing;
427
416
  `);
428
417
  await db.execute(sql`
429
418
  CREATE TABLE IF NOT EXISTS audit_events (
package/src/index.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  export * from "./bootstrap";
2
2
  export * from "./client";
3
+ export { resolveDefaultDbPath, resolveBopoInstanceRoot } from "./default-paths";
3
4
  export * from "./repositories";
4
5
  export * from "./schema";
@@ -17,7 +17,6 @@ import {
17
17
  issueAttachments,
18
18
  issueComments,
19
19
  issues,
20
- modelPricing,
21
20
  pluginConfigs,
22
21
  pluginRuns,
23
22
  plugins,
@@ -541,6 +540,15 @@ export async function listIssues(db: BopoDb, companyId: string, projectId?: stri
541
540
  return db.select().from(issues).where(where).orderBy(desc(issues.updatedAt));
542
541
  }
543
542
 
543
+ export async function getIssue(db: BopoDb, companyId: string, issueId: string) {
544
+ const [row] = await db
545
+ .select()
546
+ .from(issues)
547
+ .where(and(eq(issues.companyId, companyId), eq(issues.id, issueId)))
548
+ .limit(1);
549
+ return row ?? null;
550
+ }
551
+
544
552
  export async function createIssue(
545
553
  db: BopoDb,
546
554
  input: {
@@ -2371,70 +2379,6 @@ export async function createTemplateInstall(
2371
2379
  return row ?? null;
2372
2380
  }
2373
2381
 
2374
- export async function listModelPricing(db: BopoDb, companyId: string) {
2375
- return db
2376
- .select()
2377
- .from(modelPricing)
2378
- .where(eq(modelPricing.companyId, companyId))
2379
- .orderBy(asc(modelPricing.providerType), asc(modelPricing.modelId));
2380
- }
2381
-
2382
- export async function getModelPricing(
2383
- db: BopoDb,
2384
- input: { companyId: string; providerType: string; modelId: string }
2385
- ) {
2386
- const rows = await db
2387
- .select()
2388
- .from(modelPricing)
2389
- .where(
2390
- and(
2391
- eq(modelPricing.companyId, input.companyId),
2392
- eq(modelPricing.providerType, input.providerType),
2393
- eq(modelPricing.modelId, input.modelId)
2394
- )
2395
- )
2396
- .limit(1);
2397
- return rows[0] ?? null;
2398
- }
2399
-
2400
- export async function upsertModelPricing(
2401
- db: BopoDb,
2402
- input: {
2403
- companyId: string;
2404
- providerType: string;
2405
- modelId: string;
2406
- displayName?: string | null;
2407
- inputUsdPer1M?: string | null;
2408
- outputUsdPer1M?: string | null;
2409
- currency?: string | null;
2410
- updatedBy?: string | null;
2411
- }
2412
- ) {
2413
- await db
2414
- .insert(modelPricing)
2415
- .values({
2416
- companyId: input.companyId,
2417
- providerType: input.providerType,
2418
- modelId: input.modelId,
2419
- displayName: input.displayName ?? null,
2420
- inputUsdPer1M: input.inputUsdPer1M ?? "0.000000",
2421
- outputUsdPer1M: input.outputUsdPer1M ?? "0.000000",
2422
- currency: input.currency ?? "USD",
2423
- updatedBy: input.updatedBy ?? null
2424
- })
2425
- .onConflictDoUpdate({
2426
- target: [modelPricing.companyId, modelPricing.providerType, modelPricing.modelId],
2427
- set: compactUpdate({
2428
- displayName: input.displayName ?? null,
2429
- inputUsdPer1M: input.inputUsdPer1M ?? "0.000000",
2430
- outputUsdPer1M: input.outputUsdPer1M ?? "0.000000",
2431
- currency: input.currency ?? "USD",
2432
- updatedBy: input.updatedBy ?? null,
2433
- updatedAt: touchUpdatedAtSql
2434
- })
2435
- });
2436
- }
2437
-
2438
2382
  function compactUpdate<T extends Record<string, unknown>>(input: T) {
2439
2383
  return Object.fromEntries(Object.entries(input).filter(([, value]) => value !== undefined));
2440
2384
  }
package/src/schema.ts CHANGED
@@ -367,24 +367,6 @@ export const templateInstalls = pgTable("template_installs", {
367
367
  createdAt: timestamp("created_at", { mode: "date" }).defaultNow().notNull()
368
368
  });
369
369
 
370
- export const modelPricing = pgTable(
371
- "model_pricing",
372
- {
373
- companyId: text("company_id")
374
- .notNull()
375
- .references(() => companies.id, { onDelete: "cascade" }),
376
- providerType: text("provider_type").notNull(),
377
- modelId: text("model_id").notNull(),
378
- displayName: text("display_name"),
379
- inputUsdPer1M: numeric("input_usd_per_1m", { precision: 12, scale: 6 }).notNull().default("0"),
380
- outputUsdPer1M: numeric("output_usd_per_1m", { precision: 12, scale: 6 }).notNull().default("0"),
381
- currency: text("currency").notNull().default("USD"),
382
- updatedAt: timestamp("updated_at", { mode: "date" }).defaultNow().notNull(),
383
- updatedBy: text("updated_by")
384
- },
385
- (table) => [primaryKey({ columns: [table.companyId, table.providerType, table.modelId] })]
386
- );
387
-
388
370
  export const pluginConfigs = pgTable(
389
371
  "plugin_configs",
390
372
  {
@@ -458,7 +440,6 @@ export const schema = {
458
440
  templates,
459
441
  templateVersions,
460
442
  templateInstalls,
461
- modelPricing,
462
443
  agentIssueLabels,
463
444
  projectWorkspaces
464
445
  };