@livestore/cli 0.0.0-snapshot-2ac5fd340c97c9e07fe4c5dc6d31d5132aa6557c.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 (80) hide show
  1. package/.claude/settings.local.json +12 -0
  2. package/LICENSE +201 -0
  3. package/dist/cli +0 -0
  4. package/dist/cli.d.ts +15 -0
  5. package/dist/cli.d.ts.map +1 -0
  6. package/dist/cli.js +22 -0
  7. package/dist/cli.js.map +1 -0
  8. package/dist/commands/mcp-coach.d.ts +15 -0
  9. package/dist/commands/mcp-coach.d.ts.map +1 -0
  10. package/dist/commands/mcp-coach.js +87 -0
  11. package/dist/commands/mcp-coach.js.map +1 -0
  12. package/dist/commands/mcp-tools.d.ts +41 -0
  13. package/dist/commands/mcp-tools.d.ts.map +1 -0
  14. package/dist/commands/mcp-tools.js +148 -0
  15. package/dist/commands/mcp-tools.js.map +1 -0
  16. package/dist/commands/mcp.d.ts +5 -0
  17. package/dist/commands/mcp.d.ts.map +1 -0
  18. package/dist/commands/mcp.js +67 -0
  19. package/dist/commands/mcp.js.map +1 -0
  20. package/dist/commands/new-project.d.ts +34 -0
  21. package/dist/commands/new-project.d.ts.map +1 -0
  22. package/dist/commands/new-project.js +163 -0
  23. package/dist/commands/new-project.js.map +1 -0
  24. package/dist/mcp-content/architecture.d.ts +2 -0
  25. package/dist/mcp-content/architecture.d.ts.map +1 -0
  26. package/dist/mcp-content/architecture.js +171 -0
  27. package/dist/mcp-content/architecture.js.map +1 -0
  28. package/dist/mcp-content/features.d.ts +2 -0
  29. package/dist/mcp-content/features.d.ts.map +1 -0
  30. package/dist/mcp-content/features.js +177 -0
  31. package/dist/mcp-content/features.js.map +1 -0
  32. package/dist/mcp-content/getting-started.d.ts +2 -0
  33. package/dist/mcp-content/getting-started.d.ts.map +1 -0
  34. package/dist/mcp-content/getting-started.js +405 -0
  35. package/dist/mcp-content/getting-started.js.map +1 -0
  36. package/dist/mcp-content/overview.d.ts +2 -0
  37. package/dist/mcp-content/overview.d.ts.map +1 -0
  38. package/dist/mcp-content/overview.js +120 -0
  39. package/dist/mcp-content/overview.js.map +1 -0
  40. package/dist/mcp-content/schemas/blog.d.ts +2 -0
  41. package/dist/mcp-content/schemas/blog.d.ts.map +1 -0
  42. package/dist/mcp-content/schemas/blog.js +223 -0
  43. package/dist/mcp-content/schemas/blog.js.map +1 -0
  44. package/dist/mcp-content/schemas/ecommerce.d.ts +2 -0
  45. package/dist/mcp-content/schemas/ecommerce.d.ts.map +1 -0
  46. package/dist/mcp-content/schemas/ecommerce.js +436 -0
  47. package/dist/mcp-content/schemas/ecommerce.js.map +1 -0
  48. package/dist/mcp-content/schemas/social.d.ts +2 -0
  49. package/dist/mcp-content/schemas/social.d.ts.map +1 -0
  50. package/dist/mcp-content/schemas/social.js +339 -0
  51. package/dist/mcp-content/schemas/social.js.map +1 -0
  52. package/dist/mcp-content/schemas/todo.d.ts +2 -0
  53. package/dist/mcp-content/schemas/todo.d.ts.map +1 -0
  54. package/dist/mcp-content/schemas/todo.js +172 -0
  55. package/dist/mcp-content/schemas/todo.js.map +1 -0
  56. package/dist/mod.d.ts +2 -0
  57. package/dist/mod.d.ts.map +1 -0
  58. package/dist/mod.js +2 -0
  59. package/dist/mod.js.map +1 -0
  60. package/dist/test-tool.d.ts +2 -0
  61. package/dist/test-tool.d.ts.map +1 -0
  62. package/dist/test-tool.js +57 -0
  63. package/dist/test-tool.js.map +1 -0
  64. package/dist/tsconfig.tsbuildinfo +1 -0
  65. package/package.json +27 -0
  66. package/src/cli.ts +35 -0
  67. package/src/commands/mcp-coach.ts +121 -0
  68. package/src/commands/mcp-tools.ts +169 -0
  69. package/src/commands/mcp.ts +97 -0
  70. package/src/commands/new-project.ts +263 -0
  71. package/src/mcp-content/architecture.ts +170 -0
  72. package/src/mcp-content/features.ts +176 -0
  73. package/src/mcp-content/getting-started.ts +404 -0
  74. package/src/mcp-content/overview.ts +119 -0
  75. package/src/mcp-content/schemas/blog.ts +222 -0
  76. package/src/mcp-content/schemas/ecommerce.ts +435 -0
  77. package/src/mcp-content/schemas/social.ts +338 -0
  78. package/src/mcp-content/schemas/todo.ts +171 -0
  79. package/src/mod.ts +1 -0
  80. package/tsconfig.json +9 -0
@@ -0,0 +1,436 @@
1
+ export const ecommerceSchemaContent = `import { Events, makeSchema, Schema, SessionIdSymbol, State } from '@livestore/livestore'
2
+
3
+ // E-commerce with inventory management and order processing
4
+ export const tables = {
5
+ products: State.SQLite.table({
6
+ name: 'products',
7
+ columns: {
8
+ id: State.SQLite.text({ primaryKey: true }),
9
+ sku: State.SQLite.text(),
10
+ name: State.SQLite.text(),
11
+ description: State.SQLite.text(),
12
+ price: State.SQLite.integer(), // Store as cents to avoid floating point issues
13
+ currency: State.SQLite.text({ default: 'USD' }),
14
+ stock: State.SQLite.integer({ default: 0 }),
15
+ reservedStock: State.SQLite.integer({ default: 0 }), // For pending orders
16
+ isActive: State.SQLite.boolean({ default: true }),
17
+ weight: State.SQLite.real({ nullable: true }), // For shipping calculations
18
+ dimensions: State.SQLite.text({ nullable: true }), // JSON: {width, height, depth}
19
+ imageUrls: State.SQLite.text({ nullable: true }), // JSON array
20
+ createdAt: State.SQLite.integer({ schema: Schema.DateFromNumber }),
21
+ updatedAt: State.SQLite.integer({ schema: Schema.DateFromNumber }),
22
+ deletedAt: State.SQLite.integer({ nullable: true, schema: Schema.DateFromNumber }),
23
+ },
24
+ }),
25
+
26
+ categories: State.SQLite.table({
27
+ name: 'categories',
28
+ columns: {
29
+ id: State.SQLite.text({ primaryKey: true }),
30
+ name: State.SQLite.text(),
31
+ slug: State.SQLite.text(),
32
+ parentId: State.SQLite.text({ nullable: true }), // For hierarchical categories
33
+ description: State.SQLite.text({ nullable: true }),
34
+ imageUrl: State.SQLite.text({ nullable: true }),
35
+ sortOrder: State.SQLite.integer({ default: 0 }),
36
+ isActive: State.SQLite.boolean({ default: true }),
37
+ createdAt: State.SQLite.integer({ schema: Schema.DateFromNumber }),
38
+ },
39
+ }),
40
+
41
+ productCategories: State.SQLite.table({
42
+ name: 'product_categories',
43
+ columns: {
44
+ productId: State.SQLite.text(),
45
+ categoryId: State.SQLite.text(),
46
+ createdAt: State.SQLite.integer({ schema: Schema.DateFromNumber }),
47
+ },
48
+ }),
49
+
50
+ customers: State.SQLite.table({
51
+ name: 'customers',
52
+ columns: {
53
+ id: State.SQLite.text({ primaryKey: true }),
54
+ email: State.SQLite.text(),
55
+ firstName: State.SQLite.text({ nullable: true }),
56
+ lastName: State.SQLite.text({ nullable: true }),
57
+ phone: State.SQLite.text({ nullable: true }),
58
+ createdAt: State.SQLite.integer({ schema: Schema.DateFromNumber }),
59
+ lastOrderAt: State.SQLite.integer({ nullable: true, schema: Schema.DateFromNumber }),
60
+ },
61
+ }),
62
+
63
+ addresses: State.SQLite.table({
64
+ name: 'addresses',
65
+ columns: {
66
+ id: State.SQLite.text({ primaryKey: true }),
67
+ customerId: State.SQLite.text(),
68
+ type: State.SQLite.text({ default: 'shipping' }), // shipping, billing
69
+ firstName: State.SQLite.text(),
70
+ lastName: State.SQLite.text(),
71
+ company: State.SQLite.text({ nullable: true }),
72
+ address1: State.SQLite.text(),
73
+ address2: State.SQLite.text({ nullable: true }),
74
+ city: State.SQLite.text(),
75
+ state: State.SQLite.text(),
76
+ country: State.SQLite.text(),
77
+ postalCode: State.SQLite.text(),
78
+ isDefault: State.SQLite.boolean({ default: false }),
79
+ },
80
+ }),
81
+
82
+ orders: State.SQLite.table({
83
+ name: 'orders',
84
+ columns: {
85
+ id: State.SQLite.text({ primaryKey: true }),
86
+ orderNumber: State.SQLite.text(), // Human-readable order number
87
+ customerId: State.SQLite.text(),
88
+ status: State.SQLite.text({ default: 'draft' }), // draft, pending, paid, processing, shipped, delivered, cancelled
89
+ paymentStatus: State.SQLite.text({ default: 'pending' }), // pending, paid, failed, refunded
90
+ fulfillmentStatus: State.SQLite.text({ default: 'unfulfilled' }), // unfulfilled, partial, fulfilled
91
+
92
+ subtotal: State.SQLite.integer(), // In cents
93
+ taxAmount: State.SQLite.integer({ default: 0 }),
94
+ shippingAmount: State.SQLite.integer({ default: 0 }),
95
+ discountAmount: State.SQLite.integer({ default: 0 }),
96
+ total: State.SQLite.integer(),
97
+ currency: State.SQLite.text({ default: 'USD' }),
98
+
99
+ shippingAddress: State.SQLite.text(), // JSON
100
+ billingAddress: State.SQLite.text(), // JSON
101
+
102
+ notes: State.SQLite.text({ nullable: true }),
103
+
104
+ createdAt: State.SQLite.integer({ schema: Schema.DateFromNumber }),
105
+ updatedAt: State.SQLite.integer({ schema: Schema.DateFromNumber }),
106
+ cancelledAt: State.SQLite.integer({ nullable: true, schema: Schema.DateFromNumber }),
107
+ shippedAt: State.SQLite.integer({ nullable: true, schema: Schema.DateFromNumber }),
108
+ deliveredAt: State.SQLite.integer({ nullable: true, schema: Schema.DateFromNumber }),
109
+ },
110
+ }),
111
+
112
+ orderItems: State.SQLite.table({
113
+ name: 'order_items',
114
+ columns: {
115
+ id: State.SQLite.text({ primaryKey: true }),
116
+ orderId: State.SQLite.text(),
117
+ productId: State.SQLite.text(),
118
+ variantId: State.SQLite.text({ nullable: true }),
119
+ sku: State.SQLite.text(), // Snapshot at time of order
120
+ name: State.SQLite.text(), // Product name at time of order
121
+ quantity: State.SQLite.integer(),
122
+ unitPrice: State.SQLite.integer(), // Price per unit in cents
123
+ totalPrice: State.SQLite.integer(), // quantity * unitPrice
124
+ fulfillmentStatus: State.SQLite.text({ default: 'unfulfilled' }),
125
+ },
126
+ }),
127
+
128
+ // Inventory tracking with event sourcing
129
+ inventoryEvents: State.SQLite.table({
130
+ name: 'inventory_events',
131
+ columns: {
132
+ id: State.SQLite.text({ primaryKey: true }),
133
+ productId: State.SQLite.text(),
134
+ type: State.SQLite.text(), // 'adjustment', 'sale', 'return', 'damage', 'restock'
135
+ quantity: State.SQLite.integer(), // Can be positive or negative
136
+ reason: State.SQLite.text({ nullable: true }),
137
+ referenceId: State.SQLite.text({ nullable: true }), // Order ID, adjustment ID, etc.
138
+ createdAt: State.SQLite.integer({ schema: Schema.DateFromNumber }),
139
+ },
140
+ }),
141
+
142
+ // Shopping cart (client-side state)
143
+ cart: State.SQLite.clientDocument({
144
+ name: 'cart',
145
+ schema: Schema.Struct({
146
+ items: Schema.Array(Schema.Struct({
147
+ productId: Schema.String,
148
+ quantity: Schema.Number,
149
+ addedAt: Schema.Date,
150
+ })),
151
+ discountCode: Schema.NullOr(Schema.String),
152
+ notes: Schema.String,
153
+ }),
154
+ default: {
155
+ id: SessionIdSymbol,
156
+ value: { items: [], discountCode: null, notes: '' }
157
+ },
158
+ }),
159
+ }
160
+
161
+ export const events = {
162
+ // Product management
163
+ productCreated: Events.synced({
164
+ name: 'v1.ProductCreated',
165
+ schema: Schema.Struct({
166
+ id: Schema.String,
167
+ sku: Schema.String,
168
+ name: Schema.String,
169
+ description: Schema.String,
170
+ price: Schema.Number, // In cents
171
+ currency: Schema.String,
172
+ createdAt: Schema.Date,
173
+ }),
174
+ }),
175
+
176
+ productUpdated: Events.synced({
177
+ name: 'v1.ProductUpdated',
178
+ schema: Schema.Struct({
179
+ id: Schema.String,
180
+ name: Schema.NullOr(Schema.String),
181
+ description: Schema.NullOr(Schema.String),
182
+ price: Schema.NullOr(Schema.Number),
183
+ updatedAt: Schema.Date,
184
+ }),
185
+ }),
186
+
187
+ productStockAdjusted: Events.synced({
188
+ name: 'v1.ProductStockAdjusted',
189
+ schema: Schema.Struct({
190
+ productId: Schema.String,
191
+ adjustment: Schema.Number, // Can be positive or negative
192
+ reason: Schema.String,
193
+ referenceId: Schema.NullOr(Schema.String),
194
+ createdAt: Schema.Date,
195
+ }),
196
+ }),
197
+
198
+ productDeactivated: Events.synced({
199
+ name: 'v1.ProductDeactivated',
200
+ schema: Schema.Struct({ id: Schema.String }),
201
+ }),
202
+
203
+ // Customer management
204
+ customerCreated: Events.synced({
205
+ name: 'v1.CustomerCreated',
206
+ schema: Schema.Struct({
207
+ id: Schema.String,
208
+ email: Schema.String,
209
+ firstName: Schema.NullOr(Schema.String),
210
+ lastName: Schema.NullOr(Schema.String),
211
+ createdAt: Schema.Date,
212
+ }),
213
+ }),
214
+
215
+ // Order lifecycle with state machine
216
+ orderCreated: Events.synced({
217
+ name: 'v1.OrderCreated',
218
+ schema: Schema.Struct({
219
+ id: Schema.String,
220
+ orderNumber: Schema.String,
221
+ customerId: Schema.String,
222
+ items: Schema.Array(Schema.Struct({
223
+ productId: Schema.String,
224
+ sku: Schema.String,
225
+ name: Schema.String,
226
+ quantity: Schema.Number,
227
+ unitPrice: Schema.Number,
228
+ })),
229
+ subtotal: Schema.Number,
230
+ total: Schema.Number,
231
+ shippingAddress: Schema.Object,
232
+ billingAddress: Schema.Object,
233
+ createdAt: Schema.Date,
234
+ }),
235
+ }),
236
+
237
+ orderPaymentReceived: Events.synced({
238
+ name: 'v1.OrderPaymentReceived',
239
+ schema: Schema.Struct({
240
+ orderId: Schema.String,
241
+ amount: Schema.Number,
242
+ paymentMethod: Schema.String,
243
+ transactionId: Schema.String,
244
+ paidAt: Schema.Date,
245
+ }),
246
+ }),
247
+
248
+ orderShipped: Events.synced({
249
+ name: 'v1.OrderShipped',
250
+ schema: Schema.Struct({
251
+ orderId: Schema.String,
252
+ trackingNumber: Schema.NullOr(Schema.String),
253
+ carrier: Schema.NullOr(Schema.String),
254
+ shippedAt: Schema.Date,
255
+ }),
256
+ }),
257
+
258
+ orderDelivered: Events.synced({
259
+ name: 'v1.OrderDelivered',
260
+ schema: Schema.Struct({
261
+ orderId: Schema.String,
262
+ deliveredAt: Schema.Date,
263
+ }),
264
+ }),
265
+
266
+ orderCancelled: Events.synced({
267
+ name: 'v1.OrderCancelled',
268
+ schema: Schema.Struct({
269
+ orderId: Schema.String,
270
+ reason: Schema.String,
271
+ cancelledAt: Schema.Date,
272
+ }),
273
+ }),
274
+
275
+ // Cart management (local)
276
+ cartUpdated: tables.cart.set,
277
+ }
278
+
279
+ // Materializers with business logic and constraints
280
+ const materializers = State.SQLite.materializers(events, {
281
+ // Product materializers
282
+ 'v1.ProductCreated': ({ id, sku, name, description, price, currency, createdAt }) =>
283
+ tables.products.insert({ id, sku, name, description, price, currency, createdAt, updatedAt: createdAt }),
284
+
285
+ 'v1.ProductUpdated': ({ id, name, description, price, updatedAt }) =>
286
+ tables.products.update({
287
+ name: name ?? undefined,
288
+ description: description ?? undefined,
289
+ price: price ?? undefined,
290
+ updatedAt
291
+ }).where({ id }),
292
+
293
+ 'v1.ProductStockAdjusted': ({ productId, adjustment, reason, referenceId, createdAt }) => [
294
+ // Record the inventory event
295
+ tables.inventoryEvents.insert({
296
+ id: crypto.randomUUID(),
297
+ productId,
298
+ type: 'adjustment',
299
+ quantity: adjustment,
300
+ reason,
301
+ referenceId,
302
+ createdAt
303
+ }),
304
+ // Update product stock (eventually consistent)
305
+ tables.products.update({
306
+ stock: Math.max(0, tables.products.select('stock').where({ id: productId }).scalar() + adjustment),
307
+ updatedAt: createdAt
308
+ }).where({ id: productId }),
309
+ ],
310
+
311
+ 'v1.ProductDeactivated': ({ id }) =>
312
+ tables.products.update({ isActive: false }).where({ id }),
313
+
314
+ // Customer materializers
315
+ 'v1.CustomerCreated': ({ id, email, firstName, lastName, createdAt }) =>
316
+ tables.customers.insert({ id, email, firstName, lastName, createdAt }),
317
+
318
+ // Order materializers with inventory reservation
319
+ 'v1.OrderCreated': ({ id, orderNumber, customerId, items, subtotal, total, shippingAddress, billingAddress, createdAt }) => [
320
+ // Create the order
321
+ tables.orders.insert({
322
+ id,
323
+ orderNumber,
324
+ customerId,
325
+ status: 'pending',
326
+ subtotal,
327
+ total,
328
+ shippingAddress: JSON.stringify(shippingAddress),
329
+ billingAddress: JSON.stringify(billingAddress),
330
+ createdAt,
331
+ updatedAt: createdAt
332
+ }),
333
+ // Create order items and reserve inventory
334
+ ...items.flatMap(item => [
335
+ tables.orderItems.insert({
336
+ id: crypto.randomUUID(),
337
+ orderId: id,
338
+ productId: item.productId,
339
+ sku: item.sku,
340
+ name: item.name,
341
+ quantity: item.quantity,
342
+ unitPrice: item.unitPrice,
343
+ totalPrice: item.quantity * item.unitPrice,
344
+ }),
345
+ // Reserve stock
346
+ tables.products.update({
347
+ reservedStock: tables.products.select('reservedStock').where({ id: item.productId }).scalar() + item.quantity
348
+ }).where({ id: item.productId }),
349
+ ]),
350
+ ],
351
+
352
+ 'v1.OrderPaymentReceived': ({ orderId, amount, paymentMethod, transactionId, paidAt }) =>
353
+ tables.orders.update({
354
+ status: 'paid',
355
+ paymentStatus: 'paid',
356
+ updatedAt: paidAt
357
+ }).where({ id: orderId }),
358
+
359
+ 'v1.OrderShipped': ({ orderId, trackingNumber, carrier, shippedAt }) => [
360
+ tables.orders.update({
361
+ status: 'shipped',
362
+ fulfillmentStatus: 'fulfilled',
363
+ shippedAt,
364
+ updatedAt: shippedAt
365
+ }).where({ id: orderId }),
366
+ // Convert reserved stock to actual stock reduction
367
+ ...tables.orderItems.select().where({ orderId }).map(item =>
368
+ tables.products.update({
369
+ stock: tables.products.select('stock').where({ id: item.productId }).scalar() - item.quantity,
370
+ reservedStock: tables.products.select('reservedStock').where({ id: item.productId }).scalar() - item.quantity
371
+ }).where({ id: item.productId })
372
+ ),
373
+ ],
374
+
375
+ 'v1.OrderDelivered': ({ orderId, deliveredAt }) =>
376
+ tables.orders.update({
377
+ status: 'delivered',
378
+ deliveredAt,
379
+ updatedAt: deliveredAt
380
+ }).where({ id: orderId }),
381
+
382
+ 'v1.OrderCancelled': ({ orderId, reason, cancelledAt }) => [
383
+ tables.orders.update({
384
+ status: 'cancelled',
385
+ cancelledAt,
386
+ notes: reason,
387
+ updatedAt: cancelledAt
388
+ }).where({ id: orderId }),
389
+ // Release reserved inventory
390
+ ...tables.orderItems.select().where({ orderId }).map(item =>
391
+ tables.products.update({
392
+ reservedStock: Math.max(0, tables.products.select('reservedStock').where({ id: item.productId }).scalar() - item.quantity)
393
+ }).where({ id: item.productId })
394
+ ),
395
+ ],
396
+ })
397
+
398
+ const state = State.SQLite.makeState({ tables, materializers })
399
+
400
+ export const schema = makeSchema({ events, state })
401
+
402
+ // Example queries for business intelligence:
403
+ //
404
+ // // Available products with real-time stock
405
+ // const availableProducts$ = queryDb(
406
+ // tables.products
407
+ // .select()
408
+ // .where({ isActive: true, deletedAt: null })
409
+ // .having(tables.products.column('stock').minus(tables.products.column('reservedStock')).gt(0))
410
+ // .orderBy('name'),
411
+ // { label: 'availableProducts' }
412
+ // )
413
+ //
414
+ // // Orders requiring fulfillment
415
+ // const pendingOrders$ = queryDb(
416
+ // tables.orders
417
+ // .select()
418
+ // .join(tables.customers, 'customerId', 'id')
419
+ // .where({
420
+ // 'orders.status': 'paid',
421
+ // 'orders.fulfillmentStatus': 'unfulfilled'
422
+ // })
423
+ // .orderBy('orders.createdAt'),
424
+ // { label: 'pendingOrders' }
425
+ // )
426
+ //
427
+ // // Low stock alerts
428
+ // const lowStockProducts$ = queryDb(
429
+ // tables.products
430
+ // .select()
431
+ // .where({ isActive: true })
432
+ // .having(tables.products.column('stock').minus(tables.products.column('reservedStock')).lt(10))
433
+ // .orderBy('stock'),
434
+ // { label: 'lowStockProducts' }
435
+ // )`;
436
+ //# sourceMappingURL=ecommerce.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ecommerce.js","sourceRoot":"","sources":["../../../src/mcp-content/schemas/ecommerce.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,sBAAsB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAkbjC,CAAA"}
@@ -0,0 +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// )";
2
+ //# sourceMappingURL=social.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"social.d.ts","sourceRoot":"","sources":["../../../src/mcp-content/schemas/social.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,mBAAmB,giWAiV3B,CAAA"}