@the-package-labs/idocs-core 0.4.0 → 0.6.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.
@@ -0,0 +1,40 @@
1
+ export type PlaceholderSegment = {
2
+ kind: 'text';
3
+ text: string;
4
+ } | {
5
+ kind: 'var';
6
+ /** As written, braces or angle brackets included: `{yourname}`. */
7
+ raw: string;
8
+ /** As written, without them: `yourname`. */
9
+ name: string;
10
+ /** What `{Token}`, `<token>` and `<TOKEN>` share, so one value fills them all. */
11
+ key: string;
12
+ };
13
+ export interface Placeholder {
14
+ key: string;
15
+ /** The first spelling in the text. */
16
+ name: string;
17
+ raw: string;
18
+ /** A token or a password: kept in memory, never stored, masked on the page. */
19
+ secret: boolean;
20
+ }
21
+ export declare function varKey(name: string): string;
22
+ export declare function isSecretKey(key: string): boolean;
23
+ export declare function splitPlaceholders(text: string): PlaceholderSegment[];
24
+ /** Each distinct placeholder once, in the order the text first uses it. */
25
+ export declare function placeholdersOf(segments: PlaceholderSegment[]): Placeholder[];
26
+ /** The text to copy: values where the reader set them, the placeholder as written where not. */
27
+ export declare function fillSegments(segments: PlaceholderSegment[], values: Record<string, string>): string;
28
+ export declare function fillPlaceholders(text: string, values: Record<string, string>): string;
29
+ /** Placeholders in `segments` the reader has not set. */
30
+ export declare function unsetPlaceholders(segments: PlaceholderSegment[], values: Record<string, string>): Placeholder[];
31
+ export interface Shown {
32
+ text: string;
33
+ state: 'unset' | 'set' | 'secret';
34
+ }
35
+ /** What the page shows in place of a placeholder: the value, a mask for a secret, or the placeholder. */
36
+ export declare function shownPlaceholder(segment: Extract<PlaceholderSegment, {
37
+ kind: 'var';
38
+ }>, values: Record<string, string>): Shown;
39
+ /** Whether a code block takes placeholders: by language, and `vars` / `novars` in the fence info decide otherwise. */
40
+ export declare function takesPlaceholders(lang: string | undefined, meta: string | undefined): boolean;
package/dist/schema.d.ts CHANGED
@@ -28,10 +28,24 @@ export declare const DirectionSchema: z.ZodEnum<{
28
28
  RIGHT: "RIGHT";
29
29
  UP: "UP";
30
30
  }>;
31
+ /** One field per list item: `- name`, `- name: type` or `- name: { type, key, ref, note }`. */
32
+ declare const FieldSchema: z.ZodUnion<readonly [z.ZodString, z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNull, z.ZodObject<{
33
+ type: z.ZodOptional<z.ZodString>;
34
+ key: z.ZodOptional<z.ZodBoolean>;
35
+ ref: z.ZodOptional<z.ZodString>;
36
+ note: z.ZodOptional<z.ZodString>;
37
+ }, z.core.$strict>]>>]>;
31
38
  export declare const NodeSchema: z.ZodObject<{
32
39
  title: z.ZodOptional<z.ZodString>;
33
40
  sub: z.ZodOptional<z.ZodString>;
41
+ pill: z.ZodOptional<z.ZodString>;
34
42
  lines: z.ZodOptional<z.ZodArray<z.ZodString>>;
43
+ fields: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNull, z.ZodObject<{
44
+ type: z.ZodOptional<z.ZodString>;
45
+ key: z.ZodOptional<z.ZodBoolean>;
46
+ ref: z.ZodOptional<z.ZodString>;
47
+ note: z.ZodOptional<z.ZodString>;
48
+ }, z.core.$strict>]>>]>>>;
35
49
  icon: z.ZodOptional<z.ZodString>;
36
50
  kind: z.ZodOptional<z.ZodString>;
37
51
  family: z.ZodOptional<z.ZodEnum<{
@@ -440,10 +454,34 @@ export declare const ScenarioSchema: z.ZodObject<{
440
454
  }, z.core.$strict>], "type">>;
441
455
  }, z.core.$strict>], "type">>>;
442
456
  }, z.core.$strict>;
457
+ export declare const DefaultsSchema: z.ZodObject<{
458
+ view: z.ZodOptional<z.ZodString>;
459
+ scenario: z.ZodOptional<z.ZodString>;
460
+ mode: z.ZodOptional<z.ZodEnum<{
461
+ flow: "flow";
462
+ sequence: "sequence";
463
+ story: "story";
464
+ }>>;
465
+ sidebar: z.ZodOptional<z.ZodBoolean>;
466
+ subtitles: z.ZodOptional<z.ZodBoolean>;
467
+ autoplay: z.ZodOptional<z.ZodBoolean>;
468
+ }, z.core.$strict>;
443
469
  export declare const RootSchema: z.ZodObject<{
444
470
  $schema: z.ZodOptional<z.ZodString>;
445
471
  title: z.ZodString;
446
472
  description: z.ZodOptional<z.ZodString>;
473
+ defaults: z.ZodOptional<z.ZodObject<{
474
+ view: z.ZodOptional<z.ZodString>;
475
+ scenario: z.ZodOptional<z.ZodString>;
476
+ mode: z.ZodOptional<z.ZodEnum<{
477
+ flow: "flow";
478
+ sequence: "sequence";
479
+ story: "story";
480
+ }>>;
481
+ sidebar: z.ZodOptional<z.ZodBoolean>;
482
+ subtitles: z.ZodOptional<z.ZodBoolean>;
483
+ autoplay: z.ZodOptional<z.ZodBoolean>;
484
+ }, z.core.$strict>>;
447
485
  kinds: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
448
486
  icon: z.ZodOptional<z.ZodString>;
449
487
  family: z.ZodOptional<z.ZodEnum<{
@@ -498,7 +536,14 @@ export declare const RootSchema: z.ZodObject<{
498
536
  nodes: z.ZodRecord<z.ZodString, z.ZodObject<{
499
537
  title: z.ZodOptional<z.ZodString>;
500
538
  sub: z.ZodOptional<z.ZodString>;
539
+ pill: z.ZodOptional<z.ZodString>;
501
540
  lines: z.ZodOptional<z.ZodArray<z.ZodString>>;
541
+ fields: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNull, z.ZodObject<{
542
+ type: z.ZodOptional<z.ZodString>;
543
+ key: z.ZodOptional<z.ZodBoolean>;
544
+ ref: z.ZodOptional<z.ZodString>;
545
+ note: z.ZodOptional<z.ZodString>;
546
+ }, z.core.$strict>]>>]>>>;
502
547
  icon: z.ZodOptional<z.ZodString>;
503
548
  kind: z.ZodOptional<z.ZodString>;
504
549
  family: z.ZodOptional<z.ZodEnum<{
@@ -784,6 +829,7 @@ export declare const RootSchema: z.ZodObject<{
784
829
  }, z.core.$strict>>>;
785
830
  }, z.core.$strict>;
786
831
  export type RootInput = z.infer<typeof RootSchema>;
832
+ export type FieldInput = z.infer<typeof FieldSchema>;
787
833
  export type Step = z.infer<typeof StepSchema>;
788
834
  export declare const KNOWN_KEYS: {
789
835
  readonly root: string[];
@@ -792,6 +838,7 @@ export declare const KNOWN_KEYS: {
792
838
  readonly edge: string[];
793
839
  readonly view: string[];
794
840
  readonly scenario: string[];
841
+ readonly defaults: string[];
795
842
  };
796
843
  type Json = Record<string, unknown>;
797
844
  /**
@@ -0,0 +1,34 @@
1
+ import type { Timeline } from './timeline';
2
+ /** One stop of the slider: a step, or the steps of a `par` block that start together. */
3
+ export interface Slot {
4
+ /** First and last step of the slot, as indexes into `scenario.steps`. */
5
+ from: number;
6
+ to: number;
7
+ /** The time it covers. A slot runs until the next one starts, so pauses belong to the step before. */
8
+ t0: number;
9
+ t1: number;
10
+ }
11
+ /** A run of slots under one phase. A scenario without named phases is one section with no title. */
12
+ export interface Section {
13
+ /** Index in `scenario.phases`. */
14
+ phase: number;
15
+ title: string;
16
+ caption?: string;
17
+ /** First and last slot. */
18
+ from: number;
19
+ to: number;
20
+ }
21
+ export interface Scrubber {
22
+ slots: Slot[];
23
+ sections: Section[];
24
+ duration: number;
25
+ }
26
+ export declare function buildScrubber(tl: Timeline): Scrubber;
27
+ /** Where on the slider, 0 to 1, the moment `t` falls. */
28
+ export declare function positionAt(s: Scrubber, t: number): number;
29
+ /** The moment a place on the slider stands for. The inverse of `positionAt`. */
30
+ export declare function timeAt(s: Scrubber, position: number): number;
31
+ /** The slot a place on the slider falls in. */
32
+ export declare function slotAt(s: Scrubber, position: number): number;
33
+ /** The slot that holds step `index`, or -1. */
34
+ export declare function slotOfStep(s: Scrubber, index: number): number;
@@ -0,0 +1,22 @@
1
+ import type { CompiledDiagram, ScenarioMode } from './types';
2
+ /** What the page that shows a diagram asked for, if anything. Its choices win over the diagram's. */
3
+ export interface StartWant {
4
+ view?: string;
5
+ scenario?: string;
6
+ mode?: ScenarioMode;
7
+ }
8
+ export interface Start {
9
+ /** Always one of the diagram's views. */
10
+ view: string;
11
+ /** The scenario selected first, or null for the overview. */
12
+ scenario: string | null;
13
+ mode: ScenarioMode;
14
+ }
15
+ /** The mode a scenario is drawn in when neither it nor the page says: the diagram's, then `flow`. */
16
+ export declare const defaultMode: (diagram: CompiledDiagram) => ScenarioMode;
17
+ /**
18
+ * Where a diagram opens. The page's props come first, then what the diagram's author wrote under
19
+ * `defaults`, then the first view with nothing selected. The page choosing a scenario takes its
20
+ * view along, and one choosing a view leaves the default scenario out unless it plays there.
21
+ */
22
+ export declare function startOf(diagram: CompiledDiagram, want?: StartWant): Start;
package/dist/types.d.ts CHANGED
@@ -29,11 +29,27 @@ export interface NodeDiagram {
29
29
  /** Starts shown in place. */
30
30
  expanded?: boolean;
31
31
  }
32
+ /** A row of an entity card: one column, property or attribute of what the node stores. */
33
+ export interface CompiledField {
34
+ name: string;
35
+ type?: string;
36
+ /** Part of the primary key. */
37
+ key?: boolean;
38
+ /** The node (and field) this one points at, like a foreign key. Each one draws a relation. */
39
+ ref?: {
40
+ node: string;
41
+ field?: string;
42
+ };
43
+ note?: string;
44
+ }
32
45
  export interface CompiledNode {
33
46
  id: string;
34
47
  title: string;
35
48
  sub?: string;
49
+ /** A short label in the card header, like `TABLE` or `ES INDEX`. */
50
+ pill?: string;
36
51
  lines: string[];
52
+ fields: CompiledField[];
37
53
  icon?: IconData;
38
54
  kind?: string;
39
55
  family?: Family;
@@ -76,6 +92,9 @@ export interface CompiledEdge {
76
92
  id: string;
77
93
  from: string;
78
94
  to: string;
95
+ /** Set when the edge starts or ends on one field of an entity card. */
96
+ fromField?: string;
97
+ toField?: string;
79
98
  label?: string;
80
99
  kind: string;
81
100
  both: boolean;
@@ -147,10 +166,23 @@ export interface CompiledScenario {
147
166
  phases: CompiledPhase[];
148
167
  steps: CompiledStep[];
149
168
  }
169
+ /**
170
+ * How a diagram opens, as its author wrote it. A page's own choices (the props of `<Diagram>`) win
171
+ * over these. Validated by the compiler: the view and the scenario exist, and agree.
172
+ */
173
+ export interface DiagramDefaults {
174
+ view?: string;
175
+ scenario?: string;
176
+ mode?: ScenarioMode;
177
+ sidebar?: boolean;
178
+ subtitles?: boolean;
179
+ autoplay?: boolean;
180
+ }
150
181
  export interface CompiledDiagram {
151
182
  name: string;
152
183
  title: string;
153
184
  descriptionHtml?: string;
185
+ defaults?: DiagramDefaults;
154
186
  nodes: Record<string, CompiledNode>;
155
187
  groups: Record<string, CompiledGroup>;
156
188
  edges: Record<string, CompiledEdge>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@the-package-labs/idocs-core",
3
- "version": "0.4.0",
3
+ "version": "0.6.0",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {
@@ -1,145 +0,0 @@
1
- // src/defaults.ts
2
- var BUILTIN_KINDS = {
3
- client: { icon: "lucide:monitor", family: "slate" },
4
- user: { icon: "lucide:user", family: "slate" },
5
- ui: { icon: "lucide:layout-dashboard", family: "slate" },
6
- external: { icon: "lucide:cloud", family: "slate" },
7
- service: { icon: "lucide:server", family: "blue" },
8
- gateway: { icon: "lucide:route", family: "blue" },
9
- worker: { icon: "lucide:cog", family: "blue" },
10
- container: { icon: "lucide:container", family: "blue" },
11
- function: { icon: "lucide:square-function", family: "blue" },
12
- database: { icon: "lucide:database", family: "green" },
13
- cache: { icon: "lucide:zap", family: "green" },
14
- storage: { icon: "lucide:hard-drive", family: "green" },
15
- queue: { icon: "lucide:list-ordered", family: "amber" },
16
- agent: { icon: "lucide:bot", family: "violet" },
17
- network: { icon: "lucide:network", family: "violet" },
18
- vm: { icon: "lucide:box", family: "violet" },
19
- auth: { icon: "lucide:key-round", family: "teal" },
20
- monitor: { icon: "lucide:activity", family: "teal" }
21
- };
22
- var BUILTIN_EDGE_KINDS = {
23
- http: { label: "HTTP request / response", color: "ink", width: 1.5 },
24
- channel: { label: "Persistent channel (websocket, gRPC)", color: "accent", width: 2.4 },
25
- tunnel: { label: "Overlay tunnel", color: "tunnel", width: 5 },
26
- queue: { label: "Queue / broker", color: "ok", width: 2, dash: "2 4" },
27
- ws: { label: "WebSocket", color: "ink", width: 1.6, dash: "7 4" },
28
- data: { label: "Data access", color: "muted", width: 1.3 }
29
- };
30
- var STEP_KIND_COLORS = {
31
- request: "accent",
32
- response: "ok",
33
- error: "bad",
34
- lookup: "muted",
35
- event: "warn"
36
- };
37
- var DEFAULT_NODE_WIDTH = 178;
38
-
39
- // src/geometry.ts
40
- function polylineLength(points) {
41
- let total = 0;
42
- for (let i = 1; i < points.length; i++) total += dist(points[i - 1], points[i]);
43
- return total;
44
- }
45
- function dist(a, b) {
46
- return Math.hypot(b.x - a.x, b.y - a.y);
47
- }
48
- function pointAt(points, d) {
49
- if (points.length === 0) return { x: 0, y: 0 };
50
- let left = Math.max(0, d);
51
- for (let i = 1; i < points.length; i++) {
52
- const a = points[i - 1];
53
- const b = points[i];
54
- const len = dist(a, b);
55
- if (left <= len || i === points.length - 1) {
56
- const t = len === 0 ? 0 : Math.min(1, left / len);
57
- return { x: a.x + (b.x - a.x) * t, y: a.y + (b.y - a.y) * t };
58
- }
59
- left -= len;
60
- }
61
- return points[points.length - 1];
62
- }
63
- function roundedPath(points, radius = 8) {
64
- if (points.length === 0) return "";
65
- const first = points[0];
66
- let d = `M${r(first.x)} ${r(first.y)}`;
67
- for (let i = 1; i < points.length - 1; i++) {
68
- const prev = points[i - 1];
69
- const cur = points[i];
70
- const next = points[i + 1];
71
- const inLen = dist(prev, cur);
72
- const outLen = dist(cur, next);
73
- const rad = Math.min(radius, inLen / 2, outLen / 2);
74
- if (rad < 0.5) {
75
- d += `L${r(cur.x)} ${r(cur.y)}`;
76
- continue;
77
- }
78
- const a = {
79
- x: cur.x + (prev.x - cur.x) / inLen * rad,
80
- y: cur.y + (prev.y - cur.y) / inLen * rad
81
- };
82
- const b = {
83
- x: cur.x + (next.x - cur.x) / outLen * rad,
84
- y: cur.y + (next.y - cur.y) / outLen * rad
85
- };
86
- d += `L${r(a.x)} ${r(a.y)}Q${r(cur.x)} ${r(cur.y)} ${r(b.x)} ${r(b.y)}`;
87
- }
88
- if (points.length > 1) {
89
- const last = points[points.length - 1];
90
- d += `L${r(last.x)} ${r(last.y)}`;
91
- }
92
- return d;
93
- }
94
- function r(n) {
95
- return Math.round(n * 10) / 10;
96
- }
97
- function letterKey(index) {
98
- let n = index;
99
- let out = "";
100
- do {
101
- out = String.fromCharCode(65 + n % 26) + out;
102
- n = Math.floor(n / 26) - 1;
103
- } while (n >= 0);
104
- return out;
105
- }
106
-
107
- // src/suggest.ts
108
- function didYouMean(word, options) {
109
- let best;
110
- let bestDist = Math.max(2, Math.floor(word.length / 3)) + 1;
111
- for (const o of options) {
112
- const d = levenshtein(word.toLowerCase(), o.toLowerCase());
113
- if (d < bestDist) {
114
- best = o;
115
- bestDist = d;
116
- }
117
- }
118
- return best ? `Did you mean "${best}"?` : void 0;
119
- }
120
- function levenshtein(a, b) {
121
- const row = Array.from({ length: b.length + 1 }, (_, i) => i);
122
- for (let i = 1; i <= a.length; i++) {
123
- let prev = row[0];
124
- row[0] = i;
125
- for (let j = 1; j <= b.length; j++) {
126
- const tmp = row[j];
127
- row[j] = Math.min(row[j] + 1, row[j - 1] + 1, prev + (a[i - 1] === b[j - 1] ? 0 : 1));
128
- prev = tmp;
129
- }
130
- }
131
- return row[b.length];
132
- }
133
-
134
- export {
135
- BUILTIN_KINDS,
136
- BUILTIN_EDGE_KINDS,
137
- STEP_KIND_COLORS,
138
- DEFAULT_NODE_WIDTH,
139
- polylineLength,
140
- dist,
141
- pointAt,
142
- roundedPath,
143
- letterKey,
144
- didYouMean
145
- };