@fieldia/core 0.21.0 → 0.23.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 +116 -1
- package/package.json +1 -1
- package/schema/page.schema.json +149 -1
- package/src/index.d.mts +2 -2
- package/src/index.d.ts +2 -2
- package/src/index.js +3 -1
- package/src/index.js.map +1 -1
- package/src/index.mjs +2 -2
- package/src/index.mjs.map +1 -1
- package/src/lib/format/check-page.d.mts +3 -2
- package/src/lib/format/check-page.d.ts +3 -2
- package/src/lib/format/check-page.js +9 -4
- package/src/lib/format/check-page.js.map +1 -1
- package/src/lib/format/check-page.mjs +10 -5
- package/src/lib/format/check-page.mjs.map +1 -1
- package/src/lib/format/field.d.mts +85 -0
- package/src/lib/format/field.d.ts +85 -0
- package/src/lib/format/field.js +14 -1
- package/src/lib/format/field.js.map +1 -1
- package/src/lib/format/field.mjs +13 -0
- package/src/lib/format/field.mjs.map +1 -1
- package/src/lib/format/layout.d.mts +142 -17
- package/src/lib/format/layout.d.ts +142 -17
- package/src/lib/format/layout.js +18 -1
- package/src/lib/format/layout.js.map +1 -1
- package/src/lib/format/layout.mjs +17 -0
- package/src/lib/format/layout.mjs.map +1 -1
- package/src/lib/format/layout.types.d.mts +6 -2
- package/src/lib/format/layout.types.d.ts +6 -2
- package/src/lib/format/page.d.mts +69 -10
- package/src/lib/format/page.d.ts +69 -10
- package/src/lib/format/page.js +4 -1
- package/src/lib/format/page.js.map +1 -1
- package/src/lib/format/page.mjs +5 -2
- package/src/lib/format/page.mjs.map +1 -1
- package/src/lib/format/references.d.mts +7 -0
- package/src/lib/format/references.d.ts +7 -0
- package/src/lib/format/references.js +46 -0
- package/src/lib/format/references.js.map +1 -1
- package/src/lib/format/references.mjs +46 -0
- package/src/lib/format/references.mjs.map +1 -1
- package/src/lib/format/translate.js +3 -2
- package/src/lib/format/translate.js.map +1 -1
- package/src/lib/format/translate.mjs +3 -2
- package/src/lib/format/translate.mjs.map +1 -1
- package/src/lib/format/upgrade.d.mts +41 -0
- package/src/lib/format/upgrade.d.ts +41 -0
- package/src/lib/format/upgrade.js +41 -0
- package/src/lib/format/upgrade.js.map +1 -0
- package/src/lib/format/upgrade.mjs +37 -0
- package/src/lib/format/upgrade.mjs.map +1 -0
- package/src/lib/format/validate.d.mts +2 -1
- package/src/lib/format/validate.d.ts +2 -1
- package/src/lib/format/validate.js +4 -2
- package/src/lib/format/validate.js.map +1 -1
- package/src/lib/format/validate.mjs +4 -2
- package/src/lib/format/validate.mjs.map +1 -1
- package/src/lib/format/version.d.mts +16 -1
- package/src/lib/format/version.d.ts +16 -1
- package/src/lib/format/version.js +39 -2
- package/src/lib/format/version.js.map +1 -1
- package/src/lib/format/version.mjs +36 -1
- package/src/lib/format/version.mjs.map +1 -1
- package/src/lib/record/data-source.d.mts +224 -10
- package/src/lib/record/data-source.d.ts +224 -10
- package/src/lib/record/data-source.js +29 -0
- package/src/lib/record/data-source.js.map +1 -1
- package/src/lib/record/data-source.mjs +25 -0
- package/src/lib/record/data-source.mjs.map +1 -1
- package/src/lib/record/form.d.mts +144 -5
- package/src/lib/record/form.d.ts +144 -5
- package/src/lib/record/form.js +792 -42
- package/src/lib/record/form.js.map +1 -1
- package/src/lib/record/form.mjs +791 -43
- package/src/lib/record/form.mjs.map +1 -1
- package/src/lib/record/locales/ar.js +10 -0
- package/src/lib/record/locales/ar.js.map +1 -1
- package/src/lib/record/locales/ar.mjs +10 -0
- package/src/lib/record/locales/ar.mjs.map +1 -1
- package/src/lib/record/locales/de.js +10 -0
- package/src/lib/record/locales/de.js.map +1 -1
- package/src/lib/record/locales/de.mjs +10 -0
- package/src/lib/record/locales/de.mjs.map +1 -1
- package/src/lib/record/locales/fr.js +10 -0
- package/src/lib/record/locales/fr.js.map +1 -1
- package/src/lib/record/locales/fr.mjs +10 -0
- package/src/lib/record/locales/fr.mjs.map +1 -1
- package/src/lib/record/memory-data-source.d.mts +40 -3
- package/src/lib/record/memory-data-source.d.ts +40 -3
- package/src/lib/record/memory-data-source.js +164 -20
- package/src/lib/record/memory-data-source.js.map +1 -1
- package/src/lib/record/memory-data-source.mjs +164 -20
- package/src/lib/record/memory-data-source.mjs.map +1 -1
- package/src/lib/record/messages.d.mts +21 -0
- package/src/lib/record/messages.d.ts +21 -0
- package/src/lib/record/messages.js +10 -0
- package/src/lib/record/messages.js.map +1 -1
- package/src/lib/record/messages.mjs +10 -0
- package/src/lib/record/messages.mjs.map +1 -1
- package/src/lib/record/run.d.mts +50 -7
- package/src/lib/record/run.d.ts +50 -7
- package/src/lib/record/run.js +67 -20
- package/src/lib/record/run.js.map +1 -1
- package/src/lib/record/run.mjs +67 -20
- package/src/lib/record/run.mjs.map +1 -1
- package/src/lib/record/upload-to.d.mts +50 -0
- package/src/lib/record/upload-to.d.ts +50 -0
- package/src/lib/record/upload-to.js +117 -0
- package/src/lib/record/upload-to.js.map +1 -0
- package/src/lib/record/upload-to.mjs +114 -0
- package/src/lib/record/upload-to.mjs.map +1 -0
- package/src/lib/record/uploads.d.mts +152 -0
- package/src/lib/record/uploads.d.ts +152 -0
- package/src/lib/record/uploads.js +345 -0
- package/src/lib/record/uploads.js.map +1 -0
- package/src/lib/record/uploads.mjs +337 -0
- package/src/lib/record/uploads.mjs.map +1 -0
- package/src/lib/record/values.d.mts +6 -0
- package/src/lib/record/values.d.ts +6 -0
- package/src/lib/record/values.js.map +1 -1
- package/src/lib/record/values.mjs.map +1 -1
- package/src/runtime.d.mts +10 -6
- package/src/runtime.d.ts +10 -6
- package/src/runtime.js +19 -2
- package/src/runtime.js.map +1 -1
- package/src/runtime.mjs +7 -3
- package/src/runtime.mjs.map +1 -1
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { saveRefused } from './data-source.mjs';
|
|
2
|
+
/** The statuses that say the store will not keep this file, whatever is tried: its size, its kind, what it holds. */
|
|
3
|
+
const REFUSALS = new Set([400, 409, 413, 415, 422]);
|
|
4
|
+
const stopped = () => Object.assign(new Error('The upload was stopped'), { name: 'AbortError' });
|
|
5
|
+
/** An upload to a plain endpoint, for a data source: `{ ...source, upload: uploadTo({ url: '/api/files' }) }`. */
|
|
6
|
+
export function uploadTo(options) {
|
|
7
|
+
const method = options.method ?? 'POST';
|
|
8
|
+
return async (file, request) => {
|
|
9
|
+
if (request.signal?.aborted)
|
|
10
|
+
throw stopped();
|
|
11
|
+
const host = globalThis;
|
|
12
|
+
const given = typeof options.url === 'function' ? await options.url(file, request) : options.url;
|
|
13
|
+
const target = typeof given === 'string' ? { url: given } : given;
|
|
14
|
+
const own = typeof options.headers === 'function' ? await options.headers(file, request) : (options.headers ?? {});
|
|
15
|
+
const headers = { ...own, ...target.headers };
|
|
16
|
+
// A file the browser picked is a Blob already; one held as bytes is made one.
|
|
17
|
+
const blob = file instanceof host.Blob ? file : new host.Blob([await file.arrayBuffer()], { type: file.type });
|
|
18
|
+
let body = blob;
|
|
19
|
+
if (method === 'PUT') {
|
|
20
|
+
if (!Object.keys(headers).some((name) => name.toLowerCase() === 'content-type'))
|
|
21
|
+
headers['Content-Type'] = file.type || 'application/octet-stream';
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
const form = new host.FormData();
|
|
25
|
+
form.append(options.field ?? 'file', blob, file.name);
|
|
26
|
+
body = form;
|
|
27
|
+
}
|
|
28
|
+
const answer = await (host.XMLHttpRequest ? viaXhr : viaFetch)(host, { method, url: target.url, headers, body, file, request, withCredentials: options.withCredentials === true });
|
|
29
|
+
if (answer.status < 200 || answer.status >= 300) {
|
|
30
|
+
const said = wordsOf(answer);
|
|
31
|
+
if (REFUSALS.has(answer.status))
|
|
32
|
+
throw saveRefused({ kind: 'rule', message: said || `The store did not take ${file.name} (${answer.status})` });
|
|
33
|
+
throw new Error(said ? `${said} (${answer.status})` : `The store answered ${answer.status}`);
|
|
34
|
+
}
|
|
35
|
+
const linked = options.link ? await options.link(answer, file) : linkOf(answer, method, host);
|
|
36
|
+
if (!linked.url)
|
|
37
|
+
throw new Error(`The store's answer named no address for ${file.name}: give uploadTo a link() that reads it`);
|
|
38
|
+
return { url: linked.url, name: linked.name ?? file.name, size: linked.size ?? file.size, type: linked.type ?? file.type, ...(linked.fileId !== undefined ? { fileId: linked.fileId } : {}) };
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
function viaXhr(host, sending) {
|
|
42
|
+
const { request } = sending;
|
|
43
|
+
return new Promise((resolve, reject) => {
|
|
44
|
+
const xhr = new host.XMLHttpRequest();
|
|
45
|
+
const stop = () => xhr.abort();
|
|
46
|
+
const done = () => request.signal?.removeEventListener('abort', stop);
|
|
47
|
+
xhr.open(sending.method, sending.url);
|
|
48
|
+
for (const [name, value] of Object.entries(sending.headers))
|
|
49
|
+
xhr.setRequestHeader(name, value);
|
|
50
|
+
if (sending.withCredentials)
|
|
51
|
+
xhr.withCredentials = true;
|
|
52
|
+
xhr.upload.onprogress = (event) => request.onProgress?.(event.loaded, event.lengthComputable ? event.total : sending.file.size);
|
|
53
|
+
xhr.onload = () => (done(), resolve(answered(sending.url, xhr.status, xhr.responseText, (name) => xhr.getResponseHeader(name))));
|
|
54
|
+
// What fetch throws when the network fails: read as the network's problem.
|
|
55
|
+
xhr.onerror = () => (done(), reject(new TypeError('Failed to fetch: the network failed during the upload')));
|
|
56
|
+
xhr.onabort = () => (done(), reject(stopped()));
|
|
57
|
+
request.signal?.addEventListener('abort', stop);
|
|
58
|
+
xhr.send(sending.body);
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
async function viaFetch(host, sending) {
|
|
62
|
+
if (!host.fetch)
|
|
63
|
+
throw new Error('uploadTo needs XMLHttpRequest or fetch');
|
|
64
|
+
const response = await host.fetch(sending.url, {
|
|
65
|
+
method: sending.method,
|
|
66
|
+
headers: sending.headers,
|
|
67
|
+
body: sending.body,
|
|
68
|
+
...(sending.request.signal ? { signal: sending.request.signal } : {}),
|
|
69
|
+
...(sending.withCredentials ? { credentials: 'include' } : {}),
|
|
70
|
+
});
|
|
71
|
+
const text = await response.text();
|
|
72
|
+
// No progress on the way: the whole of it, once it is there.
|
|
73
|
+
sending.request.onProgress?.(sending.file.size, sending.file.size);
|
|
74
|
+
return answered(sending.url, response.status, text, (name) => response.headers.get(name));
|
|
75
|
+
}
|
|
76
|
+
function answered(url, status, text, header) {
|
|
77
|
+
let json;
|
|
78
|
+
try {
|
|
79
|
+
json = text ? JSON.parse(text) : undefined;
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
json = undefined;
|
|
83
|
+
}
|
|
84
|
+
return { status, url, text, json, header };
|
|
85
|
+
}
|
|
86
|
+
/** What a refusing server says, for the person: its JSON's message, or a short text. */
|
|
87
|
+
function wordsOf(answer) {
|
|
88
|
+
const json = answer.json;
|
|
89
|
+
const said = json?.message ?? (typeof json?.error === 'object' ? json.error?.message : json?.error);
|
|
90
|
+
if (typeof said === 'string' && said.trim())
|
|
91
|
+
return said.trim();
|
|
92
|
+
const text = answer.text.trim();
|
|
93
|
+
return text && text.length <= 200 && !/^\s*</.test(text) && answer.json === undefined ? text : '';
|
|
94
|
+
}
|
|
95
|
+
/** The stored file's address as the answer gives it: JSON, Location, or where a PUT put it. */
|
|
96
|
+
function linkOf(answer, method, host) {
|
|
97
|
+
const json = (answer.json && typeof answer.json === 'object' ? answer.json : {});
|
|
98
|
+
const id = json['fileId'] ?? json['id'];
|
|
99
|
+
const fileId = typeof id === 'string' || typeof id === 'number' ? id : undefined;
|
|
100
|
+
const said = json['url'] ?? json['location'];
|
|
101
|
+
const location = answer.header('location');
|
|
102
|
+
const url = typeof said === 'string' ? said : location ? against(location, answer.url, host) : method === 'PUT' ? answer.url.split('?')[0] : undefined;
|
|
103
|
+
return { ...(url ? { url } : {}), ...(fileId !== undefined ? { fileId } : {}) };
|
|
104
|
+
}
|
|
105
|
+
/** A Location read against the address the file was sent to. */
|
|
106
|
+
function against(location, sentTo, host) {
|
|
107
|
+
try {
|
|
108
|
+
return new host.URL(location, new host.URL(sentTo, host.location?.href).href).href;
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
return location;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
//# sourceMappingURL=upload-to.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"upload-to.mjs","sourceRoot":"","sources":["../../../../../../libs/core/src/lib/record/upload-to.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAA0D,MAAM,eAAe,CAAC;AAqDpG,qHAAqH;AACrH,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;AA4BpD,MAAM,OAAO,GAAG,GAAG,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,wBAAwB,CAAC,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC,CAAC;AAEjG,kHAAkH;AAClH,MAAM,UAAU,QAAQ,CAAC,OAAwB;IAC/C,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,MAAM,CAAC;IACxC,OAAO,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE;QAC7B,IAAI,OAAO,CAAC,MAAM,EAAE,OAAO;YAAE,MAAM,OAAO,EAAE,CAAC;QAC7C,MAAM,IAAI,GAAG,UAA6B,CAAC;QAC3C,MAAM,KAAK,GAAG,OAAO,OAAO,CAAC,GAAG,KAAK,UAAU,CAAC,CAAC,CAAC,MAAM,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC;QACjG,MAAM,MAAM,GAAiB,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;QAChF,MAAM,GAAG,GAAG,OAAO,OAAO,CAAC,OAAO,KAAK,UAAU,CAAC,CAAC,CAAC,MAAM,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC;QACnH,MAAM,OAAO,GAA2B,EAAE,GAAG,GAAG,EAAE,GAAG,MAAM,CAAC,OAAO,EAAE,CAAC;QACtE,8EAA8E;QAC9E,MAAM,IAAI,GAAG,IAAI,YAAY,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;QAC/G,IAAI,IAAI,GAAY,IAAI,CAAC;QACzB,IAAI,MAAM,KAAK,KAAK,EAAE,CAAC;YACrB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,cAAc,CAAC;gBAAE,OAAO,CAAC,cAAc,CAAC,GAAG,IAAI,CAAC,IAAI,IAAI,0BAA0B,CAAC;QACrJ,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YACjC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,IAAI,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;YACtD,IAAI,GAAG,IAAI,CAAC;QACd,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,eAAe,EAAE,OAAO,CAAC,eAAe,KAAK,IAAI,EAAE,CAAC,CAAC;QACnL,IAAI,MAAM,CAAC,MAAM,GAAG,GAAG,IAAI,MAAM,CAAC,MAAM,IAAI,GAAG,EAAE,CAAC;YAChD,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;YAC7B,IAAI,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC;gBAAE,MAAM,WAAW,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,IAAI,0BAA0B,IAAI,CAAC,IAAI,KAAK,MAAM,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;YAChJ,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,KAAK,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,sBAAsB,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;QAC/F,CAAC;QACD,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;QAC9F,IAAI,CAAC,MAAM,CAAC,GAAG;YAAE,MAAM,IAAI,KAAK,CAAC,2CAA2C,IAAI,CAAC,IAAI,wCAAwC,CAAC,CAAC;QAC/H,OAAO,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;IAChM,CAAC,CAAC;AACJ,CAAC;AAYD,SAAS,MAAM,CAAC,IAAU,EAAE,OAAgB;IAC1C,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC;IAC5B,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,GAAG,GAAG,IAAK,IAAI,CAAC,cAAsD,EAAE,CAAC;QAC/E,MAAM,IAAI,GAAG,GAAG,EAAE,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC;QAC/B,MAAM,IAAI,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,mBAAmB,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;QACtE,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC;QACtC,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC;YAAE,GAAG,CAAC,gBAAgB,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAC/F,IAAI,OAAO,CAAC,eAAe;YAAE,GAAG,CAAC,eAAe,GAAG,IAAI,CAAC;QACxD,GAAG,CAAC,MAAM,CAAC,UAAU,GAAG,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,gBAAgB,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAChI,GAAG,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC,CAAC,IAAI,EAAE,EAAE,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,YAAY,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QACjI,2EAA2E;QAC3E,GAAG,CAAC,OAAO,GAAG,GAAG,EAAE,CAAC,CAAC,IAAI,EAAE,EAAE,MAAM,CAAC,IAAI,SAAS,CAAC,uDAAuD,CAAC,CAAC,CAAC,CAAC;QAC7G,GAAG,CAAC,OAAO,GAAG,GAAG,EAAE,CAAC,CAAC,IAAI,EAAE,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;QAChD,OAAO,CAAC,MAAM,EAAE,gBAAgB,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;QAChD,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACzB,CAAC,CAAC,CAAC;AACL,CAAC;AAED,KAAK,UAAU,QAAQ,CAAC,IAAU,EAAE,OAAgB;IAClD,IAAI,CAAC,IAAI,CAAC,KAAK;QAAE,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;IAC3E,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE;QAC7C,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACrE,GAAG,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC/D,CAAC,CAAC;IACH,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;IACnC,6DAA6D;IAC7D,OAAO,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACnE,OAAO,QAAQ,CAAC,OAAO,CAAC,GAAG,EAAE,QAAQ,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;AAC5F,CAAC;AAED,SAAS,QAAQ,CAAC,GAAW,EAAE,MAAc,EAAE,IAAY,EAAE,MAAuC;IAClG,IAAI,IAAa,CAAC;IAClB,IAAI,CAAC;QACH,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAC7C,CAAC;IAAC,MAAM,CAAC;QACP,IAAI,GAAG,SAAS,CAAC;IACnB,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;AAC7C,CAAC;AAED,wFAAwF;AACxF,SAAS,OAAO,CAAC,MAAoB;IACnC,MAAM,IAAI,GAAG,MAAM,CAAC,IAA0D,CAAC;IAC/E,MAAM,IAAI,GAAG,IAAI,EAAE,OAAO,IAAI,CAAC,OAAO,IAAI,EAAE,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAE,IAAI,CAAC,KAAsC,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IACtI,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,IAAI,EAAE;QAAE,OAAO,IAAI,CAAC,IAAI,EAAE,CAAC;IAChE,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;IAChC,OAAO,IAAI,IAAI,IAAI,CAAC,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;AACpG,CAAC;AAED,+FAA+F;AAC/F,SAAS,MAAM,CAAC,MAAoB,EAAE,MAAc,EAAE,IAAU;IAC9D,MAAM,IAAI,GAAG,CAAC,MAAM,CAAC,IAAI,IAAI,OAAO,MAAM,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAA4B,CAAC;IAC5G,MAAM,EAAE,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC;IACxC,MAAM,MAAM,GAAG,OAAO,EAAE,KAAK,QAAQ,IAAI,OAAO,EAAE,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;IACjF,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,CAAC;IAC7C,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IAC3C,MAAM,GAAG,GAAG,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACvJ,OAAO,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;AAClF,CAAC;AAED,gEAAgE;AAChE,SAAS,OAAO,CAAC,QAAgB,EAAE,MAAc,EAAE,IAAU;IAC3D,IAAI,CAAC;QACH,OAAO,IAAI,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC;IACrF,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,QAAQ,CAAC;IAClB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import type { Field, Fields, LineField } from '../format/field.mjs';
|
|
2
|
+
import { type DataSource, type UploadFile } from './data-source.mjs';
|
|
3
|
+
import { type Messages } from './messages.mjs';
|
|
4
|
+
import type { FileValue, RecordId, Value, Values } from './values.mjs';
|
|
5
|
+
/**
|
|
6
|
+
* Files stored as they are picked. Where the data source has `upload`, a
|
|
7
|
+
* file or picture field hands each file to the form, which sends it to the
|
|
8
|
+
* app's store at once — three at a time, the rest waiting their turn, each
|
|
9
|
+
* made ready first when the field asks (a photo made smaller), one at a time
|
|
10
|
+
* — and puts the stored file's link in the field, in the order the files were
|
|
11
|
+
* picked. The form's state shows each on its way; Cancel stops one, Retry
|
|
12
|
+
* sends a failed one again. A save waits for those still going, and stops
|
|
13
|
+
* under its field for one that did not get there. A file still held as its
|
|
14
|
+
* bytes — a signature drawn, a value the app set — is stored by the save.
|
|
15
|
+
*/
|
|
16
|
+
/** A file on its way to the store, as the form's state shows it. */
|
|
17
|
+
export interface FileUpload {
|
|
18
|
+
readonly id: string;
|
|
19
|
+
/** The file or picture field it is for: on a table's line, the line's own field. */
|
|
20
|
+
readonly field: string;
|
|
21
|
+
/** For a field on a line of a table: the table's field and the line's key. */
|
|
22
|
+
readonly line?: {
|
|
23
|
+
readonly field: string;
|
|
24
|
+
readonly key: string;
|
|
25
|
+
};
|
|
26
|
+
readonly name: string;
|
|
27
|
+
readonly size: number;
|
|
28
|
+
readonly type: string;
|
|
29
|
+
/**
|
|
30
|
+
* `waiting` its turn; `preparing`, made ready first (a photo made smaller);
|
|
31
|
+
* `uploading`, `sent` of `total` bytes on their way; `failed`, not stored —
|
|
32
|
+
* Retry may mend it; `refused`, the store will not keep it, `error` says why.
|
|
33
|
+
*/
|
|
34
|
+
readonly status: 'waiting' | 'preparing' | 'uploading' | 'failed' | 'refused';
|
|
35
|
+
readonly sent: number;
|
|
36
|
+
/** The bytes in all, once the store has told them: null, and its bar moves with no number. */
|
|
37
|
+
readonly total: number | null;
|
|
38
|
+
/** Why it failed, or why the store refused it. */
|
|
39
|
+
readonly error?: string;
|
|
40
|
+
}
|
|
41
|
+
/** How files are taken, besides the field they are for. */
|
|
42
|
+
export interface UploadHow {
|
|
43
|
+
/** For a field on a line of a table: the table's field and the line's key. */
|
|
44
|
+
line?: {
|
|
45
|
+
field: string;
|
|
46
|
+
key: string;
|
|
47
|
+
};
|
|
48
|
+
/** Each file made ready before it goes, one at a time: a photo made smaller. A file it cannot make ready goes as it is. */
|
|
49
|
+
prepare?: (file: UploadFile) => Promise<UploadFile>;
|
|
50
|
+
}
|
|
51
|
+
/** How many files go to the store at once; the rest wait their turn. */
|
|
52
|
+
export declare const UPLOADS_AT_ONCE = 3;
|
|
53
|
+
/** Whether an upload is still going: waiting, being made ready, or on its way. */
|
|
54
|
+
export declare const uploadGoing: (upload: FileUpload) => boolean;
|
|
55
|
+
/** What the form gives the uploads: where files go, where their links are put, and how the state is told. */
|
|
56
|
+
export interface UploadsHost {
|
|
57
|
+
source(): DataSource | undefined;
|
|
58
|
+
/** The page's model, or a page of responses' id; for a saved form placed in a record, the record's. */
|
|
59
|
+
model(): string;
|
|
60
|
+
recordId(): RecordId | null;
|
|
61
|
+
/**
|
|
62
|
+
* Where the form's fields sit in the record its files are for, before each
|
|
63
|
+
* field's name: a saved form placed in a record keeps its answers under the
|
|
64
|
+
* part's name, so its field `doc` is `consent.doc` there. Empty otherwise.
|
|
65
|
+
*/
|
|
66
|
+
under?: string;
|
|
67
|
+
/** A line's id, once it is saved. */
|
|
68
|
+
lineId(field: string, key: string): RecordId | undefined;
|
|
69
|
+
/** A field's or a line field's definition, or null when it holds no files. */
|
|
70
|
+
fileField(field: string, line?: {
|
|
71
|
+
field: string;
|
|
72
|
+
key: string;
|
|
73
|
+
}): Field | LineField | null;
|
|
74
|
+
/** The field's value now. */
|
|
75
|
+
read(field: string, line?: {
|
|
76
|
+
field: string;
|
|
77
|
+
key: string;
|
|
78
|
+
}): Value | undefined;
|
|
79
|
+
/** Write the field: a person's pick, or (`quiet`) a save putting a link in place of the bytes. */
|
|
80
|
+
write(field: string, line: {
|
|
81
|
+
field: string;
|
|
82
|
+
key: string;
|
|
83
|
+
} | undefined, value: Value, quiet: boolean): void;
|
|
84
|
+
changed(uploads: readonly FileUpload[]): void;
|
|
85
|
+
track<T>(promise: Promise<T>): Promise<T>;
|
|
86
|
+
}
|
|
87
|
+
interface Entry {
|
|
88
|
+
id: string;
|
|
89
|
+
/** Its place in the order files were picked. */
|
|
90
|
+
seq: number;
|
|
91
|
+
field: string;
|
|
92
|
+
line?: {
|
|
93
|
+
field: string;
|
|
94
|
+
key: string;
|
|
95
|
+
};
|
|
96
|
+
file: UploadFile;
|
|
97
|
+
prepare?: (file: UploadFile) => Promise<UploadFile>;
|
|
98
|
+
/** Made ready, or needing nothing done. */
|
|
99
|
+
ready: boolean;
|
|
100
|
+
/** The file held as its bytes that this one is stored for: a save puts the link in its place. */
|
|
101
|
+
replaces?: FileValue;
|
|
102
|
+
status: FileUpload['status'];
|
|
103
|
+
sent: number;
|
|
104
|
+
total: number | null;
|
|
105
|
+
error?: string;
|
|
106
|
+
stop?: () => void;
|
|
107
|
+
/** Ends its run: stored, failed, refused or cancelled. */
|
|
108
|
+
end?: () => void;
|
|
109
|
+
}
|
|
110
|
+
/** A file held as its bytes, as the store takes a file: its name, size, kind and bytes. */
|
|
111
|
+
export declare function fileFromBytes(file: FileValue): UploadFile;
|
|
112
|
+
/**
|
|
113
|
+
* The values as a draft keeps them: a file held as its bytes is left out —
|
|
114
|
+
* a field holding one is not kept at all, and a line's loses that file —
|
|
115
|
+
* so a draft stays small enough for the browser's store, and restoring it
|
|
116
|
+
* leaves those fields as the record holds them.
|
|
117
|
+
*/
|
|
118
|
+
export declare function withoutFileBytes(fields: Fields, values: Readonly<Values>): Values;
|
|
119
|
+
/** Each file still held as its bytes in the fields that changed — on the record, or on a changed table's lines — for a save to store. */
|
|
120
|
+
export declare function fileBytesIn(fields: Fields, values: Readonly<Values>, changed: readonly string[]): {
|
|
121
|
+
field: string;
|
|
122
|
+
line?: {
|
|
123
|
+
field: string;
|
|
124
|
+
key: string;
|
|
125
|
+
};
|
|
126
|
+
file: FileValue;
|
|
127
|
+
}[];
|
|
128
|
+
/** The uploads of one form. */
|
|
129
|
+
export declare function createUploads(host: UploadsHost): {
|
|
130
|
+
/** Send files picked for a field: its ids. */
|
|
131
|
+
start(field: string, files: readonly UploadFile[], how?: {
|
|
132
|
+
line?: Entry["line"];
|
|
133
|
+
prepare?: Entry["prepare"];
|
|
134
|
+
}): string[];
|
|
135
|
+
cancel(id: string): void;
|
|
136
|
+
retry(id: string): void;
|
|
137
|
+
/** Stop every upload: the changes they were for are gone. */
|
|
138
|
+
clear(): void;
|
|
139
|
+
/** Whether any file is still going. */
|
|
140
|
+
going: () => boolean;
|
|
141
|
+
settled: () => Promise<void>;
|
|
142
|
+
/** Store each file still held as its bytes in the fields given, and wait for them all. */
|
|
143
|
+
storeBytes(found: {
|
|
144
|
+
field: string;
|
|
145
|
+
line?: Entry["line"];
|
|
146
|
+
file: FileValue;
|
|
147
|
+
}[]): Promise<void>;
|
|
148
|
+
/** What stops a save, under each field: a file that failed, or that the store refused. */
|
|
149
|
+
problems(messages: Messages): Record<string, string>;
|
|
150
|
+
};
|
|
151
|
+
export type Uploads = ReturnType<typeof createUploads>;
|
|
152
|
+
export {};
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import type { Field, Fields, LineField } from '../format/field';
|
|
2
|
+
import { type DataSource, type UploadFile } from './data-source';
|
|
3
|
+
import { type Messages } from './messages';
|
|
4
|
+
import type { FileValue, RecordId, Value, Values } from './values';
|
|
5
|
+
/**
|
|
6
|
+
* Files stored as they are picked. Where the data source has `upload`, a
|
|
7
|
+
* file or picture field hands each file to the form, which sends it to the
|
|
8
|
+
* app's store at once — three at a time, the rest waiting their turn, each
|
|
9
|
+
* made ready first when the field asks (a photo made smaller), one at a time
|
|
10
|
+
* — and puts the stored file's link in the field, in the order the files were
|
|
11
|
+
* picked. The form's state shows each on its way; Cancel stops one, Retry
|
|
12
|
+
* sends a failed one again. A save waits for those still going, and stops
|
|
13
|
+
* under its field for one that did not get there. A file still held as its
|
|
14
|
+
* bytes — a signature drawn, a value the app set — is stored by the save.
|
|
15
|
+
*/
|
|
16
|
+
/** A file on its way to the store, as the form's state shows it. */
|
|
17
|
+
export interface FileUpload {
|
|
18
|
+
readonly id: string;
|
|
19
|
+
/** The file or picture field it is for: on a table's line, the line's own field. */
|
|
20
|
+
readonly field: string;
|
|
21
|
+
/** For a field on a line of a table: the table's field and the line's key. */
|
|
22
|
+
readonly line?: {
|
|
23
|
+
readonly field: string;
|
|
24
|
+
readonly key: string;
|
|
25
|
+
};
|
|
26
|
+
readonly name: string;
|
|
27
|
+
readonly size: number;
|
|
28
|
+
readonly type: string;
|
|
29
|
+
/**
|
|
30
|
+
* `waiting` its turn; `preparing`, made ready first (a photo made smaller);
|
|
31
|
+
* `uploading`, `sent` of `total` bytes on their way; `failed`, not stored —
|
|
32
|
+
* Retry may mend it; `refused`, the store will not keep it, `error` says why.
|
|
33
|
+
*/
|
|
34
|
+
readonly status: 'waiting' | 'preparing' | 'uploading' | 'failed' | 'refused';
|
|
35
|
+
readonly sent: number;
|
|
36
|
+
/** The bytes in all, once the store has told them: null, and its bar moves with no number. */
|
|
37
|
+
readonly total: number | null;
|
|
38
|
+
/** Why it failed, or why the store refused it. */
|
|
39
|
+
readonly error?: string;
|
|
40
|
+
}
|
|
41
|
+
/** How files are taken, besides the field they are for. */
|
|
42
|
+
export interface UploadHow {
|
|
43
|
+
/** For a field on a line of a table: the table's field and the line's key. */
|
|
44
|
+
line?: {
|
|
45
|
+
field: string;
|
|
46
|
+
key: string;
|
|
47
|
+
};
|
|
48
|
+
/** Each file made ready before it goes, one at a time: a photo made smaller. A file it cannot make ready goes as it is. */
|
|
49
|
+
prepare?: (file: UploadFile) => Promise<UploadFile>;
|
|
50
|
+
}
|
|
51
|
+
/** How many files go to the store at once; the rest wait their turn. */
|
|
52
|
+
export declare const UPLOADS_AT_ONCE = 3;
|
|
53
|
+
/** Whether an upload is still going: waiting, being made ready, or on its way. */
|
|
54
|
+
export declare const uploadGoing: (upload: FileUpload) => boolean;
|
|
55
|
+
/** What the form gives the uploads: where files go, where their links are put, and how the state is told. */
|
|
56
|
+
export interface UploadsHost {
|
|
57
|
+
source(): DataSource | undefined;
|
|
58
|
+
/** The page's model, or a page of responses' id; for a saved form placed in a record, the record's. */
|
|
59
|
+
model(): string;
|
|
60
|
+
recordId(): RecordId | null;
|
|
61
|
+
/**
|
|
62
|
+
* Where the form's fields sit in the record its files are for, before each
|
|
63
|
+
* field's name: a saved form placed in a record keeps its answers under the
|
|
64
|
+
* part's name, so its field `doc` is `consent.doc` there. Empty otherwise.
|
|
65
|
+
*/
|
|
66
|
+
under?: string;
|
|
67
|
+
/** A line's id, once it is saved. */
|
|
68
|
+
lineId(field: string, key: string): RecordId | undefined;
|
|
69
|
+
/** A field's or a line field's definition, or null when it holds no files. */
|
|
70
|
+
fileField(field: string, line?: {
|
|
71
|
+
field: string;
|
|
72
|
+
key: string;
|
|
73
|
+
}): Field | LineField | null;
|
|
74
|
+
/** The field's value now. */
|
|
75
|
+
read(field: string, line?: {
|
|
76
|
+
field: string;
|
|
77
|
+
key: string;
|
|
78
|
+
}): Value | undefined;
|
|
79
|
+
/** Write the field: a person's pick, or (`quiet`) a save putting a link in place of the bytes. */
|
|
80
|
+
write(field: string, line: {
|
|
81
|
+
field: string;
|
|
82
|
+
key: string;
|
|
83
|
+
} | undefined, value: Value, quiet: boolean): void;
|
|
84
|
+
changed(uploads: readonly FileUpload[]): void;
|
|
85
|
+
track<T>(promise: Promise<T>): Promise<T>;
|
|
86
|
+
}
|
|
87
|
+
interface Entry {
|
|
88
|
+
id: string;
|
|
89
|
+
/** Its place in the order files were picked. */
|
|
90
|
+
seq: number;
|
|
91
|
+
field: string;
|
|
92
|
+
line?: {
|
|
93
|
+
field: string;
|
|
94
|
+
key: string;
|
|
95
|
+
};
|
|
96
|
+
file: UploadFile;
|
|
97
|
+
prepare?: (file: UploadFile) => Promise<UploadFile>;
|
|
98
|
+
/** Made ready, or needing nothing done. */
|
|
99
|
+
ready: boolean;
|
|
100
|
+
/** The file held as its bytes that this one is stored for: a save puts the link in its place. */
|
|
101
|
+
replaces?: FileValue;
|
|
102
|
+
status: FileUpload['status'];
|
|
103
|
+
sent: number;
|
|
104
|
+
total: number | null;
|
|
105
|
+
error?: string;
|
|
106
|
+
stop?: () => void;
|
|
107
|
+
/** Ends its run: stored, failed, refused or cancelled. */
|
|
108
|
+
end?: () => void;
|
|
109
|
+
}
|
|
110
|
+
/** A file held as its bytes, as the store takes a file: its name, size, kind and bytes. */
|
|
111
|
+
export declare function fileFromBytes(file: FileValue): UploadFile;
|
|
112
|
+
/**
|
|
113
|
+
* The values as a draft keeps them: a file held as its bytes is left out —
|
|
114
|
+
* a field holding one is not kept at all, and a line's loses that file —
|
|
115
|
+
* so a draft stays small enough for the browser's store, and restoring it
|
|
116
|
+
* leaves those fields as the record holds them.
|
|
117
|
+
*/
|
|
118
|
+
export declare function withoutFileBytes(fields: Fields, values: Readonly<Values>): Values;
|
|
119
|
+
/** Each file still held as its bytes in the fields that changed — on the record, or on a changed table's lines — for a save to store. */
|
|
120
|
+
export declare function fileBytesIn(fields: Fields, values: Readonly<Values>, changed: readonly string[]): {
|
|
121
|
+
field: string;
|
|
122
|
+
line?: {
|
|
123
|
+
field: string;
|
|
124
|
+
key: string;
|
|
125
|
+
};
|
|
126
|
+
file: FileValue;
|
|
127
|
+
}[];
|
|
128
|
+
/** The uploads of one form. */
|
|
129
|
+
export declare function createUploads(host: UploadsHost): {
|
|
130
|
+
/** Send files picked for a field: its ids. */
|
|
131
|
+
start(field: string, files: readonly UploadFile[], how?: {
|
|
132
|
+
line?: Entry["line"];
|
|
133
|
+
prepare?: Entry["prepare"];
|
|
134
|
+
}): string[];
|
|
135
|
+
cancel(id: string): void;
|
|
136
|
+
retry(id: string): void;
|
|
137
|
+
/** Stop every upload: the changes they were for are gone. */
|
|
138
|
+
clear(): void;
|
|
139
|
+
/** Whether any file is still going. */
|
|
140
|
+
going: () => boolean;
|
|
141
|
+
settled: () => Promise<void>;
|
|
142
|
+
/** Store each file still held as its bytes in the fields given, and wait for them all. */
|
|
143
|
+
storeBytes(found: {
|
|
144
|
+
field: string;
|
|
145
|
+
line?: Entry["line"];
|
|
146
|
+
file: FileValue;
|
|
147
|
+
}[]): Promise<void>;
|
|
148
|
+
/** What stops a save, under each field: a file that failed, or that the store refused. */
|
|
149
|
+
problems(messages: Messages): Record<string, string>;
|
|
150
|
+
};
|
|
151
|
+
export type Uploads = ReturnType<typeof createUploads>;
|
|
152
|
+
export {};
|