@dotit/core 1.0.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 (59) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +229 -0
  3. package/dist/aliases.d.ts +1 -0
  4. package/dist/aliases.js +8 -0
  5. package/dist/ask.d.ts +7 -0
  6. package/dist/ask.js +55 -0
  7. package/dist/browser.d.ts +12 -0
  8. package/dist/browser.js +32 -0
  9. package/dist/diff.d.ts +17 -0
  10. package/dist/diff.js +179 -0
  11. package/dist/document-css.d.ts +1 -0
  12. package/dist/document-css.js +290 -0
  13. package/dist/executor.d.ts +40 -0
  14. package/dist/executor.js +501 -0
  15. package/dist/history.d.ts +10 -0
  16. package/dist/history.js +297 -0
  17. package/dist/html-to-it.d.ts +1 -0
  18. package/dist/html-to-it.js +288 -0
  19. package/dist/index-builder.d.ts +62 -0
  20. package/dist/index-builder.js +228 -0
  21. package/dist/index.d.ts +39 -0
  22. package/dist/index.js +94 -0
  23. package/dist/language-registry.d.ts +39 -0
  24. package/dist/language-registry.js +530 -0
  25. package/dist/markdown.d.ts +1 -0
  26. package/dist/markdown.js +123 -0
  27. package/dist/merge.d.ts +6 -0
  28. package/dist/merge.js +255 -0
  29. package/dist/parser.d.ts +29 -0
  30. package/dist/parser.js +1562 -0
  31. package/dist/query.d.ts +32 -0
  32. package/dist/query.js +293 -0
  33. package/dist/renderer.d.ts +16 -0
  34. package/dist/renderer.js +1286 -0
  35. package/dist/schema.d.ts +47 -0
  36. package/dist/schema.js +574 -0
  37. package/dist/source.d.ts +3 -0
  38. package/dist/source.js +223 -0
  39. package/dist/theme.d.ts +49 -0
  40. package/dist/theme.js +113 -0
  41. package/dist/themes/corporate.json +86 -0
  42. package/dist/themes/dark.json +64 -0
  43. package/dist/themes/editorial.json +54 -0
  44. package/dist/themes/legal.json +57 -0
  45. package/dist/themes/minimal.json +50 -0
  46. package/dist/themes/print.json +54 -0
  47. package/dist/themes/technical.json +59 -0
  48. package/dist/themes/warm.json +53 -0
  49. package/dist/trust.d.ts +66 -0
  50. package/dist/trust.js +200 -0
  51. package/dist/types.d.ts +234 -0
  52. package/dist/types.js +19 -0
  53. package/dist/utils.d.ts +2 -0
  54. package/dist/utils.js +13 -0
  55. package/dist/validate.d.ts +13 -0
  56. package/dist/validate.js +711 -0
  57. package/dist/workflow.d.ts +18 -0
  58. package/dist/workflow.js +160 -0
  59. package/package.json +51 -0
@@ -0,0 +1,47 @@
1
+ import { IntentDocument, BlockType } from "./types";
2
+ export interface PropertySchema {
3
+ type: "string" | "number" | "boolean" | "date" | "enum" | "url" | "email";
4
+ required?: boolean;
5
+ default?: string | number | boolean;
6
+ enumValues?: string[];
7
+ pattern?: string;
8
+ min?: number;
9
+ max?: number;
10
+ format?: "iso-date" | "iso-datetime" | "time" | "url" | "email";
11
+ }
12
+ export interface BlockSchema {
13
+ type: BlockType;
14
+ content?: {
15
+ required?: boolean;
16
+ minLength?: number;
17
+ maxLength?: number;
18
+ pattern?: string;
19
+ };
20
+ properties?: Record<string, PropertySchema>;
21
+ allowUnknownProperties?: boolean;
22
+ }
23
+ export interface DocumentSchema {
24
+ name: string;
25
+ description?: string;
26
+ requiredBlocks?: BlockType[];
27
+ blockSchemas?: Record<string, BlockSchema>;
28
+ allowUnknownBlocks?: boolean;
29
+ }
30
+ export interface ValidationError {
31
+ blockId: string;
32
+ blockType: string;
33
+ field: string;
34
+ message: string;
35
+ severity: "error" | "warning";
36
+ }
37
+ export interface ValidationResult {
38
+ valid: boolean;
39
+ errors: ValidationError[];
40
+ warnings: ValidationError[];
41
+ }
42
+ export declare const PREDEFINED_SCHEMAS: Record<string, DocumentSchema>;
43
+ export declare function validateDocument(document: IntentDocument, schema: DocumentSchema | string): ValidationResult;
44
+ export declare function createSchema(config: Omit<DocumentSchema, "name"> & {
45
+ name: string;
46
+ }): DocumentSchema;
47
+ export declare function formatValidationResult(result: ValidationResult): string;
package/dist/schema.js ADDED
@@ -0,0 +1,574 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PREDEFINED_SCHEMAS = void 0;
4
+ exports.validateDocument = validateDocument;
5
+ exports.createSchema = createSchema;
6
+ exports.formatValidationResult = formatValidationResult;
7
+ const utils_1 = require("./utils");
8
+ exports.PREDEFINED_SCHEMAS = {
9
+ project: {
10
+ name: "project",
11
+ description: "Project planning document",
12
+ requiredBlocks: ["title"],
13
+ blockSchemas: {
14
+ task: {
15
+ type: "task",
16
+ properties: {
17
+ owner: { type: "string" },
18
+ due: { type: "date", format: "iso-date" },
19
+ priority: { type: "enum", enumValues: ["low", "medium", "high"] },
20
+ },
21
+ allowUnknownProperties: true,
22
+ },
23
+ done: {
24
+ type: "done",
25
+ properties: {
26
+ time: { type: "string", format: "time" },
27
+ },
28
+ },
29
+ },
30
+ allowUnknownBlocks: true,
31
+ },
32
+ meeting: {
33
+ name: "meeting",
34
+ description: "Meeting notes document",
35
+ requiredBlocks: ["title", "section"],
36
+ blockSchemas: {
37
+ note: {
38
+ type: "text",
39
+ content: { required: true },
40
+ },
41
+ ask: {
42
+ type: "ask",
43
+ content: { required: true },
44
+ },
45
+ task: {
46
+ type: "task",
47
+ properties: {
48
+ owner: { type: "string", required: true },
49
+ due: { type: "date", format: "iso-date", required: true },
50
+ },
51
+ },
52
+ },
53
+ allowUnknownBlocks: true,
54
+ },
55
+ article: {
56
+ name: "article",
57
+ description: "Blog post or article",
58
+ requiredBlocks: ["title", "summary"],
59
+ blockSchemas: {
60
+ image: {
61
+ type: "image",
62
+ properties: {
63
+ src: { type: "url", required: true },
64
+ at: { type: "url" },
65
+ caption: { type: "string" },
66
+ },
67
+ allowUnknownProperties: true,
68
+ },
69
+ link: {
70
+ type: "link",
71
+ content: { required: true, minLength: 1 },
72
+ properties: {
73
+ to: { type: "url", required: true },
74
+ },
75
+ },
76
+ section: {
77
+ type: "section",
78
+ content: { required: true, minLength: 1 },
79
+ },
80
+ },
81
+ allowUnknownBlocks: false,
82
+ },
83
+ checklist: {
84
+ name: "checklist",
85
+ description: "Simple task checklist",
86
+ requiredBlocks: ["title"],
87
+ blockSchemas: {
88
+ task: {
89
+ type: "task",
90
+ content: { required: true },
91
+ },
92
+ done: {
93
+ type: "done",
94
+ content: { required: true },
95
+ },
96
+ },
97
+ allowUnknownBlocks: false,
98
+ },
99
+ agentic: {
100
+ name: "agentic",
101
+ description: "Agentic workflow document (v2.0+)",
102
+ requiredBlocks: ["title"],
103
+ blockSchemas: {
104
+ step: {
105
+ type: "step",
106
+ content: { required: true },
107
+ properties: {
108
+ tool: { type: "string" },
109
+ status: {
110
+ type: "enum",
111
+ enumValues: [
112
+ "pending",
113
+ "running",
114
+ "blocked",
115
+ "failed",
116
+ "skipped",
117
+ "cancelled",
118
+ "done",
119
+ ],
120
+ },
121
+ id: { type: "string" },
122
+ depends: { type: "string" },
123
+ timeout: { type: "number" },
124
+ priority: { type: "number" },
125
+ retries: { type: "number" },
126
+ },
127
+ allowUnknownProperties: true,
128
+ },
129
+ decision: {
130
+ type: "decision",
131
+ content: { required: true },
132
+ properties: {
133
+ if: { type: "string" },
134
+ then: { type: "string" },
135
+ else: { type: "string" },
136
+ },
137
+ allowUnknownProperties: true,
138
+ },
139
+ trigger: {
140
+ type: "trigger",
141
+ content: { required: true },
142
+ properties: {
143
+ event: { type: "string" },
144
+ },
145
+ allowUnknownProperties: true,
146
+ },
147
+ loop: {
148
+ type: "loop",
149
+ content: { required: true },
150
+ properties: {
151
+ over: { type: "string" },
152
+ do: { type: "string" },
153
+ },
154
+ allowUnknownProperties: true,
155
+ },
156
+ retry: {
157
+ type: "retry",
158
+ content: { required: true },
159
+ properties: {
160
+ max: { type: "number" },
161
+ delay: { type: "number" },
162
+ backoff: {
163
+ type: "enum",
164
+ enumValues: ["linear", "exponential", "fixed"],
165
+ },
166
+ },
167
+ allowUnknownProperties: true,
168
+ },
169
+ wait: {
170
+ type: "wait",
171
+ content: { required: true },
172
+ properties: {
173
+ timeout: { type: "string" },
174
+ fallback: { type: "string" },
175
+ },
176
+ allowUnknownProperties: true,
177
+ },
178
+ parallel: {
179
+ type: "parallel",
180
+ content: { required: true },
181
+ properties: {
182
+ steps: { type: "string" },
183
+ timeout: { type: "number" },
184
+ },
185
+ allowUnknownProperties: true,
186
+ },
187
+ handoff: {
188
+ type: "handoff",
189
+ content: { required: true },
190
+ properties: {
191
+ from: { type: "string" },
192
+ to: { type: "string" },
193
+ },
194
+ allowUnknownProperties: true,
195
+ },
196
+ result: {
197
+ type: "result",
198
+ content: { required: true },
199
+ properties: {
200
+ status: {
201
+ type: "enum",
202
+ enumValues: ["success", "error", "failure"],
203
+ },
204
+ code: { type: "string" },
205
+ data: { type: "string" },
206
+ },
207
+ allowUnknownProperties: true,
208
+ },
209
+ emit: {
210
+ type: "signal",
211
+ content: { required: true },
212
+ properties: {
213
+ phase: { type: "string" },
214
+ level: { type: "string" },
215
+ updated: { type: "string" },
216
+ },
217
+ allowUnknownProperties: true,
218
+ },
219
+ },
220
+ allowUnknownBlocks: true,
221
+ },
222
+ };
223
+ function validateProperty(value, schema, fieldName) {
224
+ const errors = [];
225
+ const strValue = String(value);
226
+ if (schema.required &&
227
+ (value === undefined || value === null || value === "")) {
228
+ errors.push({
229
+ blockId: "",
230
+ blockType: "",
231
+ field: fieldName,
232
+ message: `Property "${fieldName}" is required`,
233
+ severity: "error",
234
+ });
235
+ return errors;
236
+ }
237
+ if (value === undefined || value === null || value === "") {
238
+ return errors;
239
+ }
240
+ switch (schema.type) {
241
+ case "number":
242
+ if (isNaN(Number(value))) {
243
+ errors.push({
244
+ blockId: "",
245
+ blockType: "",
246
+ field: fieldName,
247
+ message: `Property "${fieldName}" must be a number`,
248
+ severity: "error",
249
+ });
250
+ }
251
+ else {
252
+ const num = Number(value);
253
+ if (schema.min !== undefined && num < schema.min) {
254
+ errors.push({
255
+ blockId: "",
256
+ blockType: "",
257
+ field: fieldName,
258
+ message: `Property "${fieldName}" must be >= ${schema.min}`,
259
+ severity: "error",
260
+ });
261
+ }
262
+ if (schema.max !== undefined && num > schema.max) {
263
+ errors.push({
264
+ blockId: "",
265
+ blockType: "",
266
+ field: fieldName,
267
+ message: `Property "${fieldName}" must be <= ${schema.max}`,
268
+ severity: "error",
269
+ });
270
+ }
271
+ }
272
+ break;
273
+ case "date":
274
+ const date = new Date(strValue);
275
+ if (isNaN(date.getTime())) {
276
+ const isoDateRegex = /^\d{4}-\d{2}-\d{2}$/;
277
+ if (schema.format === "iso-date" && !isoDateRegex.test(strValue)) {
278
+ errors.push({
279
+ blockId: "",
280
+ blockType: "",
281
+ field: fieldName,
282
+ message: `Property "${fieldName}" must be in ISO date format (YYYY-MM-DD)`,
283
+ severity: "error",
284
+ });
285
+ }
286
+ else if (!isoDateRegex.test(strValue) && !strValue.includes("T")) {
287
+ errors.push({
288
+ blockId: "",
289
+ blockType: "",
290
+ field: fieldName,
291
+ message: `Property "${fieldName}" must be a valid date`,
292
+ severity: "error",
293
+ });
294
+ }
295
+ }
296
+ break;
297
+ case "enum":
298
+ if (schema.enumValues && !schema.enumValues.includes(strValue)) {
299
+ errors.push({
300
+ blockId: "",
301
+ blockType: "",
302
+ field: fieldName,
303
+ message: `Property "${fieldName}" must be one of: ${schema.enumValues.join(", ")}`,
304
+ severity: "error",
305
+ });
306
+ }
307
+ break;
308
+ case "url":
309
+ try {
310
+ new URL(strValue);
311
+ }
312
+ catch {
313
+ if (!strValue.startsWith("/") && !strValue.startsWith("./")) {
314
+ errors.push({
315
+ blockId: "",
316
+ blockType: "",
317
+ field: fieldName,
318
+ message: `Property "${fieldName}" must be a valid URL`,
319
+ severity: "error",
320
+ });
321
+ }
322
+ }
323
+ break;
324
+ case "email":
325
+ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
326
+ if (!emailRegex.test(strValue)) {
327
+ errors.push({
328
+ blockId: "",
329
+ blockType: "",
330
+ field: fieldName,
331
+ message: `Property "${fieldName}" must be a valid email address`,
332
+ severity: "error",
333
+ });
334
+ }
335
+ break;
336
+ case "string":
337
+ if (schema.pattern) {
338
+ let regex;
339
+ try {
340
+ regex = new RegExp(schema.pattern);
341
+ }
342
+ catch {
343
+ break;
344
+ }
345
+ if (!regex.test(strValue)) {
346
+ errors.push({
347
+ blockId: "",
348
+ blockType: "",
349
+ field: fieldName,
350
+ message: `Property "${fieldName}" does not match required pattern`,
351
+ severity: "error",
352
+ });
353
+ }
354
+ }
355
+ break;
356
+ }
357
+ if (schema.format) {
358
+ switch (schema.format) {
359
+ case "iso-date":
360
+ if (!/^\d{4}-\d{2}-\d{2}$/.test(strValue)) {
361
+ errors.push({
362
+ blockId: "",
363
+ blockType: "",
364
+ field: fieldName,
365
+ message: `Property "${fieldName}" must be ISO date (YYYY-MM-DD)`,
366
+ severity: "error",
367
+ });
368
+ }
369
+ break;
370
+ case "time":
371
+ if (!/^\d{1,2}:\d{2}(?::\d{2})?\s*(?:AM|PM)?$/i.test(strValue)) {
372
+ errors.push({
373
+ blockId: "",
374
+ blockType: "",
375
+ field: fieldName,
376
+ message: `Property "${fieldName}" must be a valid time`,
377
+ severity: "warning",
378
+ });
379
+ }
380
+ break;
381
+ }
382
+ }
383
+ return errors;
384
+ }
385
+ function validateBlock(block, schema, documentSchema) {
386
+ const errors = [];
387
+ if (schema.content) {
388
+ if (schema.content.required && (!block.content || block.content === "")) {
389
+ errors.push({
390
+ blockId: block.id,
391
+ blockType: block.type,
392
+ field: "content",
393
+ message: `Block "${block.type}" requires content`,
394
+ severity: "error",
395
+ });
396
+ }
397
+ if (block.content) {
398
+ if (schema.content.minLength !== undefined &&
399
+ block.content.length < schema.content.minLength) {
400
+ errors.push({
401
+ blockId: block.id,
402
+ blockType: block.type,
403
+ field: "content",
404
+ message: `Content must be at least ${schema.content.minLength} characters`,
405
+ severity: "error",
406
+ });
407
+ }
408
+ if (schema.content.maxLength !== undefined &&
409
+ block.content.length > schema.content.maxLength) {
410
+ errors.push({
411
+ blockId: block.id,
412
+ blockType: block.type,
413
+ field: "content",
414
+ message: `Content must be at most ${schema.content.maxLength} characters`,
415
+ severity: "error",
416
+ });
417
+ }
418
+ if (schema.content.pattern) {
419
+ const regex = new RegExp(schema.content.pattern);
420
+ if (!regex.test(block.content)) {
421
+ errors.push({
422
+ blockId: block.id,
423
+ blockType: block.type,
424
+ field: "content",
425
+ message: `Content does not match required pattern`,
426
+ severity: "error",
427
+ });
428
+ }
429
+ }
430
+ }
431
+ }
432
+ if (schema.properties) {
433
+ for (const [propName, propSchema] of Object.entries(schema.properties)) {
434
+ const value = block.properties?.[propName];
435
+ const propErrors = validateProperty(value, propSchema, propName);
436
+ errors.push(...propErrors.map((e) => ({
437
+ ...e,
438
+ blockId: block.id,
439
+ blockType: block.type,
440
+ })));
441
+ }
442
+ if (schema.allowUnknownProperties === false && block.properties) {
443
+ const knownProps = Object.keys(schema.properties);
444
+ for (const propName of Object.keys(block.properties)) {
445
+ if (!knownProps.includes(propName)) {
446
+ errors.push({
447
+ blockId: block.id,
448
+ blockType: block.type,
449
+ field: propName,
450
+ message: `Unknown property "${propName}" for block type "${block.type}"`,
451
+ severity: "warning",
452
+ });
453
+ }
454
+ }
455
+ }
456
+ }
457
+ return errors;
458
+ }
459
+ function validateDocument(document, schema) {
460
+ if (!document || !document.blocks) {
461
+ return {
462
+ valid: false,
463
+ errors: [
464
+ {
465
+ blockId: "",
466
+ blockType: "",
467
+ field: "document",
468
+ message: "Invalid document",
469
+ severity: "error",
470
+ },
471
+ ],
472
+ warnings: [],
473
+ };
474
+ }
475
+ const docSchema = typeof schema === "string" ? exports.PREDEFINED_SCHEMAS[schema] : schema;
476
+ if (!docSchema) {
477
+ return {
478
+ valid: false,
479
+ errors: [
480
+ {
481
+ blockId: "",
482
+ blockType: "",
483
+ field: "schema",
484
+ message: `Unknown schema "${schema}"`,
485
+ severity: "error",
486
+ },
487
+ ],
488
+ warnings: [],
489
+ };
490
+ }
491
+ const allBlocks = (0, utils_1.flattenBlocks)(document.blocks);
492
+ const errors = [];
493
+ const warnings = [];
494
+ if (docSchema.requiredBlocks) {
495
+ const presentTypes = new Set(allBlocks.map((b) => b.type));
496
+ for (const required of docSchema.requiredBlocks) {
497
+ if (!presentTypes.has(required)) {
498
+ errors.push({
499
+ blockId: "",
500
+ blockType: "",
501
+ field: "blocks",
502
+ message: `Document requires at least one "${required}" block`,
503
+ severity: "error",
504
+ });
505
+ }
506
+ }
507
+ }
508
+ if (docSchema.allowUnknownBlocks === false) {
509
+ const allowedTypes = new Set(Object.keys(docSchema.blockSchemas || {}));
510
+ allowedTypes.add("title");
511
+ allowedTypes.add("summary");
512
+ allowedTypes.add("section");
513
+ allowedTypes.add("sub");
514
+ allowedTypes.add("divider");
515
+ for (const block of allBlocks) {
516
+ if (!allowedTypes.has(block.type)) {
517
+ errors.push({
518
+ blockId: block.id,
519
+ blockType: block.type,
520
+ field: "type",
521
+ message: `Block type "${block.type}" is not allowed in "${docSchema.name}" documents`,
522
+ severity: "error",
523
+ });
524
+ }
525
+ }
526
+ }
527
+ if (docSchema.blockSchemas) {
528
+ for (const block of allBlocks) {
529
+ const blockSchema = docSchema.blockSchemas[block.type];
530
+ if (blockSchema) {
531
+ const blockErrors = validateBlock(block, blockSchema, docSchema);
532
+ for (const e of blockErrors) {
533
+ if (e.severity === "error")
534
+ errors.push(e);
535
+ else
536
+ warnings.push(e);
537
+ }
538
+ }
539
+ }
540
+ }
541
+ return {
542
+ valid: errors.length === 0,
543
+ errors,
544
+ warnings,
545
+ };
546
+ }
547
+ function createSchema(config) {
548
+ return {
549
+ allowUnknownBlocks: true,
550
+ ...config,
551
+ };
552
+ }
553
+ function formatValidationResult(result) {
554
+ if (result.valid && result.warnings.length === 0) {
555
+ return "✓ Document is valid";
556
+ }
557
+ const lines = [];
558
+ if (!result.valid) {
559
+ lines.push(`✗ Validation failed with ${result.errors.length} error(s):`);
560
+ for (const e of result.errors) {
561
+ lines.push(` [${e.severity.toUpperCase()}] ${e.blockType || "document"}: ${e.message}`);
562
+ }
563
+ }
564
+ if (result.warnings.length > 0) {
565
+ lines.push(`⚠ ${result.warnings.length} warning(s):`);
566
+ for (const w of result.warnings) {
567
+ lines.push(` [WARN] ${w.blockType}: ${w.message}`);
568
+ }
569
+ }
570
+ if (result.valid && result.warnings.length === 0) {
571
+ lines.push("✓ Document is valid");
572
+ }
573
+ return lines.join("\n");
574
+ }
@@ -0,0 +1,3 @@
1
+ import { IntentDocument, IntentBlock } from "./types";
2
+ export declare function documentToSource(doc: IntentDocument): string;
3
+ export declare function blockToSource(block: IntentBlock): string;