@api-client/core 0.6.4 → 0.6.7
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/build/browser.d.ts +8 -0
- package/build/browser.js +8 -0
- package/build/browser.js.map +1 -1
- package/build/index.d.ts +8 -0
- package/build/index.js +8 -0
- package/build/index.js.map +1 -1
- package/build/src/Platform.d.ts +12 -0
- package/build/src/Platform.js +13 -0
- package/build/src/Platform.js.map +1 -0
- package/build/src/authorization/OAuth2Authorization.d.ts +1 -1
- package/build/src/authorization/OidcAuthorization.d.ts +1 -0
- package/build/src/authorization/OidcAuthorization.js +3 -0
- package/build/src/authorization/OidcAuthorization.js.map +1 -1
- package/build/src/authorization/Utils.js +1 -1
- package/build/src/authorization/Utils.js.map +1 -1
- package/build/src/authorization/lib/SecurityProcessor.d.ts +33 -0
- package/build/src/authorization/lib/SecurityProcessor.js +118 -0
- package/build/src/authorization/lib/SecurityProcessor.js.map +1 -0
- package/build/src/authorization/lib/Utils.d.ts +41 -0
- package/build/src/authorization/lib/Utils.js +85 -0
- package/build/src/authorization/lib/Utils.js.map +1 -0
- package/build/src/lib/transformers/PayloadSerializer.d.ts +0 -3
- package/build/src/lib/transformers/PayloadSerializer.js +1 -3
- package/build/src/lib/transformers/PayloadSerializer.js.map +1 -1
- package/build/src/models/SerializablePayload.js +2 -1
- package/build/src/models/SerializablePayload.js.map +1 -1
- package/build/src/models/data/DataAssociation.d.ts +76 -0
- package/build/src/models/data/DataAssociation.js +151 -0
- package/build/src/models/data/DataAssociation.js.map +1 -0
- package/build/src/models/data/DataAssociationSchema.d.ts +32 -0
- package/build/src/models/data/DataAssociationSchema.js +2 -0
- package/build/src/models/data/DataAssociationSchema.js.map +1 -0
- package/build/src/models/data/DataEntity.d.ts +195 -0
- package/build/src/models/data/DataEntity.js +415 -0
- package/build/src/models/data/DataEntity.js.map +1 -0
- package/build/src/models/data/DataModel.d.ts +74 -0
- package/build/src/models/data/DataModel.js +173 -0
- package/build/src/models/data/DataModel.js.map +1 -0
- package/build/src/models/data/DataNamespace.d.ts +174 -0
- package/build/src/models/data/DataNamespace.js +424 -0
- package/build/src/models/data/DataNamespace.js.map +1 -0
- package/build/src/models/data/DataProperty.d.ts +159 -0
- package/build/src/models/data/DataProperty.js +216 -0
- package/build/src/models/data/DataProperty.js.map +1 -0
- package/build/src/models/data/DataPropertySchema.d.ts +125 -0
- package/build/src/models/data/DataPropertySchema.js +33 -0
- package/build/src/models/data/DataPropertySchema.js.map +1 -0
- package/build/src/models/legacy/Normalizer.js +1 -1
- package/build/src/models/legacy/Normalizer.js.map +1 -1
- package/build/src/models/store/File.d.ts +17 -0
- package/build/src/models/store/File.js +53 -1
- package/build/src/models/store/File.js.map +1 -1
- package/build/src/runtime/store/FilesSdk.d.ts +41 -6
- package/build/src/runtime/store/FilesSdk.js +77 -6
- package/build/src/runtime/store/FilesSdk.js.map +1 -1
- package/build/src/runtime/store/Http.d.ts +1 -0
- package/build/src/runtime/store/Http.js.map +1 -1
- package/build/src/runtime/store/HttpNode.d.ts +1 -0
- package/build/src/runtime/store/HttpNode.js +6 -4
- package/build/src/runtime/store/HttpNode.js.map +1 -1
- package/build/src/runtime/store/HttpWeb.d.ts +1 -0
- package/build/src/runtime/store/HttpWeb.js +4 -0
- package/build/src/runtime/store/HttpWeb.js.map +1 -1
- package/build/src/runtime/store/SdkBase.d.ts +1 -1
- package/package.json +1 -1
- package/src/Platform.ts +12 -0
- package/src/authorization/OAuth2Authorization.ts +1 -1
- package/src/authorization/OidcAuthorization.ts +4 -0
- package/src/authorization/Utils.ts +1 -1
- package/src/authorization/lib/SecurityProcessor.ts +141 -0
- package/src/authorization/lib/Utils.ts +89 -0
- package/src/lib/transformers/PayloadSerializer.ts +2 -4
- package/src/models/SerializablePayload.ts +2 -1
- package/src/models/data/DataAssociation.ts +189 -0
- package/src/models/data/DataAssociationSchema.ts +32 -0
- package/src/models/data/DataEntity.ts +496 -0
- package/src/models/data/DataModel.ts +206 -0
- package/src/models/data/DataNamespace.ts +503 -0
- package/src/models/data/DataProperty.ts +306 -0
- package/src/models/data/DataPropertySchema.ts +156 -0
- package/src/models/legacy/Normalizer.ts +1 -1
- package/src/models/store/File.ts +55 -1
- package/src/runtime/store/FilesSdk.ts +95 -9
- package/src/runtime/store/Http.ts +2 -0
- package/src/runtime/store/HttpNode.ts +7 -4
- package/src/runtime/store/HttpWeb.ts +5 -0
- package/src/runtime/store/SdkBase.ts +1 -1
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
import { IThing, Thing } from "../Thing.js";
|
|
2
|
+
import v4 from '../../lib/uuid.js';
|
|
3
|
+
import { DataNamespace } from "./DataNamespace.js";
|
|
4
|
+
import { IDataPropertySchema } from "./DataPropertySchema.js";
|
|
5
|
+
|
|
6
|
+
export type DataPropertyType = 'string' | 'number' | 'nil' | 'boolean' | 'date' | 'datetime' |
|
|
7
|
+
'time' | 'bytes' | 'any' | 'file';
|
|
8
|
+
export const DataPropertyTypes: DataPropertyType[] = [
|
|
9
|
+
'string', 'number', 'nil', 'boolean', 'date', 'datetime', 'time', 'bytes', 'any', 'file'
|
|
10
|
+
];
|
|
11
|
+
|
|
12
|
+
export enum DataPropertyList {
|
|
13
|
+
string = 'string',
|
|
14
|
+
number = 'number',
|
|
15
|
+
nil = 'nil',
|
|
16
|
+
boolean = 'boolean',
|
|
17
|
+
date = 'date',
|
|
18
|
+
datetime = 'datetime',
|
|
19
|
+
time = 'time',
|
|
20
|
+
bytes = 'bytes',
|
|
21
|
+
any = 'any',
|
|
22
|
+
file = 'file',
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export const Kind = 'Core#DataProperty';
|
|
26
|
+
|
|
27
|
+
export interface IPropertySchema<T> {
|
|
28
|
+
/**
|
|
29
|
+
* Whether it is a general schema for the property.
|
|
30
|
+
* All other schemas inherit from this one. This allows creating global schema description
|
|
31
|
+
* like examples, default values, minimum value, etc and then use it as a base to generate specific formats.
|
|
32
|
+
*
|
|
33
|
+
* A property may not have a global schema.
|
|
34
|
+
*/
|
|
35
|
+
global?: boolean;
|
|
36
|
+
/**
|
|
37
|
+
* The mime type this schema describes.
|
|
38
|
+
* For JSON it is `application/json`, for XML it is `application/xml` (or `text/xml`) adn so on.
|
|
39
|
+
*
|
|
40
|
+
* Note, when this value is missing then it is assumed that the schema is `global`.
|
|
41
|
+
*/
|
|
42
|
+
format?: string;
|
|
43
|
+
/**
|
|
44
|
+
* The schema definition.
|
|
45
|
+
*/
|
|
46
|
+
value: IDataPropertySchema<T>;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export interface IDataProperty {
|
|
50
|
+
kind: typeof Kind;
|
|
51
|
+
/**
|
|
52
|
+
* The key of the namespace.
|
|
53
|
+
*/
|
|
54
|
+
key: string;
|
|
55
|
+
/**
|
|
56
|
+
* The data property description.
|
|
57
|
+
*/
|
|
58
|
+
info: IThing;
|
|
59
|
+
/**
|
|
60
|
+
* Wether the data property is required.
|
|
61
|
+
*/
|
|
62
|
+
required?: boolean;
|
|
63
|
+
/**
|
|
64
|
+
* Whether the data property allows multiple items.
|
|
65
|
+
*/
|
|
66
|
+
multiple?: boolean;
|
|
67
|
+
/**
|
|
68
|
+
* Whether this property describes a primary key of the entity.
|
|
69
|
+
*/
|
|
70
|
+
primary?: boolean;
|
|
71
|
+
/**
|
|
72
|
+
* Whether this property describes an indexed property of the entity.
|
|
73
|
+
*/
|
|
74
|
+
index?: boolean;
|
|
75
|
+
/**
|
|
76
|
+
* Optional general purpose tags for the UI.
|
|
77
|
+
*/
|
|
78
|
+
tags?: string[];
|
|
79
|
+
/**
|
|
80
|
+
* For future use.
|
|
81
|
+
*
|
|
82
|
+
* The keys of the taxonomy items associated with the property.
|
|
83
|
+
*/
|
|
84
|
+
taxonomy?: string[];
|
|
85
|
+
/**
|
|
86
|
+
* The data type for this property.
|
|
87
|
+
* Note, not all schemas support the same type. For example, defining `sint32`
|
|
88
|
+
* works for protocol buffers but does not for JSON. In such case we use default
|
|
89
|
+
* translation `sint32` -> `number`. Another way it to create
|
|
90
|
+
* a derivative entity for specific schema to describe specific schema case.
|
|
91
|
+
*/
|
|
92
|
+
type: DataPropertyType;
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* While the `DataProperty` describes the general shape of the data and can be used to
|
|
96
|
+
* model the structure of the data in the system, a schema describes hwo the data
|
|
97
|
+
* should be serialized into a specific format. This allows adding example values,
|
|
98
|
+
* default values, specifying data format, etc. The assumption here is
|
|
99
|
+
* that with enough specifics provided by the user (a domain specialist)
|
|
100
|
+
* we can automatically generate a schema for the given format.
|
|
101
|
+
*/
|
|
102
|
+
schemas?: IPropertySchema<unknown>[];
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export class DataProperty {
|
|
106
|
+
kind = Kind;
|
|
107
|
+
|
|
108
|
+
key = '';
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* The description of the data namespace.
|
|
112
|
+
*/
|
|
113
|
+
info: Thing = Thing.fromName('');
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Wether the data property is required.
|
|
117
|
+
*/
|
|
118
|
+
required?: boolean;
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Whether the data property allows multiple items.
|
|
122
|
+
*/
|
|
123
|
+
multiple?: boolean;
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Whether this property describes a primary key of the entity.
|
|
127
|
+
*/
|
|
128
|
+
primary?: boolean;
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Whether this property describes an indexed property of the entity.
|
|
132
|
+
*/
|
|
133
|
+
index?: boolean;
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Optional general purpose tags for the UI.
|
|
137
|
+
*/
|
|
138
|
+
tags: string[] = [];
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Reserved for future use.
|
|
142
|
+
*
|
|
143
|
+
* The keys of the taxonomy items associated with the property.
|
|
144
|
+
*/
|
|
145
|
+
taxonomy: string[] = [];
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* The data type for this property.
|
|
149
|
+
* Note, not all schemas support the same type. For example, defining `sint32`
|
|
150
|
+
* works for protocol buffers but does not for JSON. In such case we use default
|
|
151
|
+
* translation `sint32` -> `number`. Another way it to create
|
|
152
|
+
* a derivative entity for specific schema to describe specific schema case.
|
|
153
|
+
*/
|
|
154
|
+
type: DataPropertyType = 'string';
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* While the `DataProperty` describes the general shape of the data and can be used to
|
|
158
|
+
* model the structure of the data in the system, a schema describes hwo the data
|
|
159
|
+
* should be serialized into a specific format. This allows adding example values,
|
|
160
|
+
* default values, specifying data format, etc. The assumption here is
|
|
161
|
+
* that with enough specifics provided by the user (a domain specialist)
|
|
162
|
+
* we can automatically generate a schema for the given format.
|
|
163
|
+
*/
|
|
164
|
+
schemas: IPropertySchema<unknown>[] = [];
|
|
165
|
+
|
|
166
|
+
static get supportedTypes(): DataPropertyType[] {
|
|
167
|
+
return [...DataPropertyTypes];
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
static fromName(root: DataNamespace, name: string): DataProperty {
|
|
171
|
+
const property = new DataProperty(root);
|
|
172
|
+
property.info = Thing.fromName(name);
|
|
173
|
+
return property;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
static fromType(root: DataNamespace, type: DataPropertyType): DataProperty {
|
|
177
|
+
const assoc = new DataProperty(root);
|
|
178
|
+
assoc.type = type;
|
|
179
|
+
return assoc;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* @param input The data property definition to restore.
|
|
184
|
+
*/
|
|
185
|
+
constructor(protected root: DataNamespace, input?: string | IDataProperty) {
|
|
186
|
+
let init: IDataProperty;
|
|
187
|
+
if (typeof input === 'string') {
|
|
188
|
+
init = JSON.parse(input);
|
|
189
|
+
} else if (typeof input === 'object') {
|
|
190
|
+
init = input;
|
|
191
|
+
} else {
|
|
192
|
+
init = {
|
|
193
|
+
kind: Kind,
|
|
194
|
+
key: v4(),
|
|
195
|
+
info: Thing.fromName('').toJSON(),
|
|
196
|
+
type: 'string',
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
this.new(init);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
new(init: IDataProperty): void {
|
|
203
|
+
if (!DataProperty.isDataProperty(init)) {
|
|
204
|
+
throw new Error(`Not a data property.`);
|
|
205
|
+
}
|
|
206
|
+
const { info, key = v4(), kind = Kind, multiple, required, type = DataPropertyList.string, index, primary, tags, taxonomy, schemas } = init;
|
|
207
|
+
this.kind = kind;
|
|
208
|
+
this.key = key;
|
|
209
|
+
this.type = type;
|
|
210
|
+
if (info) {
|
|
211
|
+
this.info = new Thing(info);
|
|
212
|
+
} else {
|
|
213
|
+
this.info = Thing.fromName('');
|
|
214
|
+
}
|
|
215
|
+
if (typeof multiple === 'boolean') {
|
|
216
|
+
this.multiple = multiple;
|
|
217
|
+
} else {
|
|
218
|
+
this.multiple = undefined;
|
|
219
|
+
}
|
|
220
|
+
if (typeof required === 'boolean') {
|
|
221
|
+
this.required = required;
|
|
222
|
+
} else {
|
|
223
|
+
this.required = undefined;
|
|
224
|
+
}
|
|
225
|
+
if (typeof index === 'boolean') {
|
|
226
|
+
this.index = index;
|
|
227
|
+
} else {
|
|
228
|
+
this.index = undefined;
|
|
229
|
+
}
|
|
230
|
+
if (typeof primary === 'boolean') {
|
|
231
|
+
this.primary = primary;
|
|
232
|
+
} else {
|
|
233
|
+
this.primary = undefined;
|
|
234
|
+
}
|
|
235
|
+
if (Array.isArray(tags)) {
|
|
236
|
+
this.tags = [...tags];
|
|
237
|
+
} else {
|
|
238
|
+
this.tags = [];
|
|
239
|
+
}
|
|
240
|
+
if (Array.isArray(taxonomy)) {
|
|
241
|
+
this.taxonomy = [...taxonomy];
|
|
242
|
+
} else {
|
|
243
|
+
this.taxonomy = [];
|
|
244
|
+
}
|
|
245
|
+
if (Array.isArray(schemas)) {
|
|
246
|
+
this.schemas = schemas.map(i => ({ ...i }));
|
|
247
|
+
} else {
|
|
248
|
+
this.schemas = [];
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
static isDataProperty(input: unknown): boolean {
|
|
253
|
+
const typed = input as IDataProperty;
|
|
254
|
+
if (!input || typed.kind !== Kind) {
|
|
255
|
+
return false;
|
|
256
|
+
}
|
|
257
|
+
return true;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
toJSON(): IDataProperty {
|
|
261
|
+
const result: IDataProperty = {
|
|
262
|
+
kind: Kind,
|
|
263
|
+
info: this.info.toJSON(),
|
|
264
|
+
key: this.key,
|
|
265
|
+
type: this.type || DataPropertyList.string,
|
|
266
|
+
};
|
|
267
|
+
if (typeof this.index === 'boolean') {
|
|
268
|
+
result.index = this.index;
|
|
269
|
+
}
|
|
270
|
+
if (typeof this.primary === 'boolean') {
|
|
271
|
+
result.primary = this.primary;
|
|
272
|
+
}
|
|
273
|
+
if (typeof this.multiple === 'boolean') {
|
|
274
|
+
result.multiple = this.multiple;
|
|
275
|
+
}
|
|
276
|
+
if (typeof this.required === 'boolean') {
|
|
277
|
+
result.required = this.required;
|
|
278
|
+
}
|
|
279
|
+
if (Array.isArray(this.tags) && this.tags.length) {
|
|
280
|
+
result.tags = [...this.tags];
|
|
281
|
+
}
|
|
282
|
+
if (Array.isArray(this.taxonomy) && this.taxonomy.length) {
|
|
283
|
+
result.taxonomy = [...this.taxonomy];
|
|
284
|
+
}
|
|
285
|
+
if (Array.isArray(this.schemas) && this.schemas.length) {
|
|
286
|
+
result.schemas = this.schemas.map(i => ({ ...i }));
|
|
287
|
+
}
|
|
288
|
+
return result;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* Removes self from the parent entity and the namespace definition.
|
|
293
|
+
*/
|
|
294
|
+
remove(): void {
|
|
295
|
+
const { root } = this;
|
|
296
|
+
const entity = root.definitions.entities.find(i => i.properties.some(j => j === this));
|
|
297
|
+
if (entity) {
|
|
298
|
+
const assocIndex = entity.properties.findIndex(i => i === this);
|
|
299
|
+
entity.properties.splice(assocIndex, 1);
|
|
300
|
+
}
|
|
301
|
+
const defIndex = this.root.definitions.properties.findIndex(i => i.key === this.key);
|
|
302
|
+
if (defIndex >= 0) {
|
|
303
|
+
this.root.definitions.properties.splice(defIndex, 1);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
export type NumberFormat = 'integer' | 'float' | 'long' | 'double' | 'int32' | 'int64' | 'uint32' | 'uint64' |
|
|
2
|
+
'sint32' | 'sint64' | 'fixed32' | 'fixed64' | 'sfixed32' | 'sfixed64';
|
|
3
|
+
export const NumberFormats: NumberFormat[] = [
|
|
4
|
+
'integer', 'float', 'long', 'double', 'int32', 'int64', 'uint32', 'uint64', 'sint32', 'sint64', 'fixed32', 'fixed64',
|
|
5
|
+
'sfixed32', 'sfixed64'
|
|
6
|
+
];
|
|
7
|
+
|
|
8
|
+
export enum NumberFormatList {
|
|
9
|
+
integer = 'integer',
|
|
10
|
+
float = 'float',
|
|
11
|
+
int32 = 'int32',
|
|
12
|
+
int64 = 'int64',
|
|
13
|
+
uint32 = 'uint32',
|
|
14
|
+
uint64 = 'uint64',
|
|
15
|
+
sint32 = 'sint32',
|
|
16
|
+
sint64 = 'sint64',
|
|
17
|
+
fixed32 = 'fixed32',
|
|
18
|
+
fixed64 = 'fixed64',
|
|
19
|
+
sfixed32 = 'sfixed32',
|
|
20
|
+
sfixed64 = 'sfixed64',
|
|
21
|
+
double = 'double',
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export type DateFormat = 'rfc3339' | 'rfc2616';
|
|
25
|
+
export const DateFormats: DateFormat[] = ['rfc3339', 'rfc2616'];
|
|
26
|
+
export enum DateFormatList {
|
|
27
|
+
/**
|
|
28
|
+
* The "date-time" notation of RFC3339
|
|
29
|
+
*/
|
|
30
|
+
rfc3339 = 'rfc3339',
|
|
31
|
+
/**
|
|
32
|
+
* The format defined in RFC2616.
|
|
33
|
+
*/
|
|
34
|
+
rfc2616 = 'rfc2616',
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* The difference between the DataProperty and this is that the `DataProperty` describes the general shape of
|
|
39
|
+
* the data and `IDataPropertySchema` describes how this property is translated into a specific format
|
|
40
|
+
* (like JSON, Protocol Buffer, XML, etc)
|
|
41
|
+
*/
|
|
42
|
+
export interface IDataPropertySchema<T> {
|
|
43
|
+
// Common
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* The default value for the property.
|
|
47
|
+
*/
|
|
48
|
+
default?: T;
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Enum values for the property.
|
|
52
|
+
*/
|
|
53
|
+
enum?: T[];
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* The example value for the property.
|
|
57
|
+
*/
|
|
58
|
+
examples?: T[];
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* The format of a `number` or `datetime` type.
|
|
62
|
+
*/
|
|
63
|
+
format?: NumberFormat | DateFormat;
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Minimum length of the string or a file. Value MUST be equal to or greater than 0.
|
|
67
|
+
*/
|
|
68
|
+
minLength?: number;
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* The minimum length of the string or a file. Value MUST be equal to or greater than 0.
|
|
72
|
+
*/
|
|
73
|
+
maxLength?: number;
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
// STRING
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Regular expression that this string MUST match.
|
|
80
|
+
*/
|
|
81
|
+
pattern?: string;
|
|
82
|
+
|
|
83
|
+
// NUMBER
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* The minimum value.
|
|
87
|
+
*/
|
|
88
|
+
minimum?: number;
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* The maximum value.
|
|
92
|
+
*/
|
|
93
|
+
maximum?: number;
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* A numeric instance is valid against "multipleOf" if the result of dividing the instance by this
|
|
97
|
+
* value is an integer.
|
|
98
|
+
*/
|
|
99
|
+
multipleOf?: number;
|
|
100
|
+
|
|
101
|
+
// File
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* A list of valid content-type strings for the file. The file type `*\/*` is a valid value.
|
|
105
|
+
*/
|
|
106
|
+
fileTypes?: string[];
|
|
107
|
+
|
|
108
|
+
// XML serialization
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Describes XML specific serialization.
|
|
112
|
+
*/
|
|
113
|
+
xml?: {
|
|
114
|
+
/**
|
|
115
|
+
* Whether is property should be represented as an attribute of the parent entity.
|
|
116
|
+
*
|
|
117
|
+
* ```
|
|
118
|
+
* <Person name="John Doe"></Person>
|
|
119
|
+
* ```
|
|
120
|
+
*/
|
|
121
|
+
attribute?: boolean;
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* The name of the attribute or a wrapped property to use when serializing the property.
|
|
125
|
+
*
|
|
126
|
+
* ```
|
|
127
|
+
* <Person fullName="John Doe"></Person>
|
|
128
|
+
* ```
|
|
129
|
+
*/
|
|
130
|
+
name?: string;
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* When the property is an array (has the `multiple` set to true)
|
|
134
|
+
* then it tells that the list of values should be wrapped with a parent
|
|
135
|
+
* element:
|
|
136
|
+
*
|
|
137
|
+
* ```
|
|
138
|
+
* <Person>
|
|
139
|
+
* <Person fullName="John Doe"></Person>
|
|
140
|
+
* </Person>
|
|
141
|
+
* ```
|
|
142
|
+
*
|
|
143
|
+
* Use this with the combination with `name` to describe the name of the wrapped
|
|
144
|
+
* element
|
|
145
|
+
*
|
|
146
|
+
* ```
|
|
147
|
+
* <people>
|
|
148
|
+
* <Person fullName="John Doe"></Person>
|
|
149
|
+
* </people>
|
|
150
|
+
* ```
|
|
151
|
+
*
|
|
152
|
+
* Note, this is mutually exclusive with `attribute`.
|
|
153
|
+
*/
|
|
154
|
+
wrapped?: boolean;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { ARCHistoryRequest, ARCSavedRequest } from './request/ArcRequest.js';
|
|
3
3
|
import { TransformedPayload as LegacyTransformedPayload } from './request/ArcResponse.js';
|
|
4
4
|
import { IRequestAuthorization, Kind as AuthKind } from '../RequestAuthorization.js';
|
|
5
|
-
import { hasBuffer } from '../../
|
|
5
|
+
import { hasBuffer } from '../../Platform.js';
|
|
6
6
|
|
|
7
7
|
export class Normalizer {
|
|
8
8
|
static normalizeRequest(request: unknown): ARCHistoryRequest | ARCSavedRequest | undefined {
|
package/src/models/store/File.ts
CHANGED
|
@@ -310,7 +310,7 @@ export class StoredFile {
|
|
|
310
310
|
throw new Error(`The user is required.`);
|
|
311
311
|
}
|
|
312
312
|
if (user.kind !== UserKind) {
|
|
313
|
-
throw new Error(`Invalid value for the user when setting "
|
|
313
|
+
throw new Error(`Invalid value for the user when setting "deletedInfo".`);
|
|
314
314
|
}
|
|
315
315
|
this[deletedSymbol] = true;
|
|
316
316
|
this[deletedInfoSymbol] = {
|
|
@@ -387,6 +387,60 @@ export class StoredFile {
|
|
|
387
387
|
file.lastModified.byMe = file.lastModified.user === user;
|
|
388
388
|
}
|
|
389
389
|
}
|
|
390
|
+
|
|
391
|
+
/**
|
|
392
|
+
* Static method to set the `lastModified` property on a file without creating an instance of a file meta.
|
|
393
|
+
* Useful when the meta kind is unknown.
|
|
394
|
+
*
|
|
395
|
+
* @param file The file to update. Note, this method mutates the file.
|
|
396
|
+
* @param user The user that modifies the file.
|
|
397
|
+
* @returns The same file.
|
|
398
|
+
*/
|
|
399
|
+
static setLastModified(file: IFile, user: IUser): IFile {
|
|
400
|
+
if (!file) {
|
|
401
|
+
throw new Error(`The file is required.`);
|
|
402
|
+
}
|
|
403
|
+
if (!user) {
|
|
404
|
+
throw new Error(`The user is required.`);
|
|
405
|
+
}
|
|
406
|
+
if (user.kind !== UserKind) {
|
|
407
|
+
throw new Error(`Invalid value for the user when setting "lastModified".`);
|
|
408
|
+
}
|
|
409
|
+
file.lastModified = {
|
|
410
|
+
byMe: false,
|
|
411
|
+
time: Date.now(),
|
|
412
|
+
user: user.key,
|
|
413
|
+
name: user.name,
|
|
414
|
+
};
|
|
415
|
+
return file;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
/**
|
|
419
|
+
* Similar to the instance method `setDeleted()` but without creating an instance of the file when the type is unknown.
|
|
420
|
+
*
|
|
421
|
+
* @param file The file to change. Note, this operation mutates the file.
|
|
422
|
+
* @param user The deleting user
|
|
423
|
+
* @returns The same file reference.
|
|
424
|
+
*/
|
|
425
|
+
static setDeleted(file: IFile, user: IUser): IFile {
|
|
426
|
+
if (!file) {
|
|
427
|
+
throw new Error(`The file is required.`);
|
|
428
|
+
}
|
|
429
|
+
if (!user) {
|
|
430
|
+
throw new Error(`The user is required.`);
|
|
431
|
+
}
|
|
432
|
+
if (user.kind !== UserKind) {
|
|
433
|
+
throw new Error(`Invalid value for the user when setting "deletedInfo".`);
|
|
434
|
+
}
|
|
435
|
+
file.deleted = true;
|
|
436
|
+
file.deletedInfo = {
|
|
437
|
+
byMe: false,
|
|
438
|
+
time: Date.now(),
|
|
439
|
+
user: user.key,
|
|
440
|
+
name: user.name,
|
|
441
|
+
};
|
|
442
|
+
return file;
|
|
443
|
+
}
|
|
390
444
|
}
|
|
391
445
|
|
|
392
446
|
export class File extends StoredFile {
|
|
@@ -6,10 +6,10 @@ import { IUser } from '../../models/store/User.js';
|
|
|
6
6
|
import { IFile } from '../../models/store/File.js';
|
|
7
7
|
import { Kind as ProjectKind } from '../../models/Project.js';
|
|
8
8
|
import { Kind as WorkspaceKind } from '../../models/Workspace.js';
|
|
9
|
-
import {
|
|
9
|
+
import { Kind as DataNamespaceKind } from '../../models/data/DataNamespace.js';
|
|
10
10
|
import { SdkError } from './Errors.js';
|
|
11
11
|
|
|
12
|
-
export interface
|
|
12
|
+
export interface IMetaCreateOptions {
|
|
13
13
|
/**
|
|
14
14
|
* Optional parent file id.
|
|
15
15
|
* When set it creates a file under this parent.
|
|
@@ -17,19 +17,41 @@ export interface IFileCreateOptions {
|
|
|
17
17
|
parent?: string;
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
+
export interface IMediaCreateOptions {
|
|
21
|
+
/**
|
|
22
|
+
* Optional contents mime type.
|
|
23
|
+
* Default to `application/json`.
|
|
24
|
+
*/
|
|
25
|
+
mime?: string;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface IFileCreateOptions extends IMetaCreateOptions, IMediaCreateOptions {
|
|
29
|
+
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export type FileKind = typeof ProjectKind | typeof WorkspaceKind | typeof DataNamespaceKind;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* In the store, the file is represented by the meta and the media.
|
|
36
|
+
*
|
|
37
|
+
* The meta is used to represent the file in the UI when listing files or presenting their metadata (like name, last modified, etc).
|
|
38
|
+
* The media is the actual contents of the file and is only used by application specializing in this file modification.
|
|
39
|
+
*/
|
|
20
40
|
export class FilesSdk extends SdkBase {
|
|
21
41
|
/**
|
|
22
42
|
* Lists files (spaces, projects, etc) in the store.
|
|
23
43
|
*
|
|
24
|
-
* @param kinds
|
|
44
|
+
* @param kinds Optional list of kinds to limit the file types in the result. Spaces are always included.
|
|
25
45
|
* @param options Optional query options.
|
|
26
46
|
* @param request Optional request options.
|
|
27
47
|
*/
|
|
28
|
-
async list(kinds
|
|
48
|
+
async list(kinds?: FileKind[], options?: IListOptions, request: ISdkRequestOptions = {}): Promise<IListResponse<IFile>> {
|
|
29
49
|
const token = request.token || this.sdk.token;
|
|
30
50
|
const url = this.sdk.getUrl(RouteBuilder.files());
|
|
31
51
|
this.sdk.appendListOptions(url, options);
|
|
32
|
-
|
|
52
|
+
if (Array.isArray(kinds)) {
|
|
53
|
+
kinds.forEach(k => url.searchParams.append('kind', k));
|
|
54
|
+
}
|
|
33
55
|
const result = await this.sdk.http.get(url.toString(), { token });
|
|
34
56
|
this.inspectCommonStatusCodes(result.status, result.body);
|
|
35
57
|
const E_PREFIX = 'Unable to list files. ';
|
|
@@ -57,20 +79,44 @@ export class FilesSdk extends SdkBase {
|
|
|
57
79
|
return data;
|
|
58
80
|
}
|
|
59
81
|
|
|
82
|
+
/**
|
|
83
|
+
* Creates both the meta and the media for a file.
|
|
84
|
+
*
|
|
85
|
+
* @param meta The file meta
|
|
86
|
+
* @param contents The file contents
|
|
87
|
+
* @param opts Meta and media create options.
|
|
88
|
+
* @param request Optional request details
|
|
89
|
+
* @returns The id of the created file meta.
|
|
90
|
+
*/
|
|
91
|
+
async create(meta: IFile, contents: unknown, opts: IFileCreateOptions = {}, request: ISdkRequestOptions = {}): Promise<string> {
|
|
92
|
+
const id = await this.createMeta(meta, opts, request);
|
|
93
|
+
await this.createMedia(contents, id, opts, request);
|
|
94
|
+
return id;
|
|
95
|
+
}
|
|
96
|
+
|
|
60
97
|
/**
|
|
61
98
|
* Creates a file in the store.
|
|
62
99
|
*
|
|
63
|
-
* @param file The definition of a file that extends the IFile interface
|
|
100
|
+
* @param file The definition of a file that extends the IFile interface.
|
|
64
101
|
* @param opts Optional options when creating a file
|
|
65
102
|
* @param request Optional request options.
|
|
66
103
|
* @returns The key of the creates file.
|
|
67
104
|
*/
|
|
68
|
-
async
|
|
105
|
+
async createMeta(file: IFile, opts: IMetaCreateOptions = {}, request: ISdkRequestOptions = {}): Promise<string> {
|
|
69
106
|
const token = request.token || this.sdk.token;
|
|
70
|
-
const path =
|
|
107
|
+
const path = RouteBuilder.files();
|
|
71
108
|
const url = this.sdk.getUrl(path);
|
|
109
|
+
if (opts.parent) {
|
|
110
|
+
url.searchParams.set('parent', opts.parent);
|
|
111
|
+
}
|
|
72
112
|
const body = JSON.stringify(file);
|
|
73
|
-
const result = await this.sdk.http.post(url.toString(), {
|
|
113
|
+
const result = await this.sdk.http.post(url.toString(), {
|
|
114
|
+
token,
|
|
115
|
+
body,
|
|
116
|
+
headers: {
|
|
117
|
+
'content-type': 'application/json'
|
|
118
|
+
},
|
|
119
|
+
});
|
|
74
120
|
this.inspectCommonStatusCodes(result.status, result.body);
|
|
75
121
|
const E_PREFIX = 'Unable to create a file. ';
|
|
76
122
|
if (result.status !== 204) {
|
|
@@ -90,6 +136,46 @@ export class FilesSdk extends SdkBase {
|
|
|
90
136
|
return id as string;
|
|
91
137
|
}
|
|
92
138
|
|
|
139
|
+
/**
|
|
140
|
+
* Creates a file contents (the media) after the file meta was created.
|
|
141
|
+
*
|
|
142
|
+
* @param contents The file contents to upload to the server.
|
|
143
|
+
* @param key The created file meta key.
|
|
144
|
+
* @param opts Contents create options. You can define content's mime type here.
|
|
145
|
+
* @param request Optional request.
|
|
146
|
+
*/
|
|
147
|
+
async createMedia(contents: unknown, key: string, opts: IMediaCreateOptions = {}, request: ISdkRequestOptions = {}): Promise<void> {
|
|
148
|
+
const token = request.token || this.sdk.token;
|
|
149
|
+
const path = RouteBuilder.file(key);
|
|
150
|
+
const url = this.sdk.getUrl(path);
|
|
151
|
+
url.searchParams.set('alt', 'media');
|
|
152
|
+
const mime = opts.mime || 'application/json';
|
|
153
|
+
let body: string;
|
|
154
|
+
if (mime.includes('json')) {
|
|
155
|
+
body = JSON.stringify(contents);
|
|
156
|
+
} else {
|
|
157
|
+
body = String(contents);
|
|
158
|
+
}
|
|
159
|
+
const result = await this.sdk.http.put(url.toString(), {
|
|
160
|
+
token,
|
|
161
|
+
body,
|
|
162
|
+
headers: {
|
|
163
|
+
'content-type': mime
|
|
164
|
+
},
|
|
165
|
+
});
|
|
166
|
+
this.inspectCommonStatusCodes(result.status, result.body);
|
|
167
|
+
const E_PREFIX = 'Unable to create a file. ';
|
|
168
|
+
if (result.status !== 204) {
|
|
169
|
+
this.logInvalidResponse(result);
|
|
170
|
+
let e = this.createGenericSdkError(result.body)
|
|
171
|
+
if (!e) {
|
|
172
|
+
e = new SdkError(`${E_PREFIX}${E_RESPONSE_STATUS}${result.status}`, result.status);
|
|
173
|
+
e.response = result.body;
|
|
174
|
+
}
|
|
175
|
+
throw e;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
93
179
|
/**
|
|
94
180
|
* Reads file metadata from the store.
|
|
95
181
|
*
|
|
@@ -14,5 +14,7 @@ export abstract class Http extends SdkBase {
|
|
|
14
14
|
|
|
15
15
|
abstract patch(url: string, opts?: IStoreRequestOptions): Promise<IStoreResponse>;
|
|
16
16
|
|
|
17
|
+
abstract put(url: string, opts?: IStoreRequestOptions): Promise<IStoreResponse>;
|
|
18
|
+
|
|
17
19
|
abstract delete(url: string, opts?: IStoreRequestOptions): Promise<IStoreResponse>;
|
|
18
20
|
}
|