@openfn/language-collections 0.8.6 → 0.9.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/configuration-schema.json +7 -0
- package/dist/index.cjs +100 -48
- package/dist/index.js +100 -48
- package/package.json +1 -1
- package/types/collections.d.ts +1 -1
- package/types/mock.d.ts +14 -9
|
@@ -23,6 +23,13 @@
|
|
|
23
23
|
"description": "Access token for the collection",
|
|
24
24
|
"writeOnly": true,
|
|
25
25
|
"examples": ["x.y.z"]
|
|
26
|
+
},
|
|
27
|
+
"project_id": {
|
|
28
|
+
"title": "Project Id",
|
|
29
|
+
"type": "string",
|
|
30
|
+
"description": "The project id for the run",
|
|
31
|
+
"writeOnly": true,
|
|
32
|
+
"examples": ["46569296-9d82-4a32-8737-fbe64b7851cf"]
|
|
26
33
|
}
|
|
27
34
|
},
|
|
28
35
|
"type": "object",
|
package/dist/index.cjs
CHANGED
|
@@ -52,28 +52,48 @@ var import_stream_json = __toESM(require("stream-json"), 1);
|
|
|
52
52
|
|
|
53
53
|
// src/mock.js
|
|
54
54
|
var import_undici = require("undici");
|
|
55
|
+
var MULTIPLE_MATCHES = "MULTIPLE_MATCHES_FOUND";
|
|
56
|
+
var UNKNOWN_PROJECT = "INVALID_PROJECT_ID";
|
|
55
57
|
var COLLECTION_NOT_FOUND = "COLLECTION_NOT_FOUND";
|
|
56
58
|
var INVALID_AUTH = "INVALID_AUTH";
|
|
57
59
|
function API() {
|
|
58
|
-
let
|
|
59
|
-
|
|
60
|
-
|
|
60
|
+
let collectionsByProject = {};
|
|
61
|
+
let collectionsByName = {};
|
|
62
|
+
const createCollection = (projectId, name, values = {}) => {
|
|
63
|
+
(collectionsByProject[projectId] ?? (collectionsByProject[projectId] = {}))[name] = values;
|
|
64
|
+
(collectionsByName[name] ?? (collectionsByName[name] = [])).push(values);
|
|
65
|
+
};
|
|
66
|
+
const getCollection = (projectId, name) => {
|
|
67
|
+
if (projectId) {
|
|
68
|
+
if (!(projectId in collectionsByProject)) {
|
|
69
|
+
throw new Error(UNKNOWN_PROJECT);
|
|
70
|
+
}
|
|
71
|
+
if (!(name in collectionsByProject[projectId])) {
|
|
72
|
+
throw new Error(COLLECTION_NOT_FOUND);
|
|
73
|
+
}
|
|
74
|
+
return collectionsByProject[projectId][name];
|
|
75
|
+
} else {
|
|
76
|
+
const results = collectionsByName[name] ?? [];
|
|
77
|
+
if (results.length === 0) {
|
|
78
|
+
throw new Error(COLLECTION_NOT_FOUND);
|
|
79
|
+
}
|
|
80
|
+
if (results.length > 1) {
|
|
81
|
+
throw new Error(MULTIPLE_MATCHES);
|
|
82
|
+
}
|
|
83
|
+
return collectionsByName[name][0];
|
|
84
|
+
}
|
|
61
85
|
};
|
|
62
86
|
const reset = () => {
|
|
63
|
-
|
|
87
|
+
api.collectionsByProject = collectionsByProject = {};
|
|
88
|
+
api.collectionsByName = collectionsByName = {};
|
|
64
89
|
};
|
|
65
|
-
const upsert = (name, key, value) => {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
}
|
|
69
|
-
collections[name][key] = value;
|
|
90
|
+
const upsert = (projectId, name, key, value) => {
|
|
91
|
+
const col = getCollection(projectId, name);
|
|
92
|
+
col[key] = value;
|
|
70
93
|
};
|
|
71
|
-
const fetch = (name, key, query = {}) => {
|
|
94
|
+
const fetch = (projectId, name, key, query = {}) => {
|
|
72
95
|
const { cursor = 0, limit = Infinity } = query;
|
|
73
|
-
|
|
74
|
-
throw new Error(COLLECTION_NOT_FOUND);
|
|
75
|
-
}
|
|
76
|
-
const col = collections[name];
|
|
96
|
+
const col = getCollection(projectId, name);
|
|
77
97
|
const items = [];
|
|
78
98
|
let idx = 0;
|
|
79
99
|
let count2 = 0;
|
|
@@ -99,29 +119,16 @@ function API() {
|
|
|
99
119
|
}
|
|
100
120
|
return result;
|
|
101
121
|
};
|
|
102
|
-
const
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
}
|
|
106
|
-
return collections[name][key];
|
|
122
|
+
const asJSON = (projectId, name, key) => {
|
|
123
|
+
const col = getCollection(projectId, name);
|
|
124
|
+
return JSON.parse(col[key]);
|
|
107
125
|
};
|
|
108
|
-
const
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
}
|
|
112
|
-
return JSON.parse(collections[name][key]);
|
|
126
|
+
const count = (projectId, name) => {
|
|
127
|
+
const col = getCollection(projectId, name);
|
|
128
|
+
return Object.keys(col).length;
|
|
113
129
|
};
|
|
114
|
-
const
|
|
115
|
-
|
|
116
|
-
throw new Error(COLLECTION_NOT_FOUND);
|
|
117
|
-
}
|
|
118
|
-
return Object.keys(collections[name]).length;
|
|
119
|
-
};
|
|
120
|
-
const remove2 = (name, key) => {
|
|
121
|
-
if (!(name in collections)) {
|
|
122
|
-
throw new Error(COLLECTION_NOT_FOUND);
|
|
123
|
-
}
|
|
124
|
-
const col = collections[name];
|
|
130
|
+
const remove2 = (projectId, name, key) => {
|
|
131
|
+
const col = getCollection(projectId, name);
|
|
125
132
|
const regex = new RegExp(key.replace("*", "(.*)"));
|
|
126
133
|
const removed = [];
|
|
127
134
|
for (const key2 in col) {
|
|
@@ -133,15 +140,16 @@ function API() {
|
|
|
133
140
|
return removed;
|
|
134
141
|
};
|
|
135
142
|
const api = {
|
|
136
|
-
|
|
143
|
+
asJSON,
|
|
144
|
+
collectionsByName,
|
|
145
|
+
collectionsByProject,
|
|
146
|
+
count,
|
|
137
147
|
createCollection,
|
|
138
|
-
reset,
|
|
139
|
-
upsert,
|
|
140
148
|
fetch,
|
|
149
|
+
getCollection,
|
|
141
150
|
remove: remove2,
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
count
|
|
151
|
+
reset,
|
|
152
|
+
upsert
|
|
145
153
|
};
|
|
146
154
|
return api;
|
|
147
155
|
}
|
|
@@ -165,6 +173,7 @@ function createServer(url = "https://app.openfn.org") {
|
|
|
165
173
|
const mockPool = agent.get(url);
|
|
166
174
|
const api = new API();
|
|
167
175
|
const get2 = (req) => {
|
|
176
|
+
var _a;
|
|
168
177
|
try {
|
|
169
178
|
assertAuth(req);
|
|
170
179
|
} catch (e) {
|
|
@@ -172,10 +181,12 @@ function createServer(url = "https://app.openfn.org") {
|
|
|
172
181
|
}
|
|
173
182
|
try {
|
|
174
183
|
let { name, key } = parsePath(req.path);
|
|
184
|
+
const projectId = ((_a = req.query) == null ? void 0 : _a.project_id) ?? null;
|
|
175
185
|
let body;
|
|
176
186
|
let statusCode = 200;
|
|
177
187
|
if (key) {
|
|
178
|
-
const
|
|
188
|
+
const collection = api.getCollection(projectId, name);
|
|
189
|
+
const result = collection[key];
|
|
179
190
|
if (!result) {
|
|
180
191
|
body = {};
|
|
181
192
|
statusCode = 204;
|
|
@@ -190,7 +201,7 @@ function createServer(url = "https://app.openfn.org") {
|
|
|
190
201
|
key = params.get("key") ?? "*";
|
|
191
202
|
const limit = params.get("limit") ?? Infinity;
|
|
192
203
|
const cursor = params.get("cursor") ?? 0;
|
|
193
|
-
const { items, cursor: finalCursor } = api.fetch(name, key, {
|
|
204
|
+
const { items, cursor: finalCursor } = api.fetch(projectId, name, key, {
|
|
194
205
|
limit,
|
|
195
206
|
cursor
|
|
196
207
|
});
|
|
@@ -207,13 +218,17 @@ function createServer(url = "https://app.openfn.org") {
|
|
|
207
218
|
}
|
|
208
219
|
};
|
|
209
220
|
} catch (e) {
|
|
210
|
-
if (e.message === COLLECTION_NOT_FOUND) {
|
|
221
|
+
if (e.message === COLLECTION_NOT_FOUND || e.message === UNKNOWN_PROJECT) {
|
|
211
222
|
return { statusCode: 404 };
|
|
212
223
|
}
|
|
224
|
+
if (e.message === MULTIPLE_MATCHES) {
|
|
225
|
+
return { statusCode: 409 };
|
|
226
|
+
}
|
|
213
227
|
}
|
|
214
228
|
return { statusCode: 500 };
|
|
215
229
|
};
|
|
216
230
|
const post = (req) => {
|
|
231
|
+
var _a;
|
|
217
232
|
try {
|
|
218
233
|
assertAuth(req);
|
|
219
234
|
} catch (e) {
|
|
@@ -224,8 +239,9 @@ function createServer(url = "https://app.openfn.org") {
|
|
|
224
239
|
try {
|
|
225
240
|
const { name, key } = parsePath(req.path);
|
|
226
241
|
const body = JSON.parse(req.body);
|
|
242
|
+
const projectId = ((_a = req.query) == null ? void 0 : _a.project_id) ?? null;
|
|
227
243
|
for (const { key: key2, value } of body.items) {
|
|
228
|
-
api.upsert(name, key2, value);
|
|
244
|
+
api.upsert(projectId, name, key2, value);
|
|
229
245
|
upserted++;
|
|
230
246
|
}
|
|
231
247
|
return {
|
|
@@ -239,9 +255,13 @@ function createServer(url = "https://app.openfn.org") {
|
|
|
239
255
|
if (e.message === COLLECTION_NOT_FOUND) {
|
|
240
256
|
return { statusCode: 404 };
|
|
241
257
|
}
|
|
258
|
+
if (e.message === MULTIPLE_MATCHES) {
|
|
259
|
+
return { statusCode: 409 };
|
|
260
|
+
}
|
|
242
261
|
}
|
|
243
262
|
};
|
|
244
263
|
const remove2 = (req) => {
|
|
264
|
+
var _a;
|
|
245
265
|
try {
|
|
246
266
|
assertAuth(req);
|
|
247
267
|
} catch (e) {
|
|
@@ -249,11 +269,12 @@ function createServer(url = "https://app.openfn.org") {
|
|
|
249
269
|
}
|
|
250
270
|
try {
|
|
251
271
|
let { name, key } = parsePath(req.path);
|
|
272
|
+
const projectId = ((_a = req.query) == null ? void 0 : _a.project_id) ?? null;
|
|
252
273
|
if (!key) {
|
|
253
274
|
const params = new URLSearchParams(req.query || req.path.split("?")[1]);
|
|
254
275
|
key = params.get("key") ?? "*";
|
|
255
276
|
}
|
|
256
|
-
const keys = api.remove(name, key);
|
|
277
|
+
const keys = api.remove(projectId, name, key);
|
|
257
278
|
return {
|
|
258
279
|
statusCode: 200,
|
|
259
280
|
responseOptions: {
|
|
@@ -265,6 +286,9 @@ function createServer(url = "https://app.openfn.org") {
|
|
|
265
286
|
if (e.message === COLLECTION_NOT_FOUND) {
|
|
266
287
|
return { statusCode: 404 };
|
|
267
288
|
}
|
|
289
|
+
if (e.message === MULTIPLE_MATCHES) {
|
|
290
|
+
return { statusCode: 409 };
|
|
291
|
+
}
|
|
268
292
|
}
|
|
269
293
|
};
|
|
270
294
|
mockPool.intercept({ method: "get", path: /collections\/./ }).reply(get2).persist();
|
|
@@ -591,6 +615,9 @@ var request = async (state, client2, path, options = {}) => {
|
|
|
591
615
|
Object.assign(headers, options == null ? void 0 : options.headers);
|
|
592
616
|
const { headers: _h, query: _q, ...otherOptions } = options;
|
|
593
617
|
const query = parseQuery(options);
|
|
618
|
+
if (state.configuration.project_id) {
|
|
619
|
+
query.project_id = state.configuration.project_id;
|
|
620
|
+
}
|
|
594
621
|
const args = {
|
|
595
622
|
path: import_node_path.default.posix.join(basePath, path),
|
|
596
623
|
headers,
|
|
@@ -600,11 +627,36 @@ var request = async (state, client2, path, options = {}) => {
|
|
|
600
627
|
};
|
|
601
628
|
const response = await client2.request(args);
|
|
602
629
|
if (response.statusCode >= 400) {
|
|
603
|
-
await handleError(
|
|
630
|
+
await handleError(
|
|
631
|
+
response,
|
|
632
|
+
path,
|
|
633
|
+
state.configuration.collections_endpoint,
|
|
634
|
+
query.project_id
|
|
635
|
+
);
|
|
604
636
|
}
|
|
605
637
|
return response;
|
|
606
638
|
};
|
|
607
|
-
var handleError = async (response, path, endpoint) => {
|
|
639
|
+
var handleError = async (response, path, endpoint, project_id) => {
|
|
640
|
+
if (response.statusCode === 409) {
|
|
641
|
+
if (!project_id) {
|
|
642
|
+
const [collection] = path.split("/");
|
|
643
|
+
const e2 = new Error("NO_PROJECT_ID");
|
|
644
|
+
e2.code = "NO_PROJECT_ID";
|
|
645
|
+
e2.description = `The collection "${collection}" matched multiple collections on the server and project_id was omitted`;
|
|
646
|
+
e2.collection = collection;
|
|
647
|
+
e2.endpoint = endpoint;
|
|
648
|
+
e2.fix = "Set state.configuration.project_id before using the collections API";
|
|
649
|
+
throw e2;
|
|
650
|
+
} else {
|
|
651
|
+
const [collection] = path.split("/");
|
|
652
|
+
const e2 = new Error("COLLECTION_CONFLICT");
|
|
653
|
+
e2.code = "COLLECTION_CONFLICT";
|
|
654
|
+
e2.description = `Multiple collections named "${collection}" were found on the server`;
|
|
655
|
+
e2.collection = collection;
|
|
656
|
+
e2.endpoint = endpoint;
|
|
657
|
+
e2.fix = "Contact your system administrator";
|
|
658
|
+
}
|
|
659
|
+
}
|
|
608
660
|
if (response.statusCode === 404) {
|
|
609
661
|
const [collection] = path.split("/");
|
|
610
662
|
console.error(`Error! Collection ${collection} does not exist`);
|
package/dist/index.js
CHANGED
|
@@ -27,28 +27,48 @@ import parser from "stream-json";
|
|
|
27
27
|
|
|
28
28
|
// src/mock.js
|
|
29
29
|
import { MockAgent } from "undici";
|
|
30
|
+
var MULTIPLE_MATCHES = "MULTIPLE_MATCHES_FOUND";
|
|
31
|
+
var UNKNOWN_PROJECT = "INVALID_PROJECT_ID";
|
|
30
32
|
var COLLECTION_NOT_FOUND = "COLLECTION_NOT_FOUND";
|
|
31
33
|
var INVALID_AUTH = "INVALID_AUTH";
|
|
32
34
|
function API() {
|
|
33
|
-
let
|
|
34
|
-
|
|
35
|
-
|
|
35
|
+
let collectionsByProject = {};
|
|
36
|
+
let collectionsByName = {};
|
|
37
|
+
const createCollection = (projectId, name, values = {}) => {
|
|
38
|
+
(collectionsByProject[projectId] ?? (collectionsByProject[projectId] = {}))[name] = values;
|
|
39
|
+
(collectionsByName[name] ?? (collectionsByName[name] = [])).push(values);
|
|
40
|
+
};
|
|
41
|
+
const getCollection = (projectId, name) => {
|
|
42
|
+
if (projectId) {
|
|
43
|
+
if (!(projectId in collectionsByProject)) {
|
|
44
|
+
throw new Error(UNKNOWN_PROJECT);
|
|
45
|
+
}
|
|
46
|
+
if (!(name in collectionsByProject[projectId])) {
|
|
47
|
+
throw new Error(COLLECTION_NOT_FOUND);
|
|
48
|
+
}
|
|
49
|
+
return collectionsByProject[projectId][name];
|
|
50
|
+
} else {
|
|
51
|
+
const results = collectionsByName[name] ?? [];
|
|
52
|
+
if (results.length === 0) {
|
|
53
|
+
throw new Error(COLLECTION_NOT_FOUND);
|
|
54
|
+
}
|
|
55
|
+
if (results.length > 1) {
|
|
56
|
+
throw new Error(MULTIPLE_MATCHES);
|
|
57
|
+
}
|
|
58
|
+
return collectionsByName[name][0];
|
|
59
|
+
}
|
|
36
60
|
};
|
|
37
61
|
const reset = () => {
|
|
38
|
-
|
|
62
|
+
api.collectionsByProject = collectionsByProject = {};
|
|
63
|
+
api.collectionsByName = collectionsByName = {};
|
|
39
64
|
};
|
|
40
|
-
const upsert = (name, key, value) => {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
}
|
|
44
|
-
collections[name][key] = value;
|
|
65
|
+
const upsert = (projectId, name, key, value) => {
|
|
66
|
+
const col = getCollection(projectId, name);
|
|
67
|
+
col[key] = value;
|
|
45
68
|
};
|
|
46
|
-
const fetch = (name, key, query = {}) => {
|
|
69
|
+
const fetch = (projectId, name, key, query = {}) => {
|
|
47
70
|
const { cursor = 0, limit = Infinity } = query;
|
|
48
|
-
|
|
49
|
-
throw new Error(COLLECTION_NOT_FOUND);
|
|
50
|
-
}
|
|
51
|
-
const col = collections[name];
|
|
71
|
+
const col = getCollection(projectId, name);
|
|
52
72
|
const items = [];
|
|
53
73
|
let idx = 0;
|
|
54
74
|
let count2 = 0;
|
|
@@ -74,29 +94,16 @@ function API() {
|
|
|
74
94
|
}
|
|
75
95
|
return result;
|
|
76
96
|
};
|
|
77
|
-
const
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
}
|
|
81
|
-
return collections[name][key];
|
|
97
|
+
const asJSON = (projectId, name, key) => {
|
|
98
|
+
const col = getCollection(projectId, name);
|
|
99
|
+
return JSON.parse(col[key]);
|
|
82
100
|
};
|
|
83
|
-
const
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
}
|
|
87
|
-
return JSON.parse(collections[name][key]);
|
|
101
|
+
const count = (projectId, name) => {
|
|
102
|
+
const col = getCollection(projectId, name);
|
|
103
|
+
return Object.keys(col).length;
|
|
88
104
|
};
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
throw new Error(COLLECTION_NOT_FOUND);
|
|
92
|
-
}
|
|
93
|
-
return Object.keys(collections[name]).length;
|
|
94
|
-
};
|
|
95
|
-
const remove2 = (name, key) => {
|
|
96
|
-
if (!(name in collections)) {
|
|
97
|
-
throw new Error(COLLECTION_NOT_FOUND);
|
|
98
|
-
}
|
|
99
|
-
const col = collections[name];
|
|
105
|
+
const remove2 = (projectId, name, key) => {
|
|
106
|
+
const col = getCollection(projectId, name);
|
|
100
107
|
const regex = new RegExp(key.replace("*", "(.*)"));
|
|
101
108
|
const removed = [];
|
|
102
109
|
for (const key2 in col) {
|
|
@@ -108,15 +115,16 @@ function API() {
|
|
|
108
115
|
return removed;
|
|
109
116
|
};
|
|
110
117
|
const api = {
|
|
111
|
-
|
|
118
|
+
asJSON,
|
|
119
|
+
collectionsByName,
|
|
120
|
+
collectionsByProject,
|
|
121
|
+
count,
|
|
112
122
|
createCollection,
|
|
113
|
-
reset,
|
|
114
|
-
upsert,
|
|
115
123
|
fetch,
|
|
124
|
+
getCollection,
|
|
116
125
|
remove: remove2,
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
count
|
|
126
|
+
reset,
|
|
127
|
+
upsert
|
|
120
128
|
};
|
|
121
129
|
return api;
|
|
122
130
|
}
|
|
@@ -140,6 +148,7 @@ function createServer(url = "https://app.openfn.org") {
|
|
|
140
148
|
const mockPool = agent.get(url);
|
|
141
149
|
const api = new API();
|
|
142
150
|
const get2 = (req) => {
|
|
151
|
+
var _a;
|
|
143
152
|
try {
|
|
144
153
|
assertAuth(req);
|
|
145
154
|
} catch (e) {
|
|
@@ -147,10 +156,12 @@ function createServer(url = "https://app.openfn.org") {
|
|
|
147
156
|
}
|
|
148
157
|
try {
|
|
149
158
|
let { name, key } = parsePath(req.path);
|
|
159
|
+
const projectId = ((_a = req.query) == null ? void 0 : _a.project_id) ?? null;
|
|
150
160
|
let body;
|
|
151
161
|
let statusCode = 200;
|
|
152
162
|
if (key) {
|
|
153
|
-
const
|
|
163
|
+
const collection = api.getCollection(projectId, name);
|
|
164
|
+
const result = collection[key];
|
|
154
165
|
if (!result) {
|
|
155
166
|
body = {};
|
|
156
167
|
statusCode = 204;
|
|
@@ -165,7 +176,7 @@ function createServer(url = "https://app.openfn.org") {
|
|
|
165
176
|
key = params.get("key") ?? "*";
|
|
166
177
|
const limit = params.get("limit") ?? Infinity;
|
|
167
178
|
const cursor = params.get("cursor") ?? 0;
|
|
168
|
-
const { items, cursor: finalCursor } = api.fetch(name, key, {
|
|
179
|
+
const { items, cursor: finalCursor } = api.fetch(projectId, name, key, {
|
|
169
180
|
limit,
|
|
170
181
|
cursor
|
|
171
182
|
});
|
|
@@ -182,13 +193,17 @@ function createServer(url = "https://app.openfn.org") {
|
|
|
182
193
|
}
|
|
183
194
|
};
|
|
184
195
|
} catch (e) {
|
|
185
|
-
if (e.message === COLLECTION_NOT_FOUND) {
|
|
196
|
+
if (e.message === COLLECTION_NOT_FOUND || e.message === UNKNOWN_PROJECT) {
|
|
186
197
|
return { statusCode: 404 };
|
|
187
198
|
}
|
|
199
|
+
if (e.message === MULTIPLE_MATCHES) {
|
|
200
|
+
return { statusCode: 409 };
|
|
201
|
+
}
|
|
188
202
|
}
|
|
189
203
|
return { statusCode: 500 };
|
|
190
204
|
};
|
|
191
205
|
const post = (req) => {
|
|
206
|
+
var _a;
|
|
192
207
|
try {
|
|
193
208
|
assertAuth(req);
|
|
194
209
|
} catch (e) {
|
|
@@ -199,8 +214,9 @@ function createServer(url = "https://app.openfn.org") {
|
|
|
199
214
|
try {
|
|
200
215
|
const { name, key } = parsePath(req.path);
|
|
201
216
|
const body = JSON.parse(req.body);
|
|
217
|
+
const projectId = ((_a = req.query) == null ? void 0 : _a.project_id) ?? null;
|
|
202
218
|
for (const { key: key2, value } of body.items) {
|
|
203
|
-
api.upsert(name, key2, value);
|
|
219
|
+
api.upsert(projectId, name, key2, value);
|
|
204
220
|
upserted++;
|
|
205
221
|
}
|
|
206
222
|
return {
|
|
@@ -214,9 +230,13 @@ function createServer(url = "https://app.openfn.org") {
|
|
|
214
230
|
if (e.message === COLLECTION_NOT_FOUND) {
|
|
215
231
|
return { statusCode: 404 };
|
|
216
232
|
}
|
|
233
|
+
if (e.message === MULTIPLE_MATCHES) {
|
|
234
|
+
return { statusCode: 409 };
|
|
235
|
+
}
|
|
217
236
|
}
|
|
218
237
|
};
|
|
219
238
|
const remove2 = (req) => {
|
|
239
|
+
var _a;
|
|
220
240
|
try {
|
|
221
241
|
assertAuth(req);
|
|
222
242
|
} catch (e) {
|
|
@@ -224,11 +244,12 @@ function createServer(url = "https://app.openfn.org") {
|
|
|
224
244
|
}
|
|
225
245
|
try {
|
|
226
246
|
let { name, key } = parsePath(req.path);
|
|
247
|
+
const projectId = ((_a = req.query) == null ? void 0 : _a.project_id) ?? null;
|
|
227
248
|
if (!key) {
|
|
228
249
|
const params = new URLSearchParams(req.query || req.path.split("?")[1]);
|
|
229
250
|
key = params.get("key") ?? "*";
|
|
230
251
|
}
|
|
231
|
-
const keys = api.remove(name, key);
|
|
252
|
+
const keys = api.remove(projectId, name, key);
|
|
232
253
|
return {
|
|
233
254
|
statusCode: 200,
|
|
234
255
|
responseOptions: {
|
|
@@ -240,6 +261,9 @@ function createServer(url = "https://app.openfn.org") {
|
|
|
240
261
|
if (e.message === COLLECTION_NOT_FOUND) {
|
|
241
262
|
return { statusCode: 404 };
|
|
242
263
|
}
|
|
264
|
+
if (e.message === MULTIPLE_MATCHES) {
|
|
265
|
+
return { statusCode: 409 };
|
|
266
|
+
}
|
|
243
267
|
}
|
|
244
268
|
};
|
|
245
269
|
mockPool.intercept({ method: "get", path: /collections\/./ }).reply(get2).persist();
|
|
@@ -566,6 +590,9 @@ var request = async (state, client2, path, options = {}) => {
|
|
|
566
590
|
Object.assign(headers, options == null ? void 0 : options.headers);
|
|
567
591
|
const { headers: _h, query: _q, ...otherOptions } = options;
|
|
568
592
|
const query = parseQuery(options);
|
|
593
|
+
if (state.configuration.project_id) {
|
|
594
|
+
query.project_id = state.configuration.project_id;
|
|
595
|
+
}
|
|
569
596
|
const args = {
|
|
570
597
|
path: nodepath.posix.join(basePath, path),
|
|
571
598
|
headers,
|
|
@@ -575,11 +602,36 @@ var request = async (state, client2, path, options = {}) => {
|
|
|
575
602
|
};
|
|
576
603
|
const response = await client2.request(args);
|
|
577
604
|
if (response.statusCode >= 400) {
|
|
578
|
-
await handleError(
|
|
605
|
+
await handleError(
|
|
606
|
+
response,
|
|
607
|
+
path,
|
|
608
|
+
state.configuration.collections_endpoint,
|
|
609
|
+
query.project_id
|
|
610
|
+
);
|
|
579
611
|
}
|
|
580
612
|
return response;
|
|
581
613
|
};
|
|
582
|
-
var handleError = async (response, path, endpoint) => {
|
|
614
|
+
var handleError = async (response, path, endpoint, project_id) => {
|
|
615
|
+
if (response.statusCode === 409) {
|
|
616
|
+
if (!project_id) {
|
|
617
|
+
const [collection] = path.split("/");
|
|
618
|
+
const e2 = new Error("NO_PROJECT_ID");
|
|
619
|
+
e2.code = "NO_PROJECT_ID";
|
|
620
|
+
e2.description = `The collection "${collection}" matched multiple collections on the server and project_id was omitted`;
|
|
621
|
+
e2.collection = collection;
|
|
622
|
+
e2.endpoint = endpoint;
|
|
623
|
+
e2.fix = "Set state.configuration.project_id before using the collections API";
|
|
624
|
+
throw e2;
|
|
625
|
+
} else {
|
|
626
|
+
const [collection] = path.split("/");
|
|
627
|
+
const e2 = new Error("COLLECTION_CONFLICT");
|
|
628
|
+
e2.code = "COLLECTION_CONFLICT";
|
|
629
|
+
e2.description = `Multiple collections named "${collection}" were found on the server`;
|
|
630
|
+
e2.collection = collection;
|
|
631
|
+
e2.endpoint = endpoint;
|
|
632
|
+
e2.fix = "Contact your system administrator";
|
|
633
|
+
}
|
|
634
|
+
}
|
|
583
635
|
if (response.statusCode === 404) {
|
|
584
636
|
const [collection] = path.split("/");
|
|
585
637
|
console.error(`Error! Collection ${collection} does not exist`);
|
package/package.json
CHANGED
package/types/collections.d.ts
CHANGED
|
@@ -92,7 +92,7 @@ export function streamResponse(response: any, onValue: any): Promise<any>;
|
|
|
92
92
|
export function expandQuery(query: any): any;
|
|
93
93
|
export function parseQuery(options?: {}): {};
|
|
94
94
|
export function request(state: any, client: any, path: any, options?: {}): Promise<any>;
|
|
95
|
-
export function handleError(response: any, path: any, endpoint: any): Promise<never>;
|
|
95
|
+
export function handleError(response: any, path: any, endpoint: any, project_id: any): Promise<never>;
|
|
96
96
|
/**
|
|
97
97
|
* Query options. All dates should be parseable as ISO 8601 strings, see https://simple.wikipedia.org/wiki/ISO_8601
|
|
98
98
|
*/
|
package/types/mock.d.ts
CHANGED
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
export function API(): {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
asJSON: (projectId: any, name: any, key: any) => any;
|
|
3
|
+
collectionsByName: {};
|
|
4
|
+
collectionsByProject: {};
|
|
5
|
+
count: (projectId: any, name: any) => number;
|
|
6
|
+
createCollection: (projectId: any, name: any, values?: {}) => void;
|
|
7
|
+
fetch: (projectId: any, name: any, key: any, query?: {}) => {
|
|
7
8
|
items: {
|
|
8
9
|
key: string;
|
|
9
10
|
value: any;
|
|
10
11
|
}[];
|
|
11
12
|
count: number;
|
|
12
13
|
};
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
getCollection: (projectId: any, name: any) => any;
|
|
15
|
+
remove: (projectId: any, name: any, key: any) => string[];
|
|
16
|
+
reset: () => void;
|
|
17
|
+
upsert: (projectId: any, name: any, key: any, value: any) => void;
|
|
17
18
|
};
|
|
18
19
|
export function createServer(url?: string): {
|
|
19
20
|
api: any;
|
|
@@ -25,4 +26,8 @@ export function createServer(url?: string): {
|
|
|
25
26
|
data: any;
|
|
26
27
|
}) => Promise<import("undici/types/dispatcher").default.ResponseData<null>>;
|
|
27
28
|
};
|
|
29
|
+
export const MULTIPLE_MATCHES: "MULTIPLE_MATCHES_FOUND";
|
|
30
|
+
export const UNKNOWN_PROJECT: "INVALID_PROJECT_ID";
|
|
31
|
+
export const COLLECTION_NOT_FOUND: "COLLECTION_NOT_FOUND";
|
|
32
|
+
export const INVALID_AUTH: "INVALID_AUTH";
|
|
28
33
|
import { MockAgent } from "undici/types";
|