ts-graphviz 1.0.1 → 1.1.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.
package/README.ja.md CHANGED
@@ -156,7 +156,7 @@ const dot = toDot(g);
156
156
 
157
157
  #### 宣言的な API 😎
158
158
 
159
- `Graph` や `Digraph` を作成する際に、より **DOT** 言語に近い記法を提供するために _Builder Functuion_ を使うことができます。
159
+ `Graph` や `Digraph` を作成する際に、より **DOT** 言語に近い記法を提供するために _Model Factory_ を使うことができます。
160
160
 
161
161
  **Model** にも宣言的な API を用意しており、一貫して宣言的なパラダイムを選択することもできます。
162
162
 
package/README.md CHANGED
@@ -155,7 +155,7 @@ const dot = toDot(g);
155
155
 
156
156
  #### Declarative API 😎
157
157
 
158
- When creating `Graph` or `Digraph`, you can use _Builder Function_ to provide a notation more similar to the **DOT** language.
158
+ When creating `Graph` or `Digraph`, you can use _Model Factory_ to provide a notation more similar to the **DOT** language.
159
159
 
160
160
  **Model** also has a declarative API, so you can consistently choose a declarative paradigm.
161
161
 
@@ -2,6 +2,8 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
+ require('#lib/core');
6
+
5
7
  /** @hidden */
6
8
  function isForwardRefNode(object) {
7
9
  return typeof object === 'object' && object !== null && typeof object.id === 'string';
@@ -45,6 +47,28 @@ function toNodeRefGroup(targets) {
45
47
  return targets.map((t) => toNodeRef(t));
46
48
  }
47
49
 
50
+ /**
51
+ * @group Models Context
52
+ * @alpha
53
+ */
54
+ const RootModelsContext = Object.seal({
55
+ // NOTE: RootModelsContext is also initialized after the model class is declared in the '#lib/core' module.
56
+ Graph: null,
57
+ Digraph: null,
58
+ Subgraph: null,
59
+ Node: null,
60
+ Edge: null,
61
+ });
62
+ /**
63
+ * @group Models Context
64
+ * @alpha
65
+ */
66
+ function createModelsContext(models) {
67
+ return Object.assign(Object.seal(Object.assign({}, RootModelsContext)), models);
68
+ }
69
+
70
+ exports.RootModelsContext = RootModelsContext;
71
+ exports.createModelsContext = createModelsContext;
48
72
  exports.isCompass = isCompass;
49
73
  exports.isForwardRefNode = isForwardRefNode;
50
74
  exports.isNodeModel = isNodeModel;
@@ -1612,6 +1612,28 @@ interface KeyValueMapping {
1612
1612
  */
1613
1613
  declare type Attribute<T extends AttributeKey> = KeyValueMapping[T];
1614
1614
 
1615
+ /**
1616
+ * @group Models Context
1617
+ * @beta
1618
+ */
1619
+ interface ModelsContext {
1620
+ Graph: RootGraphConstructor;
1621
+ Digraph: RootGraphConstructor;
1622
+ Subgraph: SubgraphConstructor;
1623
+ Node: NodeConstructor;
1624
+ Edge: EdgeConstructor;
1625
+ }
1626
+ /**
1627
+ * @group Models Context
1628
+ * @alpha
1629
+ */
1630
+ declare const RootModelsContext: ModelsContext;
1631
+ /**
1632
+ * @group Models Context
1633
+ * @alpha
1634
+ */
1635
+ declare function createModelsContext(models: Partial<ModelsContext>): ModelsContext;
1636
+
1615
1637
  /**
1616
1638
  * @group Models
1617
1639
  */
@@ -1718,7 +1740,7 @@ interface HasComment {
1718
1740
  * @group Models
1719
1741
  */
1720
1742
  interface HasAttributes<T extends AttributeKey> {
1721
- readonly attributes: AttributesGroup<T>;
1743
+ readonly attributes: AttributesGroupModel<T>;
1722
1744
  }
1723
1745
  /**
1724
1746
  * @group Models
@@ -1760,7 +1782,7 @@ interface Attributes<T extends AttributeKey> {
1760
1782
  /**
1761
1783
  * @group Models
1762
1784
  */
1763
- interface AttributesGroup<T extends AttributeKey> extends Attributes<T>, HasComment {}
1785
+ interface AttributesGroupModel<T extends AttributeKey> extends Attributes<T>, HasComment {}
1764
1786
  /**
1765
1787
  * @group Models
1766
1788
  */
@@ -1829,6 +1851,10 @@ interface GraphBaseModel<T extends AttributeKey = AttributeKey> extends HasComme
1829
1851
  readonly edges: ReadonlyArray<EdgeModel>;
1830
1852
  /** Subgraph objects in the graph. */
1831
1853
  readonly subgraphs: ReadonlyArray<SubgraphModel>;
1854
+ /**
1855
+ * @beta
1856
+ */
1857
+ with(models: Partial<ModelsContext>): void;
1832
1858
  /**
1833
1859
  * Add a Node to the graph.
1834
1860
  */
@@ -2181,6 +2207,42 @@ interface RootGraphModel extends GraphBaseModel<GraphAttributeKey>, DotObjectMod
2181
2207
  */
2182
2208
  strict: boolean;
2183
2209
  }
2210
+ /**
2211
+ * @group Models
2212
+ * @beta
2213
+ */
2214
+ interface RootGraphConstructor {
2215
+ new (id?: string, attributes?: GraphAttributesObject): RootGraphModel;
2216
+ new (id?: string, strict?: boolean, attributes?: GraphAttributesObject): RootGraphModel;
2217
+ new (strict?: boolean, attributes?: GraphAttributesObject): RootGraphModel;
2218
+ new (attributes?: GraphAttributesObject): RootGraphModel;
2219
+ new (...args: any[]): RootGraphModel;
2220
+ }
2221
+ /**
2222
+ * @group Models
2223
+ * @beta
2224
+ */
2225
+ interface SubgraphConstructor {
2226
+ new (id?: string, attributes?: SubgraphAttributesObject): SubgraphModel;
2227
+ new (attributes?: SubgraphAttributesObject): SubgraphModel;
2228
+ new (...args: any[]): SubgraphModel;
2229
+ }
2230
+ /**
2231
+ * @group Models
2232
+ * @beta
2233
+ */
2234
+ interface NodeConstructor {
2235
+ new (id: string, attributes?: NodeAttributesObject): NodeModel;
2236
+ new (...args: any[]): NodeModel;
2237
+ }
2238
+ /**
2239
+ * @group Models
2240
+ * @beta
2241
+ */
2242
+ interface EdgeConstructor {
2243
+ new (targets: EdgeTargetTuple, attributes?: EdgeAttributesObject): EdgeModel;
2244
+ new (...args: any[]): EdgeModel;
2245
+ }
2184
2246
  /** @hidden */
2185
2247
  declare function isForwardRefNode(object: unknown): object is ForwardRefNode;
2186
2248
  /** @hidden */
@@ -2210,7 +2272,7 @@ export {
2210
2272
  AttributeValue,
2211
2273
  Attributes,
2212
2274
  AttributesEntities,
2213
- AttributesGroup,
2275
+ AttributesGroupModel,
2214
2276
  AttributesObject,
2215
2277
  ClusterMode,
2216
2278
  ClusterSubgraphAttributeKey,
@@ -2224,6 +2286,7 @@ export {
2224
2286
  DoubleList,
2225
2287
  EdgeAttributeKey,
2226
2288
  EdgeAttributesObject,
2289
+ EdgeConstructor,
2227
2290
  EdgeModel,
2228
2291
  EdgeTarget,
2229
2292
  EdgeTargetLike,
@@ -2242,8 +2305,10 @@ export {
2242
2305
  LayerList,
2243
2306
  LayerRange,
2244
2307
  LblString,
2308
+ ModelsContext,
2245
2309
  NodeAttributeKey,
2246
2310
  NodeAttributesObject,
2311
+ NodeConstructor,
2247
2312
  NodeModel,
2248
2313
  NodeRef,
2249
2314
  NodeRefGroup,
@@ -2260,7 +2325,9 @@ export {
2260
2325
  RankType,
2261
2326
  Rankdir,
2262
2327
  Rect,
2328
+ RootGraphConstructor,
2263
2329
  RootGraphModel,
2330
+ RootModelsContext,
2264
2331
  Shape,
2265
2332
  SmoothType,
2266
2333
  SplineType,
@@ -2268,8 +2335,10 @@ export {
2268
2335
  Style,
2269
2336
  SubgraphAttributeKey,
2270
2337
  SubgraphAttributesObject,
2338
+ SubgraphConstructor,
2271
2339
  SubgraphModel,
2272
2340
  ViewPort,
2341
+ createModelsContext,
2273
2342
  isCompass,
2274
2343
  isForwardRefNode,
2275
2344
  isNodeModel,
@@ -1,3 +1,5 @@
1
+ import '#lib/core';
2
+
1
3
  /** @hidden */
2
4
  function isForwardRefNode(object) {
3
5
  return typeof object === 'object' && object !== null && typeof object.id === 'string';
@@ -41,7 +43,29 @@ function toNodeRefGroup(targets) {
41
43
  return targets.map((t) => toNodeRef(t));
42
44
  }
43
45
 
46
+ /**
47
+ * @group Models Context
48
+ * @alpha
49
+ */
50
+ const RootModelsContext = Object.seal({
51
+ // NOTE: RootModelsContext is also initialized after the model class is declared in the '#lib/core' module.
52
+ Graph: null,
53
+ Digraph: null,
54
+ Subgraph: null,
55
+ Node: null,
56
+ Edge: null,
57
+ });
58
+ /**
59
+ * @group Models Context
60
+ * @alpha
61
+ */
62
+ function createModelsContext(models) {
63
+ return Object.assign(Object.seal(Object.assign({}, RootModelsContext)), models);
64
+ }
65
+
44
66
  export {
67
+ RootModelsContext,
68
+ createModelsContext,
45
69
  isCompass,
46
70
  isForwardRefNode,
47
71
  isNodeModel,
@@ -17,6 +17,7 @@ const attribute = new Proxy(Object.freeze({}), {
17
17
  * @group Models
18
18
  */
19
19
  class DotObject {}
20
+
20
21
  /**
21
22
  * Base class for DOT objects with attributes.
22
23
  * @group Models
@@ -57,13 +58,7 @@ class AttributesBase extends DotObject {
57
58
  this.#attrs.clear();
58
59
  }
59
60
  }
60
- /**
61
- * A set of attribute values for any object.
62
- * @group Models
63
- */
64
- class AttributesGroupModel extends AttributesBase {
65
- comment;
66
- }
61
+
67
62
  /**
68
63
  * A set of attribute values for any object.
69
64
  * @group Models
@@ -79,13 +74,21 @@ class AttributeList extends AttributesBase {
79
74
  this.$$kind = $$kind;
80
75
  }
81
76
  }
77
+
82
78
  /**
83
79
  * Base class for Graph objects.
84
80
  * @group Models
85
81
  */
86
82
  class GraphBase extends AttributesBase {
83
+ /** @hidden */
84
+ #models = common.RootModelsContext;
87
85
  id;
88
86
  comment;
87
+ attributes = Object.freeze({
88
+ graph: new AttributeList('Graph'),
89
+ edge: new AttributeList('Edge'),
90
+ node: new AttributeList('Node'),
91
+ });
89
92
  get nodes() {
90
93
  return Array.from(this.#objects.nodes.values());
91
94
  }
@@ -101,6 +104,9 @@ class GraphBase extends AttributesBase {
101
104
  edges: new Set(),
102
105
  subgraphs: new Set(),
103
106
  };
107
+ with(models) {
108
+ this.#models = common.createModelsContext(models);
109
+ }
104
110
  addNode(node) {
105
111
  this.#objects.nodes.set(node.id, node);
106
112
  }
@@ -120,11 +126,10 @@ class GraphBase extends AttributesBase {
120
126
  return this.#objects.subgraphs.has(subgraph);
121
127
  }
122
128
  createSubgraph(...args) {
123
- const id = args.find((arg) => typeof arg === 'string');
124
- const attributes = args.find((arg) => typeof arg === 'object');
125
- const graph = new Subgraph(id, attributes);
126
- this.#objects.subgraphs.add(graph);
127
- return graph;
129
+ const subgraph = new this.#models.Subgraph(...args);
130
+ subgraph.with(this.#models);
131
+ this.addSubgraph(subgraph);
132
+ return subgraph;
128
133
  }
129
134
  removeNode(node) {
130
135
  this.#objects.nodes.delete(typeof node === 'string' ? node : node.id);
@@ -136,8 +141,8 @@ class GraphBase extends AttributesBase {
136
141
  this.#objects.subgraphs.delete(subgraph);
137
142
  }
138
143
  createNode(id, attributes) {
139
- const node = new Node(id, attributes);
140
- this.#objects.nodes.set(id, node);
144
+ const node = new this.#models.Node(id, attributes);
145
+ this.addNode(node);
141
146
  return node;
142
147
  }
143
148
  getSubgraph(id) {
@@ -148,8 +153,8 @@ class GraphBase extends AttributesBase {
148
153
  }
149
154
  createEdge(targets, attributes) {
150
155
  const ts = targets.map((t) => (common.isNodeRefGroupLike(t) ? common.toNodeRefGroup(t) : common.toNodeRef(t)));
151
- const edge = new Edge(ts, attributes);
152
- this.#objects.edges.add(edge);
156
+ const edge = new this.#models.Edge(ts, attributes);
157
+ this.addEdge(edge);
153
158
  return edge;
154
159
  }
155
160
  subgraph(...args) {
@@ -202,6 +207,48 @@ class GraphBase extends AttributesBase {
202
207
  this.attributes.graph.apply(attributes);
203
208
  }
204
209
  }
210
+
211
+ /**
212
+ * Base class representing a root graph(digraph, graph).
213
+ * @group Models
214
+ */
215
+ class RootGraph extends GraphBase {
216
+ get $$type() {
217
+ return 'Graph';
218
+ }
219
+ id;
220
+ strict;
221
+ constructor(...args) {
222
+ super();
223
+ this.id = args.find((arg) => typeof arg === 'string');
224
+ this.strict = args.find((arg) => typeof arg === 'boolean') ?? false;
225
+ const attributes = args.find((arg) => typeof arg === 'object' && arg !== null);
226
+ if (attributes !== undefined) {
227
+ this.apply(attributes);
228
+ }
229
+ }
230
+ }
231
+
232
+ /**
233
+ * DOT object class representing a digraph.
234
+ * @group Models
235
+ */
236
+ class Digraph extends RootGraph {
237
+ get directed() {
238
+ return true;
239
+ }
240
+ }
241
+
242
+ /**
243
+ * DOT object class representing a graph.
244
+ * @group Models
245
+ */
246
+ class Graph extends RootGraph {
247
+ get directed() {
248
+ return false;
249
+ }
250
+ }
251
+
205
252
  /**
206
253
  * DOT object class representing a subgraph.
207
254
  * @group Models
@@ -211,11 +258,6 @@ class Subgraph extends GraphBase {
211
258
  return 'Subgraph';
212
259
  }
213
260
  id;
214
- attributes = Object.freeze({
215
- graph: new AttributeList('Graph'),
216
- edge: new AttributeList('Edge'),
217
- node: new AttributeList('Node'),
218
- });
219
261
  constructor(...args) {
220
262
  super();
221
263
  this.id = args.find((arg) => typeof arg === 'string');
@@ -231,6 +273,15 @@ class Subgraph extends GraphBase {
231
273
  return false;
232
274
  }
233
275
  }
276
+
277
+ /**
278
+ * A set of attribute values for any object.
279
+ * @group Models
280
+ */
281
+ class AttributesGroup extends AttributesBase {
282
+ comment;
283
+ }
284
+
234
285
  /**
235
286
  * DOT object class representing a node.
236
287
  * @group Models
@@ -245,7 +296,7 @@ class Node extends DotObject {
245
296
  constructor(id, attributes) {
246
297
  super();
247
298
  this.id = id;
248
- this.attributes = new AttributesGroupModel(attributes);
299
+ this.attributes = new AttributesGroup(attributes);
249
300
  }
250
301
  port(port) {
251
302
  if (typeof port === 'string') {
@@ -254,6 +305,7 @@ class Node extends DotObject {
254
305
  return { id: this.id, ...port };
255
306
  }
256
307
  }
308
+
257
309
  /**
258
310
  * DOT object class representing a edge.
259
311
  * @group Models
@@ -271,93 +323,66 @@ class Edge extends DotObject {
271
323
  if (targets.length < 2 && (common.isNodeRefLike(targets[0]) && common.isNodeRefLike(targets[1])) === false) {
272
324
  throw Error('The element of Edge target is missing or not satisfied as Edge target.');
273
325
  }
274
- this.attributes = new AttributesGroupModel(attributes);
275
- }
276
- }
277
- /**
278
- * Base class representing a root graph(digraph, graph).
279
- * @group Models
280
- */
281
- class RootGraph extends GraphBase {
282
- get $$type() {
283
- return 'Graph';
284
- }
285
- id;
286
- strict;
287
- attributes = Object.freeze({
288
- graph: new AttributeList('Graph'),
289
- edge: new AttributeList('Edge'),
290
- node: new AttributeList('Node'),
291
- });
292
- constructor(...args) {
293
- super();
294
- this.id = args.find((arg) => typeof arg === 'string');
295
- this.strict = args.find((arg) => typeof arg === 'boolean') ?? false;
296
- const attributes = args.find((arg) => typeof arg === 'object' && arg !== null);
297
- if (attributes !== undefined) {
298
- this.apply(attributes);
299
- }
300
- }
301
- }
302
- /**
303
- * DOT object class representing a graph.
304
- * @group Models
305
- */
306
- class Graph extends RootGraph {
307
- get directed() {
308
- return false;
309
- }
310
- }
311
- /**
312
- * DOT object class representing a digraph.
313
- * @group Models
314
- */
315
- class Digraph extends RootGraph {
316
- get directed() {
317
- return true;
326
+ this.attributes = new AttributesGroup(attributes);
318
327
  }
319
328
  }
320
329
 
330
+ Object.assign(common.RootModelsContext, {
331
+ Graph,
332
+ Digraph,
333
+ Subgraph,
334
+ Node,
335
+ Edge,
336
+ });
337
+
321
338
  /** @hidden */
322
- function builder(directed, strictMode) {
323
- const C = directed ? Digraph : Graph;
339
+ function ModelFactoryBuilder(directed, strictMode) {
324
340
  return (...args) => {
341
+ const G = directed ? this.Digraph : this.Graph;
325
342
  const id = args.find((arg) => typeof arg === 'string');
326
343
  const attributes = args.find((arg) => typeof arg === 'object');
327
344
  const callback = args.find((arg) => typeof arg === 'function');
328
- const g = new C(id, strictMode, attributes);
345
+ const g = new G(id, strictMode, attributes);
346
+ g.with(this);
329
347
  if (typeof callback === 'function') {
330
348
  callback(g);
331
349
  }
332
350
  return g;
333
351
  };
334
352
  }
353
+ function createModelFactories(strict, context = common.RootModelsContext) {
354
+ return Object.freeze({
355
+ digraph: ModelFactoryBuilder.call(context, true, strict),
356
+ graph: ModelFactoryBuilder.call(context, false, strict),
357
+ });
358
+ }
359
+
360
+ const noStrict = createModelFactories(false);
335
361
  /**
336
362
  * API for creating directional graph objects.
337
- * @group Model Builder
363
+ * @group Model Factory
338
364
  */
339
- const digraph = builder(true, false);
365
+ const digraph = noStrict.digraph;
340
366
  /**
341
367
  * API for creating omnidirectional graph objects.
342
- * @group Model Builder
368
+ * @group Model Factory
343
369
  */
344
- const graph = builder(false, false);
370
+ const graph = noStrict.graph;
345
371
  /**
346
372
  * Provides a strict mode API.
347
- * @group Model Builder
373
+ * @group Model Factory
348
374
  */
349
- const strict = Object.freeze({
350
- /**
351
- * API for creating directional graph objects in strict mode.
352
- * @group Model Builder
353
- */
354
- digraph: builder(true, true),
355
- /**
356
- * API for creating omnidirectional graph objects in strict mode.
357
- * @group Model Builder
358
- */
359
- graph: builder(false, true),
360
- });
375
+ const strict = createModelFactories(true);
376
+ /**
377
+ * @group Model Factory
378
+ */
379
+ function withContext(models) {
380
+ const context = common.createModelsContext(models);
381
+ return Object.freeze({
382
+ ...createModelFactories(false, context),
383
+ strict: createModelFactories(true, context),
384
+ });
385
+ }
361
386
 
362
387
  /**
363
388
  * Convert Model to DOT string.
@@ -375,7 +400,7 @@ function toDot(model, options) {
375
400
 
376
401
  exports.AttributeList = AttributeList;
377
402
  exports.AttributesBase = AttributesBase;
378
- exports.AttributesGroupModel = AttributesGroupModel;
403
+ exports.AttributesGroup = AttributesGroup;
379
404
  exports.Digraph = Digraph;
380
405
  exports.DotObject = DotObject;
381
406
  exports.Edge = Edge;
@@ -389,3 +414,4 @@ exports.digraph = digraph;
389
414
  exports.graph = graph;
390
415
  exports.strict = strict;
391
416
  exports.toDot = toDot;
417
+ exports.withContext = withContext;