laranex-schema-viewer-ui 0.0.0-stage → 0.2.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 (108) hide show
  1. package/LICENSE +9 -0
  2. package/NOTICE +22 -0
  3. package/README.md +25 -2
  4. package/contract/check.mjs +53 -0
  5. package/contract/conformance/graph/composite-unordered-pairs.json +222 -0
  6. package/contract/conformance/graph/cross-connection-foreign-key.json +153 -0
  7. package/contract/conformance/graph/cross-connection-relationship.json +192 -0
  8. package/contract/conformance/graph/duplicate-foreign-keys.json +180 -0
  9. package/contract/conformance/graph/duplicate-table-names.json +311 -0
  10. package/contract/conformance/graph/foreign-key-and-relationships.json +234 -0
  11. package/contract/conformance/graph/foreign-key-only.json +162 -0
  12. package/contract/conformance/graph/link-note.json +215 -0
  13. package/contract/conformance/graph/multiple-between-tables.json +218 -0
  14. package/contract/conformance/graph/pivot.json +264 -0
  15. package/contract/conformance/graph/polymorphic.json +227 -0
  16. package/contract/conformance/graph/relationship-only.json +180 -0
  17. package/contract/conformance/graph/self-reference.json +159 -0
  18. package/contract/conformance/graph/through.json +214 -0
  19. package/contract/conformance/graph/unresolved-endpoint.json +194 -0
  20. package/contract/fixtures/invalid/backs-check-constraint.json +859 -0
  21. package/contract/fixtures/invalid/coverage-claims-complete.json +649 -0
  22. package/contract/fixtures/invalid/coverage-for-wrong-source.json +513 -0
  23. package/contract/fixtures/invalid/diagnostic-unknown-subject.json +649 -0
  24. package/contract/fixtures/invalid/drift-without-both-sources.json +656 -0
  25. package/contract/fixtures/invalid/duplicate-ids.json +551 -0
  26. package/contract/fixtures/invalid/foreign-key-across-connections.json +1176 -0
  27. package/contract/fixtures/invalid/foreign-key-column-counts.json +1269 -0
  28. package/contract/fixtures/invalid/foreign-key-unknown-target.json +859 -0
  29. package/contract/fixtures/invalid/index-columns-out-of-order.json +859 -0
  30. package/contract/fixtures/invalid/index-part-column-and-expression.json +859 -0
  31. package/contract/fixtures/invalid/link-state-mismatch.json +2994 -0
  32. package/contract/fixtures/invalid/missing-field.json +308 -0
  33. package/contract/fixtures/invalid/pivot-unknown-column.json +2994 -0
  34. package/contract/fixtures/invalid/predicate-without-partial.json +311 -0
  35. package/contract/fixtures/invalid/primary-index-not-unique.json +859 -0
  36. package/contract/fixtures/invalid/provenance-outside-source.json +311 -0
  37. package/contract/fixtures/invalid/related-model-missing.json +649 -0
  38. package/contract/fixtures/invalid/unknown-property-strict.json +312 -0
  39. package/contract/fixtures/invalid/unsupported-major.json +311 -0
  40. package/contract/fixtures/invalid/wrong-format.json +311 -0
  41. package/contract/fixtures/valid/combined-drift.json +642 -0
  42. package/contract/fixtures/valid/combined-eloquent.json +2987 -0
  43. package/contract/fixtures/valid/combined-multi-connection.json +1150 -0
  44. package/contract/fixtures/valid/database-mysql-indexes.json +502 -0
  45. package/contract/fixtures/valid/database-postgresql-indexes.json +852 -0
  46. package/contract/fixtures/valid/database-sqlite-indexes.json +304 -0
  47. package/contract/fixtures/valid/declared-multi-connection.json +424 -0
  48. package/contract/fixtures/valid/declared-sqlalchemy.json +1263 -0
  49. package/contract/schema.json +1697 -0
  50. package/dist/lib/contract-N4axHCW3.js +774 -0
  51. package/dist/lib/contract-N4axHCW3.js.map +1 -0
  52. package/dist/lib/contract.js +1 -0
  53. package/dist/lib/elk.bundled-BD4Ks5Vh.js +45982 -0
  54. package/dist/lib/elk.bundled-BD4Ks5Vh.js.map +1 -0
  55. package/dist/lib/index.js +3626 -0
  56. package/dist/lib/index.js.map +1 -0
  57. package/dist/lib/rolldown-runtime-BZwVK1dO.js +16 -0
  58. package/dist/lib/styles.css +2 -0
  59. package/dist/types/contract/document.d.ts +5 -0
  60. package/dist/types/contract/graph.d.ts +10 -0
  61. package/dist/types/contract/index.d.ts +6 -0
  62. package/dist/types/contract/serialize.d.ts +4 -0
  63. package/dist/types/contract/sha256.d.ts +1 -0
  64. package/dist/types/contract/shape.d.ts +29 -0
  65. package/dist/types/contract/types.d.ts +279 -0
  66. package/dist/types/contract/validate.d.ts +21 -0
  67. package/dist/types/contract/viewer-config.d.ts +23 -0
  68. package/dist/types/index.d.ts +4 -0
  69. package/dist/types/viewer/Browse.d.ts +25 -0
  70. package/dist/types/viewer/Details.d.ts +61 -0
  71. package/dist/types/viewer/Resizer.d.ts +9 -0
  72. package/dist/types/viewer/SchemaEdge.d.ts +19 -0
  73. package/dist/types/viewer/SchemaViewer.d.ts +25 -0
  74. package/dist/types/viewer/Search.d.ts +33 -0
  75. package/dist/types/viewer/Shortcuts.d.ts +5 -0
  76. package/dist/types/viewer/TableNode.d.ts +43 -0
  77. package/dist/types/viewer/Tour.d.ts +13 -0
  78. package/dist/types/viewer/exportImage.d.ts +65 -0
  79. package/dist/types/viewer/graph.d.ts +52 -0
  80. package/dist/types/viewer/layout.d.ts +35 -0
  81. package/dist/types/viewer/routing.d.ts +30 -0
  82. package/dist/types/viewer/theme.d.ts +6 -0
  83. package/dist/types/viewer/ui.d.ts +81 -0
  84. package/dist/viewer/app.css +1 -0
  85. package/dist/viewer/app.js +16 -0
  86. package/dist/viewer/assets/elk.bundled-Cijv1EqA.js +24 -0
  87. package/dist/viewer/assets/ibm-plex-mono-latin-400-normal-CvHOgSBP.woff +0 -0
  88. package/dist/viewer/assets/ibm-plex-mono-latin-400-normal-DMJ8VG8y.woff2 +0 -0
  89. package/dist/viewer/assets/ibm-plex-mono-latin-500-normal-CB9ihrfo.woff +0 -0
  90. package/dist/viewer/assets/ibm-plex-mono-latin-500-normal-DSY6xOcd.woff2 +0 -0
  91. package/dist/viewer/assets/ibm-plex-mono-latin-600-normal-BgSNZQsw.woff2 +0 -0
  92. package/dist/viewer/assets/ibm-plex-mono-latin-600-normal-DWFSQ4vo.woff +0 -0
  93. package/dist/viewer/assets/ibm-plex-sans-latin-400-normal-CDDApCn2.woff2 +0 -0
  94. package/dist/viewer/assets/ibm-plex-sans-latin-400-normal-CYLoc0-x.woff +0 -0
  95. package/dist/viewer/assets/ibm-plex-sans-latin-500-normal-6ng42L7E.woff2 +0 -0
  96. package/dist/viewer/assets/ibm-plex-sans-latin-500-normal-BgVn5rGT.woff +0 -0
  97. package/dist/viewer/assets/ibm-plex-sans-latin-600-normal-Cu4Hd6ag.woff +0 -0
  98. package/dist/viewer/assets/ibm-plex-sans-latin-600-normal-CuJfVYMP.woff2 +0 -0
  99. package/dist/viewer/assets/ibm-plex-sans-latin-700-normal-Bth3BMcD.woff +0 -0
  100. package/dist/viewer/assets/ibm-plex-sans-latin-700-normal-Bxkt5Cjx.woff2 +0 -0
  101. package/dist/viewer/assets/rolldown-runtime-pP25SEvz.js +1 -0
  102. package/dist/viewer/favicon.ico +0 -0
  103. package/dist/viewer/favicon.svg +1 -0
  104. package/dist/viewer/index.html +17 -0
  105. package/dist/viewer/manifest.json +120 -0
  106. package/docs/contract.md +265 -0
  107. package/docs/integration.md +71 -0
  108. package/package.json +91 -4
package/LICENSE ADDED
@@ -0,0 +1,9 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) Laranex
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6
+
7
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/NOTICE ADDED
@@ -0,0 +1,22 @@
1
+ Laranex Schema Viewer UI is licensed under the MIT License (see LICENSE).
2
+
3
+ The viewer's visual design, layout, palette and interaction model follow
4
+ Laranex Python Schema Viewer, src/laranex_schema_viewer/static/, inspected at
5
+ commit de08475 (https://github.com/laranex/python-schema-viewer).
6
+
7
+ The automatic layout (arrange modes and packed columns)
8
+ and orthogonal edge routing are adapted from Laranex Laravel Schema Viewer,
9
+ ui/src/elk.ts, ui/src/layout.ts and ui/src/routing.ts, inspected at commit
10
+ 62b056a (https://github.com/laranex/laravel-schema-viewer).
11
+
12
+ The laranex-schema contract takes its structure and camelCase naming from
13
+ Laravel Schema Viewer's serialized document (src/Schema/*.php) and its
14
+ provenance-preserving rules from Python Schema Viewer's snapshot contract
15
+ (src/laranex_schema_viewer/document.py). The graph rules follow Laravel's
16
+ src/Graph/SchemaGraph.php. All fixtures are synthetic.
17
+
18
+ Copyright (c) Laranex. Used under the MIT License reproduced in LICENSE.
19
+
20
+ The standalone bundle includes IBM Plex Sans and IBM Plex Mono
21
+ (SIL Open Font License 1.1, via @fontsource), elkjs (Eclipse Public License
22
+ 2.0), React and React DOM (MIT) and @xyflow/react (MIT).
package/README.md CHANGED
@@ -1,3 +1,26 @@
1
- # Temporary Holding Version
1
+ # Laranex Schema Viewer UI
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ One JSON contract, one shared viewer, many frameworks: the `laranex-schema` contract and the ERD viewer shared by the
4
+ Laravel, Python and Node.js schema viewers.
5
+
6
+ The contract is specified in [docs/contract.md](docs/contract.md); hosts integrate the viewer as described in
7
+ [docs/integration.md](docs/integration.md); planned work is in
8
+ [ROADMAP.md](ROADMAP.md); see `AGENTS.md` for the architecture and development workflow.
9
+
10
+ ```tsx
11
+ import { SchemaViewer } from 'laranex-schema-viewer-ui';
12
+ import 'laranex-schema-viewer-ui/styles.css';
13
+
14
+ <SchemaViewer document={laranexSchemaDocument} />;
15
+ ```
16
+
17
+ ```js
18
+ import { validateDocument, buildGraph, canonicalJson } from 'laranex-schema-viewer-ui/contract';
19
+ ```
20
+
21
+ Hosts without Node.js serve `node_modules/laranex-schema-viewer-ui/dist/viewer/` as static files with a
22
+ `snapshot.json` beside `index.html`, or use `<laranex-schema-viewer src="snapshot.json">`.
23
+
24
+ ## License
25
+
26
+ MIT. See [LICENSE](LICENSE) and [NOTICE](NOTICE).
@@ -0,0 +1,53 @@
1
+ #!/usr/bin/env node
2
+ // Checks laranex-schema documents a producer wrote, for Laravel, Python and Node.js CI alike:
3
+ //
4
+ // node node_modules/laranex-schema-viewer-ui/contract/check.mjs [--lenient] [--no-graph] [--no-canonical] FILE...
5
+ //
6
+ // By default a document must pass strict validation, store exactly the links the shared graph builder produces, and
7
+ // be written in canonical form. Exits 1 when any file fails.
8
+ import { readFileSync } from 'node:fs';
9
+ import { buildGraph, canonicalJson, validateDocument } from '../dist/lib/contract.js';
10
+
11
+ const args = process.argv.slice(2);
12
+ const flags = new Set(args.filter((a) => a.startsWith('--')));
13
+ const files = args.filter((a) => !a.startsWith('--'));
14
+ if (files.length === 0 || flags.has('--help')) {
15
+ console.error('usage: check.mjs [--lenient] [--no-graph] [--no-canonical] FILE...');
16
+ process.exit(files.length === 0 ? 2 : 0);
17
+ }
18
+
19
+ let failed = false;
20
+ for (const file of files) {
21
+ const problems = [];
22
+ const text = readFileSync(file, 'utf8');
23
+ let doc;
24
+ try {
25
+ doc = JSON.parse(text);
26
+ } catch (error) {
27
+ problems.push(`not JSON: ${error.message}`);
28
+ }
29
+ if (doc !== undefined) {
30
+ const result = validateDocument(doc, { strict: !flags.has('--lenient') });
31
+ problems.push(...result.errors);
32
+ if (result.ok && !flags.has('--no-graph')) {
33
+ const expected = buildGraph(doc);
34
+ if (canonicalJson(expected.links) !== canonicalJson(doc.links)) {
35
+ problems.push('links differ from the shared graph builder');
36
+ }
37
+ if (canonicalJson(expected.derivedLinks) !== canonicalJson(doc.derivedLinks)) {
38
+ problems.push('derivedLinks differ from the shared graph builder');
39
+ }
40
+ }
41
+ if (!flags.has('--no-canonical') && canonicalJson(doc) !== text) {
42
+ problems.push('not in canonical form (sorted keys, two-space indentation, trailing newline)');
43
+ }
44
+ }
45
+ if (problems.length) {
46
+ failed = true;
47
+ console.error(`✗ ${file}`);
48
+ problems.forEach((p) => console.error(` ${p}`));
49
+ } else {
50
+ console.log(`✓ ${file}`);
51
+ }
52
+ }
53
+ process.exit(failed ? 1 : 0);
@@ -0,0 +1,222 @@
1
+ {
2
+ "description": "Composite keys match as unordered column pairs; the link keeps the foreign key column order",
3
+ "expected": {
4
+ "derivedLinks": [],
5
+ "links": [
6
+ {
7
+ "foreignKey": "t:lines:fk:lines_product_fk",
8
+ "from": {
9
+ "columns": [
10
+ "sku",
11
+ "region"
12
+ ],
13
+ "table": "t:lines"
14
+ },
15
+ "id": "l14daded68942fdde",
16
+ "note": null,
17
+ "polymorphic": false,
18
+ "relationships": [
19
+ "r:product"
20
+ ],
21
+ "state": "both",
22
+ "to": {
23
+ "columns": [
24
+ "sku",
25
+ "region"
26
+ ],
27
+ "table": "t:products"
28
+ }
29
+ }
30
+ ]
31
+ },
32
+ "input": {
33
+ "connections": [
34
+ {
35
+ "coverage": {
36
+ "database": null,
37
+ "declared": null
38
+ },
39
+ "defaultSchema": null,
40
+ "driver": "pgsql",
41
+ "id": "connection:c",
42
+ "name": "c",
43
+ "tables": [
44
+ {
45
+ "columns": [
46
+ {
47
+ "autoIncrement": false,
48
+ "collation": null,
49
+ "comment": null,
50
+ "default": null,
51
+ "enum": null,
52
+ "generated": null,
53
+ "name": "sku",
54
+ "note": null,
55
+ "nullable": false,
56
+ "ormDefault": null,
57
+ "provenance": [
58
+ "database"
59
+ ],
60
+ "timezone": null,
61
+ "type": "integer",
62
+ "typeName": "integer"
63
+ },
64
+ {
65
+ "autoIncrement": false,
66
+ "collation": null,
67
+ "comment": null,
68
+ "default": null,
69
+ "enum": null,
70
+ "generated": null,
71
+ "name": "region",
72
+ "note": null,
73
+ "nullable": false,
74
+ "ormDefault": null,
75
+ "provenance": [
76
+ "database"
77
+ ],
78
+ "timezone": null,
79
+ "type": "integer",
80
+ "typeName": "integer"
81
+ }
82
+ ],
83
+ "comment": null,
84
+ "constraints": [],
85
+ "foreignKeys": [
86
+ {
87
+ "columns": [
88
+ "sku",
89
+ "region"
90
+ ],
91
+ "deferrable": null,
92
+ "foreignColumns": [
93
+ "sku",
94
+ "region"
95
+ ],
96
+ "foreignTable": "t:products",
97
+ "id": "t:lines:fk:lines_product_fk",
98
+ "initially": null,
99
+ "name": "lines_product_fk",
100
+ "onDelete": null,
101
+ "onUpdate": null,
102
+ "provenance": [
103
+ "database"
104
+ ]
105
+ }
106
+ ],
107
+ "id": "t:lines",
108
+ "indexes": [],
109
+ "name": "lines",
110
+ "note": null,
111
+ "owner": {
112
+ "kind": "application",
113
+ "package": null
114
+ },
115
+ "primaryKey": [],
116
+ "provenance": [
117
+ "database"
118
+ ],
119
+ "schema": null
120
+ },
121
+ {
122
+ "columns": [
123
+ {
124
+ "autoIncrement": false,
125
+ "collation": null,
126
+ "comment": null,
127
+ "default": null,
128
+ "enum": null,
129
+ "generated": null,
130
+ "name": "sku",
131
+ "note": null,
132
+ "nullable": false,
133
+ "ormDefault": null,
134
+ "provenance": [
135
+ "database"
136
+ ],
137
+ "timezone": null,
138
+ "type": "integer",
139
+ "typeName": "integer"
140
+ },
141
+ {
142
+ "autoIncrement": false,
143
+ "collation": null,
144
+ "comment": null,
145
+ "default": null,
146
+ "enum": null,
147
+ "generated": null,
148
+ "name": "region",
149
+ "note": null,
150
+ "nullable": false,
151
+ "ormDefault": null,
152
+ "provenance": [
153
+ "database"
154
+ ],
155
+ "timezone": null,
156
+ "type": "integer",
157
+ "typeName": "integer"
158
+ }
159
+ ],
160
+ "comment": null,
161
+ "constraints": [],
162
+ "foreignKeys": [],
163
+ "id": "t:products",
164
+ "indexes": [],
165
+ "name": "products",
166
+ "note": null,
167
+ "owner": {
168
+ "kind": "application",
169
+ "package": null
170
+ },
171
+ "primaryKey": [
172
+ "sku",
173
+ "region"
174
+ ],
175
+ "provenance": [
176
+ "database"
177
+ ],
178
+ "schema": null
179
+ }
180
+ ]
181
+ }
182
+ ],
183
+ "relationships": [
184
+ {
185
+ "cardinality": "many-to-one",
186
+ "collection": false,
187
+ "constraints": [],
188
+ "id": "r:product",
189
+ "inverse": null,
190
+ "join": null,
191
+ "keys": {
192
+ "from": {
193
+ "columns": [
194
+ "region",
195
+ "sku"
196
+ ],
197
+ "table": "t:lines"
198
+ },
199
+ "to": {
200
+ "columns": [
201
+ "region",
202
+ "sku"
203
+ ],
204
+ "table": "t:products"
205
+ }
206
+ },
207
+ "model": "m",
208
+ "name": "r:product",
209
+ "note": null,
210
+ "pivot": null,
211
+ "polymorphic": null,
212
+ "readOnly": false,
213
+ "relatedModel": null,
214
+ "relatedTable": "t:products",
215
+ "source": null,
216
+ "table": "t:lines",
217
+ "through": null,
218
+ "type": "test"
219
+ }
220
+ ]
221
+ }
222
+ }
@@ -0,0 +1,153 @@
1
+ {
2
+ "description": "A foreign key naming a table in another connection has no link: constraints never cross connections",
3
+ "expected": {
4
+ "derivedLinks": [],
5
+ "links": []
6
+ },
7
+ "input": {
8
+ "connections": [
9
+ {
10
+ "coverage": {
11
+ "database": null,
12
+ "declared": null
13
+ },
14
+ "defaultSchema": null,
15
+ "driver": "pgsql",
16
+ "id": "connection:a",
17
+ "name": "a",
18
+ "tables": [
19
+ {
20
+ "columns": [
21
+ {
22
+ "autoIncrement": false,
23
+ "collation": null,
24
+ "comment": null,
25
+ "default": null,
26
+ "enum": null,
27
+ "generated": null,
28
+ "name": "id",
29
+ "note": null,
30
+ "nullable": false,
31
+ "ormDefault": null,
32
+ "provenance": [
33
+ "database"
34
+ ],
35
+ "timezone": null,
36
+ "type": "integer",
37
+ "typeName": "integer"
38
+ }
39
+ ],
40
+ "comment": null,
41
+ "constraints": [],
42
+ "foreignKeys": [],
43
+ "id": "a:users",
44
+ "indexes": [],
45
+ "name": "users",
46
+ "note": null,
47
+ "owner": {
48
+ "kind": "application",
49
+ "package": null
50
+ },
51
+ "primaryKey": [
52
+ "id"
53
+ ],
54
+ "provenance": [
55
+ "database"
56
+ ],
57
+ "schema": null
58
+ }
59
+ ]
60
+ },
61
+ {
62
+ "coverage": {
63
+ "database": null,
64
+ "declared": null
65
+ },
66
+ "defaultSchema": null,
67
+ "driver": "mysql",
68
+ "id": "connection:b",
69
+ "name": "b",
70
+ "tables": [
71
+ {
72
+ "columns": [
73
+ {
74
+ "autoIncrement": false,
75
+ "collation": null,
76
+ "comment": null,
77
+ "default": null,
78
+ "enum": null,
79
+ "generated": null,
80
+ "name": "id",
81
+ "note": null,
82
+ "nullable": false,
83
+ "ormDefault": null,
84
+ "provenance": [
85
+ "database"
86
+ ],
87
+ "timezone": null,
88
+ "type": "integer",
89
+ "typeName": "integer"
90
+ },
91
+ {
92
+ "autoIncrement": false,
93
+ "collation": null,
94
+ "comment": null,
95
+ "default": null,
96
+ "enum": null,
97
+ "generated": null,
98
+ "name": "user_id",
99
+ "note": null,
100
+ "nullable": false,
101
+ "ormDefault": null,
102
+ "provenance": [
103
+ "database"
104
+ ],
105
+ "timezone": null,
106
+ "type": "integer",
107
+ "typeName": "integer"
108
+ }
109
+ ],
110
+ "comment": null,
111
+ "constraints": [],
112
+ "foreignKeys": [
113
+ {
114
+ "columns": [
115
+ "user_id"
116
+ ],
117
+ "deferrable": null,
118
+ "foreignColumns": [
119
+ "id"
120
+ ],
121
+ "foreignTable": "a:users",
122
+ "id": "b:sessions:fk:sessions_user_fk",
123
+ "initially": null,
124
+ "name": "sessions_user_fk",
125
+ "onDelete": null,
126
+ "onUpdate": null,
127
+ "provenance": [
128
+ "database"
129
+ ]
130
+ }
131
+ ],
132
+ "id": "b:sessions",
133
+ "indexes": [],
134
+ "name": "sessions",
135
+ "note": null,
136
+ "owner": {
137
+ "kind": "application",
138
+ "package": null
139
+ },
140
+ "primaryKey": [
141
+ "id"
142
+ ],
143
+ "provenance": [
144
+ "database"
145
+ ],
146
+ "schema": null
147
+ }
148
+ ]
149
+ }
150
+ ],
151
+ "relationships": []
152
+ }
153
+ }
@@ -0,0 +1,192 @@
1
+ {
2
+ "description": "A relationship from a table in one connection to a table in another is a relationship link; no constraint is implied",
3
+ "expected": {
4
+ "derivedLinks": [],
5
+ "links": [
6
+ {
7
+ "foreignKey": null,
8
+ "from": {
9
+ "columns": [
10
+ "user_id"
11
+ ],
12
+ "table": "b:sessions"
13
+ },
14
+ "id": "lf0820d9a701f3777",
15
+ "note": null,
16
+ "polymorphic": false,
17
+ "relationships": [
18
+ "r:user"
19
+ ],
20
+ "state": "relationship",
21
+ "to": {
22
+ "columns": [
23
+ "id"
24
+ ],
25
+ "table": "a:users"
26
+ }
27
+ }
28
+ ]
29
+ },
30
+ "input": {
31
+ "connections": [
32
+ {
33
+ "coverage": {
34
+ "database": null,
35
+ "declared": null
36
+ },
37
+ "defaultSchema": null,
38
+ "driver": "pgsql",
39
+ "id": "connection:a",
40
+ "name": "a",
41
+ "tables": [
42
+ {
43
+ "columns": [
44
+ {
45
+ "autoIncrement": false,
46
+ "collation": null,
47
+ "comment": null,
48
+ "default": null,
49
+ "enum": null,
50
+ "generated": null,
51
+ "name": "id",
52
+ "note": null,
53
+ "nullable": false,
54
+ "ormDefault": null,
55
+ "provenance": [
56
+ "database"
57
+ ],
58
+ "timezone": null,
59
+ "type": "integer",
60
+ "typeName": "integer"
61
+ }
62
+ ],
63
+ "comment": null,
64
+ "constraints": [],
65
+ "foreignKeys": [],
66
+ "id": "a:users",
67
+ "indexes": [],
68
+ "name": "users",
69
+ "note": null,
70
+ "owner": {
71
+ "kind": "application",
72
+ "package": null
73
+ },
74
+ "primaryKey": [
75
+ "id"
76
+ ],
77
+ "provenance": [
78
+ "database"
79
+ ],
80
+ "schema": null
81
+ }
82
+ ]
83
+ },
84
+ {
85
+ "coverage": {
86
+ "database": null,
87
+ "declared": null
88
+ },
89
+ "defaultSchema": null,
90
+ "driver": "mysql",
91
+ "id": "connection:b",
92
+ "name": "b",
93
+ "tables": [
94
+ {
95
+ "columns": [
96
+ {
97
+ "autoIncrement": false,
98
+ "collation": null,
99
+ "comment": null,
100
+ "default": null,
101
+ "enum": null,
102
+ "generated": null,
103
+ "name": "id",
104
+ "note": null,
105
+ "nullable": false,
106
+ "ormDefault": null,
107
+ "provenance": [
108
+ "database"
109
+ ],
110
+ "timezone": null,
111
+ "type": "integer",
112
+ "typeName": "integer"
113
+ },
114
+ {
115
+ "autoIncrement": false,
116
+ "collation": null,
117
+ "comment": null,
118
+ "default": null,
119
+ "enum": null,
120
+ "generated": null,
121
+ "name": "user_id",
122
+ "note": null,
123
+ "nullable": false,
124
+ "ormDefault": null,
125
+ "provenance": [
126
+ "database"
127
+ ],
128
+ "timezone": null,
129
+ "type": "integer",
130
+ "typeName": "integer"
131
+ }
132
+ ],
133
+ "comment": null,
134
+ "constraints": [],
135
+ "foreignKeys": [],
136
+ "id": "b:sessions",
137
+ "indexes": [],
138
+ "name": "sessions",
139
+ "note": null,
140
+ "owner": {
141
+ "kind": "application",
142
+ "package": null
143
+ },
144
+ "primaryKey": [
145
+ "id"
146
+ ],
147
+ "provenance": [
148
+ "database"
149
+ ],
150
+ "schema": null
151
+ }
152
+ ]
153
+ }
154
+ ],
155
+ "relationships": [
156
+ {
157
+ "cardinality": "many-to-one",
158
+ "collection": false,
159
+ "constraints": [],
160
+ "id": "r:user",
161
+ "inverse": null,
162
+ "join": null,
163
+ "keys": {
164
+ "from": {
165
+ "columns": [
166
+ "user_id"
167
+ ],
168
+ "table": "b:sessions"
169
+ },
170
+ "to": {
171
+ "columns": [
172
+ "id"
173
+ ],
174
+ "table": "a:users"
175
+ }
176
+ },
177
+ "model": "m",
178
+ "name": "r:user",
179
+ "note": null,
180
+ "pivot": null,
181
+ "polymorphic": null,
182
+ "readOnly": false,
183
+ "relatedModel": null,
184
+ "relatedTable": "a:users",
185
+ "source": null,
186
+ "table": "b:sessions",
187
+ "through": null,
188
+ "type": "test"
189
+ }
190
+ ]
191
+ }
192
+ }