@rankmyseo/storage 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/dist/index.cjs ADDED
@@ -0,0 +1,641 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var index_exports = {};
32
+ __export(index_exports, {
33
+ createSqliteStore: () => createSqliteStore,
34
+ createStore: () => createStore
35
+ });
36
+ module.exports = __toCommonJS(index_exports);
37
+ var import_server_only3 = require("server-only");
38
+
39
+ // src/factory.ts
40
+ var import_server_only2 = require("server-only");
41
+
42
+ // src/sqlite-store.ts
43
+ var import_server_only = require("server-only");
44
+ var import_node_crypto = require("crypto");
45
+ var import_better_sqlite3 = __toESM(require("better-sqlite3"), 1);
46
+ var import_better_sqlite32 = require("drizzle-orm/better-sqlite3");
47
+ var import_drizzle_orm = require("drizzle-orm");
48
+
49
+ // src/schema/sqlite.ts
50
+ var import_sqlite_core = require("drizzle-orm/sqlite-core");
51
+ var projects = (0, import_sqlite_core.sqliteTable)("rms_projects", {
52
+ id: (0, import_sqlite_core.text)("id").primaryKey(),
53
+ tenantId: (0, import_sqlite_core.text)("tenant_id").notNull(),
54
+ name: (0, import_sqlite_core.text)("name").notNull(),
55
+ domain: (0, import_sqlite_core.text)("domain").notNull(),
56
+ createdAt: (0, import_sqlite_core.integer)("created_at", { mode: "timestamp_ms" }).notNull(),
57
+ updatedAt: (0, import_sqlite_core.integer)("updated_at", { mode: "timestamp_ms" }).notNull()
58
+ });
59
+ var keywords = (0, import_sqlite_core.sqliteTable)("rms_keywords", {
60
+ id: (0, import_sqlite_core.text)("id").primaryKey(),
61
+ tenantId: (0, import_sqlite_core.text)("tenant_id").notNull(),
62
+ projectId: (0, import_sqlite_core.text)("project_id").notNull(),
63
+ text: (0, import_sqlite_core.text)("text").notNull(),
64
+ country: (0, import_sqlite_core.text)("country").notNull(),
65
+ device: (0, import_sqlite_core.text)("device").notNull(),
66
+ tags: (0, import_sqlite_core.text)("tags").notNull(),
67
+ createdAt: (0, import_sqlite_core.integer)("created_at", { mode: "timestamp_ms" }).notNull()
68
+ });
69
+ var rankSnapshots = (0, import_sqlite_core.sqliteTable)("rms_rank_snapshots", {
70
+ id: (0, import_sqlite_core.text)("id").primaryKey(),
71
+ tenantId: (0, import_sqlite_core.text)("tenant_id").notNull(),
72
+ projectId: (0, import_sqlite_core.text)("project_id").notNull(),
73
+ keywordId: (0, import_sqlite_core.text)("keyword_id").notNull(),
74
+ position: (0, import_sqlite_core.integer)("position"),
75
+ url: (0, import_sqlite_core.text)("url"),
76
+ source: (0, import_sqlite_core.text)("source").notNull(),
77
+ device: (0, import_sqlite_core.text)("device").notNull(),
78
+ country: (0, import_sqlite_core.text)("country").notNull(),
79
+ capturedAt: (0, import_sqlite_core.integer)("captured_at", { mode: "timestamp_ms" }).notNull(),
80
+ serpFeatures: (0, import_sqlite_core.text)("serp_features")
81
+ });
82
+ var audits = (0, import_sqlite_core.sqliteTable)("rms_audits", {
83
+ id: (0, import_sqlite_core.text)("id").primaryKey(),
84
+ tenantId: (0, import_sqlite_core.text)("tenant_id").notNull(),
85
+ projectId: (0, import_sqlite_core.text)("project_id").notNull(),
86
+ url: (0, import_sqlite_core.text)("url").notNull(),
87
+ score: (0, import_sqlite_core.integer)("score").notNull(),
88
+ checks: (0, import_sqlite_core.text)("checks").notNull().default("[]"),
89
+ createdAt: (0, import_sqlite_core.integer)("created_at", { mode: "timestamp_ms" }).notNull()
90
+ });
91
+ var reports = (0, import_sqlite_core.sqliteTable)("rms_reports", {
92
+ id: (0, import_sqlite_core.text)("id").primaryKey(),
93
+ tenantId: (0, import_sqlite_core.text)("tenant_id").notNull(),
94
+ projectId: (0, import_sqlite_core.text)("project_id").notNull(),
95
+ title: (0, import_sqlite_core.text)("title").notNull(),
96
+ from: (0, import_sqlite_core.integer)("from", { mode: "timestamp_ms" }).notNull(),
97
+ to: (0, import_sqlite_core.integer)("to", { mode: "timestamp_ms" }).notNull(),
98
+ summary: (0, import_sqlite_core.text)("summary"),
99
+ createdAt: (0, import_sqlite_core.integer)("created_at", { mode: "timestamp_ms" }).notNull()
100
+ });
101
+ var dashboardConfigs = (0, import_sqlite_core.sqliteTable)("rms_dashboard_configs", {
102
+ id: (0, import_sqlite_core.text)("id").primaryKey(),
103
+ tenantId: (0, import_sqlite_core.text)("tenant_id").notNull(),
104
+ projectId: (0, import_sqlite_core.text)("project_id").notNull(),
105
+ widgets: (0, import_sqlite_core.text)("widgets").notNull(),
106
+ updatedAt: (0, import_sqlite_core.integer)("updated_at", { mode: "timestamp_ms" }).notNull()
107
+ });
108
+ var blogPosts = (0, import_sqlite_core.sqliteTable)("rms_blog_posts", {
109
+ id: (0, import_sqlite_core.text)("id").primaryKey(),
110
+ tenantId: (0, import_sqlite_core.text)("tenant_id").notNull(),
111
+ projectId: (0, import_sqlite_core.text)("project_id").notNull(),
112
+ title: (0, import_sqlite_core.text)("title").notNull(),
113
+ slug: (0, import_sqlite_core.text)("slug").notNull(),
114
+ content: (0, import_sqlite_core.text)("content").notNull().default(""),
115
+ targetKeyword: (0, import_sqlite_core.text)("target_keyword").notNull().default(""),
116
+ intent: (0, import_sqlite_core.text)("intent").notNull().default("informational"),
117
+ metaTitle: (0, import_sqlite_core.text)("meta_title").notNull().default(""),
118
+ metaDescription: (0, import_sqlite_core.text)("meta_description").notNull().default(""),
119
+ status: (0, import_sqlite_core.text)("status").notNull().default("draft"),
120
+ createdAt: (0, import_sqlite_core.integer)("created_at", { mode: "timestamp_ms" }).notNull(),
121
+ updatedAt: (0, import_sqlite_core.integer)("updated_at", { mode: "timestamp_ms" }).notNull()
122
+ });
123
+ var sqliteSchema = {
124
+ projects,
125
+ keywords,
126
+ rankSnapshots,
127
+ audits,
128
+ reports,
129
+ dashboardConfigs,
130
+ blogPosts
131
+ };
132
+
133
+ // src/sqlite-store.ts
134
+ function mapBlogRow(row) {
135
+ return {
136
+ id: row.id,
137
+ tenantId: row.tenantId,
138
+ projectId: row.projectId,
139
+ title: row.title,
140
+ slug: row.slug,
141
+ content: row.content,
142
+ targetKeyword: row.targetKeyword,
143
+ intent: row.intent,
144
+ metaTitle: row.metaTitle,
145
+ metaDescription: row.metaDescription,
146
+ status: row.status,
147
+ createdAt: row.createdAt,
148
+ updatedAt: row.updatedAt
149
+ };
150
+ }
151
+ function parseChecks(raw) {
152
+ if (!raw) return [];
153
+ try {
154
+ const parsed = JSON.parse(raw);
155
+ return Array.isArray(parsed) ? parsed : [];
156
+ } catch {
157
+ return [];
158
+ }
159
+ }
160
+ function parseSummary(raw) {
161
+ if (!raw) return void 0;
162
+ try {
163
+ return JSON.parse(raw);
164
+ } catch {
165
+ return void 0;
166
+ }
167
+ }
168
+ function mapAuditRow(row) {
169
+ return {
170
+ id: row.id,
171
+ tenantId: row.tenantId,
172
+ projectId: row.projectId,
173
+ url: row.url,
174
+ score: row.score,
175
+ checks: parseChecks(row.checks),
176
+ createdAt: row.createdAt
177
+ };
178
+ }
179
+ function mapReportRow(row) {
180
+ return {
181
+ id: row.id,
182
+ tenantId: row.tenantId,
183
+ projectId: row.projectId,
184
+ title: row.title,
185
+ from: row.from,
186
+ to: row.to,
187
+ summary: parseSummary(row.summary),
188
+ createdAt: row.createdAt
189
+ };
190
+ }
191
+ function parseTags(raw) {
192
+ try {
193
+ const parsed = JSON.parse(raw);
194
+ return Array.isArray(parsed) ? parsed.filter((t) => typeof t === "string") : [];
195
+ } catch {
196
+ return [];
197
+ }
198
+ }
199
+ function migrate(sqlite) {
200
+ sqlite.exec(`
201
+ CREATE TABLE IF NOT EXISTS rms_projects (
202
+ id TEXT PRIMARY KEY,
203
+ tenant_id TEXT NOT NULL,
204
+ name TEXT NOT NULL,
205
+ domain TEXT NOT NULL,
206
+ created_at INTEGER NOT NULL,
207
+ updated_at INTEGER NOT NULL
208
+ );
209
+ CREATE TABLE IF NOT EXISTS rms_keywords (
210
+ id TEXT PRIMARY KEY,
211
+ tenant_id TEXT NOT NULL,
212
+ project_id TEXT NOT NULL,
213
+ text TEXT NOT NULL,
214
+ country TEXT NOT NULL,
215
+ device TEXT NOT NULL,
216
+ tags TEXT NOT NULL,
217
+ created_at INTEGER NOT NULL
218
+ );
219
+ CREATE TABLE IF NOT EXISTS rms_rank_snapshots (
220
+ id TEXT PRIMARY KEY,
221
+ tenant_id TEXT NOT NULL,
222
+ project_id TEXT NOT NULL,
223
+ keyword_id TEXT NOT NULL,
224
+ position INTEGER,
225
+ url TEXT,
226
+ source TEXT NOT NULL,
227
+ device TEXT NOT NULL,
228
+ country TEXT NOT NULL,
229
+ captured_at INTEGER NOT NULL,
230
+ serp_features TEXT
231
+ );
232
+ CREATE TABLE IF NOT EXISTS rms_audits (
233
+ id TEXT PRIMARY KEY,
234
+ tenant_id TEXT NOT NULL,
235
+ project_id TEXT NOT NULL,
236
+ url TEXT NOT NULL,
237
+ score INTEGER NOT NULL,
238
+ checks TEXT NOT NULL DEFAULT '[]',
239
+ created_at INTEGER NOT NULL
240
+ );
241
+ CREATE TABLE IF NOT EXISTS rms_reports (
242
+ id TEXT PRIMARY KEY,
243
+ tenant_id TEXT NOT NULL,
244
+ project_id TEXT NOT NULL,
245
+ title TEXT NOT NULL,
246
+ "from" INTEGER NOT NULL,
247
+ "to" INTEGER NOT NULL,
248
+ summary TEXT,
249
+ created_at INTEGER NOT NULL
250
+ );
251
+ CREATE TABLE IF NOT EXISTS rms_dashboard_configs (
252
+ id TEXT PRIMARY KEY,
253
+ tenant_id TEXT NOT NULL,
254
+ project_id TEXT NOT NULL,
255
+ widgets TEXT NOT NULL,
256
+ updated_at INTEGER NOT NULL
257
+ );
258
+ CREATE TABLE IF NOT EXISTS rms_blog_posts (
259
+ id TEXT PRIMARY KEY,
260
+ tenant_id TEXT NOT NULL,
261
+ project_id TEXT NOT NULL,
262
+ title TEXT NOT NULL,
263
+ slug TEXT NOT NULL,
264
+ content TEXT NOT NULL DEFAULT '',
265
+ target_keyword TEXT NOT NULL DEFAULT '',
266
+ intent TEXT NOT NULL DEFAULT 'informational',
267
+ meta_title TEXT NOT NULL DEFAULT '',
268
+ meta_description TEXT NOT NULL DEFAULT '',
269
+ status TEXT NOT NULL DEFAULT 'draft',
270
+ created_at INTEGER NOT NULL,
271
+ updated_at INTEGER NOT NULL
272
+ );
273
+ `);
274
+ try {
275
+ sqlite.exec(`ALTER TABLE rms_audits ADD COLUMN checks TEXT NOT NULL DEFAULT '[]'`);
276
+ } catch {
277
+ }
278
+ try {
279
+ sqlite.exec(`ALTER TABLE rms_reports ADD COLUMN summary TEXT`);
280
+ } catch {
281
+ }
282
+ }
283
+ function createSqliteStore(databasePath) {
284
+ const sqlite = new import_better_sqlite3.default(databasePath);
285
+ migrate(sqlite);
286
+ const db = (0, import_better_sqlite32.drizzle)(sqlite, { schema: sqliteSchema });
287
+ const keywordScopeWhere = (scope) => (0, import_drizzle_orm.and)(
288
+ (0, import_drizzle_orm.eq)(keywords.tenantId, scope.tenantId),
289
+ (0, import_drizzle_orm.eq)(keywords.projectId, scope.projectId)
290
+ );
291
+ return {
292
+ projects: {
293
+ async create(input) {
294
+ const now = /* @__PURE__ */ new Date();
295
+ const row = {
296
+ ...input,
297
+ createdAt: now,
298
+ updatedAt: now
299
+ };
300
+ db.insert(projects).values({
301
+ id: row.id,
302
+ tenantId: row.tenantId,
303
+ name: row.name,
304
+ domain: row.domain,
305
+ createdAt: row.createdAt,
306
+ updatedAt: row.updatedAt
307
+ }).run();
308
+ return row;
309
+ },
310
+ async getById(scope, id) {
311
+ const rows = db.select().from(projects).where((0, import_drizzle_orm.and)((0, import_drizzle_orm.eq)(projects.tenantId, scope.tenantId), (0, import_drizzle_orm.eq)(projects.id, id))).all();
312
+ const row = rows[0];
313
+ if (!row) return void 0;
314
+ return {
315
+ id: row.id,
316
+ tenantId: row.tenantId,
317
+ name: row.name,
318
+ domain: row.domain,
319
+ createdAt: row.createdAt,
320
+ updatedAt: row.updatedAt
321
+ };
322
+ },
323
+ async list(scope) {
324
+ return db.select().from(projects).where((0, import_drizzle_orm.eq)(projects.tenantId, scope.tenantId)).all().map((row) => ({
325
+ id: row.id,
326
+ tenantId: row.tenantId,
327
+ name: row.name,
328
+ domain: row.domain,
329
+ createdAt: row.createdAt,
330
+ updatedAt: row.updatedAt
331
+ }));
332
+ }
333
+ },
334
+ keywords: {
335
+ async create(input) {
336
+ const row = {
337
+ id: (0, import_node_crypto.randomUUID)(),
338
+ ...input,
339
+ createdAt: /* @__PURE__ */ new Date()
340
+ };
341
+ db.insert(keywords).values({
342
+ id: row.id,
343
+ tenantId: row.tenantId,
344
+ projectId: row.projectId,
345
+ text: row.text,
346
+ country: row.country,
347
+ device: row.device,
348
+ tags: JSON.stringify(row.tags),
349
+ createdAt: row.createdAt
350
+ }).run();
351
+ return row;
352
+ },
353
+ async getById(scope, id) {
354
+ const rows = db.select().from(keywords).where((0, import_drizzle_orm.and)(keywordScopeWhere(scope), (0, import_drizzle_orm.eq)(keywords.id, id))).all();
355
+ const row = rows[0];
356
+ if (!row) return void 0;
357
+ return {
358
+ id: row.id,
359
+ tenantId: row.tenantId,
360
+ projectId: row.projectId,
361
+ text: row.text,
362
+ country: row.country,
363
+ device: row.device,
364
+ tags: parseTags(row.tags),
365
+ createdAt: row.createdAt
366
+ };
367
+ },
368
+ async list(scope) {
369
+ return db.select().from(keywords).where(keywordScopeWhere(scope)).all().map((row) => ({
370
+ id: row.id,
371
+ tenantId: row.tenantId,
372
+ projectId: row.projectId,
373
+ text: row.text,
374
+ country: row.country,
375
+ device: row.device,
376
+ tags: parseTags(row.tags),
377
+ createdAt: row.createdAt
378
+ }));
379
+ },
380
+ async delete(scope, id) {
381
+ const result = db.delete(keywords).where((0, import_drizzle_orm.and)(keywordScopeWhere(scope), (0, import_drizzle_orm.eq)(keywords.id, id))).run();
382
+ return result.changes > 0;
383
+ }
384
+ },
385
+ snapshots: {
386
+ async append(input) {
387
+ const row = {
388
+ id: (0, import_node_crypto.randomUUID)(),
389
+ ...input
390
+ };
391
+ db.insert(rankSnapshots).values({
392
+ id: row.id,
393
+ tenantId: row.tenantId,
394
+ projectId: row.projectId,
395
+ keywordId: row.keywordId,
396
+ position: row.position,
397
+ url: row.url,
398
+ source: row.source,
399
+ device: row.device,
400
+ country: row.country,
401
+ capturedAt: row.capturedAt,
402
+ serpFeatures: row.serpFeatures ? JSON.stringify(row.serpFeatures) : null
403
+ }).run();
404
+ return row;
405
+ },
406
+ async listByRange(query) {
407
+ const conditions = [
408
+ (0, import_drizzle_orm.eq)(rankSnapshots.tenantId, query.tenantId),
409
+ (0, import_drizzle_orm.eq)(rankSnapshots.projectId, query.projectId),
410
+ (0, import_drizzle_orm.gte)(rankSnapshots.capturedAt, query.from),
411
+ (0, import_drizzle_orm.lte)(rankSnapshots.capturedAt, query.to)
412
+ ];
413
+ if (query.keywordId) {
414
+ conditions.push((0, import_drizzle_orm.eq)(rankSnapshots.keywordId, query.keywordId));
415
+ }
416
+ return db.select().from(rankSnapshots).where((0, import_drizzle_orm.and)(...conditions)).all().map((row) => ({
417
+ id: row.id,
418
+ tenantId: row.tenantId,
419
+ projectId: row.projectId,
420
+ keywordId: row.keywordId,
421
+ position: row.position,
422
+ url: row.url,
423
+ source: row.source,
424
+ device: row.device,
425
+ country: row.country,
426
+ capturedAt: row.capturedAt,
427
+ serpFeatures: row.serpFeatures ? JSON.parse(row.serpFeatures) : void 0
428
+ }));
429
+ }
430
+ },
431
+ audits: {
432
+ async create(input) {
433
+ const row = { ...input, checks: input.checks ?? [], createdAt: /* @__PURE__ */ new Date() };
434
+ db.insert(audits).values({
435
+ id: row.id,
436
+ tenantId: row.tenantId,
437
+ projectId: row.projectId,
438
+ url: row.url,
439
+ score: row.score,
440
+ checks: JSON.stringify(row.checks),
441
+ createdAt: row.createdAt
442
+ }).run();
443
+ return row;
444
+ },
445
+ async getById(scope, id) {
446
+ const rows = db.select().from(audits).where(
447
+ (0, import_drizzle_orm.and)(
448
+ (0, import_drizzle_orm.eq)(audits.tenantId, scope.tenantId),
449
+ (0, import_drizzle_orm.eq)(audits.projectId, scope.projectId),
450
+ (0, import_drizzle_orm.eq)(audits.id, id)
451
+ )
452
+ ).all();
453
+ const row = rows[0];
454
+ if (!row) return void 0;
455
+ return mapAuditRow(row);
456
+ },
457
+ async list(scope) {
458
+ return db.select().from(audits).where(
459
+ (0, import_drizzle_orm.and)(
460
+ (0, import_drizzle_orm.eq)(audits.tenantId, scope.tenantId),
461
+ (0, import_drizzle_orm.eq)(audits.projectId, scope.projectId)
462
+ )
463
+ ).all().map(mapAuditRow);
464
+ }
465
+ },
466
+ reports: {
467
+ async create(input) {
468
+ const row = { ...input, createdAt: /* @__PURE__ */ new Date() };
469
+ db.insert(reports).values({
470
+ id: row.id,
471
+ tenantId: row.tenantId,
472
+ projectId: row.projectId,
473
+ title: row.title,
474
+ from: row.from,
475
+ to: row.to,
476
+ summary: row.summary ? JSON.stringify(row.summary) : null,
477
+ createdAt: row.createdAt
478
+ }).run();
479
+ return row;
480
+ },
481
+ async getById(scope, id) {
482
+ const rows = db.select().from(reports).where(
483
+ (0, import_drizzle_orm.and)(
484
+ (0, import_drizzle_orm.eq)(reports.tenantId, scope.tenantId),
485
+ (0, import_drizzle_orm.eq)(reports.projectId, scope.projectId),
486
+ (0, import_drizzle_orm.eq)(reports.id, id)
487
+ )
488
+ ).all();
489
+ const row = rows[0];
490
+ if (!row) return void 0;
491
+ return mapReportRow(row);
492
+ },
493
+ async list(scope) {
494
+ return db.select().from(reports).where(
495
+ (0, import_drizzle_orm.and)(
496
+ (0, import_drizzle_orm.eq)(reports.tenantId, scope.tenantId),
497
+ (0, import_drizzle_orm.eq)(reports.projectId, scope.projectId)
498
+ )
499
+ ).all().map(mapReportRow);
500
+ }
501
+ },
502
+ dashboard: {
503
+ async get(scope) {
504
+ const rows = db.select().from(dashboardConfigs).where(
505
+ (0, import_drizzle_orm.and)(
506
+ (0, import_drizzle_orm.eq)(dashboardConfigs.tenantId, scope.tenantId),
507
+ (0, import_drizzle_orm.eq)(dashboardConfigs.projectId, scope.projectId)
508
+ )
509
+ ).all();
510
+ const row = rows[0];
511
+ if (!row) return void 0;
512
+ return {
513
+ id: row.id,
514
+ tenantId: row.tenantId,
515
+ projectId: row.projectId,
516
+ widgets: JSON.parse(row.widgets),
517
+ updatedAt: row.updatedAt
518
+ };
519
+ },
520
+ async upsert(config) {
521
+ db.insert(dashboardConfigs).values({
522
+ id: config.id,
523
+ tenantId: config.tenantId,
524
+ projectId: config.projectId,
525
+ widgets: JSON.stringify(config.widgets),
526
+ updatedAt: config.updatedAt
527
+ }).onConflictDoUpdate({
528
+ target: dashboardConfigs.id,
529
+ set: {
530
+ widgets: JSON.stringify(config.widgets),
531
+ updatedAt: config.updatedAt
532
+ }
533
+ }).run();
534
+ return config;
535
+ }
536
+ },
537
+ blog: {
538
+ async create(input) {
539
+ const now = /* @__PURE__ */ new Date();
540
+ const row = { ...input, createdAt: now, updatedAt: now };
541
+ db.insert(blogPosts).values({
542
+ id: row.id,
543
+ tenantId: row.tenantId,
544
+ projectId: row.projectId,
545
+ title: row.title,
546
+ slug: row.slug,
547
+ content: row.content,
548
+ targetKeyword: row.targetKeyword,
549
+ intent: row.intent,
550
+ metaTitle: row.metaTitle,
551
+ metaDescription: row.metaDescription,
552
+ status: row.status,
553
+ createdAt: row.createdAt,
554
+ updatedAt: row.updatedAt
555
+ }).run();
556
+ return row;
557
+ },
558
+ async getById(scope, id) {
559
+ const rows = db.select().from(blogPosts).where(
560
+ (0, import_drizzle_orm.and)(
561
+ (0, import_drizzle_orm.eq)(blogPosts.tenantId, scope.tenantId),
562
+ (0, import_drizzle_orm.eq)(blogPosts.projectId, scope.projectId),
563
+ (0, import_drizzle_orm.eq)(blogPosts.id, id)
564
+ )
565
+ ).all();
566
+ const row = rows[0];
567
+ return row ? mapBlogRow(row) : void 0;
568
+ },
569
+ async list(scope) {
570
+ return db.select().from(blogPosts).where(
571
+ (0, import_drizzle_orm.and)(
572
+ (0, import_drizzle_orm.eq)(blogPosts.tenantId, scope.tenantId),
573
+ (0, import_drizzle_orm.eq)(blogPosts.projectId, scope.projectId)
574
+ )
575
+ ).all().map(mapBlogRow);
576
+ },
577
+ async update(scope, id, patch) {
578
+ const rows = db.select().from(blogPosts).where(
579
+ (0, import_drizzle_orm.and)(
580
+ (0, import_drizzle_orm.eq)(blogPosts.tenantId, scope.tenantId),
581
+ (0, import_drizzle_orm.eq)(blogPosts.projectId, scope.projectId),
582
+ (0, import_drizzle_orm.eq)(blogPosts.id, id)
583
+ )
584
+ ).all();
585
+ const existing = rows[0];
586
+ if (!existing) return void 0;
587
+ const merged = mapBlogRow(existing);
588
+ const next = {
589
+ ...merged,
590
+ ...patch,
591
+ updatedAt: /* @__PURE__ */ new Date()
592
+ };
593
+ db.update(blogPosts).set({
594
+ title: next.title,
595
+ slug: next.slug,
596
+ content: next.content,
597
+ targetKeyword: next.targetKeyword,
598
+ intent: next.intent,
599
+ metaTitle: next.metaTitle,
600
+ metaDescription: next.metaDescription,
601
+ status: next.status,
602
+ updatedAt: next.updatedAt
603
+ }).where(
604
+ (0, import_drizzle_orm.and)(
605
+ (0, import_drizzle_orm.eq)(blogPosts.tenantId, scope.tenantId),
606
+ (0, import_drizzle_orm.eq)(blogPosts.projectId, scope.projectId),
607
+ (0, import_drizzle_orm.eq)(blogPosts.id, id)
608
+ )
609
+ ).run();
610
+ return next;
611
+ },
612
+ async delete(scope, id) {
613
+ const result = db.delete(blogPosts).where(
614
+ (0, import_drizzle_orm.and)(
615
+ (0, import_drizzle_orm.eq)(blogPosts.tenantId, scope.tenantId),
616
+ (0, import_drizzle_orm.eq)(blogPosts.projectId, scope.projectId),
617
+ (0, import_drizzle_orm.eq)(blogPosts.id, id)
618
+ )
619
+ ).run();
620
+ return result.changes > 0;
621
+ }
622
+ }
623
+ };
624
+ }
625
+
626
+ // src/factory.ts
627
+ function createStore(databaseUrl) {
628
+ if (databaseUrl.startsWith("postgres") || databaseUrl.startsWith("mysql")) {
629
+ throw new Error(
630
+ "Postgres and MySQL adapters are not implemented in M0. Use sqlite:// or :memory:"
631
+ );
632
+ }
633
+ const path = databaseUrl.startsWith("sqlite://") ? databaseUrl.slice("sqlite://".length) : databaseUrl;
634
+ return createSqliteStore(path);
635
+ }
636
+ // Annotate the CommonJS export names for ESM import in node:
637
+ 0 && (module.exports = {
638
+ createSqliteStore,
639
+ createStore
640
+ });
641
+ //# sourceMappingURL=index.cjs.map