@jd-data-limited/easy-fm 4.0.16 → 4.1.1

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 (64) hide show
  1. package/package.json +16 -7
  2. package/src/FMError.d.ts +2 -2
  3. package/src/FMError.js +507 -508
  4. package/src/FMError.ts +510 -511
  5. package/src/connection/FMHost.d.ts +23 -5
  6. package/src/connection/FMHost.js +42 -26
  7. package/src/connection/FMHost.ts +63 -49
  8. package/src/connection/HostBase.d.ts +3 -3
  9. package/src/connection/HostBase.ts +5 -5
  10. package/src/connection/database.d.ts +53 -20
  11. package/src/connection/database.js +107 -90
  12. package/src/connection/database.ts +133 -121
  13. package/src/connection/databaseBase.d.ts +11 -7
  14. package/src/connection/databaseBase.ts +8 -8
  15. package/src/connection/generateAuthorizationHeaders.d.ts +1 -1
  16. package/src/connection/generateAuthorizationHeaders.js +10 -10
  17. package/src/connection/generateAuthorizationHeaders.ts +21 -21
  18. package/src/databaseStructure.d.ts +2 -4
  19. package/src/databaseStructure.ts +3 -5
  20. package/src/index.d.ts +17 -17
  21. package/src/index.js +13 -13
  22. package/src/index.ts +24 -24
  23. package/src/layouts/layout.d.ts +17 -6
  24. package/src/layouts/layout.js +19 -8
  25. package/src/layouts/layout.ts +33 -23
  26. package/src/layouts/layoutBase.d.ts +5 -5
  27. package/src/layouts/layoutBase.ts +6 -6
  28. package/src/layouts/layoutInterface.d.ts +3 -5
  29. package/src/layouts/layoutInterface.ts +4 -6
  30. package/src/layouts/layoutRecordManager.d.ts +29 -6
  31. package/src/layouts/layoutRecordManager.js +32 -9
  32. package/src/layouts/layoutRecordManager.ts +42 -19
  33. package/src/layouts/recordFieldsMap.d.ts +2 -4
  34. package/src/layouts/recordFieldsMap.ts +2 -4
  35. package/src/models/apiResults.d.ts +7 -13
  36. package/src/models/apiResults.ts +58 -58
  37. package/src/records/field.d.ts +39 -17
  38. package/src/records/field.js +248 -131
  39. package/src/records/field.ts +160 -82
  40. package/src/records/getOperations/recordGetOperation.d.ts +44 -24
  41. package/src/records/getOperations/recordGetOperation.js +88 -61
  42. package/src/records/getOperations/recordGetOperation.ts +128 -108
  43. package/src/records/layoutRecord.d.ts +28 -14
  44. package/src/records/layoutRecord.js +69 -60
  45. package/src/records/layoutRecord.ts +121 -119
  46. package/src/records/layoutRecordBase.d.ts +2 -2
  47. package/src/records/layoutRecordBase.ts +3 -3
  48. package/src/records/portal.d.ts +19 -5
  49. package/src/records/portal.js +19 -5
  50. package/src/records/portal.ts +28 -16
  51. package/src/records/portalBase.d.ts +5 -5
  52. package/src/records/portalBase.ts +6 -6
  53. package/src/records/portalRecord.d.ts +16 -8
  54. package/src/records/portalRecord.js +16 -6
  55. package/src/records/portalRecord.ts +29 -19
  56. package/src/records/recordBase.d.ts +18 -8
  57. package/src/records/recordBase.js +23 -16
  58. package/src/records/recordBase.ts +41 -37
  59. package/src/types.d.ts +23 -30
  60. package/src/types.js +0 -5
  61. package/src/types.ts +55 -64
  62. package/src/utils/query.d.ts +7 -7
  63. package/src/utils/query.js +10 -10
  64. package/src/utils/query.ts +19 -20
@@ -1,149 +1,266 @@
1
1
  /*
2
2
  * Copyright (c) 2023-2024. See LICENSE file for more information
3
3
  */
4
- import { DownloadModes, RecordTypes } from "../types.js";
5
- import { ApiFieldDisplayTypes, ApiFieldResultTypes, ApiFieldTypes } from "../models/apiResults.js";
6
- export class Field {
7
- parent;
8
- id;
9
- _value;
10
- edited;
11
- constructor(record, id, contents) {
12
- this.parent = record;
13
- this.id = id;
14
- this._value = contents;
15
- this.edited = false;
4
+ var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
5
+ var useValue = arguments.length > 2;
6
+ for (var i = 0; i < initializers.length; i++) {
7
+ value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
16
8
  }
17
- set(content) {
18
- if (this.metadata.result === "container")
19
- throw "Cannot set container value using set(). Use upload() instead.";
20
- // @ts-ignore
21
- if (!content)
22
- this._value = "";
23
- // @ts-ignore
24
- else
25
- this._value = content;
26
- this.edited = true;
9
+ return useValue ? value : void 0;
10
+ };
11
+ var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
12
+ function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
13
+ var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
14
+ var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
15
+ var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
16
+ var _, done = false;
17
+ for (var i = decorators.length - 1; i >= 0; i--) {
18
+ var context = {};
19
+ for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
20
+ for (var p in contextIn.access) context.access[p] = contextIn.access[p];
21
+ context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
22
+ var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
23
+ if (kind === "accessor") {
24
+ if (result === void 0) continue;
25
+ if (result === null || typeof result !== "object") throw new TypeError("Object expected");
26
+ if (_ = accept(result.get)) descriptor.get = _;
27
+ if (_ = accept(result.set)) descriptor.set = _;
28
+ if (_ = accept(result.init)) initializers.unshift(_);
29
+ }
30
+ else if (_ = accept(result)) {
31
+ if (kind === "field") initializers.unshift(_);
32
+ else descriptor[key] = _;
33
+ }
27
34
  }
28
- get metadata() {
29
- if (!this.parent.layout.metadata) {
30
- // Default to a regular text field
31
- return {
32
- name: this.id.toString(),
33
- type: ApiFieldTypes.NORMAL,
34
- displayType: ApiFieldDisplayTypes.EDIT_TEXT,
35
- result: ApiFieldResultTypes.TEXT,
36
- global: false,
37
- autoEnter: true,
38
- fourDigitYear: false,
39
- maxRepeat: 1,
40
- maxCharacters: 0,
41
- notEmpty: false,
42
- numeric: false,
43
- timeOfDay: false,
44
- repetitions: 1,
45
- valueList: ""
46
- };
35
+ if (target) Object.defineProperty(target, contextIn.name, descriptor);
36
+ done = true;
37
+ };
38
+ var __setFunctionName = (this && this.__setFunctionName) || function (f, name, prefix) {
39
+ if (typeof name === "symbol") name = name.description ? "[".concat(name.description, "]") : "";
40
+ return Object.defineProperty(f, "name", { configurable: true, value: prefix ? "".concat(prefix, " ", name) : name });
41
+ };
42
+ import { RecordTypes } from '../types.js';
43
+ import { ApiFieldDisplayTypes, ApiFieldResultTypes, ApiFieldTypes } from '../models/apiResults.js';
44
+ import { FMError } from "../FMError.js";
45
+ /**
46
+ * A class representing a field in a record.
47
+ *
48
+ * @template T - The type of the field value.
49
+ */
50
+ let Field = (() => {
51
+ let _instanceExtraInitializers = [];
52
+ let _private_streamAsync_decorators;
53
+ let _private_streamAsync_descriptor;
54
+ let _arrayBuffer_decorators;
55
+ return class Field {
56
+ static {
57
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
58
+ _private_streamAsync_decorators = [containerDownloadFunction];
59
+ _arrayBuffer_decorators = [containerDownloadFunction];
60
+ __esDecorate(this, _private_streamAsync_descriptor = { value: __setFunctionName(async function () {
61
+ let req = await this.parent.layout.database._apiRequestRaw(this.string, { useCookieJar: true });
62
+ if (!req.ok || !req.body) {
63
+ throw new Error(`HTTP Error: ${req.status} (${req.statusText})`);
64
+ }
65
+ return req.body;
66
+ }, "#streamAsync") }, _private_streamAsync_decorators, { kind: "method", name: "#streamAsync", static: false, private: true, access: { has: obj => #streamAsync in obj, get: obj => obj.#streamAsync }, metadata: _metadata }, null, _instanceExtraInitializers);
67
+ __esDecorate(this, null, _arrayBuffer_decorators, { kind: "method", name: "arrayBuffer", static: false, private: false, access: { has: obj => "arrayBuffer" in obj, get: obj => obj.arrayBuffer }, metadata: _metadata }, null, _instanceExtraInitializers);
68
+ if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
47
69
  }
48
- if (this.parent.type === RecordTypes.PORTAL) {
49
- // @ts-ignore
50
- return this.parent.layout.metadata.portalMetaData[this.parent.portal.name || "portal not attached"].find(i => i.name === this.id) || {
51
- name: this.id.toString(),
52
- type: 'normal',
53
- displayType: 'editText',
54
- result: 'text',
55
- global: false,
56
- autoEnter: true,
57
- fourDigitYear: false,
58
- maxRepeat: 1,
59
- maxCharacters: 0,
60
- notEmpty: false,
61
- numeric: false,
62
- timeOfDay: false,
63
- repetitionStart: 1,
64
- repetitionEnd: 1
65
- };
70
+ parent = __runInitializers(this, _instanceExtraInitializers);
71
+ id;
72
+ _value;
73
+ edited;
74
+ static firstContainerDownload = null;
75
+ constructor(record, id, contents) {
76
+ this.parent = record;
77
+ this.id = id;
78
+ this._value = contents;
79
+ this.edited = false;
66
80
  }
67
- else {
68
- return this.parent.layout.metadata.fieldMetaData.find(i => i.name === this.id) || {
69
- name: this.id.toString(),
70
- type: ApiFieldTypes.NORMAL,
71
- displayType: ApiFieldDisplayTypes.EDIT_TEXT,
72
- result: ApiFieldResultTypes.TEXT,
73
- global: false,
74
- autoEnter: true,
75
- fourDigitYear: false,
76
- maxRepeat: 1,
77
- maxCharacters: 0,
78
- notEmpty: false,
79
- numeric: false,
80
- timeOfDay: false,
81
- repetitions: 1,
82
- valueList: ""
83
- };
81
+ /**
82
+ * Sets the value of the field.
83
+ *
84
+ * @param {T | null} content - The new content value to be set. Can be either the type T or null.
85
+ * @throws {Error} Cannot set container value using set(). Use upload() instead, if the result is a 'container'.
86
+ */
87
+ set(content) {
88
+ if (this.metadata.result === 'container')
89
+ throw new Error('Cannot set container value using set(). Use upload() instead.');
90
+ else
91
+ this._value = content;
92
+ this.edited = true;
84
93
  }
85
- }
86
- get value() {
87
- // if (this.metadata.result === "container") throw "Use await field.stream() to get the contents of a container field, instead of field.value"
88
- return this._value;
89
- }
90
- set value(value) {
91
- this._value = value;
92
- }
93
- get string() {
94
- if (typeof this._value === "string") {
95
- return this._value;
94
+ get metadata() {
95
+ if (!this.parent.layout.metadata) {
96
+ // Default to a regular text field
97
+ return {
98
+ name: this.id.toString(),
99
+ type: ApiFieldTypes.NORMAL,
100
+ displayType: ApiFieldDisplayTypes.EDIT_TEXT,
101
+ result: ApiFieldResultTypes.TEXT,
102
+ global: false,
103
+ autoEnter: true,
104
+ fourDigitYear: false,
105
+ maxRepeat: 1,
106
+ maxCharacters: 0,
107
+ notEmpty: false,
108
+ numeric: false,
109
+ timeOfDay: false,
110
+ repetitions: 1,
111
+ valueList: ''
112
+ };
113
+ }
114
+ if (this.parent.type === RecordTypes.PORTAL && this.parent.portal) {
115
+ return this.parent.layout.metadata.portalMetaData[this.parent.portal.name || 'portal not attached'].find(i => i.name === this.id) ??
116
+ {
117
+ name: this.id.toString(),
118
+ type: ApiFieldTypes.NORMAL,
119
+ displayType: ApiFieldDisplayTypes.EDIT_TEXT,
120
+ result: ApiFieldResultTypes.TEXT,
121
+ global: false,
122
+ autoEnter: true,
123
+ fourDigitYear: false,
124
+ maxRepeat: 1,
125
+ maxCharacters: 0,
126
+ notEmpty: false,
127
+ numeric: false,
128
+ timeOfDay: false,
129
+ repetitions: 1,
130
+ valueList: ''
131
+ };
132
+ }
133
+ else {
134
+ return this.parent.layout.metadata.fieldMetaData.find(i => i.name === this.id) ?? {
135
+ name: this.id.toString(),
136
+ type: ApiFieldTypes.NORMAL,
137
+ displayType: ApiFieldDisplayTypes.EDIT_TEXT,
138
+ result: ApiFieldResultTypes.TEXT,
139
+ global: false,
140
+ autoEnter: true,
141
+ fourDigitYear: false,
142
+ maxRepeat: 1,
143
+ maxCharacters: 0,
144
+ notEmpty: false,
145
+ numeric: false,
146
+ timeOfDay: false,
147
+ repetitions: 1,
148
+ valueList: ''
149
+ };
150
+ }
96
151
  }
97
- throw "Field value is not a string";
98
- }
99
- get date() {
100
- if (this._value instanceof Date) {
152
+ get value() {
153
+ // if (this.metadata.result === "container") throw "Use await field.stream() to get the contents of a container field, instead of field.value"
101
154
  return this._value;
102
155
  }
103
- throw "Field value is not a date";
104
- }
105
- get number() {
106
- if (typeof this._value === "number") {
107
- return this._value;
156
+ set value(value) {
157
+ this._value = value;
108
158
  }
109
- throw "Field value is not a number";
110
- }
111
- async upload(buffer, filename, mime) {
112
- let trace = new Error();
113
- if (this.metadata.result !== "container")
114
- throw "Cannot upload a file to the field; " + this.id + " (not a container field)";
115
- let form = new FormData();
116
- form.append("upload", new File([buffer], filename, { type: mime }));
117
- let res = await this.parent.layout.database.apiRequestRaw(`${this.parent.endpoint}/containers/${this.id}/1`, {
118
- method: "POST",
119
- // @ts-ignore
120
- body: form
121
- });
122
- if (!res.ok)
123
- throw new Error(`Upload failed with HTTP error: ${res.status} (${res.statusText})`);
124
- }
125
- async download(mode = DownloadModes.Stream) {
126
- if (this.metadata.result !== ApiFieldResultTypes.CONTAINER)
127
- throw new Error("Cannot perform download() on a non-container field");
128
- let stream = await this.parent.layout.database.streamURL(this.string);
129
- if (mode === DownloadModes.Stream) {
130
- return stream;
159
+ get string() {
160
+ if (typeof this._value === 'string') {
161
+ return this._value;
162
+ }
163
+ throw new Error('Field value is not a string');
131
164
  }
132
- let body = [];
133
- return new Promise((resolve, reject) => {
134
- stream.on("data", chunk => {
135
- body.push(chunk);
136
- });
137
- stream.on("error", (e) => {
138
- reject(e);
165
+ /**
166
+ * Uploads a file to the container field.
167
+ *
168
+ * @param {Buffer} file - The file content as a buffer.
169
+ *
170
+ * @throws {Error} - Cannot upload a file to the field if it's not a container field.
171
+ * @throws {Error} - Upload failed with HTTP error.
172
+ *
173
+ * @returns {Promise<void>} - A promise that resolves when the file is successfully uploaded.
174
+ */
175
+ async upload(file) {
176
+ if (this.metadata.result !== 'container') {
177
+ throw new Error('Cannot upload a file to the field; ' + this.id + ' (not a container field)');
178
+ }
179
+ const form = new FormData();
180
+ form.append('upload', file);
181
+ console.log(`ENDPOINT: ${this.parent.endpoint}/containers/${this.id}/1`);
182
+ const res = await this.parent.layout.database._apiRequestRaw(`${this.parent.endpoint}/containers/${this.id}/1`, {
183
+ method: 'POST',
184
+ headers: {
185
+ // Authorization: 'Bearer ' + this.parent.layout.database.token,
186
+ // 'Content-Type': 'multipart/form-data'
187
+ },
188
+ body: form
139
189
  });
140
- stream.on("end", () => {
141
- resolve({
142
- buffer: Buffer.concat(body),
143
- mime: stream.headers["content-type"],
144
- request: stream
190
+ if (!res.ok) {
191
+ console.log("RESULT:", await res.text());
192
+ throw new Error(`Upload failed with HTTP error: ${res.status} (${res.statusText})`);
193
+ }
194
+ const data = await res.json();
195
+ if (data.messages[0].code === "0")
196
+ return;
197
+ else {
198
+ console.log(data);
199
+ throw new FMError(data.messages[0].code, res.status, res);
200
+ }
201
+ }
202
+ get #streamAsync() { return _private_streamAsync_descriptor.value; }
203
+ stream() {
204
+ return this.#streamAsync();
205
+ }
206
+ async arrayBuffer() {
207
+ console.log(this.string);
208
+ const req = await this.parent.layout.database._apiRequestRaw(this.string, { useCookieJar: true });
209
+ if (!req.ok)
210
+ throw new Error(`HTTP Error: ${req.status} (${req.statusText})`);
211
+ console.log(req);
212
+ return await req.arrayBuffer();
213
+ }
214
+ };
215
+ })();
216
+ export { Field };
217
+ function containerDownloadFunction(originalMethod, context) {
218
+ async function replacementMethod(...args) {
219
+ return ContainerDownloadExecutor.processTask(() => originalMethod.call(this, ...args));
220
+ }
221
+ return replacementMethod;
222
+ }
223
+ class ContainerDownloadExecutorClass {
224
+ hasDownloadedFirstContainer = 0;
225
+ waitingFuncs = [];
226
+ constructor() { }
227
+ async processTask(task) {
228
+ let isFirstTask = this.hasDownloadedFirstContainer === 0;
229
+ if (isFirstTask) {
230
+ this.hasDownloadedFirstContainer = 1;
231
+ let res;
232
+ try {
233
+ res = await task();
234
+ }
235
+ catch (e) {
236
+ this.hasDownloadedFirstContainer = 0;
237
+ let nextTask = this.waitingFuncs.splice(0, 1)[0];
238
+ if (nextTask) {
239
+ this.processTask(nextTask.func)
240
+ .then(res => nextTask.done(res))
241
+ .catch(e => nextTask.err(e));
242
+ }
243
+ throw e;
244
+ }
245
+ this.hasDownloadedFirstContainer = 2;
246
+ for (let task of this.waitingFuncs) {
247
+ task.func()
248
+ .then((res) => task.done(res))
249
+ .catch((e) => task.err(e));
250
+ }
251
+ return res;
252
+ }
253
+ else if (this.hasDownloadedFirstContainer === 1) {
254
+ return new Promise((resolve, reject) => {
255
+ this.waitingFuncs.push({
256
+ func: task,
257
+ done: resolve,
258
+ err: reject
145
259
  });
146
260
  });
147
- });
261
+ }
262
+ else
263
+ return await task();
148
264
  }
149
265
  }
266
+ const ContainerDownloadExecutor = new ContainerDownloadExecutorClass();