digital-products 2.0.1

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 (110) hide show
  1. package/.turbo/turbo-build.log +5 -0
  2. package/CHANGELOG.md +9 -0
  3. package/README.md +535 -0
  4. package/dist/api.d.ts +99 -0
  5. package/dist/api.d.ts.map +1 -0
  6. package/dist/api.js +129 -0
  7. package/dist/api.js.map +1 -0
  8. package/dist/app.d.ts +79 -0
  9. package/dist/app.d.ts.map +1 -0
  10. package/dist/app.js +107 -0
  11. package/dist/app.js.map +1 -0
  12. package/dist/content.d.ts +58 -0
  13. package/dist/content.d.ts.map +1 -0
  14. package/dist/content.js +78 -0
  15. package/dist/content.js.map +1 -0
  16. package/dist/data.d.ts +67 -0
  17. package/dist/data.d.ts.map +1 -0
  18. package/dist/data.js +107 -0
  19. package/dist/data.js.map +1 -0
  20. package/dist/dataset.d.ts +32 -0
  21. package/dist/dataset.d.ts.map +1 -0
  22. package/dist/dataset.js +50 -0
  23. package/dist/dataset.js.map +1 -0
  24. package/dist/entities/ai.d.ts +53 -0
  25. package/dist/entities/ai.d.ts.map +1 -0
  26. package/dist/entities/ai.js +859 -0
  27. package/dist/entities/ai.js.map +1 -0
  28. package/dist/entities/content.d.ts +52 -0
  29. package/dist/entities/content.d.ts.map +1 -0
  30. package/dist/entities/content.js +784 -0
  31. package/dist/entities/content.js.map +1 -0
  32. package/dist/entities/index.d.ts +112 -0
  33. package/dist/entities/index.d.ts.map +1 -0
  34. package/dist/entities/index.js +89 -0
  35. package/dist/entities/index.js.map +1 -0
  36. package/dist/entities/interfaces.d.ts +67 -0
  37. package/dist/entities/interfaces.d.ts.map +1 -0
  38. package/dist/entities/interfaces.js +930 -0
  39. package/dist/entities/interfaces.js.map +1 -0
  40. package/dist/entities/lifecycle.d.ts +51 -0
  41. package/dist/entities/lifecycle.d.ts.map +1 -0
  42. package/dist/entities/lifecycle.js +804 -0
  43. package/dist/entities/lifecycle.js.map +1 -0
  44. package/dist/entities/products.d.ts +53 -0
  45. package/dist/entities/products.d.ts.map +1 -0
  46. package/dist/entities/products.js +798 -0
  47. package/dist/entities/products.js.map +1 -0
  48. package/dist/entities/web.d.ts +44 -0
  49. package/dist/entities/web.d.ts.map +1 -0
  50. package/dist/entities/web.js +658 -0
  51. package/dist/entities/web.js.map +1 -0
  52. package/dist/index.d.ts +29 -0
  53. package/dist/index.d.ts.map +1 -0
  54. package/dist/index.js +36 -0
  55. package/dist/index.js.map +1 -0
  56. package/dist/mcp.d.ts +101 -0
  57. package/dist/mcp.d.ts.map +1 -0
  58. package/dist/mcp.js +140 -0
  59. package/dist/mcp.js.map +1 -0
  60. package/dist/product.d.ts +37 -0
  61. package/dist/product.d.ts.map +1 -0
  62. package/dist/product.js +54 -0
  63. package/dist/product.js.map +1 -0
  64. package/dist/registry.d.ts +9 -0
  65. package/dist/registry.d.ts.map +1 -0
  66. package/dist/registry.js +32 -0
  67. package/dist/registry.js.map +1 -0
  68. package/dist/sdk.d.ts +99 -0
  69. package/dist/sdk.d.ts.map +1 -0
  70. package/dist/sdk.js +128 -0
  71. package/dist/sdk.js.map +1 -0
  72. package/dist/site.d.ts +85 -0
  73. package/dist/site.d.ts.map +1 -0
  74. package/dist/site.js +113 -0
  75. package/dist/site.js.map +1 -0
  76. package/dist/types.d.ts +528 -0
  77. package/dist/types.d.ts.map +1 -0
  78. package/dist/types.js +5 -0
  79. package/dist/types.js.map +1 -0
  80. package/example.ts +236 -0
  81. package/package.json +35 -0
  82. package/src/api.ts +140 -0
  83. package/src/app.ts +117 -0
  84. package/src/content.ts +82 -0
  85. package/src/data.ts +129 -0
  86. package/src/dataset.ts +53 -0
  87. package/src/entities/ai.ts +932 -0
  88. package/src/entities/content.ts +851 -0
  89. package/src/entities/index.ts +156 -0
  90. package/src/entities/interfaces.ts +1017 -0
  91. package/src/entities/lifecycle.ts +872 -0
  92. package/src/entities/products.ts +867 -0
  93. package/src/entities/web.ts +719 -0
  94. package/src/index.ts +55 -0
  95. package/src/mcp.ts +163 -0
  96. package/src/product.ts +59 -0
  97. package/src/registry.ts +41 -0
  98. package/src/sdk.ts +148 -0
  99. package/src/site.ts +127 -0
  100. package/src/types.ts +558 -0
  101. package/test/api.test.ts +247 -0
  102. package/test/app.test.ts +220 -0
  103. package/test/content.test.ts +171 -0
  104. package/test/data.test.ts +201 -0
  105. package/test/dataset.test.ts +181 -0
  106. package/test/mcp.test.ts +230 -0
  107. package/test/product.test.ts +200 -0
  108. package/test/sdk.test.ts +236 -0
  109. package/test/site.test.ts +245 -0
  110. package/tsconfig.json +9 -0
@@ -0,0 +1,851 @@
1
+ /**
2
+ * Content Entity Types (Nouns)
3
+ *
4
+ * Content and data products: ContentProduct, DataProduct, Dataset, Documentation, Template
5
+ *
6
+ * @packageDocumentation
7
+ */
8
+
9
+ import type { Noun } from 'ai-database'
10
+
11
+ // =============================================================================
12
+ // ContentProduct
13
+ // =============================================================================
14
+
15
+ /**
16
+ * ContentProduct entity
17
+ *
18
+ * Text/media content as a product.
19
+ */
20
+ export const ContentProduct: Noun = {
21
+ singular: 'content-product',
22
+ plural: 'content-products',
23
+ description: 'A content-based digital product',
24
+
25
+ properties: {
26
+ // Identity
27
+ name: {
28
+ type: 'string',
29
+ description: 'Content product name',
30
+ },
31
+ slug: {
32
+ type: 'string',
33
+ optional: true,
34
+ description: 'URL-friendly identifier',
35
+ },
36
+ description: {
37
+ type: 'string',
38
+ optional: true,
39
+ description: 'Product description',
40
+ },
41
+
42
+ // Classification
43
+ type: {
44
+ type: 'string',
45
+ description: 'Content type',
46
+ examples: ['course', 'book', 'newsletter', 'podcast', 'video-series', 'documentation', 'blog'],
47
+ },
48
+ format: {
49
+ type: 'string',
50
+ description: 'Primary format',
51
+ examples: ['text', 'video', 'audio', 'interactive', 'mixed'],
52
+ },
53
+ category: {
54
+ type: 'string',
55
+ optional: true,
56
+ description: 'Content category',
57
+ },
58
+
59
+ // Structure
60
+ contentFormat: {
61
+ type: 'string',
62
+ optional: true,
63
+ description: 'File format',
64
+ examples: ['markdown', 'mdx', 'html', 'json', 'yaml', 'pdf', 'epub'],
65
+ },
66
+ schema: {
67
+ type: 'json',
68
+ optional: true,
69
+ description: 'Content schema for structured content',
70
+ },
71
+ frontmatterSchema: {
72
+ type: 'json',
73
+ optional: true,
74
+ description: 'Frontmatter schema',
75
+ },
76
+
77
+ // Publishing
78
+ publishingModel: {
79
+ type: 'string',
80
+ optional: true,
81
+ description: 'Publishing model',
82
+ examples: ['one-time', 'subscription', 'freemium', 'drip', 'cohort'],
83
+ },
84
+ updateFrequency: {
85
+ type: 'string',
86
+ optional: true,
87
+ description: 'Update frequency',
88
+ examples: ['one-time', 'daily', 'weekly', 'monthly', 'on-demand'],
89
+ },
90
+
91
+ // Access
92
+ accessModel: {
93
+ type: 'string',
94
+ optional: true,
95
+ description: 'Access model',
96
+ examples: ['free', 'paid', 'subscription', 'gated', 'preview'],
97
+ },
98
+ previewPercent: {
99
+ type: 'number',
100
+ optional: true,
101
+ description: 'Percentage available for preview',
102
+ },
103
+
104
+ // Metrics
105
+ itemCount: {
106
+ type: 'number',
107
+ optional: true,
108
+ description: 'Number of content items',
109
+ },
110
+ totalDuration: {
111
+ type: 'number',
112
+ optional: true,
113
+ description: 'Total duration in minutes (for video/audio)',
114
+ },
115
+ wordCount: {
116
+ type: 'number',
117
+ optional: true,
118
+ description: 'Total word count',
119
+ },
120
+
121
+ // Status
122
+ status: {
123
+ type: 'string',
124
+ description: 'Product status',
125
+ examples: ['draft', 'production', 'published', 'archived'],
126
+ },
127
+ },
128
+
129
+ relationships: {
130
+ product: {
131
+ type: 'DigitalProduct',
132
+ description: 'Parent product',
133
+ },
134
+ items: {
135
+ type: 'ContentItem[]',
136
+ description: 'Content items',
137
+ },
138
+ categories: {
139
+ type: 'Category[]',
140
+ description: 'Content categories',
141
+ },
142
+ authors: {
143
+ type: 'Author[]',
144
+ description: 'Content authors',
145
+ },
146
+ },
147
+
148
+ actions: [
149
+ 'create',
150
+ 'update',
151
+ 'addItem',
152
+ 'removeItem',
153
+ 'publish',
154
+ 'unpublish',
155
+ 'archive',
156
+ ],
157
+
158
+ events: [
159
+ 'created',
160
+ 'updated',
161
+ 'itemAdded',
162
+ 'itemRemoved',
163
+ 'published',
164
+ 'unpublished',
165
+ 'archived',
166
+ ],
167
+ }
168
+
169
+ // =============================================================================
170
+ // DataProduct
171
+ // =============================================================================
172
+
173
+ /**
174
+ * DataProduct entity
175
+ *
176
+ * Structured data as a product.
177
+ */
178
+ export const DataProduct: Noun = {
179
+ singular: 'data-product',
180
+ plural: 'data-products',
181
+ description: 'A data-based digital product',
182
+
183
+ properties: {
184
+ // Identity
185
+ name: {
186
+ type: 'string',
187
+ description: 'Data product name',
188
+ },
189
+ slug: {
190
+ type: 'string',
191
+ optional: true,
192
+ description: 'URL-friendly identifier',
193
+ },
194
+ description: {
195
+ type: 'string',
196
+ optional: true,
197
+ description: 'Product description',
198
+ },
199
+
200
+ // Classification
201
+ type: {
202
+ type: 'string',
203
+ description: 'Data product type',
204
+ examples: ['raw', 'derived', 'aggregated', 'enriched', 'curated', 'synthetic'],
205
+ },
206
+ domain: {
207
+ type: 'string',
208
+ optional: true,
209
+ description: 'Data domain',
210
+ },
211
+
212
+ // Schema
213
+ schema: {
214
+ type: 'json',
215
+ description: 'Data schema',
216
+ },
217
+ format: {
218
+ type: 'string',
219
+ optional: true,
220
+ description: 'Data format',
221
+ examples: ['json', 'csv', 'parquet', 'avro', 'protobuf', 'arrow'],
222
+ },
223
+
224
+ // Storage
225
+ storageType: {
226
+ type: 'string',
227
+ optional: true,
228
+ description: 'Storage backend',
229
+ examples: ['postgres', 'mysql', 'mongo', 'clickhouse', 's3', 'bigquery', 'snowflake'],
230
+ },
231
+ sizeBytes: {
232
+ type: 'number',
233
+ optional: true,
234
+ description: 'Data size in bytes',
235
+ },
236
+ recordCount: {
237
+ type: 'number',
238
+ optional: true,
239
+ description: 'Number of records',
240
+ },
241
+
242
+ // Quality
243
+ qualityScore: {
244
+ type: 'number',
245
+ optional: true,
246
+ description: 'Data quality score (0-100)',
247
+ },
248
+ freshness: {
249
+ type: 'string',
250
+ optional: true,
251
+ description: 'Data freshness',
252
+ examples: ['realtime', 'hourly', 'daily', 'weekly', 'static'],
253
+ },
254
+ lastUpdatedAt: {
255
+ type: 'date',
256
+ optional: true,
257
+ description: 'Last data update',
258
+ },
259
+
260
+ // Access
261
+ accessMethod: {
262
+ type: 'string',
263
+ optional: true,
264
+ description: 'Access method',
265
+ examples: ['api', 'download', 'stream', 'query', 'embedded'],
266
+ },
267
+ apiEndpoint: {
268
+ type: 'string',
269
+ optional: true,
270
+ description: 'API endpoint for access',
271
+ },
272
+
273
+ // Governance
274
+ owner: {
275
+ type: 'string',
276
+ optional: true,
277
+ description: 'Data owner',
278
+ },
279
+ classification: {
280
+ type: 'string',
281
+ optional: true,
282
+ description: 'Data classification',
283
+ examples: ['public', 'internal', 'confidential', 'restricted', 'pii'],
284
+ },
285
+ retentionDays: {
286
+ type: 'number',
287
+ optional: true,
288
+ description: 'Data retention period in days',
289
+ },
290
+
291
+ // Status
292
+ status: {
293
+ type: 'string',
294
+ description: 'Product status',
295
+ examples: ['draft', 'active', 'deprecated', 'archived'],
296
+ },
297
+ },
298
+
299
+ relationships: {
300
+ product: {
301
+ type: 'DigitalProduct',
302
+ description: 'Parent product',
303
+ },
304
+ datasets: {
305
+ type: 'Dataset[]',
306
+ description: 'Associated datasets',
307
+ },
308
+ api: {
309
+ type: 'API',
310
+ required: false,
311
+ description: 'Access API',
312
+ },
313
+ lineage: {
314
+ type: 'DataProduct[]',
315
+ description: 'Source data products',
316
+ },
317
+ },
318
+
319
+ actions: [
320
+ 'create',
321
+ 'update',
322
+ 'ingest',
323
+ 'transform',
324
+ 'publish',
325
+ 'unpublish',
326
+ 'deprecate',
327
+ 'archive',
328
+ ],
329
+
330
+ events: [
331
+ 'created',
332
+ 'updated',
333
+ 'ingested',
334
+ 'transformed',
335
+ 'published',
336
+ 'unpublished',
337
+ 'deprecated',
338
+ 'archived',
339
+ ],
340
+ }
341
+
342
+ // =============================================================================
343
+ // Dataset
344
+ // =============================================================================
345
+
346
+ /**
347
+ * Dataset entity
348
+ *
349
+ * Curated data collection.
350
+ */
351
+ export const Dataset: Noun = {
352
+ singular: 'dataset',
353
+ plural: 'datasets',
354
+ description: 'A curated collection of data',
355
+
356
+ properties: {
357
+ // Identity
358
+ name: {
359
+ type: 'string',
360
+ description: 'Dataset name',
361
+ },
362
+ slug: {
363
+ type: 'string',
364
+ optional: true,
365
+ description: 'URL-friendly identifier',
366
+ },
367
+ description: {
368
+ type: 'string',
369
+ optional: true,
370
+ description: 'Dataset description',
371
+ },
372
+
373
+ // Schema
374
+ schema: {
375
+ type: 'json',
376
+ description: 'Dataset schema',
377
+ },
378
+ format: {
379
+ type: 'string',
380
+ description: 'Data format',
381
+ examples: ['json', 'jsonl', 'csv', 'parquet', 'arrow', 'avro'],
382
+ },
383
+
384
+ // Size
385
+ recordCount: {
386
+ type: 'number',
387
+ optional: true,
388
+ description: 'Number of records',
389
+ },
390
+ sizeBytes: {
391
+ type: 'number',
392
+ optional: true,
393
+ description: 'Size in bytes',
394
+ },
395
+ columnCount: {
396
+ type: 'number',
397
+ optional: true,
398
+ description: 'Number of columns/fields',
399
+ },
400
+
401
+ // Source
402
+ source: {
403
+ type: 'string',
404
+ optional: true,
405
+ description: 'Data source',
406
+ },
407
+ sourceUrl: {
408
+ type: 'string',
409
+ optional: true,
410
+ description: 'Source URL',
411
+ },
412
+ collectionMethod: {
413
+ type: 'string',
414
+ optional: true,
415
+ description: 'How data was collected',
416
+ examples: ['scraped', 'api', 'manual', 'generated', 'aggregated'],
417
+ },
418
+
419
+ // Temporal
420
+ startDate: {
421
+ type: 'date',
422
+ optional: true,
423
+ description: 'Data start date',
424
+ },
425
+ endDate: {
426
+ type: 'date',
427
+ optional: true,
428
+ description: 'Data end date',
429
+ },
430
+ updateFrequency: {
431
+ type: 'string',
432
+ optional: true,
433
+ description: 'Update frequency',
434
+ examples: ['static', 'daily', 'weekly', 'monthly', 'realtime'],
435
+ },
436
+
437
+ // License
438
+ license: {
439
+ type: 'string',
440
+ optional: true,
441
+ description: 'Data license',
442
+ examples: ['mit', 'cc-by', 'cc-by-sa', 'cc0', 'proprietary', 'custom'],
443
+ },
444
+ usageRestrictions: {
445
+ type: 'string',
446
+ array: true,
447
+ optional: true,
448
+ description: 'Usage restrictions',
449
+ },
450
+
451
+ // Distribution
452
+ downloadUrl: {
453
+ type: 'string',
454
+ optional: true,
455
+ description: 'Download URL',
456
+ },
457
+ downloadFormats: {
458
+ type: 'string',
459
+ array: true,
460
+ optional: true,
461
+ description: 'Available download formats',
462
+ },
463
+
464
+ // Status
465
+ status: {
466
+ type: 'string',
467
+ description: 'Dataset status',
468
+ examples: ['draft', 'published', 'deprecated', 'archived'],
469
+ },
470
+ version: {
471
+ type: 'string',
472
+ optional: true,
473
+ description: 'Dataset version',
474
+ },
475
+ },
476
+
477
+ relationships: {
478
+ dataProduct: {
479
+ type: 'DataProduct',
480
+ required: false,
481
+ description: 'Parent data product',
482
+ },
483
+ versions: {
484
+ type: 'DatasetVersion[]',
485
+ description: 'Dataset versions',
486
+ },
487
+ },
488
+
489
+ actions: [
490
+ 'create',
491
+ 'update',
492
+ 'addRecords',
493
+ 'removeRecords',
494
+ 'publish',
495
+ 'version',
496
+ 'deprecate',
497
+ 'archive',
498
+ ],
499
+
500
+ events: [
501
+ 'created',
502
+ 'updated',
503
+ 'recordsAdded',
504
+ 'recordsRemoved',
505
+ 'published',
506
+ 'versioned',
507
+ 'deprecated',
508
+ 'archived',
509
+ ],
510
+ }
511
+
512
+ // =============================================================================
513
+ // Documentation
514
+ // =============================================================================
515
+
516
+ /**
517
+ * Documentation entity
518
+ *
519
+ * Technical documentation product.
520
+ */
521
+ export const Documentation: Noun = {
522
+ singular: 'documentation',
523
+ plural: 'documentations',
524
+ description: 'Technical documentation for a product or API',
525
+
526
+ properties: {
527
+ // Identity
528
+ name: {
529
+ type: 'string',
530
+ description: 'Documentation name',
531
+ },
532
+ slug: {
533
+ type: 'string',
534
+ optional: true,
535
+ description: 'URL-friendly identifier',
536
+ },
537
+ description: {
538
+ type: 'string',
539
+ optional: true,
540
+ description: 'Documentation description',
541
+ },
542
+
543
+ // Classification
544
+ type: {
545
+ type: 'string',
546
+ description: 'Documentation type',
547
+ examples: ['api', 'guide', 'reference', 'tutorial', 'howto', 'explanation', 'changelog'],
548
+ },
549
+ audience: {
550
+ type: 'string',
551
+ optional: true,
552
+ description: 'Target audience',
553
+ examples: ['developers', 'users', 'admins', 'everyone'],
554
+ },
555
+
556
+ // Structure
557
+ format: {
558
+ type: 'string',
559
+ description: 'Content format',
560
+ examples: ['markdown', 'mdx', 'rst', 'html', 'openapi'],
561
+ },
562
+ generator: {
563
+ type: 'string',
564
+ optional: true,
565
+ description: 'Documentation generator',
566
+ examples: ['fumadocs', 'docusaurus', 'mintlify', 'readme', 'gitbook', 'custom'],
567
+ },
568
+ sourceDir: {
569
+ type: 'string',
570
+ optional: true,
571
+ description: 'Source content directory',
572
+ },
573
+
574
+ // Hosting
575
+ url: {
576
+ type: 'string',
577
+ optional: true,
578
+ description: 'Documentation URL',
579
+ },
580
+ customDomain: {
581
+ type: 'string',
582
+ optional: true,
583
+ description: 'Custom domain',
584
+ },
585
+
586
+ // Features
587
+ searchEnabled: {
588
+ type: 'boolean',
589
+ optional: true,
590
+ description: 'Search functionality enabled',
591
+ },
592
+ versioned: {
593
+ type: 'boolean',
594
+ optional: true,
595
+ description: 'Multi-version support',
596
+ },
597
+ i18n: {
598
+ type: 'boolean',
599
+ optional: true,
600
+ description: 'Internationalization support',
601
+ },
602
+ languages: {
603
+ type: 'string',
604
+ array: true,
605
+ optional: true,
606
+ description: 'Supported languages',
607
+ },
608
+
609
+ // Metrics
610
+ pageCount: {
611
+ type: 'number',
612
+ optional: true,
613
+ description: 'Number of pages',
614
+ },
615
+ lastUpdatedAt: {
616
+ type: 'date',
617
+ optional: true,
618
+ description: 'Last content update',
619
+ },
620
+
621
+ // Status
622
+ status: {
623
+ type: 'string',
624
+ description: 'Documentation status',
625
+ examples: ['draft', 'published', 'archived'],
626
+ },
627
+ version: {
628
+ type: 'string',
629
+ optional: true,
630
+ description: 'Documentation version',
631
+ },
632
+ },
633
+
634
+ relationships: {
635
+ product: {
636
+ type: 'DigitalProduct',
637
+ required: false,
638
+ description: 'Documented product',
639
+ },
640
+ api: {
641
+ type: 'API',
642
+ required: false,
643
+ description: 'Documented API',
644
+ },
645
+ pages: {
646
+ type: 'DocPage[]',
647
+ description: 'Documentation pages',
648
+ },
649
+ },
650
+
651
+ actions: [
652
+ 'create',
653
+ 'update',
654
+ 'addPage',
655
+ 'removePage',
656
+ 'publish',
657
+ 'version',
658
+ 'archive',
659
+ ],
660
+
661
+ events: [
662
+ 'created',
663
+ 'updated',
664
+ 'pageAdded',
665
+ 'pageRemoved',
666
+ 'published',
667
+ 'versioned',
668
+ 'archived',
669
+ ],
670
+ }
671
+
672
+ // =============================================================================
673
+ // Template
674
+ // =============================================================================
675
+
676
+ /**
677
+ * Template entity
678
+ *
679
+ * Reusable template or starter.
680
+ */
681
+ export const Template: Noun = {
682
+ singular: 'template',
683
+ plural: 'templates',
684
+ description: 'A reusable template or starter project',
685
+
686
+ properties: {
687
+ // Identity
688
+ name: {
689
+ type: 'string',
690
+ description: 'Template name',
691
+ },
692
+ slug: {
693
+ type: 'string',
694
+ optional: true,
695
+ description: 'URL-friendly identifier',
696
+ },
697
+ description: {
698
+ type: 'string',
699
+ optional: true,
700
+ description: 'Template description',
701
+ },
702
+
703
+ // Classification
704
+ type: {
705
+ type: 'string',
706
+ description: 'Template type',
707
+ examples: ['starter', 'boilerplate', 'scaffold', 'example', 'demo'],
708
+ },
709
+ category: {
710
+ type: 'string',
711
+ optional: true,
712
+ description: 'Template category',
713
+ },
714
+ tags: {
715
+ type: 'string',
716
+ array: true,
717
+ optional: true,
718
+ description: 'Template tags',
719
+ },
720
+
721
+ // Technology
722
+ framework: {
723
+ type: 'string',
724
+ optional: true,
725
+ description: 'Primary framework',
726
+ },
727
+ language: {
728
+ type: 'string',
729
+ optional: true,
730
+ description: 'Primary language',
731
+ },
732
+ stack: {
733
+ type: 'string',
734
+ array: true,
735
+ optional: true,
736
+ description: 'Technology stack',
737
+ },
738
+
739
+ // Source
740
+ repositoryUrl: {
741
+ type: 'string',
742
+ optional: true,
743
+ description: 'Source repository URL',
744
+ },
745
+ branch: {
746
+ type: 'string',
747
+ optional: true,
748
+ description: 'Git branch',
749
+ },
750
+
751
+ // Installation
752
+ installCommand: {
753
+ type: 'string',
754
+ optional: true,
755
+ description: 'Installation command',
756
+ },
757
+ scaffoldTool: {
758
+ type: 'string',
759
+ optional: true,
760
+ description: 'Scaffolding tool',
761
+ examples: ['create-next-app', 'degit', 'tiged', 'custom'],
762
+ },
763
+
764
+ // Configuration
765
+ configurable: {
766
+ type: 'boolean',
767
+ optional: true,
768
+ description: 'Has configuration options',
769
+ },
770
+ configSchema: {
771
+ type: 'json',
772
+ optional: true,
773
+ description: 'Configuration schema',
774
+ },
775
+
776
+ // Metrics
777
+ useCount: {
778
+ type: 'number',
779
+ optional: true,
780
+ description: 'Number of uses/clones',
781
+ },
782
+ starCount: {
783
+ type: 'number',
784
+ optional: true,
785
+ description: 'GitHub stars',
786
+ },
787
+
788
+ // Status
789
+ status: {
790
+ type: 'string',
791
+ description: 'Template status',
792
+ examples: ['draft', 'published', 'deprecated', 'archived'],
793
+ },
794
+ version: {
795
+ type: 'string',
796
+ optional: true,
797
+ description: 'Template version',
798
+ },
799
+ },
800
+
801
+ relationships: {
802
+ product: {
803
+ type: 'DigitalProduct',
804
+ required: false,
805
+ description: 'Parent product',
806
+ },
807
+ examples: {
808
+ type: 'Example[]',
809
+ description: 'Usage examples',
810
+ },
811
+ },
812
+
813
+ actions: [
814
+ 'create',
815
+ 'update',
816
+ 'publish',
817
+ 'clone',
818
+ 'fork',
819
+ 'deprecate',
820
+ 'archive',
821
+ ],
822
+
823
+ events: [
824
+ 'created',
825
+ 'updated',
826
+ 'published',
827
+ 'cloned',
828
+ 'forked',
829
+ 'deprecated',
830
+ 'archived',
831
+ ],
832
+ }
833
+
834
+ // =============================================================================
835
+ // Exports
836
+ // =============================================================================
837
+
838
+ export const ContentEntities = {
839
+ ContentProduct,
840
+ DataProduct,
841
+ Dataset,
842
+ Documentation,
843
+ Template,
844
+ }
845
+
846
+ export const ContentCategories = {
847
+ content: ['ContentProduct'],
848
+ data: ['DataProduct', 'Dataset'],
849
+ docs: ['Documentation'],
850
+ templates: ['Template'],
851
+ } as const