@elaraai/e3-cloud-types 1.0.94 → 1.1.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/README.md +16 -6
- package/dist/src/admin-user-types.d.ts +17 -17
- package/dist/src/admin-user-types.d.ts.map +1 -1
- package/dist/src/admin-user-types.js +5 -5
- package/dist/src/admin-user-types.js.map +1 -1
- package/dist/src/files-types.d.ts +3975 -332
- package/dist/src/files-types.d.ts.map +1 -1
- package/dist/src/files-types.js +428 -53
- package/dist/src/files-types.js.map +1 -1
- package/dist/src/index.d.ts +3 -3
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +4 -4
- package/dist/src/index.js.map +1 -1
- package/dist/src/invitation-types.d.ts +26 -25
- package/dist/src/invitation-types.d.ts.map +1 -1
- package/dist/src/invitation-types.js +14 -13
- package/dist/src/invitation-types.js.map +1 -1
- package/dist/src/record-history-types.d.ts +46 -0
- package/dist/src/record-history-types.d.ts.map +1 -1
- package/dist/src/record-history-types.js +23 -0
- package/dist/src/record-history-types.js.map +1 -1
- package/dist/src/release-types.d.ts +9391 -2372
- package/dist/src/release-types.d.ts.map +1 -1
- package/dist/src/release-types.js +17 -7
- package/dist/src/release-types.js.map +1 -1
- package/dist/src/repo-user.d.ts +3 -3
- package/dist/src/repo-user.d.ts.map +1 -1
- package/dist/src/repo-user.js +3 -3
- package/dist/src/repo-user.js.map +1 -1
- package/dist/src/schedule-types.d.ts +3 -3
- package/dist/src/schedule-types.d.ts.map +1 -1
- package/dist/src/schedule-types.js +3 -3
- package/dist/src/schedule-types.js.map +1 -1
- package/package.json +3 -3
package/dist/src/files-types.js
CHANGED
|
@@ -4,28 +4,47 @@
|
|
|
4
4
|
*/
|
|
5
5
|
/**
|
|
6
6
|
* Files: a solution's inputs that come from files in a bucket, as East
|
|
7
|
-
* values
|
|
7
|
+
* values; and a record's seed, and a record's mutation fed, from
|
|
8
|
+
* files.
|
|
8
9
|
*
|
|
9
10
|
* A solution declares, with `@elaraai/e3-cloud-files`, which of its inputs a
|
|
10
11
|
* source's files fill: one file, the newest under a prefix, every file under
|
|
11
|
-
* a prefix, or a listing of them ({@link FilesShapeType})
|
|
12
|
-
*
|
|
12
|
+
* a prefix, or a listing of them ({@link FilesShapeType}); a `file` or
|
|
13
|
+
* `latest` shape may name a **type**, and the file is then taken in as the
|
|
14
|
+
* beast2 value it holds rather than as a `Blob`. What a mapping fills is its
|
|
15
|
+
* **target** ({@link FilesTargetType}): an input, a record (the file is the
|
|
16
|
+
* record's state: its genesis, then a seed again), or a record's mutation
|
|
17
|
+
* (each new file is the mutation's one argument). The declarations are a
|
|
18
|
+
* {@link FilesManifestType}, deployed beside the package and checked
|
|
13
19
|
* against it. Each workspace binds a source to where its files are
|
|
14
20
|
* ({@link FilesBindingType}); a sync brings in what changed and answers a
|
|
15
|
-
* {@link FilesSyncReportType}
|
|
16
|
-
*
|
|
21
|
+
* {@link FilesSyncReportType}; a push ({@link FilesPushRequestType}) puts
|
|
22
|
+
* files from disk into a source and syncs their targets. The checks answer
|
|
23
|
+
* {@link FilesProblemType}s, each rendered as a line by
|
|
24
|
+
* {@link filesProblemText}.
|
|
17
25
|
*
|
|
18
|
-
* A file arrives as it is, a `Blob`: nothing here parses it.
|
|
26
|
+
* A file with no type arrives as it is, a `Blob`: nothing here parses it. A
|
|
27
|
+
* typed file is beast2, whose root type must be the mapping's.
|
|
28
|
+
*
|
|
29
|
+
* @remarks
|
|
30
|
+
* WIRE COMPAT: the manifest, the reports, the ledgers and a sync's job are
|
|
31
|
+
* stored (the platform's `FILES/`, `FILESJOB/` and `RELEASE/` items and its
|
|
32
|
+
* `files-sync/` objects; a local repository's `.e3-cloud/files/<ws>.json`).
|
|
33
|
+
* Their first version (a mapping by `input`, a refusal's reason a string) is
|
|
34
|
+
* read through
|
|
35
|
+
* `@elaraai/e3-cloud-files/compat`, which keeps the first version's types
|
|
36
|
+
* and lifts a value into these; every store writes these. The API's own
|
|
37
|
+
* request and response types ship with the client and CLI.
|
|
19
38
|
*/
|
|
20
|
-
import { ArrayType, BlobType, BooleanType, DateTimeType, DictType, EastTypeType, IntegerType, NullType, OptionType, StringType, StructType, VariantType, printTypeValueSummary, } from '@elaraai/east';
|
|
39
|
+
import { ArrayType, BlobType, BooleanType, DateTimeType, DictType, EastTypeType, IntegerType, NullType, OptionType, StringType, StructType, VariantType, equalFor, printTypeValueSummary, variant, } from '@elaraai/east';
|
|
21
40
|
/**
|
|
22
41
|
* Room a file's value leaves in its frame or segment for what beast2 adds:
|
|
23
42
|
* the lengths before the bytes and, in a folder, the file's path.
|
|
24
43
|
*/
|
|
25
44
|
const FILES_ENCODING_ROOM_BYTES = 64 * 1024;
|
|
26
45
|
/**
|
|
27
|
-
* The largest file `file` and `latest` take
|
|
28
|
-
* less the room its encoding takes (1 GiB less 64 KiB).
|
|
46
|
+
* The largest file `file` and `latest` take as a `Blob`: beast2's largest
|
|
47
|
+
* frame, 1 GiB, less the room its encoding takes (1 GiB less 64 KiB).
|
|
29
48
|
*/
|
|
30
49
|
export const FILES_FILE_MAX_BYTES = 1024 * 1024 * 1024 - FILES_ENCODING_ROOM_BYTES;
|
|
31
50
|
/**
|
|
@@ -33,6 +52,22 @@ export const FILES_FILE_MAX_BYTES = 1024 * 1024 * 1024 - FILES_ENCODING_ROOM_BYT
|
|
|
33
52
|
* the room its path and lengths take (64 MiB less 64 KiB).
|
|
34
53
|
*/
|
|
35
54
|
export const FILES_FOLDER_ENTRY_MAX_BYTES = 64 * 1024 * 1024 - FILES_ENCODING_ROOM_BYTES;
|
|
55
|
+
/**
|
|
56
|
+
* The largest typed file whose value is no collection, and the largest file
|
|
57
|
+
* a mutation is fed: beast2's largest frame, 1 GiB, which a sandbox holds
|
|
58
|
+
* whole. A typed collection has no limit but its segments'.
|
|
59
|
+
*/
|
|
60
|
+
export const FILES_TYPED_VALUE_MAX_BYTES = 1024 * 1024 * 1024;
|
|
61
|
+
/**
|
|
62
|
+
* The largest segment of a typed collection: beast2's, 64 MiB. A file
|
|
63
|
+
* written with a larger one is refused, naming the fix (write it again
|
|
64
|
+
* with a current writer).
|
|
65
|
+
*/
|
|
66
|
+
export const FILES_SEGMENT_MAX_BYTES = 64 * 1024 * 1024;
|
|
67
|
+
/** The most files one push plans. */
|
|
68
|
+
export const FILES_PUSH_MAX_FILES = 1000;
|
|
69
|
+
/** The part a push's multipart upload is cut in, and the most one PUT sends: 64 MiB. */
|
|
70
|
+
export const FILES_PUSH_PART_BYTES = 64 * 1024 * 1024;
|
|
36
71
|
/** A file's row in a `listing` input. */
|
|
37
72
|
export const FilesListingRowType = StructType({
|
|
38
73
|
/** Its size in bytes */
|
|
@@ -42,7 +77,7 @@ export const FilesListingRowType = StructType({
|
|
|
42
77
|
/** Its ETag: changes whenever its bytes do */
|
|
43
78
|
etag: StringType,
|
|
44
79
|
});
|
|
45
|
-
/** The input type of a `file` or `latest` mapping: the file's bytes. */
|
|
80
|
+
/** The input type of a `file` or `latest` mapping with no type: the file's bytes. */
|
|
46
81
|
export const FilesFileType = BlobType;
|
|
47
82
|
/** The input type of a `folder` mapping: each file's path, relative to the prefix, to its bytes. */
|
|
48
83
|
export const FilesFolderType = DictType(StringType, BlobType);
|
|
@@ -52,9 +87,10 @@ export const FilesListingType = DictType(StringType, FilesListingRowType);
|
|
|
52
87
|
* What a mapping selects from its source, relative to where the workspace
|
|
53
88
|
* binds the source.
|
|
54
89
|
*
|
|
55
|
-
* - `file`: one key
|
|
90
|
+
* - `file`: one key. As a `Blob`, or, with `type`, as the beast2 value of
|
|
91
|
+
* that type the file holds.
|
|
56
92
|
* - `latest`: the greatest key under a prefix that matches `include`, as a
|
|
57
|
-
* `Blob
|
|
93
|
+
* `Blob` or, with `type`, as the value it holds.
|
|
58
94
|
* - `folder`: every key under a prefix that matches `include`, as a
|
|
59
95
|
* `Dict<String, Blob>` keyed by its path relative to the prefix.
|
|
60
96
|
* - `listing`: the same keys' sizes, times and ETags, without their bytes.
|
|
@@ -63,22 +99,102 @@ export const FilesListingType = DictType(StringType, FilesListingRowType);
|
|
|
63
99
|
* within one segment of the path, `**` across segments, `?` one character,
|
|
64
100
|
* `[abc]`, `[a-z]` and `[!abc]` one character of a set, and `{csv,json}` any
|
|
65
101
|
* of its alternatives, each a glob itself.
|
|
102
|
+
*
|
|
103
|
+
* A record's or a mutation's mapping selects one file (`file` or `latest`)
|
|
104
|
+
* and names its type: the record's state type, or the mutation's one
|
|
105
|
+
* argument's.
|
|
66
106
|
*/
|
|
67
107
|
export const FilesShapeType = VariantType({
|
|
68
|
-
file: StructType({ key: StringType }),
|
|
69
|
-
latest: StructType({ prefix: StringType, include: OptionType(StringType) }),
|
|
108
|
+
file: StructType({ key: StringType, type: OptionType(EastTypeType) }),
|
|
109
|
+
latest: StructType({ prefix: StringType, include: OptionType(StringType), type: OptionType(EastTypeType) }),
|
|
70
110
|
folder: StructType({ prefix: StringType, include: OptionType(StringType) }),
|
|
71
111
|
listing: StructType({ prefix: StringType, include: OptionType(StringType) }),
|
|
72
112
|
});
|
|
73
|
-
/**
|
|
74
|
-
|
|
75
|
-
|
|
113
|
+
/**
|
|
114
|
+
* What a mapping fills.
|
|
115
|
+
*
|
|
116
|
+
* - `input`: the dataset `.inputs.<name>`.
|
|
117
|
+
* - `record`: the record `.records.<name>`, seeded: its file is its first
|
|
118
|
+
* state (its genesis), and a changed file its state again while nothing
|
|
119
|
+
* has mutated it since.
|
|
120
|
+
* - `mutation`: one of a record's mutations, fed: each new file is the
|
|
121
|
+
* mutation's one argument, applied once.
|
|
122
|
+
*/
|
|
123
|
+
export const FilesTargetType = VariantType({
|
|
76
124
|
input: StringType,
|
|
125
|
+
record: StringType,
|
|
126
|
+
mutation: StructType({ record: StringType, mutation: StringType }),
|
|
127
|
+
});
|
|
128
|
+
/** Whether two targets are the same. */
|
|
129
|
+
export const sameFilesTarget = equalFor(FilesTargetType);
|
|
130
|
+
/**
|
|
131
|
+
* A target as one text: `orders`, `record:customers`,
|
|
132
|
+
* `mutation:prices.load_prices`. What the CLI takes (`--as`, `--target`) and
|
|
133
|
+
* prints, and what {@link parseFilesTarget} reads back.
|
|
134
|
+
*
|
|
135
|
+
* @param target - The target
|
|
136
|
+
* @returns Its text
|
|
137
|
+
*/
|
|
138
|
+
export function filesTargetText(target) {
|
|
139
|
+
switch (target.type) {
|
|
140
|
+
case 'input': return target.value;
|
|
141
|
+
case 'record': return `record:${target.value}`;
|
|
142
|
+
case 'mutation': return `mutation:${target.value.record}.${target.value.mutation}`;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* A target, from its text ({@link filesTargetText}): a bare name is an
|
|
147
|
+
* input's. A mutation's text is split at its last dot (e3 lets a name hold
|
|
148
|
+
* one): a record's name may hold a dot, and a mutation whose name holds one
|
|
149
|
+
* cannot be named in this form, only as a structured target (a sync
|
|
150
|
+
* request's `targets`).
|
|
151
|
+
*
|
|
152
|
+
* @param text - `name`, `input:name`, `record:name` or `mutation:record.name`
|
|
153
|
+
* @returns The target, or null for text of another form
|
|
154
|
+
*/
|
|
155
|
+
export function parseFilesTarget(text) {
|
|
156
|
+
const colon = text.indexOf(':');
|
|
157
|
+
if (colon < 0)
|
|
158
|
+
return text === '' ? null : variant('input', text);
|
|
159
|
+
const kind = text.slice(0, colon);
|
|
160
|
+
const rest = text.slice(colon + 1);
|
|
161
|
+
if (rest === '')
|
|
162
|
+
return null;
|
|
163
|
+
switch (kind) {
|
|
164
|
+
case 'input': return variant('input', rest);
|
|
165
|
+
case 'record': return variant('record', rest);
|
|
166
|
+
case 'mutation': {
|
|
167
|
+
const dot = rest.lastIndexOf('.');
|
|
168
|
+
if (dot <= 0 || dot === rest.length - 1)
|
|
169
|
+
return null;
|
|
170
|
+
return variant('mutation', { record: rest.slice(0, dot), mutation: rest.slice(dot + 1) });
|
|
171
|
+
}
|
|
172
|
+
default: return null;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* A target in words: `input orders`, `record customers`,
|
|
177
|
+
* `mutation load_prices of customers`.
|
|
178
|
+
*
|
|
179
|
+
* @param target - The target
|
|
180
|
+
* @returns The words
|
|
181
|
+
*/
|
|
182
|
+
export function filesTargetWords(target) {
|
|
183
|
+
switch (target.type) {
|
|
184
|
+
case 'input': return `input ${target.value}`;
|
|
185
|
+
case 'record': return `record ${target.value}`;
|
|
186
|
+
case 'mutation': return `mutation ${target.value.mutation} of ${target.value.record}`;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
/** One target a source's files fill. */
|
|
190
|
+
export const FilesMappingType = StructType({
|
|
191
|
+
/** What the files fill */
|
|
192
|
+
target: FilesTargetType,
|
|
77
193
|
/** The source's name */
|
|
78
194
|
source: StringType,
|
|
79
195
|
shape: FilesShapeType,
|
|
80
196
|
});
|
|
81
|
-
/** A solution's declarations: its sources, and the
|
|
197
|
+
/** A solution's declarations: its sources, and the targets they fill. */
|
|
82
198
|
export const FilesManifestType = StructType({
|
|
83
199
|
/** The sources' names, in the order they were declared */
|
|
84
200
|
sources: ArrayType(StringType),
|
|
@@ -100,14 +216,52 @@ export const FilesBindingType = StructType({
|
|
|
100
216
|
profile: OptionType(StringType),
|
|
101
217
|
latest: OptionType(IntegerType),
|
|
102
218
|
});
|
|
219
|
+
/**
|
|
220
|
+
* Why a sync did not take a file.
|
|
221
|
+
*
|
|
222
|
+
* - `too_large`: over its shape's limit, in bytes.
|
|
223
|
+
* - `segment_too_large`: a typed collection written with a segment over
|
|
224
|
+
* beast2's 64 MiB; written again with a current writer, it is taken.
|
|
225
|
+
* - `unreadable`: the source would not give it (archived, changed since it
|
|
226
|
+
* was listed, closed to the reader).
|
|
227
|
+
* - `not_beast2`: a typed mapping's file that is no beast2 container.
|
|
228
|
+
* - `type_mismatch`: a typed mapping's file holding a value of another
|
|
229
|
+
* type than the mapping's.
|
|
230
|
+
* - `mutation`: a feed the mutation did not commit: its outcome
|
|
231
|
+
* (`invalid`, `timed_out`, `failed`) and what it said; tried again once
|
|
232
|
+
* the file changes.
|
|
233
|
+
* - `missing`: the file the mapping names is not there.
|
|
234
|
+
* - `other`: a reason stored before these were told apart.
|
|
235
|
+
*/
|
|
236
|
+
export const FilesRefusalReasonType = VariantType({
|
|
237
|
+
too_large: StructType({ size: IntegerType, limit: IntegerType }),
|
|
238
|
+
segment_too_large: StructType({ bytes: IntegerType, limit: IntegerType }),
|
|
239
|
+
unreadable: StringType,
|
|
240
|
+
not_beast2: StringType,
|
|
241
|
+
type_mismatch: StructType({ expected: EastTypeType, actual: EastTypeType }),
|
|
242
|
+
mutation: StructType({ outcome: StringType, message: StringType }),
|
|
243
|
+
missing: StringType,
|
|
244
|
+
other: StringType,
|
|
245
|
+
});
|
|
103
246
|
/** A file a sync did not take, and why. */
|
|
104
247
|
export const FilesRefusalType = StructType({
|
|
105
248
|
key: StringType,
|
|
106
|
-
reason:
|
|
249
|
+
reason: FilesRefusalReasonType,
|
|
250
|
+
});
|
|
251
|
+
/** A typed file a sync took in: the value it holds. */
|
|
252
|
+
export const FilesTakenType = StructType({
|
|
253
|
+
/** The file's key */
|
|
254
|
+
key: StringType,
|
|
255
|
+
/** The value's type: the mapping's */
|
|
256
|
+
type: EastTypeType,
|
|
257
|
+
/** The collection's rows, where the store counts them */
|
|
258
|
+
rows: OptionType(IntegerType),
|
|
259
|
+
/** `carried` whole, or `split` into pieces by intake units */
|
|
260
|
+
how: VariantType({ carried: NullType, split: NullType }),
|
|
107
261
|
});
|
|
108
262
|
/** What one sync did for one mapping. */
|
|
109
263
|
export const FilesMappingReportType = StructType({
|
|
110
|
-
|
|
264
|
+
target: FilesTargetType,
|
|
111
265
|
/** Files new since the last sync */
|
|
112
266
|
added: IntegerType,
|
|
113
267
|
/** Files whose bytes changed */
|
|
@@ -116,12 +270,20 @@ export const FilesMappingReportType = StructType({
|
|
|
116
270
|
removed: IntegerType,
|
|
117
271
|
/** Files as they were */
|
|
118
272
|
unchanged: IntegerType,
|
|
119
|
-
/** Files not taken
|
|
273
|
+
/** Files not taken, and why */
|
|
120
274
|
refused: ArrayType(FilesRefusalType),
|
|
121
275
|
/** The bytes taken in */
|
|
122
276
|
bytes: IntegerType,
|
|
123
|
-
/** Whether the
|
|
277
|
+
/** Whether the target's value changed */
|
|
124
278
|
updated: BooleanType,
|
|
279
|
+
/** The typed value taken in, for a typed mapping that took its file */
|
|
280
|
+
taken: OptionType(FilesTakenType),
|
|
281
|
+
/** The commit a seed or a feed made: `$init`, `$seed`, or the mutation's */
|
|
282
|
+
commit: OptionType(StringType),
|
|
283
|
+
/** Why a seed was not applied: the record has been mutated since its seed */
|
|
284
|
+
kept: OptionType(StringType),
|
|
285
|
+
/** Why a feed waits: its record has no state yet; tried again by the next sync */
|
|
286
|
+
waiting: OptionType(StringType),
|
|
125
287
|
});
|
|
126
288
|
/** What one sync did. */
|
|
127
289
|
export const FilesSyncReportType = StructType({
|
|
@@ -131,25 +293,66 @@ export const FilesSyncReportType = StructType({
|
|
|
131
293
|
dryRun: BooleanType,
|
|
132
294
|
mappings: ArrayType(FilesMappingReportType),
|
|
133
295
|
});
|
|
296
|
+
/** What a target took of one file. */
|
|
297
|
+
export const FilesLedgerEntryType = StructType({
|
|
298
|
+
etag: StringType,
|
|
299
|
+
size: IntegerType,
|
|
300
|
+
/** The file's SHA-256, where the sync hashed it (a typed file, a push) */
|
|
301
|
+
sha256: OptionType(StringType),
|
|
302
|
+
/** When the file was last written, as its listing said */
|
|
303
|
+
modified: OptionType(DateTimeType),
|
|
304
|
+
});
|
|
134
305
|
/**
|
|
135
|
-
* What
|
|
136
|
-
* sync wrote (its hash), and what it was
|
|
137
|
-
* where its source was bound, as one
|
|
138
|
-
*
|
|
139
|
-
*
|
|
306
|
+
* What a target took last: each file's ETag, size and hash by its key, the
|
|
307
|
+
* value the sync wrote (its hash) or the commit it made, and what it was
|
|
308
|
+
* taken under: the mapping's shape and where its source was bound, as one
|
|
309
|
+
* text. A sync trusts it only while the target still holds that value (or
|
|
310
|
+
* that commit is its head) and the mapping and binding are as they were, so
|
|
311
|
+
* a ledger a sync wrote under other declarations, or from elsewhere, is
|
|
140
312
|
* never read against these. The CLI keeps it in a local repository's state
|
|
141
313
|
* file, the platform in its store.
|
|
142
314
|
*/
|
|
143
315
|
export const FilesLedgerType = StructType({
|
|
144
|
-
entries: DictType(StringType,
|
|
316
|
+
entries: DictType(StringType, FilesLedgerEntryType),
|
|
317
|
+
/** The value the sync wrote, its hash: an input's */
|
|
145
318
|
value: OptionType(StringType),
|
|
146
319
|
under: OptionType(StringType),
|
|
320
|
+
/** The commit the sync made: a record's seed, a mutation's last feed */
|
|
321
|
+
commit: OptionType(StringType),
|
|
322
|
+
/** The SHA-256 of a feed the mutation refused: not tried again until the file changes */
|
|
323
|
+
tried: OptionType(StringType),
|
|
324
|
+
/**
|
|
325
|
+
* A typed intake under way across rounds: the file (its key and ETag, so
|
|
326
|
+
* another file is never resumed as it), its SHA-256 once its bytes are
|
|
327
|
+
* placed in the store (the delivery its intake resumes), else where its
|
|
328
|
+
* staging stood (the platform's own progress, as text)
|
|
329
|
+
*/
|
|
330
|
+
taking: OptionType(StructType({ key: StringType, etag: StringType, sha256: OptionType(StringType), staging: OptionType(StringType) })),
|
|
331
|
+
});
|
|
332
|
+
/** What a mapping holds, from its ledger: the file it took last. */
|
|
333
|
+
export const FilesHeldType = StructType({
|
|
334
|
+
key: StringType,
|
|
335
|
+
size: IntegerType,
|
|
336
|
+
modified: OptionType(DateTimeType),
|
|
337
|
+
sha256: OptionType(StringType),
|
|
338
|
+
/** The commit it made, for a record or a mutation */
|
|
339
|
+
commit: OptionType(StringType),
|
|
147
340
|
});
|
|
148
|
-
/** A
|
|
341
|
+
/** A mapping's state: what it holds, and whether its record is pending. */
|
|
342
|
+
export const FilesMappingStatusType = StructType({
|
|
343
|
+
target: FilesTargetType,
|
|
344
|
+
/** The file it holds; none before its first sync, or for a folder or listing */
|
|
345
|
+
holds: OptionType(FilesHeldType),
|
|
346
|
+
/** A record mapping whose record has no state yet: seeded by the next sync */
|
|
347
|
+
pending: BooleanType,
|
|
348
|
+
});
|
|
349
|
+
/** A workspace's Files: its declarations, its bindings, its last sync, and what each mapping holds. */
|
|
149
350
|
export const FilesStatusType = StructType({
|
|
150
351
|
manifest: OptionType(FilesManifestType),
|
|
151
352
|
bindings: ArrayType(FilesBindingType),
|
|
152
353
|
lastSync: OptionType(FilesSyncReportType),
|
|
354
|
+
/** Each declared mapping's state, in the declarations' order; none without declarations */
|
|
355
|
+
mappings: ArrayType(FilesMappingStatusType),
|
|
153
356
|
});
|
|
154
357
|
/**
|
|
155
358
|
* A bucket a deployment lets a repository's bindings point into, and the
|
|
@@ -168,7 +371,7 @@ export const FilesPackageType = StructType({
|
|
|
168
371
|
});
|
|
169
372
|
/** A deployed workspace's Files, as `GET …/files` answers them. */
|
|
170
373
|
export const FilesWorkspaceType = StructType({
|
|
171
|
-
/** Its declarations, its bindings
|
|
374
|
+
/** Its declarations, its bindings, its last sync and what each mapping holds */
|
|
172
375
|
status: FilesStatusType,
|
|
173
376
|
/** Where the repository's bindings may point */
|
|
174
377
|
granted: ArrayType(FilesGrantType),
|
|
@@ -192,8 +395,10 @@ export const FilesDeployRequestType = StructType({
|
|
|
192
395
|
export const FilesSyncRequestType = StructType({
|
|
193
396
|
/** List what a sync would take, and take nothing */
|
|
194
397
|
dryRun: BooleanType,
|
|
195
|
-
/** Only these
|
|
196
|
-
|
|
398
|
+
/** Only these targets; every declared target when none */
|
|
399
|
+
targets: OptionType(ArrayType(FilesTargetType)),
|
|
400
|
+
/** Records whose file is taken as their state again (`$seed`) whatever has mutated them since */
|
|
401
|
+
reset: ArrayType(StringType),
|
|
197
402
|
});
|
|
198
403
|
/** What a sync's request did: started a sync, its id; or found one under way, its id, and started nothing. */
|
|
199
404
|
export const FilesSyncStartType = VariantType({
|
|
@@ -217,19 +422,104 @@ export const FilesSyncJobType = StructType({
|
|
|
217
422
|
/** Who asked for it: their email, else their subject */
|
|
218
423
|
by: StringType,
|
|
219
424
|
dryRun: BooleanType,
|
|
220
|
-
|
|
425
|
+
targets: OptionType(ArrayType(FilesTargetType)),
|
|
426
|
+
reset: ArrayType(StringType),
|
|
221
427
|
state: FilesSyncStateType,
|
|
222
428
|
startedAt: DateTimeType,
|
|
223
429
|
finishedAt: OptionType(DateTimeType),
|
|
224
|
-
/** What it has taken, per
|
|
430
|
+
/** What it has taken, per target; whole once it has ended */
|
|
225
431
|
report: OptionType(FilesSyncReportType),
|
|
226
432
|
});
|
|
433
|
+
/** A file a push offers: its name, where it came from, its size, its hash and its beast2 type. */
|
|
434
|
+
export const FilesPushFileType = StructType({
|
|
435
|
+
/** Its name: a file's own, or its path relative to the directory it came from */
|
|
436
|
+
name: StringType,
|
|
437
|
+
/** The directory it came from, its own name, when a directory was pushed */
|
|
438
|
+
directory: OptionType(StringType),
|
|
439
|
+
size: IntegerType,
|
|
440
|
+
/** Its SHA-256, hex */
|
|
441
|
+
sha256: StringType,
|
|
442
|
+
/** The root type its beast2 header declares; none for a file that is no beast2 */
|
|
443
|
+
type: OptionType(EastTypeType),
|
|
444
|
+
});
|
|
445
|
+
/** A push's plan asked for (`POST …/files/push`): the files, and the target they are all for, if named. */
|
|
446
|
+
export const FilesPushRequestType = StructType({
|
|
447
|
+
files: ArrayType(FilesPushFileType),
|
|
448
|
+
/** The target every file is for ({@link filesTargetText}; a bare name when unique across kinds); none to match each by its name */
|
|
449
|
+
as: OptionType(StringType),
|
|
450
|
+
});
|
|
451
|
+
/**
|
|
452
|
+
* How a planned file is put: one presigned PUT bound to its SHA-256; a
|
|
453
|
+
* multipart upload the platform created, a presigned URL per part,
|
|
454
|
+
* completed by `POST …/files/push/complete`; or `external`, a bucket the
|
|
455
|
+
* platform does not write, which the client puts with its own credentials.
|
|
456
|
+
*/
|
|
457
|
+
export const FilesPushUploadType = VariantType({
|
|
458
|
+
single: StructType({ url: StringType, headers: DictType(StringType, StringType) }),
|
|
459
|
+
multipart: StructType({
|
|
460
|
+
uploadId: StringType,
|
|
461
|
+
/** Each part's bytes but the last's */
|
|
462
|
+
partBytes: IntegerType,
|
|
463
|
+
parts: ArrayType(StructType({ number: IntegerType, url: StringType })),
|
|
464
|
+
}),
|
|
465
|
+
external: NullType,
|
|
466
|
+
});
|
|
467
|
+
/**
|
|
468
|
+
* Why a push does not put a file.
|
|
469
|
+
*
|
|
470
|
+
* - `no_mapping`: no mapping takes a file of its name.
|
|
471
|
+
* - `ambiguous`: several would; name one with `as`.
|
|
472
|
+
* - `unknown_target`: `as` names no mapping.
|
|
473
|
+
* - `shape_mismatch`: a directory for a mapping that takes one file, or a
|
|
474
|
+
* file for one that takes a folder (`directory`: which was offered).
|
|
475
|
+
* - `not_included`: a file the mapping's `include` glob leaves out, which
|
|
476
|
+
* no sync would take.
|
|
477
|
+
* - `not_latest`: a `latest` mapping whose source holds a greater key.
|
|
478
|
+
* - `type_mismatch`, `not_beast2`, `too_large`: as a sync refuses them.
|
|
479
|
+
*/
|
|
480
|
+
export const FilesPushRefusalType = VariantType({
|
|
481
|
+
no_mapping: NullType,
|
|
482
|
+
ambiguous: ArrayType(FilesTargetType),
|
|
483
|
+
unknown_target: StringType,
|
|
484
|
+
shape_mismatch: StructType({ target: FilesTargetType, directory: BooleanType }),
|
|
485
|
+
not_included: StructType({ target: FilesTargetType, include: StringType }),
|
|
486
|
+
not_latest: StructType({ target: FilesTargetType, greatest: StringType }),
|
|
487
|
+
type_mismatch: StructType({ target: FilesTargetType, expected: EastTypeType, actual: EastTypeType }),
|
|
488
|
+
not_beast2: StructType({ target: FilesTargetType, expected: EastTypeType }),
|
|
489
|
+
too_large: StructType({ target: FilesTargetType, size: IntegerType, limit: IntegerType }),
|
|
490
|
+
});
|
|
491
|
+
/** What a push does with one file: puts it at a key, finds it there already, or refuses it. */
|
|
492
|
+
export const FilesPushOutcomeType = VariantType({
|
|
493
|
+
put: StructType({ target: FilesTargetType, source: StringType, key: StringType, upload: FilesPushUploadType }),
|
|
494
|
+
unchanged: StructType({ target: FilesTargetType, source: StringType, key: StringType }),
|
|
495
|
+
refused: FilesPushRefusalType,
|
|
496
|
+
});
|
|
497
|
+
/** A push's plan: each file's outcome, and the bindings the puts go to. */
|
|
498
|
+
export const FilesPushPlanType = StructType({
|
|
499
|
+
/** The bindings of the sources any file is put to */
|
|
500
|
+
bindings: ArrayType(FilesBindingType),
|
|
501
|
+
files: ArrayType(StructType({ name: StringType, directory: OptionType(StringType), outcome: FilesPushOutcomeType })),
|
|
502
|
+
});
|
|
503
|
+
/** The completion of a multipart upload a plan created (`POST …/files/push/complete`). */
|
|
504
|
+
export const FilesPushCompleteRequestType = StructType({
|
|
505
|
+
key: StringType,
|
|
506
|
+
uploadId: StringType,
|
|
507
|
+
parts: ArrayType(StructType({ number: IntegerType, etag: StringType })),
|
|
508
|
+
});
|
|
509
|
+
/** A completed upload: the object's ETag. */
|
|
510
|
+
export const FilesPushCompleteResponseType = StructType({ etag: StringType });
|
|
227
511
|
/**
|
|
228
512
|
* Why declarations do not fit a package, or a binding does not fit them.
|
|
229
513
|
*
|
|
230
|
-
* - Against the package: `input_missing`, `input_not_writable`,
|
|
231
|
-
*
|
|
232
|
-
*
|
|
514
|
+
* - Against the package: `input_missing`, `input_not_writable`,
|
|
515
|
+
* `input_type`; `record_missing`, `record_type`; `mutation_missing`,
|
|
516
|
+
* `mutation_arity` (a fed mutation takes exactly one argument),
|
|
517
|
+
* `mutation_patch` (a `patch` mutation takes a patch, not a value),
|
|
518
|
+
* `mutation_type`.
|
|
519
|
+
* - The declarations themselves: `duplicate_target` (two mappings fill one
|
|
520
|
+
* target), `target_shape` (a record or mutation mapped to a folder or a
|
|
521
|
+
* listing), `target_untyped` (a record or mutation mapping naming no
|
|
522
|
+
* type), `invalid_name` (a name e3 refuses), `invalid_key` (a key or
|
|
233
523
|
* prefix that is empty or not relative), `invalid_include` (a glob that
|
|
234
524
|
* matches nothing well-formed).
|
|
235
525
|
* - Bindings: `source_unknown` (bound, but not declared), `source_unbound`
|
|
@@ -237,7 +527,7 @@ export const FilesSyncJobType = StructType({
|
|
|
237
527
|
* `not_granted` (the deployment grants no source holding the URL), and
|
|
238
528
|
* `local_only` (`profile` or `latest`, on a deployed workspace).
|
|
239
529
|
*
|
|
240
|
-
* Types are compared exactly: `expected` is the
|
|
530
|
+
* Types are compared exactly: `expected` is the mapping's, `actual` the
|
|
241
531
|
* package's.
|
|
242
532
|
*
|
|
243
533
|
* @remarks
|
|
@@ -248,10 +538,18 @@ export const FilesProblemType = VariantType({
|
|
|
248
538
|
input_missing: StructType({ input: StringType, expected: EastTypeType }),
|
|
249
539
|
input_not_writable: StructType({ input: StringType }),
|
|
250
540
|
input_type: StructType({ input: StringType, expected: EastTypeType, actual: EastTypeType }),
|
|
251
|
-
|
|
541
|
+
record_missing: StructType({ record: StringType, expected: EastTypeType }),
|
|
542
|
+
record_type: StructType({ record: StringType, expected: EastTypeType, actual: EastTypeType }),
|
|
543
|
+
mutation_missing: StructType({ record: StringType, mutation: StringType }),
|
|
544
|
+
mutation_arity: StructType({ record: StringType, mutation: StringType, arity: IntegerType }),
|
|
545
|
+
mutation_patch: StructType({ record: StringType, mutation: StringType }),
|
|
546
|
+
mutation_type: StructType({ record: StringType, mutation: StringType, expected: EastTypeType, actual: EastTypeType }),
|
|
547
|
+
duplicate_target: StructType({ target: FilesTargetType }),
|
|
548
|
+
target_shape: StructType({ target: FilesTargetType }),
|
|
549
|
+
target_untyped: StructType({ target: FilesTargetType }),
|
|
252
550
|
invalid_name: StructType({ kind: StringType, name: StringType, reason: StringType }),
|
|
253
|
-
invalid_key: StructType({
|
|
254
|
-
invalid_include: StructType({
|
|
551
|
+
invalid_key: StructType({ target: FilesTargetType, key: StringType, reason: StringType }),
|
|
552
|
+
invalid_include: StructType({ target: FilesTargetType, include: StringType, reason: StringType }),
|
|
255
553
|
source_unknown: StructType({ source: StringType }),
|
|
256
554
|
source_unbound: StructType({ source: StringType }),
|
|
257
555
|
invalid_url: StructType({ source: StringType, url: StringType, reason: StringType }),
|
|
@@ -259,28 +557,59 @@ export const FilesProblemType = VariantType({
|
|
|
259
557
|
local_only: StructType({ source: StringType, option: StringType }),
|
|
260
558
|
});
|
|
261
559
|
/**
|
|
262
|
-
* What a deploy of declarations did: kept them, with the
|
|
560
|
+
* What a deploy of declarations did: kept them, with the targets whose
|
|
263
561
|
* declaration changed, which the next sync takes again whole; checked them
|
|
264
562
|
* and kept nothing (a dry run); or refused them, naming every problem. Each
|
|
265
563
|
* names the package the workspace runs, which they were checked against.
|
|
266
564
|
*/
|
|
267
565
|
export const FilesDeployResponseType = VariantType({
|
|
268
|
-
deployed: StructType({ package: FilesPackageType, retaken: ArrayType(
|
|
566
|
+
deployed: StructType({ package: FilesPackageType, retaken: ArrayType(FilesTargetType) }),
|
|
269
567
|
checked: StructType({ package: FilesPackageType }),
|
|
270
568
|
refused: StructType({ package: FilesPackageType, problems: ArrayType(FilesProblemType) }),
|
|
271
569
|
});
|
|
272
570
|
/**
|
|
273
|
-
* What a bind did: kept the binding, with the
|
|
571
|
+
* What a bind did: kept the binding, with the targets the next sync takes
|
|
274
572
|
* again whole when it moved; or refused it, naming every problem.
|
|
275
573
|
*/
|
|
276
574
|
export const FilesBindResponseType = VariantType({
|
|
277
|
-
bound: StructType({ retaken: ArrayType(
|
|
575
|
+
bound: StructType({ retaken: ArrayType(FilesTargetType) }),
|
|
278
576
|
refused: ArrayType(FilesProblemType),
|
|
279
577
|
});
|
|
280
|
-
/**
|
|
281
|
-
|
|
578
|
+
/**
|
|
579
|
+
* A type, briefly, as the problems and refusals print it.
|
|
580
|
+
*
|
|
581
|
+
* @param type - The type
|
|
582
|
+
* @returns Its summary, a few levels deep
|
|
583
|
+
*/
|
|
584
|
+
export function filesTypeWords(type) {
|
|
282
585
|
return printTypeValueSummary(type, 3, 4);
|
|
283
586
|
}
|
|
587
|
+
/**
|
|
588
|
+
* A refusal's reason as words that follow the file's key.
|
|
589
|
+
*
|
|
590
|
+
* @param reason - The reason
|
|
591
|
+
* @returns The words
|
|
592
|
+
*/
|
|
593
|
+
export function filesRefusalText(reason) {
|
|
594
|
+
switch (reason.type) {
|
|
595
|
+
case 'too_large':
|
|
596
|
+
return `is ${reason.value.size} bytes, over the ${reason.value.limit} its mapping takes`;
|
|
597
|
+
case 'segment_too_large':
|
|
598
|
+
return `holds a segment of ${reason.value.bytes} bytes, over beast2's ${reason.value.limit}: write it again with a current writer`;
|
|
599
|
+
case 'unreadable':
|
|
600
|
+
return reason.value;
|
|
601
|
+
case 'not_beast2':
|
|
602
|
+
return `is not a beast2 file (${reason.value})`;
|
|
603
|
+
case 'type_mismatch':
|
|
604
|
+
return `holds ${filesTypeWords(reason.value.actual)}; its mapping declares ${filesTypeWords(reason.value.expected)}`;
|
|
605
|
+
case 'mutation':
|
|
606
|
+
return `was not applied: the mutation answered ${reason.value.outcome}${reason.value.message === '' ? '' : ` (${reason.value.message})`}`;
|
|
607
|
+
case 'missing':
|
|
608
|
+
return reason.value;
|
|
609
|
+
case 'other':
|
|
610
|
+
return reason.value;
|
|
611
|
+
}
|
|
612
|
+
}
|
|
284
613
|
/**
|
|
285
614
|
* A problem as one line, which the CLI prints and an error's message carries.
|
|
286
615
|
*
|
|
@@ -290,19 +619,35 @@ function typeWords(type) {
|
|
|
290
619
|
export function filesProblemText(problem) {
|
|
291
620
|
switch (problem.type) {
|
|
292
621
|
case 'input_missing':
|
|
293
|
-
return `input ${problem.value.input}: the package has no such input (a ${
|
|
622
|
+
return `input ${problem.value.input}: the package has no such input (a ${filesTypeWords(problem.value.expected)} is declared)`;
|
|
294
623
|
case 'input_not_writable':
|
|
295
624
|
return `input ${problem.value.input}: it isn't an input the package lets anything write, so no file can fill it`;
|
|
296
625
|
case 'input_type':
|
|
297
|
-
return `input ${problem.value.input}: the package declares ${
|
|
298
|
-
case '
|
|
299
|
-
return `
|
|
626
|
+
return `input ${problem.value.input}: the package declares ${filesTypeWords(problem.value.actual)}, but its files fill a ${filesTypeWords(problem.value.expected)}`;
|
|
627
|
+
case 'record_missing':
|
|
628
|
+
return `record ${problem.value.record}: the package has no such record (a ${filesTypeWords(problem.value.expected)} is declared)`;
|
|
629
|
+
case 'record_type':
|
|
630
|
+
return `record ${problem.value.record}: the package declares its state ${filesTypeWords(problem.value.actual)}, but its file holds a ${filesTypeWords(problem.value.expected)}`;
|
|
631
|
+
case 'mutation_missing':
|
|
632
|
+
return `mutation ${problem.value.mutation} of ${problem.value.record}: the package has no such mutation on the record`;
|
|
633
|
+
case 'mutation_arity':
|
|
634
|
+
return `mutation ${problem.value.mutation} of ${problem.value.record}: it takes ${problem.value.arity} arguments, and a fed mutation takes exactly one`;
|
|
635
|
+
case 'mutation_patch':
|
|
636
|
+
return `mutation ${problem.value.mutation} of ${problem.value.record}: a patch mutation takes a patch, not a value, so no file can feed it`;
|
|
637
|
+
case 'mutation_type':
|
|
638
|
+
return `mutation ${problem.value.mutation} of ${problem.value.record}: its argument is ${filesTypeWords(problem.value.actual)}, but its file holds a ${filesTypeWords(problem.value.expected)}`;
|
|
639
|
+
case 'duplicate_target':
|
|
640
|
+
return `${filesTargetWords(problem.value.target)}: more than one mapping fills it`;
|
|
641
|
+
case 'target_shape':
|
|
642
|
+
return `${filesTargetWords(problem.value.target)}: a record or a mutation takes one file (file or latest), not a folder or a listing`;
|
|
643
|
+
case 'target_untyped':
|
|
644
|
+
return `${filesTargetWords(problem.value.target)}: its mapping names no type, and a record's or a mutation's file is a typed value`;
|
|
300
645
|
case 'invalid_name':
|
|
301
646
|
return `${problem.value.kind} ${problem.value.name}: ${problem.value.reason}`;
|
|
302
647
|
case 'invalid_key':
|
|
303
|
-
return
|
|
648
|
+
return `${filesTargetWords(problem.value.target)}: '${problem.value.key}' ${problem.value.reason}`;
|
|
304
649
|
case 'invalid_include':
|
|
305
|
-
return
|
|
650
|
+
return `${filesTargetWords(problem.value.target)}: include '${problem.value.include}' ${problem.value.reason}`;
|
|
306
651
|
case 'source_unknown':
|
|
307
652
|
return `source ${problem.value.source}: the declarations have no such source`;
|
|
308
653
|
case 'source_unbound':
|
|
@@ -315,4 +660,34 @@ export function filesProblemText(problem) {
|
|
|
315
660
|
return `source ${problem.value.source}: ${problem.value.option} applies to a local repository only`;
|
|
316
661
|
}
|
|
317
662
|
}
|
|
663
|
+
/**
|
|
664
|
+
* A push's refusal as words that follow the file's name.
|
|
665
|
+
*
|
|
666
|
+
* @param refusal - The refusal
|
|
667
|
+
* @returns The words
|
|
668
|
+
*/
|
|
669
|
+
export function filesPushRefusalText(refusal) {
|
|
670
|
+
switch (refusal.type) {
|
|
671
|
+
case 'no_mapping':
|
|
672
|
+
return 'no mapping takes a file of this name: name its target with --as';
|
|
673
|
+
case 'ambiguous':
|
|
674
|
+
return `several mappings would take it (${refusal.value.map(filesTargetText).join(', ')}): name one with --as`;
|
|
675
|
+
case 'unknown_target':
|
|
676
|
+
return `no mapping fills ${refusal.value}`;
|
|
677
|
+
case 'shape_mismatch':
|
|
678
|
+
return refusal.value.directory
|
|
679
|
+
? `${filesTargetWords(refusal.value.target)} takes one file, not a directory`
|
|
680
|
+
: `${filesTargetWords(refusal.value.target)} takes a folder of files, not one file`;
|
|
681
|
+
case 'not_included':
|
|
682
|
+
return `${filesTargetWords(refusal.value.target)} takes only files matching '${refusal.value.include}', which this name does not`;
|
|
683
|
+
case 'not_latest':
|
|
684
|
+
return `${filesTargetWords(refusal.value.target)} takes the greatest key under its prefix, and ${refusal.value.greatest} is greater`;
|
|
685
|
+
case 'type_mismatch':
|
|
686
|
+
return `holds ${filesTypeWords(refusal.value.actual)}; ${filesTargetWords(refusal.value.target)} declares ${filesTypeWords(refusal.value.expected)}`;
|
|
687
|
+
case 'not_beast2':
|
|
688
|
+
return `is not a beast2 file, and ${filesTargetWords(refusal.value.target)} takes a ${filesTypeWords(refusal.value.expected)}`;
|
|
689
|
+
case 'too_large':
|
|
690
|
+
return `is ${refusal.value.size} bytes, over the ${refusal.value.limit} ${filesTargetWords(refusal.value.target)} takes`;
|
|
691
|
+
}
|
|
692
|
+
}
|
|
318
693
|
//# sourceMappingURL=files-types.js.map
|