meadow-integration 1.0.5 → 1.0.6
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/.dockerignore +11 -0
- package/Docker-Build.sh +2 -0
- package/Docker-Compose.sh +2 -0
- package/Docker-Push.sh +2 -0
- package/Docker-Tag.sh +2 -0
- package/Dockerfile +28 -0
- package/Dockerfile_LUXURYCode +23 -0
- package/README.md +139 -25
- package/docker-compose.yml +16 -0
- package/docs/README.md +65 -18
- package/docs/_cover.md +3 -2
- package/docs/_sidebar.md +52 -7
- package/docs/_topbar.md +2 -0
- package/docs/api/clone-rest-client.md +278 -0
- package/docs/api/connection-manager.md +179 -0
- package/docs/api/guid-map.md +234 -0
- package/docs/api/integration-adapter.md +283 -0
- package/docs/api/operation.md +241 -0
- package/docs/api/sync-entity-initial.md +227 -0
- package/docs/api/sync-entity-ongoing.md +244 -0
- package/docs/api/sync.md +213 -0
- package/docs/api/tabular-check.md +213 -0
- package/docs/api/tabular-transform.md +316 -0
- package/docs/architecture.md +423 -0
- package/docs/cli/comprehensionarray.md +111 -0
- package/docs/cli/comprehensionintersect.md +132 -0
- package/docs/cli/csvcheck.md +111 -0
- package/docs/cli/csvtransform.md +170 -0
- package/docs/cli/data-clone.md +277 -0
- package/docs/cli/jsonarraytransform.md +166 -0
- package/docs/cli/load-comprehension.md +129 -0
- package/docs/cli/objectarraytocsv.md +159 -0
- package/docs/cli/overview.md +96 -0
- package/docs/cli/serve.md +102 -0
- package/docs/cli/tsvtransform.md +144 -0
- package/docs/data-clone/configuration.md +357 -0
- package/docs/data-clone/connection-manager.md +206 -0
- package/docs/data-clone/docker.md +290 -0
- package/docs/data-clone/overview.md +173 -0
- package/docs/data-clone/sync-modes.md +186 -0
- package/docs/implementation-reference.md +311 -0
- package/docs/overview.md +156 -0
- package/docs/quickstart.md +233 -0
- package/docs/rest/comprehension-push.md +209 -0
- package/docs/rest/comprehension.md +506 -0
- package/docs/rest/csv.md +255 -0
- package/docs/rest/entity-generation.md +158 -0
- package/docs/rest/json-array.md +243 -0
- package/docs/rest/overview.md +120 -0
- package/docs/rest/status.md +63 -0
- package/docs/rest/tsv.md +241 -0
- package/docs/retold-catalog.json +93 -3
- package/docs/retold-keyword-index.json +23683 -1901
- package/package.json +6 -3
- package/scripts/run.sh +18 -0
- package/source/Meadow-Integration.js +15 -1
- package/source/cli/Default-Meadow-Integration-Configuration.json +37 -2
- package/source/cli/Meadow-Integration-CLI-Program.js +4 -1
- package/source/cli/commands/Meadow-Integration-Command-DataClone.js +284 -0
- package/source/services/clone/Meadow-Service-ConnectionManager.js +251 -0
- package/source/services/clone/Meadow-Service-Operation.js +196 -0
- package/source/services/clone/Meadow-Service-RestClient.js +364 -0
- package/source/services/clone/Meadow-Service-Sync-Entity-Initial.js +367 -0
- package/source/services/clone/Meadow-Service-Sync-Entity-Ongoing.js +457 -0
- package/source/services/clone/Meadow-Service-Sync.js +142 -0
- /package/docs/examples/bookstore/{mapping_books_Author.json → mapping_books_author.json} +0 -0
- /package/docs/examples/bookstore/{mapping_books_Book.json → mapping_books_book.json} +0 -0
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
# Comprehension Push Endpoints
|
|
2
|
+
|
|
3
|
+
These endpoints push comprehension data to Meadow REST API servers using the Integration Adapter. Each entity in the comprehension is pushed via create/upsert operations against the target API.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## POST /1.0/Comprehension/Push
|
|
8
|
+
|
|
9
|
+
Push an in-memory comprehension object to Meadow REST APIs.
|
|
10
|
+
|
|
11
|
+
### Request Body
|
|
12
|
+
|
|
13
|
+
| Property | Type | Required | Default | Description |
|
|
14
|
+
|----------|------|----------|---------|-------------|
|
|
15
|
+
| `Comprehension` | object | Yes | - | The comprehension object to push |
|
|
16
|
+
| `ServerURL` | string | No | Configured default | Target Meadow API server base URL (e.g. `http://localhost:8080/1.0/`) |
|
|
17
|
+
| `GUIDPrefix` | string | No | - | GUID prefix applied across the entire adapter set |
|
|
18
|
+
| `EntityGUIDPrefix` | string | No | - | GUID prefix applied per entity |
|
|
19
|
+
|
|
20
|
+
### Response
|
|
21
|
+
|
|
22
|
+
```json
|
|
23
|
+
{
|
|
24
|
+
"Success": true,
|
|
25
|
+
"EntitiesPushed": ["Book", "Author"],
|
|
26
|
+
"Message": "Pushed comprehension for 2 entity(ies)."
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### Error Responses
|
|
31
|
+
|
|
32
|
+
| Status | Condition |
|
|
33
|
+
|--------|-----------|
|
|
34
|
+
| 400 | No valid `Comprehension` object provided |
|
|
35
|
+
| 500 | Error during the push operation |
|
|
36
|
+
|
|
37
|
+
### curl Example
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
curl -s -X POST http://localhost:8086/1.0/Comprehension/Push \
|
|
41
|
+
-H "Content-Type: application/json" \
|
|
42
|
+
-d '{
|
|
43
|
+
"Comprehension": {
|
|
44
|
+
"Book": {
|
|
45
|
+
"B001": { "GUIDBook": "B001", "Title": "Dune", "Author": "Frank Herbert" },
|
|
46
|
+
"B002": { "GUIDBook": "B002", "Title": "Neuromancer", "Author": "William Gibson" }
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
"ServerURL": "http://localhost:8080/1.0/"
|
|
50
|
+
}'
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
With GUID prefix:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
curl -s -X POST http://localhost:8086/1.0/Comprehension/Push \
|
|
57
|
+
-H "Content-Type: application/json" \
|
|
58
|
+
-d '{
|
|
59
|
+
"Comprehension": {
|
|
60
|
+
"Book": {
|
|
61
|
+
"B001": { "GUIDBook": "B001", "Title": "Dune" }
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
"ServerURL": "http://localhost:8080/1.0/",
|
|
65
|
+
"GUIDPrefix": "INTG-",
|
|
66
|
+
"EntityGUIDPrefix": "BK-"
|
|
67
|
+
}'
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### JavaScript Example (dependency-free)
|
|
71
|
+
|
|
72
|
+
```javascript
|
|
73
|
+
const http = require('http');
|
|
74
|
+
|
|
75
|
+
const requestBody = JSON.stringify({
|
|
76
|
+
Comprehension: {
|
|
77
|
+
Book: {
|
|
78
|
+
'B001': { GUIDBook: 'B001', Title: 'Dune', Author: 'Frank Herbert' },
|
|
79
|
+
'B002': { GUIDBook: 'B002', Title: 'Neuromancer', Author: 'William Gibson' }
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
ServerURL: 'http://localhost:8080/1.0/'
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
const options = {
|
|
86
|
+
hostname: 'localhost',
|
|
87
|
+
port: 8086,
|
|
88
|
+
path: '/1.0/Comprehension/Push',
|
|
89
|
+
method: 'POST',
|
|
90
|
+
headers: {
|
|
91
|
+
'Content-Type': 'application/json',
|
|
92
|
+
'Content-Length': Buffer.byteLength(requestBody)
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
const req = http.request(options, (res) => {
|
|
97
|
+
let data = '';
|
|
98
|
+
res.on('data', (chunk) => { data += chunk; });
|
|
99
|
+
res.on('end', () => {
|
|
100
|
+
const result = JSON.parse(data);
|
|
101
|
+
if (result.Success) {
|
|
102
|
+
console.log('Push successful!');
|
|
103
|
+
console.log('Entities pushed:', result.EntitiesPushed.join(', '));
|
|
104
|
+
} else {
|
|
105
|
+
console.error('Push failed:', result.Error);
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
req.on('error', (err) => { console.error('Request error:', err.message); });
|
|
110
|
+
req.write(requestBody);
|
|
111
|
+
req.end();
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## POST /1.0/Comprehension/PushFile
|
|
117
|
+
|
|
118
|
+
Push a comprehension stored in a JSON file to Meadow REST APIs.
|
|
119
|
+
|
|
120
|
+
### Request Body
|
|
121
|
+
|
|
122
|
+
| Property | Type | Required | Default | Description |
|
|
123
|
+
|----------|------|----------|---------|-------------|
|
|
124
|
+
| `File` | string | Yes | - | Path to a comprehension JSON file |
|
|
125
|
+
| `ServerURL` | string | No | Configured default | Target Meadow API server base URL |
|
|
126
|
+
| `GUIDPrefix` | string | No | - | GUID prefix applied across the entire adapter set |
|
|
127
|
+
| `EntityGUIDPrefix` | string | No | - | GUID prefix applied per entity |
|
|
128
|
+
|
|
129
|
+
### Response
|
|
130
|
+
|
|
131
|
+
```json
|
|
132
|
+
{
|
|
133
|
+
"Success": true,
|
|
134
|
+
"EntitiesPushed": ["Book"],
|
|
135
|
+
"Message": "Pushed comprehension for 1 entity(ies)."
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### Error Responses
|
|
140
|
+
|
|
141
|
+
| Status | Condition |
|
|
142
|
+
|--------|-----------|
|
|
143
|
+
| 400 | Missing `File` or file is not valid JSON |
|
|
144
|
+
| 404 | File does not exist |
|
|
145
|
+
| 500 | Error during the push operation |
|
|
146
|
+
|
|
147
|
+
### curl Example
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
curl -s -X POST http://localhost:8086/1.0/Comprehension/PushFile \
|
|
151
|
+
-H "Content-Type: application/json" \
|
|
152
|
+
-d '{
|
|
153
|
+
"File": "/data/books_comprehension.json",
|
|
154
|
+
"ServerURL": "http://localhost:8080/1.0/"
|
|
155
|
+
}'
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### JavaScript Example (dependency-free)
|
|
159
|
+
|
|
160
|
+
```javascript
|
|
161
|
+
const http = require('http');
|
|
162
|
+
|
|
163
|
+
const requestBody = JSON.stringify({
|
|
164
|
+
File: '/data/books_comprehension.json',
|
|
165
|
+
ServerURL: 'http://localhost:8080/1.0/'
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
const options = {
|
|
169
|
+
hostname: 'localhost',
|
|
170
|
+
port: 8086,
|
|
171
|
+
path: '/1.0/Comprehension/PushFile',
|
|
172
|
+
method: 'POST',
|
|
173
|
+
headers: {
|
|
174
|
+
'Content-Type': 'application/json',
|
|
175
|
+
'Content-Length': Buffer.byteLength(requestBody)
|
|
176
|
+
}
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
const req = http.request(options, (res) => {
|
|
180
|
+
let data = '';
|
|
181
|
+
res.on('data', (chunk) => { data += chunk; });
|
|
182
|
+
res.on('end', () => {
|
|
183
|
+
const result = JSON.parse(data);
|
|
184
|
+
if (result.Success) {
|
|
185
|
+
console.log('Push successful!');
|
|
186
|
+
console.log('Entities pushed:', result.EntitiesPushed.join(', '));
|
|
187
|
+
console.log(result.Message);
|
|
188
|
+
} else {
|
|
189
|
+
console.error('Push failed:', result.Error);
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
});
|
|
193
|
+
req.on('error', (err) => { console.error('Request error:', err.message); });
|
|
194
|
+
req.write(requestBody);
|
|
195
|
+
req.end();
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
---
|
|
199
|
+
|
|
200
|
+
## How the Push Works
|
|
201
|
+
|
|
202
|
+
The push operation uses the Meadow Integration Adapter to send records to a target Meadow REST API server:
|
|
203
|
+
|
|
204
|
+
1. Each top-level key in the comprehension is treated as an entity name.
|
|
205
|
+
2. An Integration Adapter is created for each entity.
|
|
206
|
+
3. All records under that entity are added as source records.
|
|
207
|
+
4. The adapter calls `integrateRecords`, which issues create or upsert calls to the target server.
|
|
208
|
+
|
|
209
|
+
The GUID prefix is derived automatically from the capital letters of the entity name (e.g. `BookAuthor` becomes `BA`), but you can override it with `GUIDPrefix` and `EntityGUIDPrefix`.
|
|
@@ -0,0 +1,506 @@
|
|
|
1
|
+
# Comprehension Endpoints
|
|
2
|
+
|
|
3
|
+
These endpoints operate on comprehension objects -- GUID-keyed hashes of entity records. They provide intersection (merging), conversion to arrays, and conversion to CSV.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## POST /1.0/Comprehension/Intersect
|
|
8
|
+
|
|
9
|
+
Merge two in-memory comprehension objects together. Records from the secondary comprehension are merged into the primary. When both comprehensions contain the same GUID, the secondary record's properties are merged onto the primary record using `Object.assign`.
|
|
10
|
+
|
|
11
|
+
### Request Body
|
|
12
|
+
|
|
13
|
+
| Property | Type | Required | Default | Description |
|
|
14
|
+
|----------|------|----------|---------|-------------|
|
|
15
|
+
| `PrimaryComprehension` | object | Yes | - | The primary comprehension object |
|
|
16
|
+
| `SecondaryComprehension` | object | Yes | - | The secondary comprehension to merge in |
|
|
17
|
+
| `Entity` | string | No | Auto-inferred from first key | Entity name to intersect on |
|
|
18
|
+
|
|
19
|
+
### Response
|
|
20
|
+
|
|
21
|
+
Returns the merged comprehension object.
|
|
22
|
+
|
|
23
|
+
### Error Responses
|
|
24
|
+
|
|
25
|
+
| Status | Condition |
|
|
26
|
+
|--------|-----------|
|
|
27
|
+
| 400 | Missing `PrimaryComprehension` or `SecondaryComprehension`, or no entity could be inferred |
|
|
28
|
+
|
|
29
|
+
### curl Example
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
curl -s -X POST http://localhost:8086/1.0/Comprehension/Intersect \
|
|
33
|
+
-H "Content-Type: application/json" \
|
|
34
|
+
-d '{
|
|
35
|
+
"PrimaryComprehension": {
|
|
36
|
+
"Book": {
|
|
37
|
+
"B001": { "GUIDBook": "B001", "title": "Dune" },
|
|
38
|
+
"B002": { "GUIDBook": "B002", "title": "Neuromancer" }
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
"SecondaryComprehension": {
|
|
42
|
+
"Book": {
|
|
43
|
+
"B001": { "GUIDBook": "B001", "author": "Frank Herbert" },
|
|
44
|
+
"B003": { "GUIDBook": "B003", "title": "Snow Crash", "author": "Neal Stephenson" }
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
"Entity": "Book"
|
|
48
|
+
}'
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### JavaScript Example (dependency-free)
|
|
52
|
+
|
|
53
|
+
```javascript
|
|
54
|
+
const http = require('http');
|
|
55
|
+
|
|
56
|
+
const requestBody = JSON.stringify({
|
|
57
|
+
PrimaryComprehension: {
|
|
58
|
+
Book: {
|
|
59
|
+
'B001': { GUIDBook: 'B001', title: 'Dune' },
|
|
60
|
+
'B002': { GUIDBook: 'B002', title: 'Neuromancer' }
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
SecondaryComprehension: {
|
|
64
|
+
Book: {
|
|
65
|
+
'B001': { GUIDBook: 'B001', author: 'Frank Herbert' },
|
|
66
|
+
'B003': { GUIDBook: 'B003', title: 'Snow Crash', author: 'Neal Stephenson' }
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
Entity: 'Book'
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
const options = {
|
|
73
|
+
hostname: 'localhost',
|
|
74
|
+
port: 8086,
|
|
75
|
+
path: '/1.0/Comprehension/Intersect',
|
|
76
|
+
method: 'POST',
|
|
77
|
+
headers: {
|
|
78
|
+
'Content-Type': 'application/json',
|
|
79
|
+
'Content-Length': Buffer.byteLength(requestBody)
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
const req = http.request(options, (res) => {
|
|
84
|
+
let data = '';
|
|
85
|
+
res.on('data', (chunk) => { data += chunk; });
|
|
86
|
+
res.on('end', () => {
|
|
87
|
+
const merged = JSON.parse(data);
|
|
88
|
+
console.log('Merged Books:', Object.keys(merged.Book).length);
|
|
89
|
+
// B001 now has both title and author
|
|
90
|
+
console.log('B001:', merged.Book['B001']);
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
req.on('error', (err) => { console.error('Request error:', err.message); });
|
|
94
|
+
req.write(requestBody);
|
|
95
|
+
req.end();
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
## POST /1.0/Comprehension/IntersectFiles
|
|
101
|
+
|
|
102
|
+
Merge two comprehension files together. Identical behavior to `/Intersect` but reads comprehensions from JSON files on disk.
|
|
103
|
+
|
|
104
|
+
### Request Body
|
|
105
|
+
|
|
106
|
+
| Property | Type | Required | Default | Description |
|
|
107
|
+
|----------|------|----------|---------|-------------|
|
|
108
|
+
| `File` | string | Yes | - | Path to the primary comprehension JSON file |
|
|
109
|
+
| `IntersectFile` | string | Yes | - | Path to the secondary comprehension JSON file |
|
|
110
|
+
| `Entity` | string | No | Auto-inferred | Entity name to intersect on |
|
|
111
|
+
|
|
112
|
+
### Error Responses
|
|
113
|
+
|
|
114
|
+
| Status | Condition |
|
|
115
|
+
|--------|-----------|
|
|
116
|
+
| 400 | Missing `File` or `IntersectFile`, or files are not valid JSON |
|
|
117
|
+
| 404 | Primary or secondary file does not exist |
|
|
118
|
+
|
|
119
|
+
### curl Example
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
curl -s -X POST http://localhost:8086/1.0/Comprehension/IntersectFiles \
|
|
123
|
+
-H "Content-Type: application/json" \
|
|
124
|
+
-d '{
|
|
125
|
+
"File": "/data/books_primary.json",
|
|
126
|
+
"IntersectFile": "/data/books_secondary.json",
|
|
127
|
+
"Entity": "Book"
|
|
128
|
+
}'
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### JavaScript Example (dependency-free)
|
|
132
|
+
|
|
133
|
+
```javascript
|
|
134
|
+
const http = require('http');
|
|
135
|
+
|
|
136
|
+
const requestBody = JSON.stringify({
|
|
137
|
+
File: '/data/books_primary.json',
|
|
138
|
+
IntersectFile: '/data/books_secondary.json',
|
|
139
|
+
Entity: 'Book'
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
const options = {
|
|
143
|
+
hostname: 'localhost',
|
|
144
|
+
port: 8086,
|
|
145
|
+
path: '/1.0/Comprehension/IntersectFiles',
|
|
146
|
+
method: 'POST',
|
|
147
|
+
headers: {
|
|
148
|
+
'Content-Type': 'application/json',
|
|
149
|
+
'Content-Length': Buffer.byteLength(requestBody)
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
const req = http.request(options, (res) => {
|
|
154
|
+
let data = '';
|
|
155
|
+
res.on('data', (chunk) => { data += chunk; });
|
|
156
|
+
res.on('end', () => {
|
|
157
|
+
const merged = JSON.parse(data);
|
|
158
|
+
console.log('Merged comprehension:', JSON.stringify(merged, null, 2));
|
|
159
|
+
});
|
|
160
|
+
});
|
|
161
|
+
req.on('error', (err) => { console.error('Request error:', err.message); });
|
|
162
|
+
req.write(requestBody);
|
|
163
|
+
req.end();
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
## POST /1.0/Comprehension/ToArray
|
|
169
|
+
|
|
170
|
+
Convert a GUID-keyed comprehension object into a flat array of records. This is useful when you need to iterate over records without dealing with GUID keys.
|
|
171
|
+
|
|
172
|
+
### Request Body
|
|
173
|
+
|
|
174
|
+
| Property | Type | Required | Default | Description |
|
|
175
|
+
|----------|------|----------|---------|-------------|
|
|
176
|
+
| `Comprehension` | object | Yes | - | The comprehension object to convert |
|
|
177
|
+
| `Entity` | string | No | Auto-inferred from first key | Entity name to extract records from |
|
|
178
|
+
|
|
179
|
+
### Response
|
|
180
|
+
|
|
181
|
+
Returns a JSON array of record objects:
|
|
182
|
+
|
|
183
|
+
```json
|
|
184
|
+
[
|
|
185
|
+
{ "GUIDBook": "B001", "title": "Dune", "author": "Frank Herbert" },
|
|
186
|
+
{ "GUIDBook": "B002", "title": "Neuromancer", "author": "William Gibson" }
|
|
187
|
+
]
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
### Error Responses
|
|
191
|
+
|
|
192
|
+
| Status | Condition |
|
|
193
|
+
|--------|-----------|
|
|
194
|
+
| 400 | Missing `Comprehension`, or no entity could be inferred |
|
|
195
|
+
|
|
196
|
+
### curl Example
|
|
197
|
+
|
|
198
|
+
```bash
|
|
199
|
+
curl -s -X POST http://localhost:8086/1.0/Comprehension/ToArray \
|
|
200
|
+
-H "Content-Type: application/json" \
|
|
201
|
+
-d '{
|
|
202
|
+
"Comprehension": {
|
|
203
|
+
"Book": {
|
|
204
|
+
"B001": { "GUIDBook": "B001", "title": "Dune" },
|
|
205
|
+
"B002": { "GUIDBook": "B002", "title": "Neuromancer" }
|
|
206
|
+
}
|
|
207
|
+
},
|
|
208
|
+
"Entity": "Book"
|
|
209
|
+
}'
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
### JavaScript Example (dependency-free)
|
|
213
|
+
|
|
214
|
+
```javascript
|
|
215
|
+
const http = require('http');
|
|
216
|
+
|
|
217
|
+
const requestBody = JSON.stringify({
|
|
218
|
+
Comprehension: {
|
|
219
|
+
Book: {
|
|
220
|
+
'B001': { GUIDBook: 'B001', title: 'Dune', author: 'Frank Herbert' },
|
|
221
|
+
'B002': { GUIDBook: 'B002', title: 'Neuromancer', author: 'William Gibson' }
|
|
222
|
+
}
|
|
223
|
+
},
|
|
224
|
+
Entity: 'Book'
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
const options = {
|
|
228
|
+
hostname: 'localhost',
|
|
229
|
+
port: 8086,
|
|
230
|
+
path: '/1.0/Comprehension/ToArray',
|
|
231
|
+
method: 'POST',
|
|
232
|
+
headers: {
|
|
233
|
+
'Content-Type': 'application/json',
|
|
234
|
+
'Content-Length': Buffer.byteLength(requestBody)
|
|
235
|
+
}
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
const req = http.request(options, (res) => {
|
|
239
|
+
let data = '';
|
|
240
|
+
res.on('data', (chunk) => { data += chunk; });
|
|
241
|
+
res.on('end', () => {
|
|
242
|
+
const records = JSON.parse(data);
|
|
243
|
+
console.log(`Converted ${records.length} records to array`);
|
|
244
|
+
records.forEach((rec) => {
|
|
245
|
+
console.log(` ${rec.GUIDBook}: ${rec.title}`);
|
|
246
|
+
});
|
|
247
|
+
});
|
|
248
|
+
});
|
|
249
|
+
req.on('error', (err) => { console.error('Request error:', err.message); });
|
|
250
|
+
req.write(requestBody);
|
|
251
|
+
req.end();
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
---
|
|
255
|
+
|
|
256
|
+
## POST /1.0/Comprehension/ToArrayFromFile
|
|
257
|
+
|
|
258
|
+
Convert a comprehension JSON file to an array of records.
|
|
259
|
+
|
|
260
|
+
### Request Body
|
|
261
|
+
|
|
262
|
+
| Property | Type | Required | Default | Description |
|
|
263
|
+
|----------|------|----------|---------|-------------|
|
|
264
|
+
| `File` | string | Yes | - | Path to a comprehension JSON file |
|
|
265
|
+
| `Entity` | string | No | Auto-inferred | Entity name to extract records from |
|
|
266
|
+
|
|
267
|
+
### Error Responses
|
|
268
|
+
|
|
269
|
+
| Status | Condition |
|
|
270
|
+
|--------|-----------|
|
|
271
|
+
| 400 | Missing `File`, or file is not valid JSON |
|
|
272
|
+
| 404 | File does not exist |
|
|
273
|
+
|
|
274
|
+
### curl Example
|
|
275
|
+
|
|
276
|
+
```bash
|
|
277
|
+
curl -s -X POST http://localhost:8086/1.0/Comprehension/ToArrayFromFile \
|
|
278
|
+
-H "Content-Type: application/json" \
|
|
279
|
+
-d '{
|
|
280
|
+
"File": "/data/books_comprehension.json",
|
|
281
|
+
"Entity": "Book"
|
|
282
|
+
}'
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
### JavaScript Example (dependency-free)
|
|
286
|
+
|
|
287
|
+
```javascript
|
|
288
|
+
const http = require('http');
|
|
289
|
+
|
|
290
|
+
const requestBody = JSON.stringify({
|
|
291
|
+
File: '/data/books_comprehension.json',
|
|
292
|
+
Entity: 'Book'
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
const options = {
|
|
296
|
+
hostname: 'localhost',
|
|
297
|
+
port: 8086,
|
|
298
|
+
path: '/1.0/Comprehension/ToArrayFromFile',
|
|
299
|
+
method: 'POST',
|
|
300
|
+
headers: {
|
|
301
|
+
'Content-Type': 'application/json',
|
|
302
|
+
'Content-Length': Buffer.byteLength(requestBody)
|
|
303
|
+
}
|
|
304
|
+
};
|
|
305
|
+
|
|
306
|
+
const req = http.request(options, (res) => {
|
|
307
|
+
let data = '';
|
|
308
|
+
res.on('data', (chunk) => { data += chunk; });
|
|
309
|
+
res.on('end', () => {
|
|
310
|
+
const records = JSON.parse(data);
|
|
311
|
+
console.log(`${records.length} records loaded from file`);
|
|
312
|
+
});
|
|
313
|
+
});
|
|
314
|
+
req.on('error', (err) => { console.error('Request error:', err.message); });
|
|
315
|
+
req.write(requestBody);
|
|
316
|
+
req.end();
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
---
|
|
320
|
+
|
|
321
|
+
## POST /1.0/Comprehension/ToCSV
|
|
322
|
+
|
|
323
|
+
Convert a comprehension or an array of records to CSV format. Nested objects are flattened using dot-notation keys. The response Content-Type is `text/csv`.
|
|
324
|
+
|
|
325
|
+
### Request Body
|
|
326
|
+
|
|
327
|
+
You can provide data in one of two forms:
|
|
328
|
+
|
|
329
|
+
**Option A -- Records array:**
|
|
330
|
+
|
|
331
|
+
| Property | Type | Required | Description |
|
|
332
|
+
|----------|------|----------|-------------|
|
|
333
|
+
| `Records` | array | Yes | Array of record objects |
|
|
334
|
+
|
|
335
|
+
**Option B -- Comprehension object:**
|
|
336
|
+
|
|
337
|
+
| Property | Type | Required | Description |
|
|
338
|
+
|----------|------|----------|-------------|
|
|
339
|
+
| `Comprehension` | object | Yes | Comprehension object |
|
|
340
|
+
| `Entity` | string | No | Entity name (auto-detected if single entity) |
|
|
341
|
+
|
|
342
|
+
### Response
|
|
343
|
+
|
|
344
|
+
Returns raw CSV text with `Content-Type: text/csv`:
|
|
345
|
+
|
|
346
|
+
```
|
|
347
|
+
GUIDBook,author,title
|
|
348
|
+
B001,Frank Herbert,Dune
|
|
349
|
+
B002,William Gibson,Neuromancer
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
### Error Responses
|
|
353
|
+
|
|
354
|
+
| Status | Condition |
|
|
355
|
+
|--------|-----------|
|
|
356
|
+
| 400 | No valid `Records` or `Comprehension` provided, empty records, or multiple entities without `Entity` specified |
|
|
357
|
+
|
|
358
|
+
### curl Example
|
|
359
|
+
|
|
360
|
+
From a records array:
|
|
361
|
+
|
|
362
|
+
```bash
|
|
363
|
+
curl -s -X POST http://localhost:8086/1.0/Comprehension/ToCSV \
|
|
364
|
+
-H "Content-Type: application/json" \
|
|
365
|
+
-d '{
|
|
366
|
+
"Records": [
|
|
367
|
+
{ "id": 1, "name": "Alice", "role": "Engineer" },
|
|
368
|
+
{ "id": 2, "name": "Bob", "role": "Designer" }
|
|
369
|
+
]
|
|
370
|
+
}'
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
From a comprehension:
|
|
374
|
+
|
|
375
|
+
```bash
|
|
376
|
+
curl -s -X POST http://localhost:8086/1.0/Comprehension/ToCSV \
|
|
377
|
+
-H "Content-Type: application/json" \
|
|
378
|
+
-d '{
|
|
379
|
+
"Comprehension": {
|
|
380
|
+
"Employee": {
|
|
381
|
+
"E1": { "id": 1, "name": "Alice" },
|
|
382
|
+
"E2": { "id": 2, "name": "Bob" }
|
|
383
|
+
}
|
|
384
|
+
},
|
|
385
|
+
"Entity": "Employee"
|
|
386
|
+
}'
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
### JavaScript Example (dependency-free)
|
|
390
|
+
|
|
391
|
+
```javascript
|
|
392
|
+
const http = require('http');
|
|
393
|
+
|
|
394
|
+
const requestBody = JSON.stringify({
|
|
395
|
+
Records: [
|
|
396
|
+
{ id: 1, name: 'Alice', role: 'Engineer' },
|
|
397
|
+
{ id: 2, name: 'Bob', role: 'Designer' },
|
|
398
|
+
{ id: 3, name: 'Carol', role: 'Manager' }
|
|
399
|
+
]
|
|
400
|
+
});
|
|
401
|
+
|
|
402
|
+
const options = {
|
|
403
|
+
hostname: 'localhost',
|
|
404
|
+
port: 8086,
|
|
405
|
+
path: '/1.0/Comprehension/ToCSV',
|
|
406
|
+
method: 'POST',
|
|
407
|
+
headers: {
|
|
408
|
+
'Content-Type': 'application/json',
|
|
409
|
+
'Content-Length': Buffer.byteLength(requestBody)
|
|
410
|
+
}
|
|
411
|
+
};
|
|
412
|
+
|
|
413
|
+
const req = http.request(options, (res) => {
|
|
414
|
+
let data = '';
|
|
415
|
+
res.on('data', (chunk) => { data += chunk; });
|
|
416
|
+
res.on('end', () => {
|
|
417
|
+
// Response is raw CSV text
|
|
418
|
+
console.log('CSV output:');
|
|
419
|
+
console.log(data);
|
|
420
|
+
});
|
|
421
|
+
});
|
|
422
|
+
req.on('error', (err) => { console.error('Request error:', err.message); });
|
|
423
|
+
req.write(requestBody);
|
|
424
|
+
req.end();
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
---
|
|
428
|
+
|
|
429
|
+
## POST /1.0/Comprehension/ToCSVFromFile
|
|
430
|
+
|
|
431
|
+
Convert a JSON file (containing either a comprehension or an array) to CSV format.
|
|
432
|
+
|
|
433
|
+
### Request Body
|
|
434
|
+
|
|
435
|
+
| Property | Type | Required | Default | Description |
|
|
436
|
+
|----------|------|----------|---------|-------------|
|
|
437
|
+
| `File` | string | Yes | - | Path to a JSON file (array or comprehension) |
|
|
438
|
+
| `Entity` | string | No | Auto-detected | Entity name (required if comprehension has multiple entities) |
|
|
439
|
+
|
|
440
|
+
### Response
|
|
441
|
+
|
|
442
|
+
Returns raw CSV text with `Content-Type: text/csv`.
|
|
443
|
+
|
|
444
|
+
### Error Responses
|
|
445
|
+
|
|
446
|
+
| Status | Condition |
|
|
447
|
+
|--------|-----------|
|
|
448
|
+
| 400 | Missing `File`, file is not valid JSON, or no records found |
|
|
449
|
+
| 404 | File does not exist |
|
|
450
|
+
|
|
451
|
+
### curl Example
|
|
452
|
+
|
|
453
|
+
```bash
|
|
454
|
+
curl -s -X POST http://localhost:8086/1.0/Comprehension/ToCSVFromFile \
|
|
455
|
+
-H "Content-Type: application/json" \
|
|
456
|
+
-d '{
|
|
457
|
+
"File": "/data/employees.json",
|
|
458
|
+
"Entity": "Employee"
|
|
459
|
+
}'
|
|
460
|
+
```
|
|
461
|
+
|
|
462
|
+
Save the CSV output to a file:
|
|
463
|
+
|
|
464
|
+
```bash
|
|
465
|
+
curl -s -X POST http://localhost:8086/1.0/Comprehension/ToCSVFromFile \
|
|
466
|
+
-H "Content-Type: application/json" \
|
|
467
|
+
-d '{
|
|
468
|
+
"File": "/data/employees.json"
|
|
469
|
+
}' > /data/employees.csv
|
|
470
|
+
```
|
|
471
|
+
|
|
472
|
+
### JavaScript Example (dependency-free)
|
|
473
|
+
|
|
474
|
+
```javascript
|
|
475
|
+
const http = require('http');
|
|
476
|
+
const fs = require('fs');
|
|
477
|
+
|
|
478
|
+
const requestBody = JSON.stringify({
|
|
479
|
+
File: '/data/employees.json',
|
|
480
|
+
Entity: 'Employee'
|
|
481
|
+
});
|
|
482
|
+
|
|
483
|
+
const options = {
|
|
484
|
+
hostname: 'localhost',
|
|
485
|
+
port: 8086,
|
|
486
|
+
path: '/1.0/Comprehension/ToCSVFromFile',
|
|
487
|
+
method: 'POST',
|
|
488
|
+
headers: {
|
|
489
|
+
'Content-Type': 'application/json',
|
|
490
|
+
'Content-Length': Buffer.byteLength(requestBody)
|
|
491
|
+
}
|
|
492
|
+
};
|
|
493
|
+
|
|
494
|
+
const req = http.request(options, (res) => {
|
|
495
|
+
let data = '';
|
|
496
|
+
res.on('data', (chunk) => { data += chunk; });
|
|
497
|
+
res.on('end', () => {
|
|
498
|
+
// Write CSV to file
|
|
499
|
+
fs.writeFileSync('/data/employees.csv', data);
|
|
500
|
+
console.log('CSV written to /data/employees.csv');
|
|
501
|
+
});
|
|
502
|
+
});
|
|
503
|
+
req.on('error', (err) => { console.error('Request error:', err.message); });
|
|
504
|
+
req.write(requestBody);
|
|
505
|
+
req.end();
|
|
506
|
+
```
|