@livestore/cli 0.4.0-dev.9 → 0.5.0-dev.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.
Files changed (136) hide show
  1. package/dist/.tsbuildinfo +1 -0
  2. package/dist/__tests__/fixtures/mock-config.d.ts +63 -0
  3. package/dist/__tests__/fixtures/mock-config.d.ts.map +1 -0
  4. package/dist/__tests__/fixtures/mock-config.js +94 -0
  5. package/dist/__tests__/fixtures/mock-config.js.map +1 -0
  6. package/dist/__tests__/sync-operations.test.d.ts +2 -0
  7. package/dist/__tests__/sync-operations.test.d.ts.map +1 -0
  8. package/dist/__tests__/sync-operations.test.js +167 -0
  9. package/dist/__tests__/sync-operations.test.js.map +1 -0
  10. package/dist/bin.js +6 -5
  11. package/dist/bin.js.map +1 -1
  12. package/dist/cli.d.ts +2 -9
  13. package/dist/cli.d.ts.map +1 -1
  14. package/dist/cli.js +4 -5
  15. package/dist/cli.js.map +1 -1
  16. package/dist/commands/__fixtures__/mcp-protocol-server.d.ts +2 -0
  17. package/dist/commands/__fixtures__/mcp-protocol-server.d.ts.map +1 -0
  18. package/dist/commands/__fixtures__/mcp-protocol-server.js +10 -0
  19. package/dist/commands/__fixtures__/mcp-protocol-server.js.map +1 -0
  20. package/dist/commands/import-export.d.ts +20 -0
  21. package/dist/commands/import-export.d.ts.map +1 -0
  22. package/dist/commands/import-export.js +135 -0
  23. package/dist/commands/import-export.js.map +1 -0
  24. package/dist/commands/mcp-coach.d.ts +21 -12
  25. package/dist/commands/mcp-coach.d.ts.map +1 -1
  26. package/dist/commands/mcp-coach.js +49 -53
  27. package/dist/commands/mcp-coach.js.map +1 -1
  28. package/dist/commands/mcp-protocols.d.ts +7 -0
  29. package/dist/commands/mcp-protocols.d.ts.map +1 -0
  30. package/dist/commands/mcp-protocols.js +12 -0
  31. package/dist/commands/mcp-protocols.js.map +1 -0
  32. package/dist/commands/mcp-protocols.test.d.ts +2 -0
  33. package/dist/commands/mcp-protocols.test.d.ts.map +1 -0
  34. package/dist/commands/mcp-protocols.test.js +60 -0
  35. package/dist/commands/mcp-protocols.test.js.map +1 -0
  36. package/dist/commands/mcp-stdio.test.d.ts +2 -0
  37. package/dist/commands/mcp-stdio.test.d.ts.map +1 -0
  38. package/dist/commands/mcp-stdio.test.js +79 -0
  39. package/dist/commands/mcp-stdio.test.js.map +1 -0
  40. package/dist/commands/mcp-tool-handlers.d.ts +6 -0
  41. package/dist/commands/mcp-tool-handlers.d.ts.map +1 -0
  42. package/dist/commands/{mcp-tools.js → mcp-tool-handlers.js} +80 -45
  43. package/dist/commands/mcp-tool-handlers.js.map +1 -0
  44. package/dist/commands/mcp-tools-defs.d.ts +134 -0
  45. package/dist/commands/mcp-tools-defs.d.ts.map +1 -0
  46. package/dist/commands/mcp-tools-defs.js +285 -0
  47. package/dist/commands/mcp-tools-defs.js.map +1 -0
  48. package/dist/commands/mcp-tools-defs.test.d.ts +2 -0
  49. package/dist/commands/mcp-tools-defs.test.d.ts.map +1 -0
  50. package/dist/commands/mcp-tools-defs.test.js +11 -0
  51. package/dist/commands/mcp-tools-defs.test.js.map +1 -0
  52. package/dist/commands/mcp.d.ts +1 -3
  53. package/dist/commands/mcp.d.ts.map +1 -1
  54. package/dist/commands/mcp.js +7 -5
  55. package/dist/commands/mcp.js.map +1 -1
  56. package/dist/commands/new-project.d.ts +22 -23
  57. package/dist/commands/new-project.d.ts.map +1 -1
  58. package/dist/commands/new-project.js +85 -44
  59. package/dist/commands/new-project.js.map +1 -1
  60. package/dist/mcp-content/architecture.d.ts +1 -1
  61. package/dist/mcp-content/architecture.d.ts.map +1 -1
  62. package/dist/mcp-content/architecture.js +3 -3
  63. package/dist/mcp-content/features.d.ts +1 -1
  64. package/dist/mcp-content/features.d.ts.map +1 -1
  65. package/dist/mcp-content/features.js +1 -1
  66. package/dist/mcp-content/getting-started.d.ts +1 -1
  67. package/dist/mcp-content/getting-started.d.ts.map +1 -1
  68. package/dist/mcp-content/getting-started.js +37 -37
  69. package/dist/mcp-content/overview.d.ts +1 -1
  70. package/dist/mcp-content/overview.d.ts.map +1 -1
  71. package/dist/mcp-content/overview.js +6 -6
  72. package/dist/mcp-content/schemas/blog.d.ts +1 -1
  73. package/dist/mcp-content/schemas/blog.d.ts.map +1 -1
  74. package/dist/mcp-content/schemas/blog.js +25 -25
  75. package/dist/mcp-content/schemas/ecommerce.d.ts +1 -1
  76. package/dist/mcp-content/schemas/ecommerce.d.ts.map +1 -1
  77. package/dist/mcp-content/schemas/ecommerce.js +67 -67
  78. package/dist/mcp-content/schemas/social.d.ts +1 -1
  79. package/dist/mcp-content/schemas/social.d.ts.map +1 -1
  80. package/dist/mcp-content/schemas/social.js +48 -48
  81. package/dist/mcp-content/schemas/todo.d.ts +1 -1
  82. package/dist/mcp-content/schemas/todo.d.ts.map +1 -1
  83. package/dist/mcp-content/schemas/todo.js +35 -35
  84. package/dist/mcp-runtime/runtime.d.ts +48 -0
  85. package/dist/mcp-runtime/runtime.d.ts.map +1 -0
  86. package/dist/mcp-runtime/runtime.js +107 -0
  87. package/dist/mcp-runtime/runtime.js.map +1 -0
  88. package/dist/module-loader.d.ts +22 -0
  89. package/dist/module-loader.d.ts.map +1 -0
  90. package/dist/module-loader.js +75 -0
  91. package/dist/module-loader.js.map +1 -0
  92. package/dist/package-manager.d.ts +38 -0
  93. package/dist/package-manager.d.ts.map +1 -0
  94. package/dist/package-manager.js +33 -0
  95. package/dist/package-manager.js.map +1 -0
  96. package/dist/package-manager.test.d.ts +2 -0
  97. package/dist/package-manager.test.d.ts.map +1 -0
  98. package/dist/package-manager.test.js +57 -0
  99. package/dist/package-manager.test.js.map +1 -0
  100. package/dist/sync-operations.d.ts +115 -0
  101. package/dist/sync-operations.d.ts.map +1 -0
  102. package/dist/sync-operations.js +178 -0
  103. package/dist/sync-operations.js.map +1 -0
  104. package/package.json +57 -15
  105. package/src/__tests__/fixtures/mock-config.ts +112 -0
  106. package/src/__tests__/sync-operations.test.ts +218 -0
  107. package/src/bin.ts +8 -6
  108. package/src/cli.ts +5 -6
  109. package/src/commands/__fixtures__/mcp-protocol-server.ts +12 -0
  110. package/src/commands/import-export.ts +283 -0
  111. package/src/commands/mcp-coach.ts +76 -75
  112. package/src/commands/mcp-protocols.test.ts +76 -0
  113. package/src/commands/mcp-protocols.ts +12 -0
  114. package/src/commands/mcp-stdio.test.ts +93 -0
  115. package/src/commands/{mcp-tools.ts → mcp-tool-handlers.ts} +100 -61
  116. package/src/commands/mcp-tools-defs.test.ts +13 -0
  117. package/src/commands/mcp-tools-defs.ts +320 -0
  118. package/src/commands/mcp.ts +10 -6
  119. package/src/commands/new-project.ts +124 -57
  120. package/src/mcp-content/architecture.ts +3 -3
  121. package/src/mcp-content/features.ts +1 -1
  122. package/src/mcp-content/getting-started.ts +37 -37
  123. package/src/mcp-content/overview.ts +6 -6
  124. package/src/mcp-content/schemas/blog.ts +25 -25
  125. package/src/mcp-content/schemas/ecommerce.ts +67 -67
  126. package/src/mcp-content/schemas/social.ts +48 -48
  127. package/src/mcp-content/schemas/todo.ts +35 -35
  128. package/src/mcp-runtime/runtime.ts +147 -0
  129. package/src/module-loader.ts +94 -0
  130. package/src/package-manager.test.ts +66 -0
  131. package/src/package-manager.ts +44 -0
  132. package/src/sync-operations.ts +360 -0
  133. package/dist/commands/mcp-tools.d.ts +0 -58
  134. package/dist/commands/mcp-tools.d.ts.map +0 -1
  135. package/dist/commands/mcp-tools.js.map +0 -1
  136. package/dist/tsconfig.tsbuildinfo +0 -1
@@ -22,7 +22,7 @@ export const tables = {
22
22
  deletedAt: State.SQLite.integer({ nullable: true, schema: Schema.DateFromNumber }),
23
23
  },
24
24
  }),
25
-
25
+
26
26
  categories: State.SQLite.table({
27
27
  name: 'categories',
28
28
  columns: {
@@ -37,7 +37,7 @@ export const tables = {
37
37
  createdAt: State.SQLite.integer({ schema: Schema.DateFromNumber }),
38
38
  },
39
39
  }),
40
-
40
+
41
41
  productCategories: State.SQLite.table({
42
42
  name: 'product_categories',
43
43
  columns: {
@@ -46,7 +46,7 @@ export const tables = {
46
46
  createdAt: State.SQLite.integer({ schema: Schema.DateFromNumber }),
47
47
  },
48
48
  }),
49
-
49
+
50
50
  customers: State.SQLite.table({
51
51
  name: 'customers',
52
52
  columns: {
@@ -59,7 +59,7 @@ export const tables = {
59
59
  lastOrderAt: State.SQLite.integer({ nullable: true, schema: Schema.DateFromNumber }),
60
60
  },
61
61
  }),
62
-
62
+
63
63
  addresses: State.SQLite.table({
64
64
  name: 'addresses',
65
65
  columns: {
@@ -78,7 +78,7 @@ export const tables = {
78
78
  isDefault: State.SQLite.boolean({ default: false }),
79
79
  },
80
80
  }),
81
-
81
+
82
82
  orders: State.SQLite.table({
83
83
  name: 'orders',
84
84
  columns: {
@@ -88,19 +88,19 @@ export const tables = {
88
88
  status: State.SQLite.text({ default: 'draft' }), // draft, pending, paid, processing, shipped, delivered, cancelled
89
89
  paymentStatus: State.SQLite.text({ default: 'pending' }), // pending, paid, failed, refunded
90
90
  fulfillmentStatus: State.SQLite.text({ default: 'unfulfilled' }), // unfulfilled, partial, fulfilled
91
-
91
+
92
92
  subtotal: State.SQLite.integer(), // In cents
93
93
  taxAmount: State.SQLite.integer({ default: 0 }),
94
94
  shippingAmount: State.SQLite.integer({ default: 0 }),
95
95
  discountAmount: State.SQLite.integer({ default: 0 }),
96
96
  total: State.SQLite.integer(),
97
97
  currency: State.SQLite.text({ default: 'USD' }),
98
-
98
+
99
99
  shippingAddress: State.SQLite.text(), // JSON
100
100
  billingAddress: State.SQLite.text(), // JSON
101
-
101
+
102
102
  notes: State.SQLite.text({ nullable: true }),
103
-
103
+
104
104
  createdAt: State.SQLite.integer({ schema: Schema.DateFromNumber }),
105
105
  updatedAt: State.SQLite.integer({ schema: Schema.DateFromNumber }),
106
106
  cancelledAt: State.SQLite.integer({ nullable: true, schema: Schema.DateFromNumber }),
@@ -108,7 +108,7 @@ export const tables = {
108
108
  deliveredAt: State.SQLite.integer({ nullable: true, schema: Schema.DateFromNumber }),
109
109
  },
110
110
  }),
111
-
111
+
112
112
  orderItems: State.SQLite.table({
113
113
  name: 'order_items',
114
114
  columns: {
@@ -124,7 +124,7 @@ export const tables = {
124
124
  fulfillmentStatus: State.SQLite.text({ default: 'unfulfilled' }),
125
125
  },
126
126
  }),
127
-
127
+
128
128
  // Inventory tracking with event sourcing
129
129
  inventoryEvents: State.SQLite.table({
130
130
  name: 'inventory_events',
@@ -138,7 +138,7 @@ export const tables = {
138
138
  createdAt: State.SQLite.integer({ schema: Schema.DateFromNumber }),
139
139
  },
140
140
  }),
141
-
141
+
142
142
  // Shopping cart (client-side state)
143
143
  cart: State.SQLite.clientDocument({
144
144
  name: 'cart',
@@ -151,8 +151,8 @@ export const tables = {
151
151
  discountCode: Schema.NullOr(Schema.String),
152
152
  notes: Schema.String,
153
153
  }),
154
- default: {
155
- id: SessionIdSymbol,
154
+ default: {
155
+ id: SessionIdSymbol,
156
156
  value: { items: [], discountCode: null, notes: '' }
157
157
  },
158
158
  }),
@@ -172,7 +172,7 @@ export const events = {
172
172
  createdAt: Schema.Date,
173
173
  }),
174
174
  }),
175
-
175
+
176
176
  productUpdated: Events.synced({
177
177
  name: 'v1.ProductUpdated',
178
178
  schema: Schema.Struct({
@@ -183,7 +183,7 @@ export const events = {
183
183
  updatedAt: Schema.Date,
184
184
  }),
185
185
  }),
186
-
186
+
187
187
  productStockAdjusted: Events.synced({
188
188
  name: 'v1.ProductStockAdjusted',
189
189
  schema: Schema.Struct({
@@ -194,12 +194,12 @@ export const events = {
194
194
  createdAt: Schema.Date,
195
195
  }),
196
196
  }),
197
-
197
+
198
198
  productDeactivated: Events.synced({
199
199
  name: 'v1.ProductDeactivated',
200
200
  schema: Schema.Struct({ id: Schema.String }),
201
201
  }),
202
-
202
+
203
203
  // Customer management
204
204
  customerCreated: Events.synced({
205
205
  name: 'v1.CustomerCreated',
@@ -211,7 +211,7 @@ export const events = {
211
211
  createdAt: Schema.Date,
212
212
  }),
213
213
  }),
214
-
214
+
215
215
  // Order lifecycle with state machine
216
216
  orderCreated: Events.synced({
217
217
  name: 'v1.OrderCreated',
@@ -233,7 +233,7 @@ export const events = {
233
233
  createdAt: Schema.Date,
234
234
  }),
235
235
  }),
236
-
236
+
237
237
  orderPaymentReceived: Events.synced({
238
238
  name: 'v1.OrderPaymentReceived',
239
239
  schema: Schema.Struct({
@@ -244,7 +244,7 @@ export const events = {
244
244
  paidAt: Schema.Date,
245
245
  }),
246
246
  }),
247
-
247
+
248
248
  orderShipped: Events.synced({
249
249
  name: 'v1.OrderShipped',
250
250
  schema: Schema.Struct({
@@ -254,7 +254,7 @@ export const events = {
254
254
  shippedAt: Schema.Date,
255
255
  }),
256
256
  }),
257
-
257
+
258
258
  orderDelivered: Events.synced({
259
259
  name: 'v1.OrderDelivered',
260
260
  schema: Schema.Struct({
@@ -262,7 +262,7 @@ export const events = {
262
262
  deliveredAt: Schema.Date,
263
263
  }),
264
264
  }),
265
-
265
+
266
266
  orderCancelled: Events.synced({
267
267
  name: 'v1.OrderCancelled',
268
268
  schema: Schema.Struct({
@@ -271,7 +271,7 @@ export const events = {
271
271
  cancelledAt: Schema.Date,
272
272
  }),
273
273
  }),
274
-
274
+
275
275
  // Cart management (local)
276
276
  cartUpdated: tables.cart.set,
277
277
  }
@@ -281,58 +281,58 @@ const materializers = State.SQLite.materializers(events, {
281
281
  // Product materializers
282
282
  'v1.ProductCreated': ({ id, sku, name, description, price, currency, createdAt }) =>
283
283
  tables.products.insert({ id, sku, name, description, price, currency, createdAt, updatedAt: createdAt }),
284
-
284
+
285
285
  'v1.ProductUpdated': ({ id, name, description, price, updatedAt }) =>
286
- tables.products.update({
286
+ tables.products.update({
287
287
  name: name ?? undefined,
288
- description: description ?? undefined,
288
+ description: description ?? undefined,
289
289
  price: price ?? undefined,
290
- updatedAt
290
+ updatedAt
291
291
  }).where({ id }),
292
-
292
+
293
293
  'v1.ProductStockAdjusted': ({ productId, adjustment, reason, referenceId, createdAt }) => [
294
294
  // Record the inventory event
295
- tables.inventoryEvents.insert({
295
+ tables.inventoryEvents.insert({
296
296
  id: crypto.randomUUID(),
297
- productId,
297
+ productId,
298
298
  type: 'adjustment',
299
- quantity: adjustment,
300
- reason,
301
- referenceId,
302
- createdAt
299
+ quantity: adjustment,
300
+ reason,
301
+ referenceId,
302
+ createdAt
303
303
  }),
304
304
  // Update product stock (eventually consistent)
305
- tables.products.update({
305
+ tables.products.update({
306
306
  stock: Math.max(0, tables.products.select('stock').where({ id: productId }).scalar() + adjustment),
307
307
  updatedAt: createdAt
308
308
  }).where({ id: productId }),
309
309
  ],
310
-
310
+
311
311
  'v1.ProductDeactivated': ({ id }) =>
312
312
  tables.products.update({ isActive: false }).where({ id }),
313
-
313
+
314
314
  // Customer materializers
315
315
  'v1.CustomerCreated': ({ id, email, firstName, lastName, createdAt }) =>
316
316
  tables.customers.insert({ id, email, firstName, lastName, createdAt }),
317
-
317
+
318
318
  // Order materializers with inventory reservation
319
319
  'v1.OrderCreated': ({ id, orderNumber, customerId, items, subtotal, total, shippingAddress, billingAddress, createdAt }) => [
320
320
  // Create the order
321
- tables.orders.insert({
322
- id,
323
- orderNumber,
324
- customerId,
321
+ tables.orders.insert({
322
+ id,
323
+ orderNumber,
324
+ customerId,
325
325
  status: 'pending',
326
- subtotal,
327
- total,
326
+ subtotal,
327
+ total,
328
328
  shippingAddress: JSON.stringify(shippingAddress),
329
329
  billingAddress: JSON.stringify(billingAddress),
330
- createdAt,
331
- updatedAt: createdAt
330
+ createdAt,
331
+ updatedAt: createdAt
332
332
  }),
333
333
  // Create order items and reserve inventory
334
334
  ...items.flatMap(item => [
335
- tables.orderItems.insert({
335
+ tables.orderItems.insert({
336
336
  id: crypto.randomUUID(),
337
337
  orderId: id,
338
338
  productId: item.productId,
@@ -343,52 +343,52 @@ const materializers = State.SQLite.materializers(events, {
343
343
  totalPrice: item.quantity * item.unitPrice,
344
344
  }),
345
345
  // Reserve stock
346
- tables.products.update({
346
+ tables.products.update({
347
347
  reservedStock: tables.products.select('reservedStock').where({ id: item.productId }).scalar() + item.quantity
348
348
  }).where({ id: item.productId }),
349
349
  ]),
350
350
  ],
351
-
351
+
352
352
  'v1.OrderPaymentReceived': ({ orderId, amount, paymentMethod, transactionId, paidAt }) =>
353
- tables.orders.update({
354
- status: 'paid',
353
+ tables.orders.update({
354
+ status: 'paid',
355
355
  paymentStatus: 'paid',
356
- updatedAt: paidAt
356
+ updatedAt: paidAt
357
357
  }).where({ id: orderId }),
358
-
358
+
359
359
  'v1.OrderShipped': ({ orderId, trackingNumber, carrier, shippedAt }) => [
360
- tables.orders.update({
360
+ tables.orders.update({
361
361
  status: 'shipped',
362
362
  fulfillmentStatus: 'fulfilled',
363
363
  shippedAt,
364
- updatedAt: shippedAt
364
+ updatedAt: shippedAt
365
365
  }).where({ id: orderId }),
366
366
  // Convert reserved stock to actual stock reduction
367
- ...tables.orderItems.select().where({ orderId }).map(item =>
368
- tables.products.update({
367
+ ...tables.orderItems.select().where({ orderId }).map(item =>
368
+ tables.products.update({
369
369
  stock: tables.products.select('stock').where({ id: item.productId }).scalar() - item.quantity,
370
370
  reservedStock: tables.products.select('reservedStock').where({ id: item.productId }).scalar() - item.quantity
371
371
  }).where({ id: item.productId })
372
372
  ),
373
373
  ],
374
-
374
+
375
375
  'v1.OrderDelivered': ({ orderId, deliveredAt }) =>
376
- tables.orders.update({
376
+ tables.orders.update({
377
377
  status: 'delivered',
378
378
  deliveredAt,
379
- updatedAt: deliveredAt
379
+ updatedAt: deliveredAt
380
380
  }).where({ id: orderId }),
381
-
381
+
382
382
  'v1.OrderCancelled': ({ orderId, reason, cancelledAt }) => [
383
- tables.orders.update({
383
+ tables.orders.update({
384
384
  status: 'cancelled',
385
385
  cancelledAt,
386
386
  notes: reason,
387
- updatedAt: cancelledAt
387
+ updatedAt: cancelledAt
388
388
  }).where({ id: orderId }),
389
389
  // Release reserved inventory
390
- ...tables.orderItems.select().where({ orderId }).map(item =>
391
- tables.products.update({
390
+ ...tables.orderItems.select().where({ orderId }).map(item =>
391
+ tables.products.update({
392
392
  reservedStock: Math.max(0, tables.products.select('reservedStock').where({ id: item.productId }).scalar() - item.quantity)
393
393
  }).where({ id: item.productId })
394
394
  ),
@@ -416,7 +416,7 @@ export const schema = makeSchema({ events, state })
416
416
  // tables.orders
417
417
  // .select()
418
418
  // .join(tables.customers, 'customerId', 'id')
419
- // .where({
419
+ // .where({
420
420
  // 'orders.status': 'paid',
421
421
  // 'orders.fulfillmentStatus': 'unfulfilled'
422
422
  // })
@@ -1,2 +1,2 @@
1
- export declare const socialSchemaContent = "import { Events, makeSchema, Schema, SessionIdSymbol, State } from '@livestore/livestore'\n\n// Social network with activity feeds and real-time interactions\nexport const tables = {\n users: State.SQLite.table({\n name: 'users',\n columns: {\n id: State.SQLite.text({ primaryKey: true }),\n username: State.SQLite.text(),\n email: State.SQLite.text(),\n displayName: State.SQLite.text(),\n bio: State.SQLite.text({ nullable: true }),\n avatarUrl: State.SQLite.text({ nullable: true }),\n isVerified: State.SQLite.boolean({ default: false }),\n createdAt: State.SQLite.integer({ schema: Schema.DateFromNumber }),\n lastActiveAt: State.SQLite.integer({ nullable: true, schema: Schema.DateFromNumber }),\n // Privacy settings\n isPrivate: State.SQLite.boolean({ default: false }),\n allowsFollowers: State.SQLite.boolean({ default: true }),\n },\n }),\n \n posts: State.SQLite.table({\n name: 'posts',\n columns: {\n id: State.SQLite.text({ primaryKey: true }),\n authorId: State.SQLite.text(),\n content: State.SQLite.text(),\n mediaUrls: State.SQLite.text({ nullable: true }), // JSON array of media URLs\n replyToId: State.SQLite.text({ nullable: true }), // For threading\n visibility: State.SQLite.text({ default: 'public' }), // public, followers, private\n createdAt: State.SQLite.integer({ schema: Schema.DateFromNumber }),\n editedAt: State.SQLite.integer({ nullable: true, schema: Schema.DateFromNumber }),\n deletedAt: State.SQLite.integer({ nullable: true, schema: Schema.DateFromNumber }),\n },\n }),\n \n follows: State.SQLite.table({\n name: 'follows',\n columns: {\n followerId: State.SQLite.text(),\n followingId: State.SQLite.text(),\n status: State.SQLite.text({ default: 'active' }), // active, pending, blocked\n createdAt: State.SQLite.integer({ schema: Schema.DateFromNumber }),\n approvedAt: State.SQLite.integer({ nullable: true, schema: Schema.DateFromNumber }),\n },\n }),\n \n likes: State.SQLite.table({\n name: 'likes',\n columns: {\n userId: State.SQLite.text(),\n postId: State.SQLite.text(),\n createdAt: State.SQLite.integer({ schema: Schema.DateFromNumber }),\n },\n }),\n \n // Aggregate tables for performance (eventually consistent)\n postStats: State.SQLite.table({\n name: 'post_stats',\n columns: {\n postId: State.SQLite.text({ primaryKey: true }),\n likeCount: State.SQLite.integer({ default: 0 }),\n replyCount: State.SQLite.integer({ default: 0 }),\n shareCount: State.SQLite.integer({ default: 0 }),\n lastUpdated: State.SQLite.integer({ schema: Schema.DateFromNumber }),\n },\n }),\n \n userStats: State.SQLite.table({\n name: 'user_stats', \n columns: {\n userId: State.SQLite.text({ primaryKey: true }),\n followerCount: State.SQLite.integer({ default: 0 }),\n followingCount: State.SQLite.integer({ default: 0 }),\n postCount: State.SQLite.integer({ default: 0 }),\n lastUpdated: State.SQLite.integer({ schema: Schema.DateFromNumber }),\n },\n }),\n \n // Client-side state for UI\n feedState: State.SQLite.clientDocument({\n name: 'feedState',\n schema: Schema.Struct({\n currentFeed: Schema.Literal('home', 'discover', 'following'),\n lastRefresh: Schema.Date,\n scrollPosition: Schema.Number,\n }),\n default: { \n id: SessionIdSymbol, \n value: { currentFeed: 'home', lastRefresh: new Date(), scrollPosition: 0 }\n },\n }),\n}\n\nexport const events = {\n // User events\n userCreated: Events.synced({\n name: 'v1.UserCreated',\n schema: Schema.Struct({\n id: Schema.String,\n username: Schema.String,\n email: Schema.String,\n displayName: Schema.String,\n createdAt: Schema.Date,\n }),\n }),\n \n userProfileUpdated: Events.synced({\n name: 'v1.UserProfileUpdated',\n schema: Schema.Struct({\n id: Schema.String,\n displayName: Schema.NullOr(Schema.String),\n bio: Schema.NullOr(Schema.String),\n avatarUrl: Schema.NullOr(Schema.String),\n }),\n }),\n \n userPrivacySettingsChanged: Events.synced({\n name: 'v1.UserPrivacySettingsChanged',\n schema: Schema.Struct({\n id: Schema.String,\n isPrivate: Schema.Boolean,\n allowsFollowers: Schema.Boolean,\n }),\n }),\n \n userLastActiveUpdated: Events.synced({\n name: 'v1.UserLastActiveUpdated',\n schema: Schema.Struct({\n id: Schema.String,\n lastActiveAt: Schema.Date,\n }),\n }),\n \n // Post events\n postCreated: Events.synced({\n name: 'v1.PostCreated',\n schema: Schema.Struct({\n id: Schema.String,\n authorId: Schema.String,\n content: Schema.String,\n mediaUrls: Schema.NullOr(Schema.Array(Schema.String)),\n replyToId: Schema.NullOr(Schema.String),\n visibility: Schema.Literal('public', 'followers', 'private'),\n createdAt: Schema.Date,\n }),\n }),\n \n postEdited: Events.synced({\n name: 'v1.PostEdited',\n schema: Schema.Struct({\n id: Schema.String,\n content: Schema.String,\n editedAt: Schema.Date,\n }),\n }),\n \n postDeleted: Events.synced({\n name: 'v1.PostDeleted',\n schema: Schema.Struct({\n id: Schema.String,\n deletedAt: Schema.Date,\n }),\n }),\n \n // Social interaction events\n followRequested: Events.synced({\n name: 'v1.FollowRequested',\n schema: Schema.Struct({\n followerId: Schema.String,\n followingId: Schema.String,\n createdAt: Schema.Date,\n }),\n }),\n \n followApproved: Events.synced({\n name: 'v1.FollowApproved',\n schema: Schema.Struct({\n followerId: Schema.String,\n followingId: Schema.String,\n approvedAt: Schema.Date,\n }),\n }),\n \n unfollowed: Events.synced({\n name: 'v1.Unfollowed',\n schema: Schema.Struct({\n followerId: Schema.String,\n followingId: Schema.String,\n }),\n }),\n \n postLiked: Events.synced({\n name: 'v1.PostLiked',\n schema: Schema.Struct({\n userId: Schema.String,\n postId: Schema.String,\n createdAt: Schema.Date,\n }),\n }),\n \n postUnliked: Events.synced({\n name: 'v1.PostUnliked',\n schema: Schema.Struct({\n userId: Schema.String,\n postId: Schema.String,\n }),\n }),\n \n // Local UI state\n feedStateUpdated: tables.feedState.set,\n}\n\n// Materializers with eventual consistency for aggregates\nconst materializers = State.SQLite.materializers(events, {\n // User materializers\n 'v1.UserCreated': ({ id, username, email, displayName, createdAt }) => [\n tables.users.insert({ id, username, email, displayName, createdAt }),\n tables.userStats.insert({ userId: id, lastUpdated: createdAt }),\n ],\n \n 'v1.UserProfileUpdated': ({ id, displayName, bio, avatarUrl }) =>\n tables.users.update({ displayName, bio, avatarUrl }).where({ id }),\n \n 'v1.UserPrivacySettingsChanged': ({ id, isPrivate, allowsFollowers }) =>\n tables.users.update({ isPrivate, allowsFollowers }).where({ id }),\n \n 'v1.UserLastActiveUpdated': ({ id, lastActiveAt }) =>\n tables.users.update({ lastActiveAt }).where({ id }),\n \n // Post materializers\n 'v1.PostCreated': ({ id, authorId, content, mediaUrls, replyToId, visibility, createdAt }) => [\n tables.posts.insert({ \n id, \n authorId, \n content, \n mediaUrls: mediaUrls ? JSON.stringify(mediaUrls) : null,\n replyToId, \n visibility, \n createdAt \n }),\n tables.postStats.insert({ postId: id, lastUpdated: createdAt }),\n // Update user post count\n tables.userStats.update({ \n postCount: tables.userStats.select('postCount').where({ userId: authorId }).scalar() + 1,\n lastUpdated: createdAt\n }).where({ userId: authorId }),\n ],\n \n 'v1.PostEdited': ({ id, content, editedAt }) =>\n tables.posts.update({ content, editedAt }).where({ id }),\n \n 'v1.PostDeleted': ({ id, deletedAt }) =>\n tables.posts.update({ deletedAt }).where({ id }),\n \n // Follow materializers\n 'v1.FollowRequested': ({ followerId, followingId, createdAt }) =>\n tables.follows.insert({ followerId, followingId, status: 'pending', createdAt }),\n \n 'v1.FollowApproved': ({ followerId, followingId, approvedAt }) => [\n tables.follows.update({ status: 'active', approvedAt }).where({ followerId, followingId }),\n // Update follower counts\n tables.userStats.update({ \n followerCount: tables.userStats.select('followerCount').where({ userId: followingId }).scalar() + 1,\n lastUpdated: approvedAt\n }).where({ userId: followingId }),\n tables.userStats.update({ \n followingCount: tables.userStats.select('followingCount').where({ userId: followerId }).scalar() + 1,\n lastUpdated: approvedAt\n }).where({ userId: followerId }),\n ],\n \n 'v1.Unfollowed': ({ followerId, followingId }) => [\n tables.follows.delete().where({ followerId, followingId }),\n // Update follower counts (eventual consistency)\n tables.userStats.update({ \n followerCount: Math.max(0, tables.userStats.select('followerCount').where({ userId: followingId }).scalar() - 1),\n lastUpdated: new Date()\n }).where({ userId: followingId }),\n tables.userStats.update({ \n followingCount: Math.max(0, tables.userStats.select('followingCount').where({ userId: followerId }).scalar() - 1),\n lastUpdated: new Date()\n }).where({ userId: followerId }),\n ],\n \n // Like materializers (idempotent)\n 'v1.PostLiked': ({ userId, postId, createdAt }) => [\n tables.likes.insert({ userId, postId, createdAt }),\n // Update like count\n tables.postStats.update({ \n likeCount: tables.postStats.select('likeCount').where({ postId }).scalar() + 1,\n lastUpdated: createdAt\n }).where({ postId }),\n ],\n \n 'v1.PostUnliked': ({ userId, postId }) => [\n tables.likes.delete().where({ userId, postId }),\n // Update like count\n tables.postStats.update({ \n likeCount: Math.max(0, tables.postStats.select('likeCount').where({ postId }).scalar() - 1),\n lastUpdated: new Date()\n }).where({ postId }),\n ],\n})\n\nconst state = State.SQLite.makeState({ tables, materializers })\n\nexport const schema = makeSchema({ events, state })\n\n// Example queries for activity feeds:\n//\n// // Home feed - posts from followed users\n// const homeFeed$ = (userId: string) => queryDb(\n// tables.posts\n// .select()\n// .join(tables.follows, 'authorId', 'followingId')\n// .join(tables.users, 'authorId', 'id')\n// .leftJoin(tables.postStats, 'id', 'postId')\n// .where({ \n// followerId: userId, \n// 'follows.status': 'active',\n// 'posts.deletedAt': null,\n// 'posts.visibility': ['public', 'followers']\n// })\n// .orderBy('createdAt', 'desc')\n// .limit(50),\n// { label: `homeFeed-${userId}` }\n// )\n//\n// // User profile with stats\n// const userProfile$ = (username: string) => queryDb(\n// tables.users\n// .select()\n// .leftJoin(tables.userStats, 'id', 'userId')\n// .where({ username }),\n// { label: `userProfile-${username}` }\n// )";
1
+ export declare const socialSchemaContent = "import { Events, makeSchema, Schema, SessionIdSymbol, State } from '@livestore/livestore'\n\n// Social network with activity feeds and real-time interactions\nexport const tables = {\n users: State.SQLite.table({\n name: 'users',\n columns: {\n id: State.SQLite.text({ primaryKey: true }),\n username: State.SQLite.text(),\n email: State.SQLite.text(),\n displayName: State.SQLite.text(),\n bio: State.SQLite.text({ nullable: true }),\n avatarUrl: State.SQLite.text({ nullable: true }),\n isVerified: State.SQLite.boolean({ default: false }),\n createdAt: State.SQLite.integer({ schema: Schema.DateFromNumber }),\n lastActiveAt: State.SQLite.integer({ nullable: true, schema: Schema.DateFromNumber }),\n // Privacy settings\n isPrivate: State.SQLite.boolean({ default: false }),\n allowsFollowers: State.SQLite.boolean({ default: true }),\n },\n }),\n\n posts: State.SQLite.table({\n name: 'posts',\n columns: {\n id: State.SQLite.text({ primaryKey: true }),\n authorId: State.SQLite.text(),\n content: State.SQLite.text(),\n mediaUrls: State.SQLite.text({ nullable: true }), // JSON array of media URLs\n replyToId: State.SQLite.text({ nullable: true }), // For threading\n visibility: State.SQLite.text({ default: 'public' }), // public, followers, private\n createdAt: State.SQLite.integer({ schema: Schema.DateFromNumber }),\n editedAt: State.SQLite.integer({ nullable: true, schema: Schema.DateFromNumber }),\n deletedAt: State.SQLite.integer({ nullable: true, schema: Schema.DateFromNumber }),\n },\n }),\n\n follows: State.SQLite.table({\n name: 'follows',\n columns: {\n followerId: State.SQLite.text(),\n followingId: State.SQLite.text(),\n status: State.SQLite.text({ default: 'active' }), // active, pending, blocked\n createdAt: State.SQLite.integer({ schema: Schema.DateFromNumber }),\n approvedAt: State.SQLite.integer({ nullable: true, schema: Schema.DateFromNumber }),\n },\n }),\n\n likes: State.SQLite.table({\n name: 'likes',\n columns: {\n userId: State.SQLite.text(),\n postId: State.SQLite.text(),\n createdAt: State.SQLite.integer({ schema: Schema.DateFromNumber }),\n },\n }),\n\n // Aggregate tables for performance (eventually consistent)\n postStats: State.SQLite.table({\n name: 'post_stats',\n columns: {\n postId: State.SQLite.text({ primaryKey: true }),\n likeCount: State.SQLite.integer({ default: 0 }),\n replyCount: State.SQLite.integer({ default: 0 }),\n shareCount: State.SQLite.integer({ default: 0 }),\n lastUpdated: State.SQLite.integer({ schema: Schema.DateFromNumber }),\n },\n }),\n\n userStats: State.SQLite.table({\n name: 'user_stats',\n columns: {\n userId: State.SQLite.text({ primaryKey: true }),\n followerCount: State.SQLite.integer({ default: 0 }),\n followingCount: State.SQLite.integer({ default: 0 }),\n postCount: State.SQLite.integer({ default: 0 }),\n lastUpdated: State.SQLite.integer({ schema: Schema.DateFromNumber }),\n },\n }),\n\n // Client-side state for UI\n feedState: State.SQLite.clientDocument({\n name: 'feedState',\n schema: Schema.Struct({\n currentFeed: Schema.Literal('home', 'discover', 'following'),\n lastRefresh: Schema.Date,\n scrollPosition: Schema.Number,\n }),\n default: {\n id: SessionIdSymbol,\n value: { currentFeed: 'home', lastRefresh: new Date(), scrollPosition: 0 }\n },\n }),\n}\n\nexport const events = {\n // User events\n userCreated: Events.synced({\n name: 'v1.UserCreated',\n schema: Schema.Struct({\n id: Schema.String,\n username: Schema.String,\n email: Schema.String,\n displayName: Schema.String,\n createdAt: Schema.Date,\n }),\n }),\n\n userProfileUpdated: Events.synced({\n name: 'v1.UserProfileUpdated',\n schema: Schema.Struct({\n id: Schema.String,\n displayName: Schema.NullOr(Schema.String),\n bio: Schema.NullOr(Schema.String),\n avatarUrl: Schema.NullOr(Schema.String),\n }),\n }),\n\n userPrivacySettingsChanged: Events.synced({\n name: 'v1.UserPrivacySettingsChanged',\n schema: Schema.Struct({\n id: Schema.String,\n isPrivate: Schema.Boolean,\n allowsFollowers: Schema.Boolean,\n }),\n }),\n\n userLastActiveUpdated: Events.synced({\n name: 'v1.UserLastActiveUpdated',\n schema: Schema.Struct({\n id: Schema.String,\n lastActiveAt: Schema.Date,\n }),\n }),\n\n // Post events\n postCreated: Events.synced({\n name: 'v1.PostCreated',\n schema: Schema.Struct({\n id: Schema.String,\n authorId: Schema.String,\n content: Schema.String,\n mediaUrls: Schema.NullOr(Schema.Array(Schema.String)),\n replyToId: Schema.NullOr(Schema.String),\n visibility: Schema.Literal('public', 'followers', 'private'),\n createdAt: Schema.Date,\n }),\n }),\n\n postEdited: Events.synced({\n name: 'v1.PostEdited',\n schema: Schema.Struct({\n id: Schema.String,\n content: Schema.String,\n editedAt: Schema.Date,\n }),\n }),\n\n postDeleted: Events.synced({\n name: 'v1.PostDeleted',\n schema: Schema.Struct({\n id: Schema.String,\n deletedAt: Schema.Date,\n }),\n }),\n\n // Social interaction events\n followRequested: Events.synced({\n name: 'v1.FollowRequested',\n schema: Schema.Struct({\n followerId: Schema.String,\n followingId: Schema.String,\n createdAt: Schema.Date,\n }),\n }),\n\n followApproved: Events.synced({\n name: 'v1.FollowApproved',\n schema: Schema.Struct({\n followerId: Schema.String,\n followingId: Schema.String,\n approvedAt: Schema.Date,\n }),\n }),\n\n unfollowed: Events.synced({\n name: 'v1.Unfollowed',\n schema: Schema.Struct({\n followerId: Schema.String,\n followingId: Schema.String,\n }),\n }),\n\n postLiked: Events.synced({\n name: 'v1.PostLiked',\n schema: Schema.Struct({\n userId: Schema.String,\n postId: Schema.String,\n createdAt: Schema.Date,\n }),\n }),\n\n postUnliked: Events.synced({\n name: 'v1.PostUnliked',\n schema: Schema.Struct({\n userId: Schema.String,\n postId: Schema.String,\n }),\n }),\n\n // Local UI state\n feedStateUpdated: tables.feedState.set,\n}\n\n// Materializers with eventual consistency for aggregates\nconst materializers = State.SQLite.materializers(events, {\n // User materializers\n 'v1.UserCreated': ({ id, username, email, displayName, createdAt }) => [\n tables.users.insert({ id, username, email, displayName, createdAt }),\n tables.userStats.insert({ userId: id, lastUpdated: createdAt }),\n ],\n\n 'v1.UserProfileUpdated': ({ id, displayName, bio, avatarUrl }) =>\n tables.users.update({ displayName, bio, avatarUrl }).where({ id }),\n\n 'v1.UserPrivacySettingsChanged': ({ id, isPrivate, allowsFollowers }) =>\n tables.users.update({ isPrivate, allowsFollowers }).where({ id }),\n\n 'v1.UserLastActiveUpdated': ({ id, lastActiveAt }) =>\n tables.users.update({ lastActiveAt }).where({ id }),\n\n // Post materializers\n 'v1.PostCreated': ({ id, authorId, content, mediaUrls, replyToId, visibility, createdAt }) => [\n tables.posts.insert({\n id,\n authorId,\n content,\n mediaUrls: mediaUrls ? JSON.stringify(mediaUrls) : null,\n replyToId,\n visibility,\n createdAt\n }),\n tables.postStats.insert({ postId: id, lastUpdated: createdAt }),\n // Update user post count\n tables.userStats.update({\n postCount: tables.userStats.select('postCount').where({ userId: authorId }).scalar() + 1,\n lastUpdated: createdAt\n }).where({ userId: authorId }),\n ],\n\n 'v1.PostEdited': ({ id, content, editedAt }) =>\n tables.posts.update({ content, editedAt }).where({ id }),\n\n 'v1.PostDeleted': ({ id, deletedAt }) =>\n tables.posts.update({ deletedAt }).where({ id }),\n\n // Follow materializers\n 'v1.FollowRequested': ({ followerId, followingId, createdAt }) =>\n tables.follows.insert({ followerId, followingId, status: 'pending', createdAt }),\n\n 'v1.FollowApproved': ({ followerId, followingId, approvedAt }) => [\n tables.follows.update({ status: 'active', approvedAt }).where({ followerId, followingId }),\n // Update follower counts\n tables.userStats.update({\n followerCount: tables.userStats.select('followerCount').where({ userId: followingId }).scalar() + 1,\n lastUpdated: approvedAt\n }).where({ userId: followingId }),\n tables.userStats.update({\n followingCount: tables.userStats.select('followingCount').where({ userId: followerId }).scalar() + 1,\n lastUpdated: approvedAt\n }).where({ userId: followerId }),\n ],\n\n 'v1.Unfollowed': ({ followerId, followingId }) => [\n tables.follows.delete().where({ followerId, followingId }),\n // Update follower counts (eventual consistency)\n tables.userStats.update({\n followerCount: Math.max(0, tables.userStats.select('followerCount').where({ userId: followingId }).scalar() - 1),\n lastUpdated: new Date()\n }).where({ userId: followingId }),\n tables.userStats.update({\n followingCount: Math.max(0, tables.userStats.select('followingCount').where({ userId: followerId }).scalar() - 1),\n lastUpdated: new Date()\n }).where({ userId: followerId }),\n ],\n\n // Like materializers (idempotent)\n 'v1.PostLiked': ({ userId, postId, createdAt }) => [\n tables.likes.insert({ userId, postId, createdAt }),\n // Update like count\n tables.postStats.update({\n likeCount: tables.postStats.select('likeCount').where({ postId }).scalar() + 1,\n lastUpdated: createdAt\n }).where({ postId }),\n ],\n\n 'v1.PostUnliked': ({ userId, postId }) => [\n tables.likes.delete().where({ userId, postId }),\n // Update like count\n tables.postStats.update({\n likeCount: Math.max(0, tables.postStats.select('likeCount').where({ postId }).scalar() - 1),\n lastUpdated: new Date()\n }).where({ postId }),\n ],\n})\n\nconst state = State.SQLite.makeState({ tables, materializers })\n\nexport const schema = makeSchema({ events, state })\n\n// Example queries for activity feeds:\n//\n// // Home feed - posts from followed users\n// const homeFeed$ = (userId: string) => queryDb(\n// tables.posts\n// .select()\n// .join(tables.follows, 'authorId', 'followingId')\n// .join(tables.users, 'authorId', 'id')\n// .leftJoin(tables.postStats, 'id', 'postId')\n// .where({\n// followerId: userId,\n// 'follows.status': 'active',\n// 'posts.deletedAt': null,\n// 'posts.visibility': ['public', 'followers']\n// })\n// .orderBy('createdAt', 'desc')\n// .limit(50),\n// { label: `homeFeed-${userId}` }\n// )\n//\n// // User profile with stats\n// const userProfile$ = (username: string) => queryDb(\n// tables.users\n// .select()\n// .leftJoin(tables.userStats, 'id', 'userId')\n// .where({ username }),\n// { label: `userProfile-${username}` }\n// )";
2
2
  //# sourceMappingURL=social.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"social.d.ts","sourceRoot":"","sources":["../../../src/mcp-content/schemas/social.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,mBAAmB,giWAiV3B,CAAA"}
1
+ {"version":3,"file":"social.d.ts","sourceRoot":"","sources":["../../../src/mcp-content/schemas/social.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,mBAAmB,u8VAiV3B,CAAA"}