@naisys/hub-database 3.0.0-beta.10

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.
Files changed (50) hide show
  1. package/README.md +84 -0
  2. package/dist/dbConfig.js +4 -0
  3. package/dist/generated/prisma/browser.js +17 -0
  4. package/dist/generated/prisma/client.js +34 -0
  5. package/dist/generated/prisma/commonInputTypes.js +10 -0
  6. package/dist/generated/prisma/enums.js +56 -0
  7. package/dist/generated/prisma/internal/class.js +49 -0
  8. package/dist/generated/prisma/internal/prismaNamespace.js +248 -0
  9. package/dist/generated/prisma/internal/prismaNamespaceBrowser.js +219 -0
  10. package/dist/generated/prisma/models/attachments.js +1 -0
  11. package/dist/generated/prisma/models/config_revisions.js +1 -0
  12. package/dist/generated/prisma/models/context_log.js +1 -0
  13. package/dist/generated/prisma/models/costs.js +1 -0
  14. package/dist/generated/prisma/models/hosts.js +1 -0
  15. package/dist/generated/prisma/models/mail_attachments.js +1 -0
  16. package/dist/generated/prisma/models/mail_messages.js +1 -0
  17. package/dist/generated/prisma/models/mail_recipients.js +1 -0
  18. package/dist/generated/prisma/models/models.js +1 -0
  19. package/dist/generated/prisma/models/run_session.js +1 -0
  20. package/dist/generated/prisma/models/schema_version.js +1 -0
  21. package/dist/generated/prisma/models/user_hosts.js +1 -0
  22. package/dist/generated/prisma/models/user_notifications.js +1 -0
  23. package/dist/generated/prisma/models/users.js +1 -0
  24. package/dist/generated/prisma/models/variables.js +1 -0
  25. package/dist/generated/prisma/models.js +1 -0
  26. package/dist/hubDatabaseService.js +38 -0
  27. package/dist/hubSessionService.js +112 -0
  28. package/dist/index.js +13 -0
  29. package/dist/prismaClient.js +21 -0
  30. package/package.json +42 -0
  31. package/prisma/migrations/20260223234341_init/migration.sql +237 -0
  32. package/prisma/migrations/20260225041145_add_host_restricted/migration.sql +20 -0
  33. package/prisma/migrations/20260227000000_add_host_type/migration.sql +21 -0
  34. package/prisma/migrations/20260302000000_make_from_user_id_not_null/migration.sql +37 -0
  35. package/prisma/migrations/20260302100000_add_cost_suspended_reason/migration.sql +2 -0
  36. package/prisma/migrations/20260305000000_make_participant_ids_not_null/migration.sql +31 -0
  37. package/prisma/migrations/20260306000000_add_host_last_ip/migration.sql +1 -0
  38. package/prisma/migrations/20260310000000_rename_participant_ids_to_participants/migration.sql +61 -0
  39. package/prisma/migrations/20260312000000_fix_empty_enum_strings/migration.sql +31 -0
  40. package/prisma/migrations/20260313000000_add_user_enabled/migration.sql +5 -0
  41. package/prisma/migrations/20260327000000_add_config_revisions/migration.sql +13 -0
  42. package/prisma/migrations/20260328000000_add_from_recipient_type/migration.sql +13 -0
  43. package/prisma/migrations/20260328100000_add_spend_limit_reset_at/migration.sql +1 -0
  44. package/prisma/migrations/20260328200000_add_budget_left/migration.sql +1 -0
  45. package/prisma/migrations/20260401000000_rename_workspace_to_tool/migration.sql +2 -0
  46. package/prisma/migrations/20260403000000_add_export_to_shell/migration.sql +2 -0
  47. package/prisma/migrations/20260404000000_add_attachment_public_id/migration.sql +8 -0
  48. package/prisma/migrations/migration_lock.toml +3 -0
  49. package/prisma/schema.prisma +307 -0
  50. package/prisma.config.ts +18 -0
@@ -0,0 +1,248 @@
1
+ /* !!! This is code generated by Prisma. Do not edit directly. !!! */
2
+ /* eslint-disable */
3
+ // biome-ignore-all lint: generated file
4
+ // @ts-nocheck
5
+ /*
6
+ * WARNING: This is an internal file that is subject to change!
7
+ *
8
+ * 🛑 Under no circumstances should you import this file directly! 🛑
9
+ *
10
+ * All exports from this file are wrapped under a `Prisma` namespace object in the client.ts file.
11
+ * While this enables partial backward compatibility, it is not part of the stable public API.
12
+ *
13
+ * If you are looking for your Models, Enums, and Input Types, please import them from the respective
14
+ * model files in the `model` directory!
15
+ */
16
+ import * as runtime from "@prisma/client/runtime/client";
17
+ /**
18
+ * Prisma Errors
19
+ */
20
+ export const PrismaClientKnownRequestError = runtime.PrismaClientKnownRequestError;
21
+ export const PrismaClientUnknownRequestError = runtime.PrismaClientUnknownRequestError;
22
+ export const PrismaClientRustPanicError = runtime.PrismaClientRustPanicError;
23
+ export const PrismaClientInitializationError = runtime.PrismaClientInitializationError;
24
+ export const PrismaClientValidationError = runtime.PrismaClientValidationError;
25
+ /**
26
+ * Re-export of sql-template-tag
27
+ */
28
+ export const sql = runtime.sqltag;
29
+ export const empty = runtime.empty;
30
+ export const join = runtime.join;
31
+ export const raw = runtime.raw;
32
+ export const Sql = runtime.Sql;
33
+ /**
34
+ * Decimal.js
35
+ */
36
+ export const Decimal = runtime.Decimal;
37
+ export const getExtensionContext = runtime.Extensions.getExtensionContext;
38
+ /**
39
+ * Prisma Client JS version: 7.6.0
40
+ * Query Engine version: 75cbdc1eb7150937890ad5465d861175c6624711
41
+ */
42
+ export const prismaVersion = {
43
+ client: "7.6.0",
44
+ engine: "75cbdc1eb7150937890ad5465d861175c6624711"
45
+ };
46
+ export const NullTypes = {
47
+ DbNull: runtime.NullTypes.DbNull,
48
+ JsonNull: runtime.NullTypes.JsonNull,
49
+ AnyNull: runtime.NullTypes.AnyNull,
50
+ };
51
+ /**
52
+ * Helper for filtering JSON entries that have `null` on the database (empty on the db)
53
+ *
54
+ * @see https://www.prisma.io/docs/concepts/components/prisma-client/working-with-fields/working-with-json-fields#filtering-on-a-json-field
55
+ */
56
+ export const DbNull = runtime.DbNull;
57
+ /**
58
+ * Helper for filtering JSON entries that have JSON `null` values (not empty on the db)
59
+ *
60
+ * @see https://www.prisma.io/docs/concepts/components/prisma-client/working-with-fields/working-with-json-fields#filtering-on-a-json-field
61
+ */
62
+ export const JsonNull = runtime.JsonNull;
63
+ /**
64
+ * Helper for filtering JSON entries that are `Prisma.DbNull` or `Prisma.JsonNull`
65
+ *
66
+ * @see https://www.prisma.io/docs/concepts/components/prisma-client/working-with-fields/working-with-json-fields#filtering-on-a-json-field
67
+ */
68
+ export const AnyNull = runtime.AnyNull;
69
+ export const ModelName = {
70
+ context_log: 'context_log',
71
+ costs: 'costs',
72
+ mail_messages: 'mail_messages',
73
+ attachments: 'attachments',
74
+ mail_attachments: 'mail_attachments',
75
+ mail_recipients: 'mail_recipients',
76
+ users: 'users',
77
+ user_notifications: 'user_notifications',
78
+ user_hosts: 'user_hosts',
79
+ run_session: 'run_session',
80
+ schema_version: 'schema_version',
81
+ hosts: 'hosts',
82
+ config_revisions: 'config_revisions',
83
+ variables: 'variables',
84
+ models: 'models'
85
+ };
86
+ /**
87
+ * Enums
88
+ */
89
+ export const TransactionIsolationLevel = runtime.makeStrictEnum({
90
+ Serializable: 'Serializable'
91
+ });
92
+ export const Context_logScalarFieldEnum = {
93
+ id: 'id',
94
+ user_id: 'user_id',
95
+ run_id: 'run_id',
96
+ session_id: 'session_id',
97
+ host_id: 'host_id',
98
+ role: 'role',
99
+ source: 'source',
100
+ type: 'type',
101
+ message: 'message',
102
+ attachment_id: 'attachment_id',
103
+ created_at: 'created_at'
104
+ };
105
+ export const CostsScalarFieldEnum = {
106
+ id: 'id',
107
+ user_id: 'user_id',
108
+ run_id: 'run_id',
109
+ session_id: 'session_id',
110
+ host_id: 'host_id',
111
+ source: 'source',
112
+ model: 'model',
113
+ cost: 'cost',
114
+ input_tokens: 'input_tokens',
115
+ output_tokens: 'output_tokens',
116
+ cache_write_tokens: 'cache_write_tokens',
117
+ cache_read_tokens: 'cache_read_tokens',
118
+ created_at: 'created_at'
119
+ };
120
+ export const Mail_messagesScalarFieldEnum = {
121
+ id: 'id',
122
+ from_user_id: 'from_user_id',
123
+ host_id: 'host_id',
124
+ kind: 'kind',
125
+ participants: 'participants',
126
+ subject: 'subject',
127
+ body: 'body',
128
+ created_at: 'created_at'
129
+ };
130
+ export const AttachmentsScalarFieldEnum = {
131
+ id: 'id',
132
+ public_id: 'public_id',
133
+ filepath: 'filepath',
134
+ filename: 'filename',
135
+ file_size: 'file_size',
136
+ file_hash: 'file_hash',
137
+ purpose: 'purpose',
138
+ uploaded_by: 'uploaded_by',
139
+ created_at: 'created_at'
140
+ };
141
+ export const Mail_attachmentsScalarFieldEnum = {
142
+ message_id: 'message_id',
143
+ attachment_id: 'attachment_id',
144
+ created_at: 'created_at'
145
+ };
146
+ export const Mail_recipientsScalarFieldEnum = {
147
+ id: 'id',
148
+ message_id: 'message_id',
149
+ user_id: 'user_id',
150
+ type: 'type',
151
+ read_at: 'read_at',
152
+ archived_at: 'archived_at',
153
+ created_at: 'created_at'
154
+ };
155
+ export const UsersScalarFieldEnum = {
156
+ id: 'id',
157
+ uuid: 'uuid',
158
+ username: 'username',
159
+ title: 'title',
160
+ api_key: 'api_key',
161
+ lead_user_id: 'lead_user_id',
162
+ config: 'config',
163
+ created_at: 'created_at',
164
+ updated_at: 'updated_at',
165
+ enabled: 'enabled',
166
+ archived: 'archived'
167
+ };
168
+ export const User_notificationsScalarFieldEnum = {
169
+ user_id: 'user_id',
170
+ latest_host_id: 'latest_host_id',
171
+ latest_log_id: 'latest_log_id',
172
+ latest_mail_id: 'latest_mail_id',
173
+ latest_chat_id: 'latest_chat_id',
174
+ last_active: 'last_active',
175
+ cost_suspended_reason: 'cost_suspended_reason',
176
+ spend_limit_reset_at: 'spend_limit_reset_at',
177
+ budget_left: 'budget_left',
178
+ updated_at: 'updated_at'
179
+ };
180
+ export const User_hostsScalarFieldEnum = {
181
+ user_id: 'user_id',
182
+ host_id: 'host_id',
183
+ created_at: 'created_at'
184
+ };
185
+ export const Run_sessionScalarFieldEnum = {
186
+ user_id: 'user_id',
187
+ run_id: 'run_id',
188
+ session_id: 'session_id',
189
+ host_id: 'host_id',
190
+ last_active: 'last_active',
191
+ model_name: 'model_name',
192
+ latest_log_id: 'latest_log_id',
193
+ total_lines: 'total_lines',
194
+ total_cost: 'total_cost',
195
+ created_at: 'created_at',
196
+ updated_at: 'updated_at'
197
+ };
198
+ export const Schema_versionScalarFieldEnum = {
199
+ id: 'id',
200
+ version: 'version',
201
+ updated: 'updated'
202
+ };
203
+ export const HostsScalarFieldEnum = {
204
+ id: 'id',
205
+ name: 'name',
206
+ restricted: 'restricted',
207
+ host_type: 'host_type',
208
+ last_ip: 'last_ip',
209
+ last_active: 'last_active',
210
+ created_at: 'created_at'
211
+ };
212
+ export const Config_revisionsScalarFieldEnum = {
213
+ id: 'id',
214
+ user_id: 'user_id',
215
+ config: 'config',
216
+ changed_by_id: 'changed_by_id',
217
+ created_at: 'created_at'
218
+ };
219
+ export const VariablesScalarFieldEnum = {
220
+ key: 'key',
221
+ value: 'value',
222
+ export_to_shell: 'export_to_shell',
223
+ created_by: 'created_by',
224
+ updated_by: 'updated_by',
225
+ created_at: 'created_at',
226
+ updated_at: 'updated_at'
227
+ };
228
+ export const ModelsScalarFieldEnum = {
229
+ id: 'id',
230
+ key: 'key',
231
+ type: 'type',
232
+ label: 'label',
233
+ version_name: 'version_name',
234
+ is_builtin: 'is_builtin',
235
+ is_custom: 'is_custom',
236
+ meta: 'meta',
237
+ created_at: 'created_at',
238
+ updated_at: 'updated_at'
239
+ };
240
+ export const SortOrder = {
241
+ asc: 'asc',
242
+ desc: 'desc'
243
+ };
244
+ export const NullsOrder = {
245
+ first: 'first',
246
+ last: 'last'
247
+ };
248
+ export const defineExtension = runtime.Extensions.defineExtension;
@@ -0,0 +1,219 @@
1
+ /* !!! This is code generated by Prisma. Do not edit directly. !!! */
2
+ /* eslint-disable */
3
+ // biome-ignore-all lint: generated file
4
+ // @ts-nocheck
5
+ /*
6
+ * WARNING: This is an internal file that is subject to change!
7
+ *
8
+ * 🛑 Under no circumstances should you import this file directly! 🛑
9
+ *
10
+ * All exports from this file are wrapped under a `Prisma` namespace object in the browser.ts file.
11
+ * While this enables partial backward compatibility, it is not part of the stable public API.
12
+ *
13
+ * If you are looking for your Models, Enums, and Input Types, please import them from the respective
14
+ * model files in the `model` directory!
15
+ */
16
+ import * as runtime from "@prisma/client/runtime/index-browser";
17
+ export const Decimal = runtime.Decimal;
18
+ export const NullTypes = {
19
+ DbNull: runtime.NullTypes.DbNull,
20
+ JsonNull: runtime.NullTypes.JsonNull,
21
+ AnyNull: runtime.NullTypes.AnyNull,
22
+ };
23
+ /**
24
+ * Helper for filtering JSON entries that have `null` on the database (empty on the db)
25
+ *
26
+ * @see https://www.prisma.io/docs/concepts/components/prisma-client/working-with-fields/working-with-json-fields#filtering-on-a-json-field
27
+ */
28
+ export const DbNull = runtime.DbNull;
29
+ /**
30
+ * Helper for filtering JSON entries that have JSON `null` values (not empty on the db)
31
+ *
32
+ * @see https://www.prisma.io/docs/concepts/components/prisma-client/working-with-fields/working-with-json-fields#filtering-on-a-json-field
33
+ */
34
+ export const JsonNull = runtime.JsonNull;
35
+ /**
36
+ * Helper for filtering JSON entries that are `Prisma.DbNull` or `Prisma.JsonNull`
37
+ *
38
+ * @see https://www.prisma.io/docs/concepts/components/prisma-client/working-with-fields/working-with-json-fields#filtering-on-a-json-field
39
+ */
40
+ export const AnyNull = runtime.AnyNull;
41
+ export const ModelName = {
42
+ context_log: 'context_log',
43
+ costs: 'costs',
44
+ mail_messages: 'mail_messages',
45
+ attachments: 'attachments',
46
+ mail_attachments: 'mail_attachments',
47
+ mail_recipients: 'mail_recipients',
48
+ users: 'users',
49
+ user_notifications: 'user_notifications',
50
+ user_hosts: 'user_hosts',
51
+ run_session: 'run_session',
52
+ schema_version: 'schema_version',
53
+ hosts: 'hosts',
54
+ config_revisions: 'config_revisions',
55
+ variables: 'variables',
56
+ models: 'models'
57
+ };
58
+ /*
59
+ * Enums
60
+ */
61
+ export const TransactionIsolationLevel = runtime.makeStrictEnum({
62
+ Serializable: 'Serializable'
63
+ });
64
+ export const Context_logScalarFieldEnum = {
65
+ id: 'id',
66
+ user_id: 'user_id',
67
+ run_id: 'run_id',
68
+ session_id: 'session_id',
69
+ host_id: 'host_id',
70
+ role: 'role',
71
+ source: 'source',
72
+ type: 'type',
73
+ message: 'message',
74
+ attachment_id: 'attachment_id',
75
+ created_at: 'created_at'
76
+ };
77
+ export const CostsScalarFieldEnum = {
78
+ id: 'id',
79
+ user_id: 'user_id',
80
+ run_id: 'run_id',
81
+ session_id: 'session_id',
82
+ host_id: 'host_id',
83
+ source: 'source',
84
+ model: 'model',
85
+ cost: 'cost',
86
+ input_tokens: 'input_tokens',
87
+ output_tokens: 'output_tokens',
88
+ cache_write_tokens: 'cache_write_tokens',
89
+ cache_read_tokens: 'cache_read_tokens',
90
+ created_at: 'created_at'
91
+ };
92
+ export const Mail_messagesScalarFieldEnum = {
93
+ id: 'id',
94
+ from_user_id: 'from_user_id',
95
+ host_id: 'host_id',
96
+ kind: 'kind',
97
+ participants: 'participants',
98
+ subject: 'subject',
99
+ body: 'body',
100
+ created_at: 'created_at'
101
+ };
102
+ export const AttachmentsScalarFieldEnum = {
103
+ id: 'id',
104
+ public_id: 'public_id',
105
+ filepath: 'filepath',
106
+ filename: 'filename',
107
+ file_size: 'file_size',
108
+ file_hash: 'file_hash',
109
+ purpose: 'purpose',
110
+ uploaded_by: 'uploaded_by',
111
+ created_at: 'created_at'
112
+ };
113
+ export const Mail_attachmentsScalarFieldEnum = {
114
+ message_id: 'message_id',
115
+ attachment_id: 'attachment_id',
116
+ created_at: 'created_at'
117
+ };
118
+ export const Mail_recipientsScalarFieldEnum = {
119
+ id: 'id',
120
+ message_id: 'message_id',
121
+ user_id: 'user_id',
122
+ type: 'type',
123
+ read_at: 'read_at',
124
+ archived_at: 'archived_at',
125
+ created_at: 'created_at'
126
+ };
127
+ export const UsersScalarFieldEnum = {
128
+ id: 'id',
129
+ uuid: 'uuid',
130
+ username: 'username',
131
+ title: 'title',
132
+ api_key: 'api_key',
133
+ lead_user_id: 'lead_user_id',
134
+ config: 'config',
135
+ created_at: 'created_at',
136
+ updated_at: 'updated_at',
137
+ enabled: 'enabled',
138
+ archived: 'archived'
139
+ };
140
+ export const User_notificationsScalarFieldEnum = {
141
+ user_id: 'user_id',
142
+ latest_host_id: 'latest_host_id',
143
+ latest_log_id: 'latest_log_id',
144
+ latest_mail_id: 'latest_mail_id',
145
+ latest_chat_id: 'latest_chat_id',
146
+ last_active: 'last_active',
147
+ cost_suspended_reason: 'cost_suspended_reason',
148
+ spend_limit_reset_at: 'spend_limit_reset_at',
149
+ budget_left: 'budget_left',
150
+ updated_at: 'updated_at'
151
+ };
152
+ export const User_hostsScalarFieldEnum = {
153
+ user_id: 'user_id',
154
+ host_id: 'host_id',
155
+ created_at: 'created_at'
156
+ };
157
+ export const Run_sessionScalarFieldEnum = {
158
+ user_id: 'user_id',
159
+ run_id: 'run_id',
160
+ session_id: 'session_id',
161
+ host_id: 'host_id',
162
+ last_active: 'last_active',
163
+ model_name: 'model_name',
164
+ latest_log_id: 'latest_log_id',
165
+ total_lines: 'total_lines',
166
+ total_cost: 'total_cost',
167
+ created_at: 'created_at',
168
+ updated_at: 'updated_at'
169
+ };
170
+ export const Schema_versionScalarFieldEnum = {
171
+ id: 'id',
172
+ version: 'version',
173
+ updated: 'updated'
174
+ };
175
+ export const HostsScalarFieldEnum = {
176
+ id: 'id',
177
+ name: 'name',
178
+ restricted: 'restricted',
179
+ host_type: 'host_type',
180
+ last_ip: 'last_ip',
181
+ last_active: 'last_active',
182
+ created_at: 'created_at'
183
+ };
184
+ export const Config_revisionsScalarFieldEnum = {
185
+ id: 'id',
186
+ user_id: 'user_id',
187
+ config: 'config',
188
+ changed_by_id: 'changed_by_id',
189
+ created_at: 'created_at'
190
+ };
191
+ export const VariablesScalarFieldEnum = {
192
+ key: 'key',
193
+ value: 'value',
194
+ export_to_shell: 'export_to_shell',
195
+ created_by: 'created_by',
196
+ updated_by: 'updated_by',
197
+ created_at: 'created_at',
198
+ updated_at: 'updated_at'
199
+ };
200
+ export const ModelsScalarFieldEnum = {
201
+ id: 'id',
202
+ key: 'key',
203
+ type: 'type',
204
+ label: 'label',
205
+ version_name: 'version_name',
206
+ is_builtin: 'is_builtin',
207
+ is_custom: 'is_custom',
208
+ meta: 'meta',
209
+ created_at: 'created_at',
210
+ updated_at: 'updated_at'
211
+ };
212
+ export const SortOrder = {
213
+ asc: 'asc',
214
+ desc: 'desc'
215
+ };
216
+ export const NullsOrder = {
217
+ first: 'first',
218
+ last: 'last'
219
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,38 @@
1
+ import { deployPrismaMigrations } from "@naisys/common-node";
2
+ import { existsSync, mkdirSync } from "fs";
3
+ import { dirname } from "path";
4
+ import { fileURLToPath } from "url";
5
+ import { hubDbPath } from "./dbConfig.js";
6
+ import { createPrismaClient } from "./prismaClient.js";
7
+ export async function createHubDatabaseService() {
8
+ /** We run migration scripts if this is greater than what's in the schema_version table */
9
+ const HUB_DB_VERSION = 34;
10
+ const dbPath = hubDbPath();
11
+ // Ensure database directory exists
12
+ const databaseDir = dirname(dbPath);
13
+ if (!existsSync(databaseDir)) {
14
+ mkdirSync(databaseDir, { recursive: true });
15
+ }
16
+ await runMigrations();
17
+ const prisma = await createPrismaClient(dbPath);
18
+ async function runMigrations() {
19
+ const currentFilePath = fileURLToPath(import.meta.url);
20
+ const databasePackageDir = dirname(dirname(currentFilePath));
21
+ await deployPrismaMigrations({
22
+ packageDir: databasePackageDir,
23
+ databasePath: dbPath,
24
+ expectedVersion: HUB_DB_VERSION,
25
+ });
26
+ }
27
+ function getSchemaVersion() {
28
+ return HUB_DB_VERSION;
29
+ }
30
+ async function disconnect() {
31
+ await prisma.$disconnect();
32
+ }
33
+ return {
34
+ hubDb: prisma,
35
+ getSchemaVersion,
36
+ disconnect,
37
+ };
38
+ }
@@ -0,0 +1,112 @@
1
+ import { existsSync } from "fs";
2
+ import { hubDbPath } from "./dbConfig.js";
3
+ import { createPrismaClient } from "./prismaClient.js";
4
+ let prisma = null;
5
+ /**
6
+ * Initialize hub sessions by connecting to the shared naisys_hub.db.
7
+ * Idempotent — returns early if already initialized.
8
+ * No-ops gracefully if NAISYS_FOLDER is unset or the database doesn't exist.
9
+ */
10
+ export async function createHubDatabaseClient() {
11
+ if (prisma)
12
+ return true;
13
+ const dbPath = hubDbPath();
14
+ if (!existsSync(dbPath))
15
+ return false;
16
+ prisma = await createPrismaClient(dbPath);
17
+ return true;
18
+ }
19
+ /**
20
+ * Find an agent (from the hub `users` table) by API key.
21
+ */
22
+ export async function findAgentByApiKey(apiKey) {
23
+ if (!prisma)
24
+ return null;
25
+ const user = await prisma.users.findUnique({
26
+ where: { api_key: apiKey },
27
+ select: { uuid: true, username: true },
28
+ });
29
+ return user;
30
+ }
31
+ /**
32
+ * Find a hub agent by its numeric ID.
33
+ */
34
+ export async function getHubAgentById(id) {
35
+ if (!prisma)
36
+ return null;
37
+ return prisma.users.findUnique({
38
+ where: { id },
39
+ select: { id: true, uuid: true, username: true },
40
+ });
41
+ }
42
+ /**
43
+ * Look up an agent's API key by UUID.
44
+ */
45
+ export async function getAgentApiKeyByUuid(uuid) {
46
+ if (!prisma)
47
+ return null;
48
+ const user = await prisma.users.findFirst({
49
+ where: { uuid },
50
+ select: { api_key: true },
51
+ });
52
+ return user?.api_key ?? null;
53
+ }
54
+ /**
55
+ * Get the latest run_id and current session start time for a hub user by UUID.
56
+ */
57
+ export async function getLatestRunInfoByUuid(uuid) {
58
+ if (!prisma)
59
+ return null;
60
+ const user = await prisma.users.findFirst({
61
+ where: { uuid },
62
+ select: { id: true },
63
+ });
64
+ if (!user)
65
+ return null;
66
+ const latest = await prisma.run_session.findFirst({
67
+ where: { user_id: user.id },
68
+ orderBy: [{ run_id: "desc" }, { session_id: "desc" }],
69
+ select: { run_id: true, created_at: true },
70
+ });
71
+ if (!latest)
72
+ return null;
73
+ return { runId: latest.run_id, sessionStart: latest.created_at };
74
+ }
75
+ /**
76
+ * Sum the cost of all cost entries for a hub user (by UUID) within a time range.
77
+ */
78
+ export async function sumCostsByUuid(uuid, from, to) {
79
+ if (!prisma)
80
+ return 0;
81
+ const user = await prisma.users.findFirst({
82
+ where: { uuid },
83
+ select: { id: true },
84
+ });
85
+ if (!user)
86
+ return 0;
87
+ const result = await prisma.costs.aggregate({
88
+ _sum: { cost: true },
89
+ where: {
90
+ user_id: user.id,
91
+ created_at: { gte: from, lte: to },
92
+ },
93
+ });
94
+ return result._sum.cost ?? 0;
95
+ }
96
+ /**
97
+ * Rotate an agent's API key by UUID.
98
+ */
99
+ export async function rotateAgentApiKeyByUuid(uuid, newKey) {
100
+ if (!prisma)
101
+ throw new Error("Hub database not initialized");
102
+ const user = await prisma.users.findFirst({
103
+ where: { uuid },
104
+ select: { id: true },
105
+ });
106
+ if (!user)
107
+ throw new Error("Agent not found in hub database");
108
+ await prisma.users.update({
109
+ where: { id: user.id },
110
+ data: { api_key: newKey },
111
+ });
112
+ }
package/dist/index.js ADDED
@@ -0,0 +1,13 @@
1
+ // Re-export Database Service
2
+ export { createHubDatabaseService, } from "./hubDatabaseService.js";
3
+ // Re-export Migration Helper
4
+ export { deployPrismaMigrations } from "@naisys/common-node";
5
+ // Re-export Hub Session Service
6
+ export { createHubDatabaseClient, findAgentByApiKey, getAgentApiKeyByUuid, getHubAgentById, getLatestRunInfoByUuid, rotateAgentApiKeyByUuid, sumCostsByUuid, } from "./hubSessionService.js";
7
+ // Re-export Prisma Client and all generated types
8
+ export * from "./generated/prisma/client.js";
9
+ export { PrismaClient } from "./generated/prisma/client.js";
10
+ // Re-export Prisma enums
11
+ export * from "./generated/prisma/enums.js";
12
+ // Re-export Prisma client factory
13
+ export { createPrismaClient } from "./prismaClient.js";