@intelligo-dev/core 1.0.0-beta.1 → 1.0.0-beta.13
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/NOTICE +6 -0
- package/README.md +102 -0
- package/dist/attachments/errors.d.ts +7 -0
- package/dist/attachments/errors.d.ts.map +1 -0
- package/dist/attachments/errors.js +11 -0
- package/dist/attachments/errors.js.map +1 -0
- package/dist/attachments/index.d.ts +8 -0
- package/dist/attachments/index.d.ts.map +1 -0
- package/dist/attachments/index.js +7 -0
- package/dist/attachments/index.js.map +1 -0
- package/dist/attachments/service.d.ts +45 -0
- package/dist/attachments/service.d.ts.map +1 -0
- package/dist/attachments/service.js +100 -0
- package/dist/attachments/service.js.map +1 -0
- package/dist/attachments/types.d.ts +6 -0
- package/dist/attachments/types.d.ts.map +1 -0
- package/dist/attachments/types.js +2 -0
- package/dist/attachments/types.js.map +1 -0
- package/dist/conversations/errors.d.ts +2 -8
- package/dist/conversations/errors.d.ts.map +1 -1
- package/dist/conversations/errors.js +2 -8
- package/dist/conversations/errors.js.map +1 -1
- package/dist/conversations/index.d.ts +4 -12
- package/dist/conversations/index.d.ts.map +1 -1
- package/dist/conversations/index.js +2 -11
- package/dist/conversations/index.js.map +1 -1
- package/dist/conversations/service.d.ts +49 -61
- package/dist/conversations/service.d.ts.map +1 -1
- package/dist/conversations/service.js +110 -83
- package/dist/conversations/service.js.map +1 -1
- package/dist/conversations/types.d.ts +1 -4
- package/dist/conversations/types.d.ts.map +1 -1
- package/dist/conversations/types.js +0 -3
- package/dist/conversations/types.js.map +1 -1
- package/dist/db/client.d.ts +21 -10
- package/dist/db/client.d.ts.map +1 -1
- package/dist/db/client.js +43 -18
- package/dist/db/client.js.map +1 -1
- package/dist/db/index.d.ts +3 -3
- package/dist/db/index.d.ts.map +1 -1
- package/dist/db/index.js +3 -7
- package/dist/db/index.js.map +1 -1
- package/dist/db/schema/agents.d.ts +14 -51
- package/dist/db/schema/agents.d.ts.map +1 -1
- package/dist/db/schema/agents.js +9 -21
- package/dist/db/schema/agents.js.map +1 -1
- package/dist/db/schema/ai.d.ts +86 -1556
- package/dist/db/schema/ai.d.ts.map +1 -1
- package/dist/db/schema/ai.js +32 -236
- package/dist/db/schema/ai.js.map +1 -1
- package/dist/db/schema/auth.d.ts +5 -34
- package/dist/db/schema/auth.d.ts.map +1 -1
- package/dist/db/schema/auth.js +25 -56
- package/dist/db/schema/auth.js.map +1 -1
- package/dist/db/schema/billing.d.ts +136 -107
- package/dist/db/schema/billing.d.ts.map +1 -1
- package/dist/db/schema/billing.js +72 -60
- package/dist/db/schema/billing.js.map +1 -1
- package/dist/db/schema/feature-flags.d.ts +3 -12
- package/dist/db/schema/feature-flags.d.ts.map +1 -1
- package/dist/db/schema/feature-flags.js +3 -12
- package/dist/db/schema/feature-flags.js.map +1 -1
- package/dist/db/schema/identity.d.ts +12 -274
- package/dist/db/schema/identity.d.ts.map +1 -1
- package/dist/db/schema/identity.js +19 -104
- package/dist/db/schema/identity.js.map +1 -1
- package/dist/db/schema/index.d.ts +8 -15
- package/dist/db/schema/index.d.ts.map +1 -1
- package/dist/db/schema/index.js +12 -42
- package/dist/db/schema/index.js.map +1 -1
- package/dist/db/schema/notifications.d.ts +3 -17
- package/dist/db/schema/notifications.d.ts.map +1 -1
- package/dist/db/schema/notifications.js +3 -17
- package/dist/db/schema/notifications.js.map +1 -1
- package/dist/db/schema/usage.d.ts +94 -77
- package/dist/db/schema/usage.d.ts.map +1 -1
- package/dist/db/schema/usage.js +59 -89
- package/dist/db/schema/usage.js.map +1 -1
- package/dist/db/validate.d.ts +2 -11
- package/dist/db/validate.d.ts.map +1 -1
- package/dist/db/validate.js +6 -17
- package/dist/db/validate.js.map +1 -1
- package/dist/db/workspace-queries.d.ts +5 -29
- package/dist/db/workspace-queries.d.ts.map +1 -1
- package/dist/db/workspace-queries.js +5 -29
- package/dist/db/workspace-queries.js.map +1 -1
- package/dist/documents/classifier.d.ts +5 -12
- package/dist/documents/classifier.d.ts.map +1 -1
- package/dist/documents/classifier.js +16 -16
- package/dist/documents/classifier.js.map +1 -1
- package/dist/documents/errors.d.ts +2 -10
- package/dist/documents/errors.d.ts.map +1 -1
- package/dist/documents/errors.js +2 -10
- package/dist/documents/errors.js.map +1 -1
- package/dist/documents/index.d.ts +4 -13
- package/dist/documents/index.d.ts.map +1 -1
- package/dist/documents/index.js +3 -12
- package/dist/documents/index.js.map +1 -1
- package/dist/documents/service.d.ts +19 -26
- package/dist/documents/service.d.ts.map +1 -1
- package/dist/documents/service.js +44 -38
- package/dist/documents/service.js.map +1 -1
- package/dist/documents/types.d.ts +6 -10
- package/dist/documents/types.d.ts.map +1 -1
- package/dist/documents/types.js +0 -3
- package/dist/documents/types.js.map +1 -1
- package/dist/email/brand.d.ts +17 -0
- package/dist/email/brand.d.ts.map +1 -0
- package/dist/email/brand.js +9 -0
- package/dist/email/brand.js.map +1 -0
- package/dist/email/index.d.ts +4 -4
- package/dist/email/index.js +4 -4
- package/dist/email/provider.d.ts +1 -7
- package/dist/email/provider.d.ts.map +1 -1
- package/dist/email/provider.js +10 -19
- package/dist/email/provider.js.map +1 -1
- package/dist/email/send.d.ts +12 -12
- package/dist/email/send.d.ts.map +1 -1
- package/dist/email/send.js +5 -19
- package/dist/email/send.js.map +1 -1
- package/dist/email/senders.d.ts +17 -30
- package/dist/email/senders.d.ts.map +1 -1
- package/dist/email/senders.js +33 -47
- package/dist/email/senders.js.map +1 -1
- package/dist/email/templates/base-layout.d.ts +1 -1
- package/dist/email/templates/base-layout.d.ts.map +1 -1
- package/dist/email/templates/base-layout.js +4 -6
- package/dist/email/templates/base-layout.js.map +1 -1
- package/dist/email/templates/index.d.ts +10 -10
- package/dist/email/templates/index.d.ts.map +1 -1
- package/dist/email/templates/index.js +10 -16
- package/dist/email/templates/index.js.map +1 -1
- package/dist/email/templates/password-reset.d.ts +2 -2
- package/dist/email/templates/password-reset.d.ts.map +1 -1
- package/dist/email/templates/password-reset.js +10 -22
- package/dist/email/templates/password-reset.js.map +1 -1
- package/dist/email/templates/payment-failed.d.ts +2 -2
- package/dist/email/templates/payment-failed.d.ts.map +1 -1
- package/dist/email/templates/payment-failed.js +11 -24
- package/dist/email/templates/payment-failed.js.map +1 -1
- package/dist/email/templates/quota-warning.d.ts +4 -4
- package/dist/email/templates/quota-warning.d.ts.map +1 -1
- package/dist/email/templates/quota-warning.js +19 -39
- package/dist/email/templates/quota-warning.js.map +1 -1
- package/dist/email/templates/subscription-confirmed.d.ts +2 -2
- package/dist/email/templates/subscription-confirmed.d.ts.map +1 -1
- package/dist/email/templates/subscription-confirmed.js +13 -28
- package/dist/email/templates/subscription-confirmed.js.map +1 -1
- package/dist/email/templates/trial-expiry.d.ts +2 -2
- package/dist/email/templates/trial-expiry.d.ts.map +1 -1
- package/dist/email/templates/trial-expiry.js +12 -36
- package/dist/email/templates/trial-expiry.js.map +1 -1
- package/dist/email/templates/trial-warning.d.ts +2 -2
- package/dist/email/templates/trial-warning.d.ts.map +1 -1
- package/dist/email/templates/trial-warning.js +15 -32
- package/dist/email/templates/trial-warning.js.map +1 -1
- package/dist/email/templates/verify-email.d.ts +2 -2
- package/dist/email/templates/verify-email.d.ts.map +1 -1
- package/dist/email/templates/verify-email.js +10 -22
- package/dist/email/templates/verify-email.js.map +1 -1
- package/dist/email/templates/welcome.d.ts +2 -2
- package/dist/email/templates/welcome.d.ts.map +1 -1
- package/dist/email/templates/welcome.js +13 -20
- package/dist/email/templates/welcome.js.map +1 -1
- package/dist/email/templates/workspace-invitation.d.ts +2 -2
- package/dist/email/templates/workspace-invitation.d.ts.map +1 -1
- package/dist/email/templates/workspace-invitation.js +12 -26
- package/dist/email/templates/workspace-invitation.js.map +1 -1
- package/dist/env.d.ts +5 -10
- package/dist/env.d.ts.map +1 -1
- package/dist/env.js +41 -31
- package/dist/env.js.map +1 -1
- package/dist/identity/audit.d.ts +11 -24
- package/dist/identity/audit.d.ts.map +1 -1
- package/dist/identity/audit.js +13 -27
- package/dist/identity/audit.js.map +1 -1
- package/dist/identity/errors.d.ts +4 -12
- package/dist/identity/errors.d.ts.map +1 -1
- package/dist/identity/errors.js +2 -8
- package/dist/identity/errors.js.map +1 -1
- package/dist/identity/index.d.ts +5 -13
- package/dist/identity/index.d.ts.map +1 -1
- package/dist/identity/index.js +4 -12
- package/dist/identity/index.js.map +1 -1
- package/dist/identity/service.d.ts +13 -47
- package/dist/identity/service.d.ts.map +1 -1
- package/dist/identity/service.js +31 -78
- package/dist/identity/service.js.map +1 -1
- package/dist/identity/types.d.ts +1 -4
- package/dist/identity/types.d.ts.map +1 -1
- package/dist/identity/types.js +0 -3
- package/dist/identity/types.js.map +1 -1
- package/dist/index.d.ts +1 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -10
- package/dist/index.js.map +1 -1
- package/dist/logger.d.ts +7 -18
- package/dist/logger.d.ts.map +1 -1
- package/dist/logger.js +45 -49
- package/dist/logger.js.map +1 -1
- package/dist/money.d.ts +95 -0
- package/dist/money.d.ts.map +1 -0
- package/dist/money.js +208 -0
- package/dist/money.js.map +1 -0
- package/dist/notifications/index.d.ts +9 -43
- package/dist/notifications/index.d.ts.map +1 -1
- package/dist/notifications/index.js +9 -49
- package/dist/notifications/index.js.map +1 -1
- package/dist/notifications/triggers.d.ts +9 -32
- package/dist/notifications/triggers.d.ts.map +1 -1
- package/dist/notifications/triggers.js +21 -58
- package/dist/notifications/triggers.js.map +1 -1
- package/dist/notifications/types.d.ts +1 -10
- package/dist/notifications/types.d.ts.map +1 -1
- package/dist/notifications/types.js +0 -9
- package/dist/notifications/types.js.map +1 -1
- package/dist/prompt.d.ts +38 -0
- package/dist/prompt.d.ts.map +1 -0
- package/dist/prompt.js +118 -0
- package/dist/prompt.js.map +1 -0
- package/dist/registry.d.ts +32 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +60 -0
- package/dist/registry.js.map +1 -0
- package/dist/request-context.d.ts +49 -0
- package/dist/request-context.d.ts.map +1 -0
- package/dist/request-context.js +100 -0
- package/dist/request-context.js.map +1 -0
- package/dist/storage/index.d.ts +65 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/storage/index.js +109 -0
- package/dist/storage/index.js.map +1 -0
- package/package.json +74 -24
- package/src/attachments/errors.ts +18 -0
- package/src/attachments/index.ts +22 -0
- package/src/attachments/service.ts +178 -0
- package/src/attachments/types.ts +6 -0
- package/src/conversations/errors.ts +45 -0
- package/src/conversations/index.ts +39 -0
- package/src/conversations/service.ts +594 -0
- package/src/conversations/types.ts +15 -0
- package/src/db/client.ts +91 -0
- package/src/db/index.ts +3 -0
- package/src/db/migrations/0000_baseline.sql +652 -0
- package/src/db/migrations/0001_reconcile_chain_built_databases.sql +53 -0
- package/src/db/migrations/0002_webhook_claim_lease.sql +1 -0
- package/src/db/migrations/README.md +74 -36
- package/src/db/migrations/legacy-chain.json +197 -0
- package/src/db/migrations/meta/0000_snapshot.json +4182 -157
- package/src/db/migrations/meta/0002_snapshot.json +2478 -368
- package/src/db/migrations/meta/_journal.json +6 -279
- package/src/db/schema/agents.ts +57 -0
- package/src/db/schema/ai.ts +174 -0
- package/src/db/schema/auth.ts +183 -0
- package/src/db/schema/billing.ts +209 -0
- package/src/db/schema/feature-flags.ts +20 -0
- package/src/db/schema/identity.ts +250 -0
- package/src/db/schema/index.ts +12 -0
- package/src/db/schema/notifications.ts +31 -0
- package/src/db/schema/usage.ts +269 -0
- package/src/db/validate.ts +63 -0
- package/src/db/workspace-queries.ts +64 -0
- package/src/documents/classifier.ts +61 -0
- package/src/documents/errors.ts +44 -0
- package/src/documents/index.ts +24 -0
- package/src/documents/service.ts +256 -0
- package/src/documents/types.ts +24 -0
- package/src/email/brand.ts +24 -0
- package/src/email/index.ts +19 -0
- package/src/email/provider.ts +278 -0
- package/src/email/send.ts +169 -0
- package/src/email/senders.ts +292 -0
- package/src/email/templates/base-layout.tsx +145 -0
- package/src/email/templates/index.ts +28 -0
- package/src/email/templates/password-reset.tsx +72 -0
- package/src/email/templates/payment-failed.tsx +77 -0
- package/src/email/templates/quota-warning.tsx +118 -0
- package/src/email/templates/subscription-confirmed.tsx +91 -0
- package/src/email/templates/trial-expiry.tsx +124 -0
- package/src/email/templates/trial-warning.tsx +104 -0
- package/src/email/templates/verify-email.tsx +72 -0
- package/src/email/templates/welcome.tsx +64 -0
- package/src/email/templates/workspace-invitation.tsx +105 -0
- package/src/env.ts +180 -0
- package/src/identity/audit.ts +65 -0
- package/src/identity/errors.ts +44 -0
- package/src/identity/index.ts +26 -0
- package/src/identity/service.ts +202 -0
- package/src/identity/types.ts +28 -0
- package/src/index.ts +4 -0
- package/src/logger.ts +198 -0
- package/src/money.ts +270 -0
- package/src/notifications/index.ts +108 -0
- package/src/notifications/triggers.ts +158 -0
- package/src/notifications/types.ts +18 -0
- package/src/prompt.ts +142 -0
- package/src/registry.ts +75 -0
- package/src/request-context.ts +137 -0
- package/src/storage/index.ts +153 -0
- package/dist/db/schema/rag.d.ts +0 -171
- package/dist/db/schema/rag.d.ts.map +0 -1
- package/dist/db/schema/rag.js +0 -42
- package/dist/db/schema/rag.js.map +0 -1
- package/src/db/migrations/0000_sharp_night_nurse.sql +0 -52
- package/src/db/migrations/0001_hesitant_vapor.sql +0 -40
- package/src/db/migrations/0002_numerous_lady_vermin.sql +0 -235
- package/src/db/migrations/0003_mighty_jean_grey.sql +0 -37
- package/src/db/migrations/0004_cynical_grandmaster.sql +0 -2
- package/src/db/migrations/0005_careful_switch.sql +0 -8
- package/src/db/migrations/0006_tense_blue_marvel.sql +0 -16
- package/src/db/migrations/0007_next_squadron_sinister.sql +0 -1
- package/src/db/migrations/0008_powerful_scream.sql +0 -39
- package/src/db/migrations/0009_sad_ink.sql +0 -1
- package/src/db/migrations/0010_shocking_omega_flight.sql +0 -2
- package/src/db/migrations/0011_ambiguous_otto_octavius.sql +0 -151
- package/src/db/migrations/0011_hnsw_vector_index.sql +0 -17
- package/src/db/migrations/0012_user_profiles.sql +0 -30
- package/src/db/migrations/0013_trending_seasonal_columns.sql +0 -9
- package/src/db/migrations/0014_add_product_type_to_agents.sql +0 -6
- package/src/db/migrations/0015_new_v1_tables.sql +0 -149
- package/src/db/migrations/0016_document_types.sql +0 -30
- package/src/db/migrations/0017_document_metadata.sql +0 -2
- package/src/db/migrations/0018_identity_graph.sql +0 -200
- package/src/db/migrations/0019_db_driven_prompts.sql +0 -20
- package/src/db/migrations/0020_pending_extractions.sql +0 -35
- package/src/db/migrations/0021_rag_documents.sql +0 -39
- package/src/db/migrations/0022_user_quotas_usage_jsonb.sql +0 -70
- package/src/db/migrations/0023_user_facts_user_scoped_unique.sql +0 -17
- package/src/db/migrations/0024_user_memories_hnsw.sql +0 -23
- package/src/db/migrations/0025_audit_trigger_errcode.sql +0 -21
- package/src/db/migrations/0026_user_profile_snapshots_composite_pk.sql +0 -17
- package/src/db/migrations/0027_billing_settings_mnt_columns.sql +0 -54
- package/src/db/migrations/0028_trial_credits_normalized_email.sql +0 -37
- package/src/db/migrations/0029_usage_records_conversation_idx.sql +0 -13
- package/src/db/migrations/0030_pending_extractions_composite_idx.sql +0 -11
- package/src/db/migrations/0031_rag_documents_hnsw.sql +0 -16
- package/src/db/migrations/0032_rate_limit_unique_idx.sql +0 -16
- package/src/db/migrations/0033_pending_extractions_partial_idx.sql +0 -18
- package/src/db/migrations/0034_rate_limit_count.sql +0 -9
- package/src/db/migrations/0035_credit_reservations.sql +0 -24
- package/src/db/migrations/0036_executions_audit_jobs.sql +0 -96
- package/src/db/migrations/0037_rate_limit_minute_bucket.sql +0 -46
- package/src/db/migrations/0038_user_quotas_generic_usage.sql +0 -25
- package/src/db/migrations/0039_platform_admin_impersonation.sql +0 -27
- package/src/db/migrations/0040_ee_audit_chain.sql +0 -23
- package/src/db/migrations/meta/0001_snapshot.json +0 -631
- package/src/db/migrations/meta/0003_snapshot.json +0 -2488
- package/src/db/migrations/meta/0004_snapshot.json +0 -2500
- package/src/db/migrations/meta/0005_snapshot.json +0 -2548
- package/src/db/migrations/meta/0006_snapshot.json +0 -2650
- package/src/db/migrations/meta/0007_snapshot.json +0 -2657
- package/src/db/migrations/meta/0008_snapshot.json +0 -2719
- package/src/db/migrations/meta/0009_snapshot.json +0 -2726
- package/src/db/migrations/meta/0010_snapshot.json +0 -2739
- package/src/db/migrations/meta/0011_snapshot.json +0 -3886
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { pgTable, text, timestamp, boolean, index } from "drizzle-orm/pg-core";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* User-scoped, not workspace-scoped, so a user sees their notifications from
|
|
5
|
+
* every workspace in one place. `userId` references the users table by
|
|
6
|
+
* convention (no FK); `workspaceId` is null for user-level notifications.
|
|
7
|
+
*/
|
|
8
|
+
export const notifications = pgTable(
|
|
9
|
+
"notifications",
|
|
10
|
+
{
|
|
11
|
+
id: text("id")
|
|
12
|
+
.primaryKey()
|
|
13
|
+
.$defaultFn(() => crypto.randomUUID()),
|
|
14
|
+
userId: text("user_id").notNull(),
|
|
15
|
+
workspaceId: text("workspace_id"),
|
|
16
|
+
type: text("type").notNull(),
|
|
17
|
+
title: text("title").notNull(),
|
|
18
|
+
message: text("message").notNull(),
|
|
19
|
+
isRead: boolean("is_read").notNull().default(false),
|
|
20
|
+
metadata: text("metadata"),
|
|
21
|
+
createdAt: timestamp("created_at").notNull().defaultNow(),
|
|
22
|
+
},
|
|
23
|
+
(table) => [
|
|
24
|
+
index("notifications_user_id_idx").on(table.userId),
|
|
25
|
+
index("notifications_user_id_is_read_idx").on(table.userId, table.isRead),
|
|
26
|
+
index("notifications_created_at_idx").on(table.createdAt),
|
|
27
|
+
]
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
export type Notification = typeof notifications.$inferSelect;
|
|
31
|
+
export type InsertNotification = typeof notifications.$inferInsert;
|
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Token consumption per request and aggregated per period, which the quota
|
|
3
|
+
* engine checks before AI requests and records into after them.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
pgTable,
|
|
8
|
+
text,
|
|
9
|
+
timestamp,
|
|
10
|
+
integer,
|
|
11
|
+
bigint,
|
|
12
|
+
real,
|
|
13
|
+
index,
|
|
14
|
+
unique,
|
|
15
|
+
jsonb,
|
|
16
|
+
} from "drizzle-orm/pg-core";
|
|
17
|
+
import { organization, users } from "./auth";
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* One row per AI request: tokens, model and agent, for per-model and
|
|
21
|
+
* per-agent reporting.
|
|
22
|
+
*/
|
|
23
|
+
export const usageRecords = pgTable(
|
|
24
|
+
"usage_records",
|
|
25
|
+
{
|
|
26
|
+
id: text("id").primaryKey(),
|
|
27
|
+
workspaceId: text("workspace_id")
|
|
28
|
+
.notNull()
|
|
29
|
+
.references(() => organization.id, { onDelete: "cascade" }),
|
|
30
|
+
userId: text("user_id")
|
|
31
|
+
.notNull()
|
|
32
|
+
.references(() => users.id, { onDelete: "cascade" }),
|
|
33
|
+
type: text("type").notNull(), // "ai_tokens", "api_call"
|
|
34
|
+
model: text("model"), // "gpt-4o", "gpt-4o-mini"
|
|
35
|
+
agent: text("agent"), // the product's agent slug
|
|
36
|
+
inputTokens: integer("input_tokens").notNull().default(0),
|
|
37
|
+
outputTokens: integer("output_tokens").notNull().default(0),
|
|
38
|
+
totalTokens: integer("total_tokens").notNull().default(0),
|
|
39
|
+
/**
|
|
40
|
+
* What the provider charged, in USD micros. Integer on purpose: float
|
|
41
|
+
* arithmetic accumulates sub-cent error over many records.
|
|
42
|
+
*/
|
|
43
|
+
providerCostMicros: bigint("provider_cost_micros", { mode: "number" })
|
|
44
|
+
.notNull()
|
|
45
|
+
.default(0),
|
|
46
|
+
/** Snapshots of the rate and margin this charge was computed with. */
|
|
47
|
+
marginBp: integer("margin_bp").notNull().default(0),
|
|
48
|
+
usdRateMicros: bigint("usd_rate_micros", { mode: "number" })
|
|
49
|
+
.notNull()
|
|
50
|
+
.default(0),
|
|
51
|
+
/** Authoritative charge, in micros of `currency`. */
|
|
52
|
+
chargedMicros: bigint("charged_micros", { mode: "number" })
|
|
53
|
+
.notNull()
|
|
54
|
+
.default(0),
|
|
55
|
+
currency: text("currency").notNull().default("USD"),
|
|
56
|
+
/** Request correlation id for log tracing */
|
|
57
|
+
requestId: text("request_id"),
|
|
58
|
+
/**
|
|
59
|
+
* Owning execution (@intelligo-dev/executions). No FK: the executions
|
|
60
|
+
* table is owned by another package and this column is written by
|
|
61
|
+
* the settlement path, which may run before or after the execution
|
|
62
|
+
* row's terminal update.
|
|
63
|
+
*/
|
|
64
|
+
executionId: text("execution_id"),
|
|
65
|
+
/** Conversation/chat id for grouping in usage dashboards */
|
|
66
|
+
conversationId: text("conversation_id"),
|
|
67
|
+
metadata: text("metadata"), // JSON string for additional data
|
|
68
|
+
recordedAt: timestamp("recorded_at").notNull().defaultNow(),
|
|
69
|
+
},
|
|
70
|
+
(table) => [
|
|
71
|
+
index("usage_records_workspace_id_idx").on(table.workspaceId),
|
|
72
|
+
index("usage_records_workspace_recorded_at_idx").on(
|
|
73
|
+
table.workspaceId,
|
|
74
|
+
table.recordedAt
|
|
75
|
+
),
|
|
76
|
+
index("usage_records_workspace_type_idx").on(table.workspaceId, table.type),
|
|
77
|
+
index("usage_records_conversation_id_idx").on(table.conversationId),
|
|
78
|
+
index("usage_records_execution_id_idx").on(table.executionId),
|
|
79
|
+
]
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* One row per workspace per billing period, incremented atomically, so a
|
|
84
|
+
* quota check is O(1) instead of a SUM over usage_records.
|
|
85
|
+
*/
|
|
86
|
+
export const monthlyUsage = pgTable(
|
|
87
|
+
"monthly_usage",
|
|
88
|
+
{
|
|
89
|
+
id: text("id").primaryKey(),
|
|
90
|
+
workspaceId: text("workspace_id")
|
|
91
|
+
.notNull()
|
|
92
|
+
.references(() => organization.id, { onDelete: "cascade" }),
|
|
93
|
+
periodStart: timestamp("period_start").notNull(),
|
|
94
|
+
periodEnd: timestamp("period_end").notNull(),
|
|
95
|
+
tokensUsed: integer("tokens_used").notNull().default(0),
|
|
96
|
+
/** The plan allowance spent this period, in micros of `currency`. */
|
|
97
|
+
allowanceUsedMicros: bigint("allowance_used_micros", { mode: "number" })
|
|
98
|
+
.notNull()
|
|
99
|
+
.default(0),
|
|
100
|
+
currency: text("currency").notNull().default("USD"),
|
|
101
|
+
requestCount: integer("request_count").notNull().default(0),
|
|
102
|
+
updatedAt: timestamp("updated_at").notNull().defaultNow(),
|
|
103
|
+
},
|
|
104
|
+
(table) => [
|
|
105
|
+
unique("monthly_usage_workspace_period_unique").on(
|
|
106
|
+
table.workspaceId,
|
|
107
|
+
table.periodStart
|
|
108
|
+
),
|
|
109
|
+
index("monthly_usage_workspace_id_idx").on(table.workspaceId),
|
|
110
|
+
]
|
|
111
|
+
);
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* One-time trial grant, one per workspace (unique constraint). Separate from
|
|
115
|
+
* purchased credits; used when the plan quota is exceeded or the credit
|
|
116
|
+
* balance is zero. Status: active → depleted, converted or expired.
|
|
117
|
+
*/
|
|
118
|
+
export const trialCredits = pgTable(
|
|
119
|
+
"trial_credits",
|
|
120
|
+
{
|
|
121
|
+
id: text("id").primaryKey(),
|
|
122
|
+
workspaceId: text("workspace_id")
|
|
123
|
+
.notNull()
|
|
124
|
+
.unique()
|
|
125
|
+
.references(() => organization.id, { onDelete: "cascade" }),
|
|
126
|
+
initialCredits: integer("initial_credits").notNull().default(100000),
|
|
127
|
+
creditsUsed: integer("credits_used").notNull().default(0),
|
|
128
|
+
creditsRemaining: integer("credits_remaining").notNull().default(100000),
|
|
129
|
+
/** The grant, in micros of `currency`. */
|
|
130
|
+
initialMicros: bigint("initial_micros", { mode: "number" })
|
|
131
|
+
.notNull()
|
|
132
|
+
.default(0),
|
|
133
|
+
usedMicros: bigint("used_micros", { mode: "number" }).notNull().default(0),
|
|
134
|
+
remainingMicros: bigint("remaining_micros", { mode: "number" })
|
|
135
|
+
.notNull()
|
|
136
|
+
.default(0),
|
|
137
|
+
currency: text("currency").notNull().default("USD"),
|
|
138
|
+
status: text("status").notNull().default("active"), // active|depleted|converted|expired
|
|
139
|
+
provisionedAt: timestamp("provisioned_at").notNull().defaultNow(),
|
|
140
|
+
trialEndDate: timestamp("trial_end_date"), // 14 days from provisioning
|
|
141
|
+
depletedAt: timestamp("depleted_at"),
|
|
142
|
+
convertedAt: timestamp("converted_at"),
|
|
143
|
+
createdByIp: text("created_by_ip"),
|
|
144
|
+
createdByEmail: text("created_by_email"),
|
|
145
|
+
/**
|
|
146
|
+
* Canonical form of createdByEmail for the per-email abuse check,
|
|
147
|
+
* stored so the count can use an index instead of a full-table scan.
|
|
148
|
+
*/
|
|
149
|
+
normalizedEmail: text("normalized_email"),
|
|
150
|
+
},
|
|
151
|
+
(table) => [
|
|
152
|
+
index("trial_credits_expiry_idx").on(table.status, table.trialEndDate),
|
|
153
|
+
index("trial_credits_normalized_email_idx").on(table.normalizedEmail),
|
|
154
|
+
]
|
|
155
|
+
);
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* One row per (workspace, endpoint, minute bucket). Each request upserts the
|
|
159
|
+
* row and atomically increments `count`, so N concurrent requests observe
|
|
160
|
+
* 1..N and exactly `limit` are admitted. Old buckets are deleted by the
|
|
161
|
+
* billing-maintenance job.
|
|
162
|
+
*/
|
|
163
|
+
export const rateLimitEntries = pgTable(
|
|
164
|
+
"rate_limit_entries",
|
|
165
|
+
{
|
|
166
|
+
id: text("id").primaryKey(),
|
|
167
|
+
workspaceId: text("workspace_id")
|
|
168
|
+
.notNull()
|
|
169
|
+
.references(() => organization.id, { onDelete: "cascade" }),
|
|
170
|
+
endpoint: text("endpoint").notNull().default("chat"),
|
|
171
|
+
requestedAt: timestamp("requested_at").notNull().defaultNow(),
|
|
172
|
+
/** Floored minute bucket for unique constraint enforcement */
|
|
173
|
+
minuteBucket: timestamp("minute_bucket").notNull(),
|
|
174
|
+
/** Requests observed in this bucket — incremented via upsert */
|
|
175
|
+
count: integer("count").notNull().default(1),
|
|
176
|
+
},
|
|
177
|
+
(table) => [
|
|
178
|
+
index("rate_limit_entries_window_idx").on(
|
|
179
|
+
table.workspaceId,
|
|
180
|
+
table.endpoint,
|
|
181
|
+
table.requestedAt
|
|
182
|
+
),
|
|
183
|
+
unique("rate_limit_entries_unique_bucket_idx").on(
|
|
184
|
+
table.workspaceId,
|
|
185
|
+
table.endpoint,
|
|
186
|
+
table.minuteBucket
|
|
187
|
+
),
|
|
188
|
+
]
|
|
189
|
+
);
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Sent quota and trial notifications. The unique constraint on
|
|
193
|
+
* (workspaceId, type, periodKey) keeps one notification from being sent
|
|
194
|
+
* twice in a billing period.
|
|
195
|
+
*/
|
|
196
|
+
export const notificationHistory = pgTable(
|
|
197
|
+
"notification_history",
|
|
198
|
+
{
|
|
199
|
+
id: text("id").primaryKey(),
|
|
200
|
+
workspaceId: text("workspace_id")
|
|
201
|
+
.notNull()
|
|
202
|
+
.references(() => organization.id, { onDelete: "cascade" }),
|
|
203
|
+
type: text("type").notNull(), // "quota_warning_80", "quota_warning_100", "trial_warning_20", "trial_depleted"
|
|
204
|
+
periodKey: text("period_key").notNull(), // "2026-02" for monthly, "trial" for one-time
|
|
205
|
+
sentAt: timestamp("sent_at").notNull().defaultNow(),
|
|
206
|
+
channel: text("channel").notNull().default("console"), // "console" | "email"
|
|
207
|
+
metadata: text("metadata"), // JSON string for additional context
|
|
208
|
+
},
|
|
209
|
+
(table) => [
|
|
210
|
+
unique("notification_history_dedup_unique").on(
|
|
211
|
+
table.workspaceId,
|
|
212
|
+
table.type,
|
|
213
|
+
table.periodKey
|
|
214
|
+
),
|
|
215
|
+
index("notification_history_workspace_id_idx").on(table.workspaceId),
|
|
216
|
+
]
|
|
217
|
+
);
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Per-user, per-action usage counters, one row per user and workspace (not
|
|
221
|
+
* per period). Counters live in the `usage` JSONB map and increment
|
|
222
|
+
* atomically in SQL, so a quota check is O(1).
|
|
223
|
+
*/
|
|
224
|
+
export const userQuotas = pgTable(
|
|
225
|
+
"user_quotas",
|
|
226
|
+
{
|
|
227
|
+
id: text("id").primaryKey(),
|
|
228
|
+
userId: text("user_id")
|
|
229
|
+
.notNull()
|
|
230
|
+
.references(() => users.id, { onDelete: "cascade" }),
|
|
231
|
+
workspaceId: text("workspace_id")
|
|
232
|
+
.notNull()
|
|
233
|
+
.references(() => organization.id, { onDelete: "cascade" }),
|
|
234
|
+
plan: text("plan").notNull().default("free"), // free | standard | pro
|
|
235
|
+
/**
|
|
236
|
+
* Per-action counters keyed by the product's own action slugs
|
|
237
|
+
* (`usage["chat"] = 42`), so a product adds a counter without a
|
|
238
|
+
* migration.
|
|
239
|
+
*/
|
|
240
|
+
usage: jsonb("usage").notNull().default({}),
|
|
241
|
+
totalCostUsd: real("total_cost_usd").notNull().default(0),
|
|
242
|
+
createdAt: timestamp("created_at").notNull().defaultNow(),
|
|
243
|
+
updatedAt: timestamp("updated_at").notNull().defaultNow(),
|
|
244
|
+
},
|
|
245
|
+
(table) => [
|
|
246
|
+
index("user_quotas_user_id_idx").on(table.userId),
|
|
247
|
+
index("user_quotas_workspace_id_idx").on(table.workspaceId),
|
|
248
|
+
// Unique per (user, workspace), not per user: a user in a paid and a
|
|
249
|
+
// free workspace must not share one plan and one set of counters.
|
|
250
|
+
unique("user_quotas_user_workspace_unique").on(
|
|
251
|
+
table.userId,
|
|
252
|
+
table.workspaceId
|
|
253
|
+
),
|
|
254
|
+
]
|
|
255
|
+
);
|
|
256
|
+
|
|
257
|
+
export type UserQuota = typeof userQuotas.$inferSelect;
|
|
258
|
+
export type InsertUserQuota = typeof userQuotas.$inferInsert;
|
|
259
|
+
export type UsageRecord = typeof usageRecords.$inferSelect;
|
|
260
|
+
export type InsertUsageRecord = typeof usageRecords.$inferInsert;
|
|
261
|
+
export type MonthlyUsage = typeof monthlyUsage.$inferSelect;
|
|
262
|
+
export type InsertMonthlyUsage = typeof monthlyUsage.$inferInsert;
|
|
263
|
+
export type TrialCredit = typeof trialCredits.$inferSelect;
|
|
264
|
+
export type InsertTrialCredit = typeof trialCredits.$inferInsert;
|
|
265
|
+
export type RateLimitEntry = typeof rateLimitEntries.$inferSelect;
|
|
266
|
+
export type InsertRateLimitEntry = typeof rateLimitEntries.$inferInsert;
|
|
267
|
+
export type NotificationHistoryRecord = typeof notificationHistory.$inferSelect;
|
|
268
|
+
export type InsertNotificationHistoryRecord =
|
|
269
|
+
typeof notificationHistory.$inferInsert;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { db } from "./client";
|
|
2
|
+
import { sql } from "drizzle-orm";
|
|
3
|
+
|
|
4
|
+
export interface DatabaseValidationResult {
|
|
5
|
+
isConnected: boolean;
|
|
6
|
+
tablesExist: boolean;
|
|
7
|
+
error?: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/** Checks that the database answers and the four auth tables exist. */
|
|
11
|
+
export async function validateDatabaseConnection(): Promise<DatabaseValidationResult> {
|
|
12
|
+
try {
|
|
13
|
+
await db.execute(sql`SELECT 1`);
|
|
14
|
+
|
|
15
|
+
const result = await db.execute(sql`
|
|
16
|
+
SELECT COUNT(*) as table_count
|
|
17
|
+
FROM information_schema.tables
|
|
18
|
+
WHERE table_schema = 'public'
|
|
19
|
+
AND table_name IN ('users', 'sessions', 'accounts', 'verifications')
|
|
20
|
+
`);
|
|
21
|
+
|
|
22
|
+
const tableCount = Number(result.rows[0]?.table_count ?? 0);
|
|
23
|
+
const tablesExist = tableCount === 4;
|
|
24
|
+
|
|
25
|
+
return {
|
|
26
|
+
isConnected: true,
|
|
27
|
+
tablesExist,
|
|
28
|
+
error: tablesExist
|
|
29
|
+
? undefined
|
|
30
|
+
: "Auth tables do not exist. Run 'intelligo migrate' to apply the framework's migration chain.",
|
|
31
|
+
};
|
|
32
|
+
} catch (error) {
|
|
33
|
+
return {
|
|
34
|
+
isConnected: false,
|
|
35
|
+
tablesExist: false,
|
|
36
|
+
error: error instanceof Error ? error.message : "Unknown database error",
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** Startup check: throws with setup instructions when validation fails. */
|
|
42
|
+
export async function requireDatabaseConnection(): Promise<void> {
|
|
43
|
+
const result = await validateDatabaseConnection();
|
|
44
|
+
|
|
45
|
+
if (!result.isConnected) {
|
|
46
|
+
throw new Error(
|
|
47
|
+
`❌ Database connection failed: ${result.error}\n\n` +
|
|
48
|
+
`Make sure DATABASE_URL is configured in .env.local\n` +
|
|
49
|
+
`Example: DATABASE_URL=postgres://user:pass@host/db`
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (!result.tablesExist) {
|
|
54
|
+
throw new Error(
|
|
55
|
+
`❌ Database tables do not exist.\n\n` +
|
|
56
|
+
`Run the following commands to set up the database:\n` +
|
|
57
|
+
` 1. intelligo migrate (applies the framework's migration chain)\n` +
|
|
58
|
+
` 2. drizzle-kit migrate (your own tables, if any)`
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
console.log("✓ Database connection validated");
|
|
63
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Workspace scoping for tables with a `workspaceId` column. Every query on
|
|
3
|
+
* such a table filters by the workspace resolved from `requireWorkspace()`.
|
|
4
|
+
* Organization, member and invitation rows go through the Better-Auth API,
|
|
5
|
+
* which scopes them to the caller's session.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { eq, and, type SQL } from "drizzle-orm";
|
|
9
|
+
import type { PgColumn } from "drizzle-orm/pg-core";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Creates a workspace-scoped WHERE condition for any table with a workspaceId column.
|
|
13
|
+
* Use it in every custom Drizzle query to enforce workspace isolation.
|
|
14
|
+
*
|
|
15
|
+
* @param workspaceIdColumn - The workspaceId column from the table schema
|
|
16
|
+
* @param workspaceId - The active workspace ID from requireWorkspace()
|
|
17
|
+
* @returns SQL condition: workspaceId = ?
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```typescript
|
|
21
|
+
* const { workspace } = await requireWorkspace();
|
|
22
|
+
* const conversations = await db
|
|
23
|
+
* .select()
|
|
24
|
+
* .from(conversationsTable)
|
|
25
|
+
* .where(workspaceEq(conversationsTable.workspaceId, workspace.id));
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export function workspaceEq(
|
|
29
|
+
workspaceIdColumn: PgColumn,
|
|
30
|
+
workspaceId: string
|
|
31
|
+
): SQL {
|
|
32
|
+
return eq(workspaceIdColumn, workspaceId);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Combines a workspace scope condition with additional WHERE conditions.
|
|
37
|
+
*
|
|
38
|
+
* @param workspaceIdColumn - The workspaceId column from the table schema
|
|
39
|
+
* @param workspaceId - The active workspace ID from requireWorkspace()
|
|
40
|
+
* @param additionalConditions - Extra WHERE conditions to AND together
|
|
41
|
+
* @returns Combined SQL condition: workspaceId = ? AND ...
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* ```typescript
|
|
45
|
+
* const { workspace } = await requireWorkspace();
|
|
46
|
+
* const activeConversations = await db
|
|
47
|
+
* .select()
|
|
48
|
+
* .from(conversationsTable)
|
|
49
|
+
* .where(
|
|
50
|
+
* withWorkspaceFilter(
|
|
51
|
+
* conversationsTable.workspaceId,
|
|
52
|
+
* workspace.id,
|
|
53
|
+
* eq(conversationsTable.status, "active")
|
|
54
|
+
* )
|
|
55
|
+
* );
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
export function withWorkspaceFilter(
|
|
59
|
+
workspaceIdColumn: PgColumn,
|
|
60
|
+
workspaceId: string,
|
|
61
|
+
...additionalConditions: SQL[]
|
|
62
|
+
): SQL {
|
|
63
|
+
return and(eq(workspaceIdColumn, workspaceId), ...additionalConditions)!;
|
|
64
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Document title classifier. Products register their title patterns here;
|
|
3
|
+
* the documents service uses them to derive agent labels and the "report"
|
|
4
|
+
* filter. Kept free of the db import so client code and tests can load it.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { createRegistry } from "../registry";
|
|
8
|
+
|
|
9
|
+
export type DocumentPatternEntry = {
|
|
10
|
+
/** Stable product slug — same one used across product configs. */
|
|
11
|
+
productSlug: string;
|
|
12
|
+
/** Human-readable agent label rendered in the documents UI. */
|
|
13
|
+
agentLabel: string;
|
|
14
|
+
/** Case-insensitive substring patterns; a document matches when its
|
|
15
|
+
* title contains ANY of these, whatever the case of either. */
|
|
16
|
+
patterns: string[];
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Keyed by product slug rather than appended, so a composition root that
|
|
21
|
+
* runs twice (or two copies of it) replaces the entry instead of matching
|
|
22
|
+
* the same patterns twice. Insertion order decides first-match
|
|
23
|
+
* classification.
|
|
24
|
+
*/
|
|
25
|
+
const registry = createRegistry<DocumentPatternEntry>("core/document-patterns");
|
|
26
|
+
|
|
27
|
+
export function registerDocumentPatterns(entry: DocumentPatternEntry): void {
|
|
28
|
+
registry.set(entry.productSlug, entry);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function classifyDocumentTitle(title: string): {
|
|
32
|
+
productSlug: string | null;
|
|
33
|
+
agentLabel: string;
|
|
34
|
+
} {
|
|
35
|
+
const lower = title.toLowerCase();
|
|
36
|
+
for (const entry of registry.values()) {
|
|
37
|
+
if (entry.patterns.some((p) => lower.includes(p.toLowerCase()))) {
|
|
38
|
+
return { productSlug: entry.productSlug, agentLabel: entry.agentLabel };
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return { productSlug: null, agentLabel: "AI Assistant" };
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** Returns true when the document looks like it belongs to any registered product. */
|
|
45
|
+
export function isProductDocument(
|
|
46
|
+
title: string,
|
|
47
|
+
productSlug?: string
|
|
48
|
+
): boolean {
|
|
49
|
+
const { productSlug: matched } = classifyDocumentTitle(title);
|
|
50
|
+
if (!matched) return false;
|
|
51
|
+
if (productSlug) return matched === productSlug;
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export function listRegisteredDocumentPatterns(): readonly DocumentPatternEntry[] {
|
|
56
|
+
return [...registry.values()];
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function clearDocumentPatternRegistry(): void {
|
|
60
|
+
registry.clear();
|
|
61
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Thrown by the documents service for every failure it recognizes. Shaping
|
|
3
|
+
* it into a transport envelope is the caller's job.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* - `not_found` — no document (or no version of it) exists at the
|
|
8
|
+
* given id within the actor's workspace/user scope.
|
|
9
|
+
* - `forbidden` — a document with this id exists but is owned by a
|
|
10
|
+
* different user within the same workspace.
|
|
11
|
+
* - `invalid_input` — a caller-supplied argument failed a basic
|
|
12
|
+
* invariant (e.g. an unparsable or out-of-window delete timestamp).
|
|
13
|
+
* - `database_error` — the underlying insert/update did not return the
|
|
14
|
+
* row it was expected to.
|
|
15
|
+
*/
|
|
16
|
+
export type DocumentServiceErrorCode =
|
|
17
|
+
"not_found" | "forbidden" | "invalid_input" | "database_error";
|
|
18
|
+
|
|
19
|
+
export class DocumentServiceError extends Error {
|
|
20
|
+
readonly code: DocumentServiceErrorCode;
|
|
21
|
+
// The ES2020 target predates `Error.cause`; declared so `err.cause`
|
|
22
|
+
// type-checks for callers.
|
|
23
|
+
readonly cause?: unknown;
|
|
24
|
+
|
|
25
|
+
constructor(
|
|
26
|
+
code: DocumentServiceErrorCode,
|
|
27
|
+
message: string,
|
|
28
|
+
options?: { cause?: unknown }
|
|
29
|
+
) {
|
|
30
|
+
super(message);
|
|
31
|
+
this.name = "DocumentServiceError";
|
|
32
|
+
this.code = code;
|
|
33
|
+
if (options?.cause !== undefined) {
|
|
34
|
+
(this as { cause?: unknown }).cause = options.cause;
|
|
35
|
+
}
|
|
36
|
+
Object.setPrototypeOf(this, DocumentServiceError.prototype);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function isDocumentServiceError(
|
|
41
|
+
error: unknown
|
|
42
|
+
): error is DocumentServiceError {
|
|
43
|
+
return error instanceof DocumentServiceError;
|
|
44
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export {
|
|
2
|
+
getUserDocuments,
|
|
3
|
+
getDocument,
|
|
4
|
+
getDocumentVersions,
|
|
5
|
+
saveDocument,
|
|
6
|
+
deleteDocumentVersions,
|
|
7
|
+
} from "./service";
|
|
8
|
+
|
|
9
|
+
export {
|
|
10
|
+
DocumentServiceError,
|
|
11
|
+
isDocumentServiceError,
|
|
12
|
+
type DocumentServiceErrorCode,
|
|
13
|
+
} from "./errors";
|
|
14
|
+
|
|
15
|
+
export type { DocumentActor, DocumentFilter, DocumentListItem } from "./types";
|
|
16
|
+
|
|
17
|
+
export {
|
|
18
|
+
registerDocumentPatterns,
|
|
19
|
+
classifyDocumentTitle,
|
|
20
|
+
isProductDocument,
|
|
21
|
+
listRegisteredDocumentPatterns,
|
|
22
|
+
clearDocumentPatternRegistry,
|
|
23
|
+
type DocumentPatternEntry,
|
|
24
|
+
} from "./classifier";
|