@giveitsmaller/sdk 0.4.0 → 0.7.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/dist/_audit.js +67 -0
- package/dist/builder.d.ts +406 -0
- package/dist/builder.js +706 -0
- package/dist/client.d.ts +96 -2
- package/dist/client.js +968 -33
- package/dist/credentials.d.ts +61 -0
- package/dist/credentials.js +200 -0
- package/dist/ergonomic/preset_resolver.d.ts +75 -0
- package/dist/ergonomic/preset_resolver.js +568 -0
- package/dist/ergonomic/presets/_translate.d.ts +11 -0
- package/dist/ergonomic/presets/_translate.js +35 -0
- package/dist/ergonomic/presets/audio_compress.d.ts +16 -0
- package/dist/ergonomic/presets/audio_compress.js +45 -0
- package/dist/ergonomic/presets/document_epub_compress.d.ts +14 -0
- package/dist/ergonomic/presets/document_epub_compress.js +34 -0
- package/dist/ergonomic/presets/document_odf_compress.d.ts +14 -0
- package/dist/ergonomic/presets/document_odf_compress.js +34 -0
- package/dist/ergonomic/presets/document_office_compress.d.ts +16 -0
- package/dist/ergonomic/presets/document_office_compress.js +40 -0
- package/dist/ergonomic/presets/document_pdf_compress.d.ts +14 -0
- package/dist/ergonomic/presets/document_pdf_compress.js +35 -0
- package/dist/ergonomic/presets/image_compress.d.ts +43 -0
- package/dist/ergonomic/presets/image_compress.js +95 -0
- package/dist/ergonomic/presets/index.d.ts +77 -0
- package/dist/ergonomic/presets/index.js +216 -0
- package/dist/ergonomic/presets/video_compress.d.ts +30 -0
- package/dist/ergonomic/presets/video_compress.js +83 -0
- package/dist/errors.d.ts +251 -1
- package/dist/errors.js +268 -0
- package/dist/generated/sdk_spec/enums.d.ts +195 -0
- package/dist/generated/sdk_spec/enums.js +127 -0
- package/dist/generated/sdk_spec/errors.d.ts +16 -0
- package/dist/generated/sdk_spec/errors.js +473 -0
- package/dist/generated/sdk_spec/index.d.ts +4 -0
- package/dist/generated/sdk_spec/index.js +7 -0
- package/dist/generated/sdk_spec/presets.d.ts +6 -0
- package/dist/generated/sdk_spec/presets.js +157 -0
- package/dist/generated/sdk_spec/version.d.ts +3 -0
- package/dist/generated/sdk_spec/version.js +6 -0
- package/dist/gisl.d.ts +112 -0
- package/dist/gisl.js +266 -0
- package/dist/index.d.ts +17 -7
- package/dist/index.js +33 -3
- package/dist/merge.d.ts +142 -0
- package/dist/merge.js +411 -0
- package/dist/sse.d.ts +20 -1
- package/dist/sse.js +62 -3
- package/dist/types.d.ts +144 -14
- package/dist/types.js +18 -0
- package/package.json +2 -2
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
// T4a — PresetDefaults immutable builder + presetDefaults() factory.
|
|
2
|
+
//
|
|
3
|
+
// Implements the user-facing path for layered preset configuration:
|
|
4
|
+
//
|
|
5
|
+
// const defaults = presetDefaults()
|
|
6
|
+
// .imageCompress(OptimizeFor.Size, { quality: 75 })
|
|
7
|
+
// .videoCompress(OptimizeFor.Quality);
|
|
8
|
+
//
|
|
9
|
+
// const client = await gisl.create({ presetDefaults: defaults });
|
|
10
|
+
//
|
|
11
|
+
// `T4a` ships only the typed slot and the builder semantics — the
|
|
12
|
+
// resolver (T4b) reads `defaults.cellFor(media, op, level)` and merges
|
|
13
|
+
// shipped defaults + this user delta + per-call overrides at workflow-
|
|
14
|
+
// create time.
|
|
15
|
+
//
|
|
16
|
+
// **Semantics**
|
|
17
|
+
// - `cellFor(media, op, level)` returns the USER-SUPPLIED DELTA stored
|
|
18
|
+
// by the matching `.imageCompress(level, input)` call, or `undefined`
|
|
19
|
+
// if no such delta was registered. It does NOT return shipped defaults
|
|
20
|
+
// — those live on the leaf class (`*.shippedDefaultsFor(level)`).
|
|
21
|
+
// - Per-cell methods are immutable: each returns a fresh `PresetDefaults`
|
|
22
|
+
// carrying the original entries plus the new (cell, level) registration.
|
|
23
|
+
// Calling the same method twice on the same instance yields two
|
|
24
|
+
// distinct objects.
|
|
25
|
+
// - Calling `.imageCompress(level)` with no input registers an empty
|
|
26
|
+
// delta — the resolver will see "this cell asked for `level` with no
|
|
27
|
+
// overrides" and apply shipped defaults verbatim.
|
|
28
|
+
import { ImageCompressPresetOptions, } from './image_compress.js';
|
|
29
|
+
import { AudioCompressPresetOptions, } from './audio_compress.js';
|
|
30
|
+
import { VideoCompressPresetOptions, } from './video_compress.js';
|
|
31
|
+
import { DocumentPdfCompressPresetOptions, } from './document_pdf_compress.js';
|
|
32
|
+
import { DocumentOfficeCompressPresetOptions, } from './document_office_compress.js';
|
|
33
|
+
import { DocumentOdfCompressPresetOptions, } from './document_odf_compress.js';
|
|
34
|
+
import { DocumentEpubCompressPresetOptions, } from './document_epub_compress.js';
|
|
35
|
+
// Re-export everything callers need from this module's root.
|
|
36
|
+
export { ImageCompressPresetOptions, } from './image_compress.js';
|
|
37
|
+
export { AudioCompressPresetOptions, } from './audio_compress.js';
|
|
38
|
+
export { VideoCompressPresetOptions, } from './video_compress.js';
|
|
39
|
+
export { DocumentPdfCompressPresetOptions, } from './document_pdf_compress.js';
|
|
40
|
+
export { DocumentOfficeCompressPresetOptions, } from './document_office_compress.js';
|
|
41
|
+
export { DocumentOdfCompressPresetOptions, } from './document_odf_compress.js';
|
|
42
|
+
export { DocumentEpubCompressPresetOptions, } from './document_epub_compress.js';
|
|
43
|
+
// Re-export ergonomic enums for callers (single canonical path).
|
|
44
|
+
export { OptimizeFor, ImageMode, ImageFit, ImageMetadataPolicy, IccProfilePolicy, ImageFormat, VideoCodec, VideoPreset, VideoFit, AudioBitrate, AudioCodec, AudioSampleRate, PdfProfile, PdfColorspace, } from '../../generated/sdk_spec/enums.js';
|
|
45
|
+
function cellKeyOf(media, op) {
|
|
46
|
+
return `${media}_${op}`;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Per-cell field-merge: parent fields ⊕ child fields where defined.
|
|
50
|
+
* Re-construct the leaf DTO via the matching `<LeafClass>.from(merged)`
|
|
51
|
+
* call so the result is a freshly-frozen `*PresetOptions` instance —
|
|
52
|
+
* NOT a mutated reference into either input. Used by
|
|
53
|
+
* {@link PresetDefaults.merge} when both parent and child registered
|
|
54
|
+
* the same `(cellKey, level)` tuple.
|
|
55
|
+
*
|
|
56
|
+
* `definedFieldsOf` filters undefined values out of each instance
|
|
57
|
+
* BEFORE the merge: with TS `useDefineForClassFields` (the ES2022
|
|
58
|
+
* default), `readonly mode?: ImageMode` declarations initialise the
|
|
59
|
+
* field as an enumerable own property with value `undefined` BEFORE
|
|
60
|
+
* the ctor body runs. A naive `Object.assign({}, parent, child)`
|
|
61
|
+
* therefore lets child's `undefined` overwrite parent's defined value
|
|
62
|
+
* — caught by CI on PR #125 first run. Filter-then-spread restores
|
|
63
|
+
* the documented merge-not-replace semantics.
|
|
64
|
+
*
|
|
65
|
+
* @internal
|
|
66
|
+
*/
|
|
67
|
+
function definedFieldsOf(opts) {
|
|
68
|
+
const out = {};
|
|
69
|
+
for (const key of Object.keys(opts)) {
|
|
70
|
+
const value = opts[key];
|
|
71
|
+
if (value !== undefined)
|
|
72
|
+
out[key] = value;
|
|
73
|
+
}
|
|
74
|
+
return out;
|
|
75
|
+
}
|
|
76
|
+
function mergePresetOptions(cellKey, parentOpts, childOpts) {
|
|
77
|
+
// Child fields win on overlap; parent fills the remaining gaps.
|
|
78
|
+
// `definedFieldsOf` strips undefined-valued slots that TS class
|
|
79
|
+
// field declarations create even when the ctor body skipped the
|
|
80
|
+
// assignment (see helper docblock).
|
|
81
|
+
const mergedFields = {
|
|
82
|
+
...definedFieldsOf(parentOpts),
|
|
83
|
+
...definedFieldsOf(childOpts),
|
|
84
|
+
};
|
|
85
|
+
switch (cellKey) {
|
|
86
|
+
case 'image_compress':
|
|
87
|
+
return ImageCompressPresetOptions.from(mergedFields);
|
|
88
|
+
case 'audio_compress':
|
|
89
|
+
return AudioCompressPresetOptions.from(mergedFields);
|
|
90
|
+
case 'video_compress':
|
|
91
|
+
return VideoCompressPresetOptions.from(mergedFields);
|
|
92
|
+
case 'document_pdf_compress':
|
|
93
|
+
return DocumentPdfCompressPresetOptions.from(mergedFields);
|
|
94
|
+
case 'document_office_compress':
|
|
95
|
+
return DocumentOfficeCompressPresetOptions.from(mergedFields);
|
|
96
|
+
case 'document_odf_compress':
|
|
97
|
+
return DocumentOdfCompressPresetOptions.from(mergedFields);
|
|
98
|
+
case 'document_epub_compress':
|
|
99
|
+
return DocumentEpubCompressPresetOptions.from(mergedFields);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Append `(level, options)` into a fresh map under `cellKey`, returning
|
|
104
|
+
* a new outer map. Both layers stay immutable — callers' references to
|
|
105
|
+
* the previous PresetDefaults remain unchanged.
|
|
106
|
+
*/
|
|
107
|
+
function withCellEntry(prev, cellKey, level, options) {
|
|
108
|
+
const next = new Map(prev);
|
|
109
|
+
const prevEntries = prev.get(cellKey);
|
|
110
|
+
const nextEntries = new Map(prevEntries ?? []);
|
|
111
|
+
nextEntries.set(level, options);
|
|
112
|
+
next.set(cellKey, nextEntries);
|
|
113
|
+
return next;
|
|
114
|
+
}
|
|
115
|
+
export class PresetDefaults {
|
|
116
|
+
cells;
|
|
117
|
+
constructor(cells) {
|
|
118
|
+
this.cells = cells;
|
|
119
|
+
Object.freeze(this);
|
|
120
|
+
}
|
|
121
|
+
/** Empty builder — entry point for `presetDefaults()`. @internal */
|
|
122
|
+
static _empty() {
|
|
123
|
+
return new PresetDefaults(new Map());
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Deep-merge two {@link PresetDefaults} into a new instance (T4c —
|
|
127
|
+
* `ULAlOP6j`). Used by `withPresetDefaults` to stack scoped derives:
|
|
128
|
+
* `client.withPresetDefaults(a).withPresetDefaults(b)` produces a
|
|
129
|
+
* scoped layer equivalent to `merge(a, b)` — `b`'s per-cell fields
|
|
130
|
+
* override `a`'s where defined; `a`'s fields fill gaps.
|
|
131
|
+
*
|
|
132
|
+
* Per-cell semantics (codex r2 #5 — scalar-leaf merge):
|
|
133
|
+
* - If a `(cellKey, level)` entry is present in EITHER only, take it
|
|
134
|
+
* verbatim.
|
|
135
|
+
* - If present in both, merge the per-cell `*Input` shapes via
|
|
136
|
+
* `Object.assign({}, parentInput, childInput)` and re-construct
|
|
137
|
+
* the leaf DTO. Every cell-DTO field is a scalar (primitive,
|
|
138
|
+
* enum-string, or `string | number` for `targetSize`) — shallow
|
|
139
|
+
* merge gives the correct field-wise override.
|
|
140
|
+
*
|
|
141
|
+
* Parent and child instances are unaffected.
|
|
142
|
+
*/
|
|
143
|
+
static merge(parent, child) {
|
|
144
|
+
const merged = new Map();
|
|
145
|
+
// Seed with a clone of parent's entries (one inner Map per cellKey
|
|
146
|
+
// so child writes don't bleed back into parent's frozen structure).
|
|
147
|
+
for (const [cellKey, entries] of parent.cells) {
|
|
148
|
+
merged.set(cellKey, new Map(entries));
|
|
149
|
+
}
|
|
150
|
+
// Overlay child entries. Same (cellKey, level) → field-merge;
|
|
151
|
+
// child-only → take verbatim.
|
|
152
|
+
for (const [cellKey, childEntries] of child.cells) {
|
|
153
|
+
const target = merged.get(cellKey);
|
|
154
|
+
if (target === undefined) {
|
|
155
|
+
merged.set(cellKey, new Map(childEntries));
|
|
156
|
+
continue;
|
|
157
|
+
}
|
|
158
|
+
for (const [level, childOpts] of childEntries) {
|
|
159
|
+
const parentOpts = target.get(level);
|
|
160
|
+
if (parentOpts === undefined) {
|
|
161
|
+
target.set(level, childOpts);
|
|
162
|
+
continue;
|
|
163
|
+
}
|
|
164
|
+
target.set(level, mergePresetOptions(cellKey, parentOpts, childOpts));
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
return new PresetDefaults(merged);
|
|
168
|
+
}
|
|
169
|
+
/** Register a (level, delta) on the image-compress cell. Immutable. */
|
|
170
|
+
imageCompress(level, input = {}) {
|
|
171
|
+
return new PresetDefaults(withCellEntry(this.cells, 'image_compress', level, ImageCompressPresetOptions.from(input)));
|
|
172
|
+
}
|
|
173
|
+
/** Register a (level, delta) on the audio-compress cell. Immutable. */
|
|
174
|
+
audioCompress(level, input = {}) {
|
|
175
|
+
return new PresetDefaults(withCellEntry(this.cells, 'audio_compress', level, AudioCompressPresetOptions.from(input)));
|
|
176
|
+
}
|
|
177
|
+
/** Register a (level, delta) on the video-compress cell. Immutable. */
|
|
178
|
+
videoCompress(level, input = {}) {
|
|
179
|
+
return new PresetDefaults(withCellEntry(this.cells, 'video_compress', level, VideoCompressPresetOptions.from(input)));
|
|
180
|
+
}
|
|
181
|
+
/** Register a (level, delta) on the document-pdf-compress cell. Immutable. */
|
|
182
|
+
pdfCompress(level, input = {}) {
|
|
183
|
+
return new PresetDefaults(withCellEntry(this.cells, 'document_pdf_compress', level, DocumentPdfCompressPresetOptions.from(input)));
|
|
184
|
+
}
|
|
185
|
+
/** Register a (level, delta) on the document-office-compress cell. Immutable. */
|
|
186
|
+
officeCompress(level, input = {}) {
|
|
187
|
+
return new PresetDefaults(withCellEntry(this.cells, 'document_office_compress', level, DocumentOfficeCompressPresetOptions.from(input)));
|
|
188
|
+
}
|
|
189
|
+
/** Register a (level, delta) on the document-odf-compress cell. Immutable. */
|
|
190
|
+
odfCompress(level, input = {}) {
|
|
191
|
+
return new PresetDefaults(withCellEntry(this.cells, 'document_odf_compress', level, DocumentOdfCompressPresetOptions.from(input)));
|
|
192
|
+
}
|
|
193
|
+
/** Register a (level, delta) on the document-epub-compress cell. Immutable. */
|
|
194
|
+
epubCompress(level, input = {}) {
|
|
195
|
+
return new PresetDefaults(withCellEntry(this.cells, 'document_epub_compress', level, DocumentEpubCompressPresetOptions.from(input)));
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Return the user-supplied delta registered for `(media, op, level)`,
|
|
199
|
+
* or `undefined` if none was registered.
|
|
200
|
+
*
|
|
201
|
+
* @internal — consumed by the T4b resolver. Not part of the public
|
|
202
|
+
* surface; the resolver imports it via the type-only re-export.
|
|
203
|
+
*/
|
|
204
|
+
cellFor(media, op, level) {
|
|
205
|
+
const entries = this.cells.get(cellKeyOf(media, op));
|
|
206
|
+
return entries?.get(level);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Construct an empty {@link PresetDefaults} builder. Chain per-cell
|
|
211
|
+
* methods to register layered defaults; the resolver in T4b consumes
|
|
212
|
+
* the result via `cellFor(...)`.
|
|
213
|
+
*/
|
|
214
|
+
export function presetDefaults() {
|
|
215
|
+
return PresetDefaults._empty();
|
|
216
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { VideoCodec, VideoPreset, VideoFit, AudioCodec, AudioBitrate, OptimizeFor } from '../../generated/sdk_spec/enums.js';
|
|
2
|
+
export interface VideoCompressPresetOptionsInput {
|
|
3
|
+
readonly codec?: VideoCodec;
|
|
4
|
+
readonly targetSize?: string | number;
|
|
5
|
+
readonly crf?: number;
|
|
6
|
+
readonly preset?: VideoPreset;
|
|
7
|
+
readonly width?: number;
|
|
8
|
+
readonly height?: number;
|
|
9
|
+
readonly fit?: VideoFit;
|
|
10
|
+
readonly fps?: number;
|
|
11
|
+
readonly faststart?: boolean;
|
|
12
|
+
readonly audioCodec?: AudioCodec;
|
|
13
|
+
readonly audioBitrate?: AudioBitrate;
|
|
14
|
+
}
|
|
15
|
+
export declare class VideoCompressPresetOptions {
|
|
16
|
+
readonly codec?: VideoCodec;
|
|
17
|
+
readonly targetSize?: string | number;
|
|
18
|
+
readonly crf?: number;
|
|
19
|
+
readonly preset?: VideoPreset;
|
|
20
|
+
readonly width?: number;
|
|
21
|
+
readonly height?: number;
|
|
22
|
+
readonly fit?: VideoFit;
|
|
23
|
+
readonly fps?: number;
|
|
24
|
+
readonly faststart?: boolean;
|
|
25
|
+
readonly audioCodec?: AudioCodec;
|
|
26
|
+
readonly audioBitrate?: AudioBitrate;
|
|
27
|
+
private constructor();
|
|
28
|
+
static from(input: VideoCompressPresetOptionsInput): VideoCompressPresetOptions;
|
|
29
|
+
static shippedDefaultsFor(level: OptimizeFor): VideoCompressPresetOptions;
|
|
30
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
// T4a — VideoCompressPresetOptions leaf DTO.
|
|
2
|
+
//
|
|
3
|
+
// Field set per ticket VhIj4S7T: video = 11 fields
|
|
4
|
+
// (codec, targetSize, crf, preset, width, height, fit, fps, faststart,
|
|
5
|
+
// audioCodec, audioBitrate).
|
|
6
|
+
// Deliberately excluded: encodingMode + targetSizeBytes (raw wire —
|
|
7
|
+
// replaced by ergonomic `targetSize: string|number` which the SDK derives
|
|
8
|
+
// at resolve time in T4b), trim_start/trim_end (per-call content selection).
|
|
9
|
+
//
|
|
10
|
+
// `targetSize` accepts `string` (e.g. "50MB") or `number` (bytes). The
|
|
11
|
+
// resolver in T4b converts to the wire `target_size_bytes` and sets
|
|
12
|
+
// `encoding_mode: target_size` accordingly.
|
|
13
|
+
import { shippedDefaultsFor as f3ShippedDefaultsFor } from '../../generated/sdk_spec/presets.js';
|
|
14
|
+
import { translateEnum } from './_translate.js';
|
|
15
|
+
export class VideoCompressPresetOptions {
|
|
16
|
+
codec;
|
|
17
|
+
targetSize;
|
|
18
|
+
crf;
|
|
19
|
+
preset;
|
|
20
|
+
width;
|
|
21
|
+
height;
|
|
22
|
+
fit;
|
|
23
|
+
fps;
|
|
24
|
+
faststart;
|
|
25
|
+
audioCodec;
|
|
26
|
+
audioBitrate;
|
|
27
|
+
constructor(input) {
|
|
28
|
+
if (input.codec !== undefined)
|
|
29
|
+
this.codec = input.codec;
|
|
30
|
+
if (input.targetSize !== undefined)
|
|
31
|
+
this.targetSize = input.targetSize;
|
|
32
|
+
if (input.crf !== undefined)
|
|
33
|
+
this.crf = input.crf;
|
|
34
|
+
if (input.preset !== undefined)
|
|
35
|
+
this.preset = input.preset;
|
|
36
|
+
if (input.width !== undefined)
|
|
37
|
+
this.width = input.width;
|
|
38
|
+
if (input.height !== undefined)
|
|
39
|
+
this.height = input.height;
|
|
40
|
+
if (input.fit !== undefined)
|
|
41
|
+
this.fit = input.fit;
|
|
42
|
+
if (input.fps !== undefined)
|
|
43
|
+
this.fps = input.fps;
|
|
44
|
+
if (input.faststart !== undefined)
|
|
45
|
+
this.faststart = input.faststart;
|
|
46
|
+
if (input.audioCodec !== undefined)
|
|
47
|
+
this.audioCodec = input.audioCodec;
|
|
48
|
+
if (input.audioBitrate !== undefined)
|
|
49
|
+
this.audioBitrate = input.audioBitrate;
|
|
50
|
+
Object.freeze(this);
|
|
51
|
+
}
|
|
52
|
+
static from(input) {
|
|
53
|
+
return new VideoCompressPresetOptions(input);
|
|
54
|
+
}
|
|
55
|
+
static shippedDefaultsFor(level) {
|
|
56
|
+
const cell = f3ShippedDefaultsFor('video_compress', level);
|
|
57
|
+
const input = {};
|
|
58
|
+
const mut = input;
|
|
59
|
+
if ('codec' in cell)
|
|
60
|
+
mut.codec = translateEnum('VideoCodec', cell.codec);
|
|
61
|
+
if ('targetSize' in cell)
|
|
62
|
+
mut.targetSize = cell.targetSize;
|
|
63
|
+
if ('crf' in cell)
|
|
64
|
+
mut.crf = cell.crf;
|
|
65
|
+
if ('preset' in cell)
|
|
66
|
+
mut.preset = translateEnum('VideoPreset', cell.preset);
|
|
67
|
+
if ('width' in cell)
|
|
68
|
+
mut.width = cell.width;
|
|
69
|
+
if ('height' in cell)
|
|
70
|
+
mut.height = cell.height;
|
|
71
|
+
if ('fit' in cell)
|
|
72
|
+
mut.fit = translateEnum('VideoFit', cell.fit);
|
|
73
|
+
if ('fps' in cell)
|
|
74
|
+
mut.fps = cell.fps;
|
|
75
|
+
if ('faststart' in cell)
|
|
76
|
+
mut.faststart = cell.faststart;
|
|
77
|
+
if ('audioCodec' in cell)
|
|
78
|
+
mut.audioCodec = translateEnum('AudioCodec', cell.audioCodec);
|
|
79
|
+
if ('audioBitrate' in cell)
|
|
80
|
+
mut.audioBitrate = translateEnum('AudioBitrate', cell.audioBitrate);
|
|
81
|
+
return new VideoCompressPresetOptions(input);
|
|
82
|
+
}
|
|
83
|
+
}
|
package/dist/errors.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AuthErrorResponse, BalanceExhaustedResponse, FeatureNotAvailableResponse, FeatureTierRestrictedResponse, TierRestrictionResponse, WorkflowExpiredResponse } from '@giveitsmaller/contracts/openapi';
|
|
1
|
+
import type { AuthErrorResponse, BalanceExhaustedResponse, FeatureNotAvailableResponse, FeatureTierRestrictedResponse, ProbePendingResponse, TierRestrictionResponse, UploadDurationExceedsTierResponse, UploadSizeExceedsTierResponse, WorkflowExpiredResponse } from '@giveitsmaller/contracts/openapi';
|
|
2
2
|
export declare class GislError extends Error {
|
|
3
3
|
constructor(message: string);
|
|
4
4
|
}
|
|
@@ -62,6 +62,37 @@ export declare class GislFeatureNotAvailableError extends GislApiError {
|
|
|
62
62
|
readonly payload: FeatureNotAvailableResponse;
|
|
63
63
|
constructor(statusCode: number, errorMessage: string, payload: FeatureNotAvailableResponse, path?: string, extra?: Omit<GislApiErrorOptions, 'payload'>);
|
|
64
64
|
}
|
|
65
|
+
/**
|
|
66
|
+
* 422 response on `POST /api/workflows` when a job references an upload
|
|
67
|
+
* whose server-side probe hasn't completed at workflow-create time. The
|
|
68
|
+
* server rejects rather than silently routing as `short_form` (which
|
|
69
|
+
* hard-fails long video clips).
|
|
70
|
+
*
|
|
71
|
+
* **Recovery contract** (per contracts ProbePendingResponse docblock):
|
|
72
|
+
* poll `POST /api/uploads/{id}/probe` for the pending upload until
|
|
73
|
+
* `probe_status` is terminal (`ok` → re-`POST /api/workflows` the same
|
|
74
|
+
* request; `corrupt` / `unsupported_codec` → surface the probe error).
|
|
75
|
+
* The `Retry-After` response header (when present) suggests a delay
|
|
76
|
+
* in seconds before the next poll/retry.
|
|
77
|
+
*
|
|
78
|
+
* `payload.jobRef` identifies which job in the multi-job request triggered
|
|
79
|
+
* the probe-pending rejection.
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
* try {
|
|
83
|
+
* await client.createWorkflow({ jobs });
|
|
84
|
+
* } catch (e) {
|
|
85
|
+
* if (e instanceof GislProbePendingError) {
|
|
86
|
+
* await waitForProbe(e.payload.jobRef);
|
|
87
|
+
* // retry...
|
|
88
|
+
* }
|
|
89
|
+
* throw e;
|
|
90
|
+
* }
|
|
91
|
+
*/
|
|
92
|
+
export declare class GislProbePendingError extends GislApiError {
|
|
93
|
+
readonly payload: ProbePendingResponse;
|
|
94
|
+
constructor(statusCode: number, errorMessage: string, payload: ProbePendingResponse, path?: string, extra?: Omit<GislApiErrorOptions, 'payload'>);
|
|
95
|
+
}
|
|
65
96
|
export declare class GislWorkflowExpiredError extends GislApiError {
|
|
66
97
|
readonly payload: WorkflowExpiredResponse;
|
|
67
98
|
constructor(statusCode: number, errorMessage: string, payload: WorkflowExpiredResponse, path?: string, extra?: Omit<GislApiErrorOptions, 'payload'>);
|
|
@@ -70,9 +101,228 @@ export declare class GislAuthError extends GislApiError {
|
|
|
70
101
|
readonly payload: AuthErrorResponse;
|
|
71
102
|
constructor(statusCode: number, errorMessage: string, payload: AuthErrorResponse, path?: string, extra?: Omit<GislApiErrorOptions, 'payload'>);
|
|
72
103
|
}
|
|
104
|
+
/**
|
|
105
|
+
* Discriminates the four upload-too-big shapes the server can return:
|
|
106
|
+
* - `size_tier` — 422 `upload_size_exceeds_tier` (typed payload present)
|
|
107
|
+
* - `duration_tier` — 422 `upload_duration_exceeds_tier` (typed payload present)
|
|
108
|
+
* - `absolute_413` — 413, the absolute across-tier cap. The contract models
|
|
109
|
+
* 413 as a plain `ErrorEnvelope` with NO `error_type`
|
|
110
|
+
* discriminator, so there is NO typed payload for it.
|
|
111
|
+
* - `cap_v2_multipart` — 422 `FILE_TOO_LARGE_FOR_MULTIPART` (SDK-3 / Wb6ebOMM,
|
|
112
|
+
* pre-S3 capacity reject on the resume-support endpoints).
|
|
113
|
+
* The contract carries no structured payload for this
|
|
114
|
+
* code today — `payload` is undefined for this kind.
|
|
115
|
+
*
|
|
116
|
+
* **Caveat for exhaustive-narrowing consumers.** The `cap_v2_multipart` value
|
|
117
|
+
* was added in TS SDK 0.5.0 / PHP SDK 0.3.0. A consumer writing
|
|
118
|
+
* `switch (e.kind) { case 'size_tier': ... case 'duration_tier': ... default:
|
|
119
|
+
* absurd(e.kind); }` against the prior 3-value union now sees a non-exhaustive
|
|
120
|
+
* switch and must add the new arm. The bump is logged in CHANGELOG.md.
|
|
121
|
+
*/
|
|
122
|
+
export type GislUploadCapKind = 'size_tier' | 'duration_tier' | 'absolute_413' | 'cap_v2_multipart';
|
|
123
|
+
/**
|
|
124
|
+
* A single class covering all three "upload exceeds a size/duration cap"
|
|
125
|
+
* responses (422 size-tier, 422 duration-tier, 413 absolute).
|
|
126
|
+
*
|
|
127
|
+
* CONSCIOUS DEVIATION from the one-typed-payload-per-class invariant that the
|
|
128
|
+
* other structured subclasses follow (`GislBalanceExhaustedError`,
|
|
129
|
+
* `GislWorkflowExpiredError`, …). Justification: the card mandates this single
|
|
130
|
+
* `GislUploadCapExceededError` name and SDK-3 / E2E-1 are blocked-on it, so
|
|
131
|
+
* splitting into size/duration subclasses would break a cross-ticket naming
|
|
132
|
+
* contract; and 413 carries no typed envelope at all (plain `ErrorEnvelope`),
|
|
133
|
+
* so a one-payload-per-class split could not cover it uniformly anyway. The
|
|
134
|
+
* `kind` discriminant + a union-typed (possibly absent) `payload` is the
|
|
135
|
+
* deliberate trade-off. This is the only structured error in the tree that
|
|
136
|
+
* does not bind exactly one payload type — documented here in the same spirit
|
|
137
|
+
* as the inline PHP↔TS divergence notes.
|
|
138
|
+
*
|
|
139
|
+
* The two multipart-part errors below are deliberately NOT folded in with a
|
|
140
|
+
* `kind`: they carry different fields (`partNumber`/`uploadId` for an instance
|
|
141
|
+
* PUT failure vs `requiredParts`/`maxParts` for the count-ceiling guard) and
|
|
142
|
+
* are thrown from the multipart path, not the response handler.
|
|
143
|
+
*/
|
|
144
|
+
export declare class GislUploadCapExceededError extends GislApiError {
|
|
145
|
+
readonly kind: GislUploadCapKind;
|
|
146
|
+
readonly payload: UploadSizeExceedsTierResponse | UploadDurationExceedsTierResponse | undefined;
|
|
147
|
+
constructor(statusCode: number, errorMessage: string, kind: GislUploadCapKind, payload: UploadSizeExceedsTierResponse | UploadDurationExceedsTierResponse | undefined, path?: string, extra?: Omit<GislApiErrorOptions, 'payload'>);
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* 404 `MULTIPART_SESSION_NOT_FOUND` — the durable multipart session referenced
|
|
151
|
+
* by a resume / status / presign / keepalive call cannot be located (expired
|
|
152
|
+
* past its 48h manifest TTL, deleted, or never existed). Thrown by the SDK-3
|
|
153
|
+
* resume-support endpoints (`getUploadStatus`, `presignParts`,
|
|
154
|
+
* `keepaliveUpload`, and the resume branch of `uploadFile`).
|
|
155
|
+
*
|
|
156
|
+
* Carries no typed structured payload — the contract for the 3 resume-support
|
|
157
|
+
* endpoints models this code as a plain `ErrorEnvelope`. Consumers should
|
|
158
|
+
* detect via `instanceof` and abandon the resume; a fresh `uploadFile()` call
|
|
159
|
+
* (without `resumeUploadId`) will start a new session.
|
|
160
|
+
*/
|
|
161
|
+
export declare class GislMultipartSessionNotFoundError extends GislApiError {
|
|
162
|
+
constructor(statusCode: number, errorMessage: string, path?: string, options?: GislApiErrorOptions);
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* 403 `MULTIPART_SESSION_OWNERSHIP` — the caller is authenticated but the
|
|
166
|
+
* multipart session belongs to a different user. Thrown by the SDK-3
|
|
167
|
+
* resume-support endpoints. The session itself exists (otherwise the server
|
|
168
|
+
* would return 404 NOT_FOUND); the caller's identity simply doesn't match
|
|
169
|
+
* `manifest.userId`. Consumers should abandon the resume.
|
|
170
|
+
*/
|
|
171
|
+
export declare class GislMultipartSessionOwnershipError extends GislApiError {
|
|
172
|
+
constructor(statusCode: number, errorMessage: string, path?: string, options?: GislApiErrorOptions);
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* 403 `MULTIPART_SESSION_AUTH_REQUIRED` — the multipart session was initiated
|
|
176
|
+
* anonymously (no `manifest.userId`) and the SDK-3 resume-support endpoints
|
|
177
|
+
* refuse to serve it on an authed caller. There is no "claim" workflow today
|
|
178
|
+
* to bind an authed identity to an anonymously-started session; that is the
|
|
179
|
+
* future flip tracked at upstream ticket 8LABloaz. Consumers hitting this on
|
|
180
|
+
* resume should abandon and re-upload from scratch under the authed identity.
|
|
181
|
+
*/
|
|
182
|
+
export declare class GislMultipartSessionAuthRequiredError extends GislApiError {
|
|
183
|
+
constructor(statusCode: number, errorMessage: string, path?: string, options?: GislApiErrorOptions);
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Optional structured metadata attached to a {@link GislConfigError}. The
|
|
187
|
+
* preset resolver (T4b) raises errors with these fields populated so
|
|
188
|
+
* callers can branch on machine-readable codes rather than parsing the
|
|
189
|
+
* human message. Every field is optional — existing call sites that
|
|
190
|
+
* throw `new GislConfigError(message)` keep working unchanged.
|
|
191
|
+
*/
|
|
192
|
+
export interface GislConfigErrorMetadata {
|
|
193
|
+
/**
|
|
194
|
+
* Machine-readable error code. Resolver-side values today:
|
|
195
|
+
* `'invalid_combination'`, `'missing_dependency'`, `'type_mismatch'`,
|
|
196
|
+
* `'unknown_field'`, `'invalid_target_size'`. Other call sites may add
|
|
197
|
+
* codes — the union is open.
|
|
198
|
+
*/
|
|
199
|
+
readonly reason?: string;
|
|
200
|
+
/**
|
|
201
|
+
* Field names (camelCase) that participated in the rejection. For
|
|
202
|
+
* `invalid_combination` reasons this is the *pair* that conflicts
|
|
203
|
+
* (e.g. `['targetSize', 'codec']`); for `missing_dependency` this is
|
|
204
|
+
* the dependent field plus the field whose value blocks it.
|
|
205
|
+
*/
|
|
206
|
+
readonly conflictingFields?: readonly string[];
|
|
207
|
+
/**
|
|
208
|
+
* The merged wire-shape snapshot the resolver computed BEFORE the
|
|
209
|
+
* validation rejected it. Lets callers see "what would have been
|
|
210
|
+
* sent" for debugging without re-running the chain.
|
|
211
|
+
*/
|
|
212
|
+
readonly resolvedSnapshot?: Readonly<Record<string, unknown>>;
|
|
213
|
+
/**
|
|
214
|
+
* Short human-readable remediation hint specific to the error. E.g.
|
|
215
|
+
* "Switch codec to H264, or drop targetSize and use crf instead."
|
|
216
|
+
*/
|
|
217
|
+
readonly suggestion?: string;
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Root of the LOCAL config-error tree — thrown before any HTTP/file I/O.
|
|
221
|
+
* Sibling of `GislApiError` (which represents server-side error envelopes).
|
|
222
|
+
* Reserve for fail-early errors raised by the ergonomic-layer factory or
|
|
223
|
+
* credential-chain resolver when the caller hasn't supplied something the
|
|
224
|
+
* SDK needs to make a request. Never carries an HTTP status code.
|
|
225
|
+
*
|
|
226
|
+
* Optional `metadata` (T4b — `27rE1fZn`) carries structured fields used
|
|
227
|
+
* by the preset resolver and other ergonomic-layer validators. Existing
|
|
228
|
+
* call sites that pass `(message)` keep working — metadata is purely
|
|
229
|
+
* additive and defaults to `undefined`.
|
|
230
|
+
*/
|
|
231
|
+
export declare class GislConfigError extends GislError {
|
|
232
|
+
readonly reason?: string;
|
|
233
|
+
readonly conflictingFields?: readonly string[];
|
|
234
|
+
readonly resolvedSnapshot?: Readonly<Record<string, unknown>>;
|
|
235
|
+
readonly suggestion?: string;
|
|
236
|
+
constructor(message: string, metadata?: GislConfigErrorMetadata);
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* The ergonomic-layer factory `gisl.create()` could not resolve an API key
|
|
240
|
+
* from any of explicit arg, `GISL_API_KEY` env, or shared-config profile,
|
|
241
|
+
* AND the caller did not opt into anonymous or cookie-mode. Thrown BEFORE
|
|
242
|
+
* any file read or HTTP request — calls to `client.compress(...)`, `.run()`,
|
|
243
|
+
* etc., synchronously fail with this error.
|
|
244
|
+
*/
|
|
245
|
+
export declare class GislMissingCredentialsError extends GislConfigError {
|
|
246
|
+
constructor(message: string);
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* The caller used `gisl.anonymous()` and then invoked an operation that is
|
|
250
|
+
* not in the anonymous-capable allowlist. Local-only — thrown before any I/O.
|
|
251
|
+
* Distinct from server-side `GislAuthError` (401/403 on the wire).
|
|
252
|
+
*/
|
|
253
|
+
export declare class GislFeatureRequiresAuthError extends GislConfigError {
|
|
254
|
+
readonly operation: string;
|
|
255
|
+
constructor(operation: string, message: string);
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* `MergeBuilder.sequence(...)` referenced an asset that wasn't declared in
|
|
259
|
+
* the prior `client.merge(...)` call. Local validation runs BEFORE upload
|
|
260
|
+
* so the caller fails fast on the typo without burning bandwidth.
|
|
261
|
+
*/
|
|
262
|
+
export declare class GislUndeclaredAssetError extends GislConfigError {
|
|
263
|
+
readonly assetId: string;
|
|
264
|
+
readonly declaredAssets: readonly string[];
|
|
265
|
+
constructor(assetId: string, declaredAssets: readonly string[]);
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* `MergeBuilder.sequence(...)` was called but at least one declared asset
|
|
269
|
+
* wasn't referenced. Almost always a bug (wasted upload). Escape via
|
|
270
|
+
* `allowUnusedAssets: true` on the merge options.
|
|
271
|
+
*/
|
|
272
|
+
export declare class GislUnusedAssetError extends GislConfigError {
|
|
273
|
+
readonly unusedAssets: readonly string[];
|
|
274
|
+
constructor(unusedAssets: readonly string[]);
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* `MergeBuilder.sequence(...)` on an image merge was given a `clip(ref, opts)`
|
|
278
|
+
* entry. Image merges have NO per-input options in the wire today — `transition`
|
|
279
|
+
* applies at the merge level and is uniform across all joins.
|
|
280
|
+
*/
|
|
281
|
+
export declare class GislPerInputOptionsNotSupportedError extends GislConfigError {
|
|
282
|
+
readonly mediaKind: string;
|
|
283
|
+
constructor(mediaKind: string);
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Thrown by future chain methods (`.compress()` / `.thumbnail()` /
|
|
287
|
+
* `.convert()` on an `OperationBuilder`) when the previous step produces
|
|
288
|
+
* MULTIPLE artifacts and the caller didn't explicitly call `.mapEach(...)`
|
|
289
|
+
* to opt into per-artifact fan-out. T6 ships the error class + the
|
|
290
|
+
* `.mapEach(...)` method; the chain methods themselves are a separate
|
|
291
|
+
* follow-up card, so this error is currently dormant — but the type +
|
|
292
|
+
* audit-gate registration land here so the future chain-method PR is a
|
|
293
|
+
* pure addition with no public-API churn.
|
|
294
|
+
*/
|
|
295
|
+
export declare class GislChainCardinalityMismatchError extends GislConfigError {
|
|
296
|
+
readonly previousOperation: string;
|
|
297
|
+
readonly attemptedOperation: string;
|
|
298
|
+
constructor(previousOperation: string, attemptedOperation: string);
|
|
299
|
+
}
|
|
73
300
|
export declare class GislTimeoutError extends GislError {
|
|
74
301
|
constructor(message: string);
|
|
75
302
|
}
|
|
76
303
|
export declare class GislAbortError extends GislError {
|
|
77
304
|
constructor(message: string);
|
|
78
305
|
}
|
|
306
|
+
/**
|
|
307
|
+
* A single S3 multipart part PUT failed terminally (after the configured
|
|
308
|
+
* retry attempts) or could not be read. Subclasses `GislError` — NOT
|
|
309
|
+
* `GislApiError` — because it carries no contract error envelope and is
|
|
310
|
+
* thrown from the multipart upload path, never from the response handler.
|
|
311
|
+
* Mirrors the `GislAbortError` shape, plus the failing part's identifiers.
|
|
312
|
+
*/
|
|
313
|
+
export declare class GislMultipartPartError extends GislError {
|
|
314
|
+
readonly partNumber: number;
|
|
315
|
+
readonly uploadId: string;
|
|
316
|
+
constructor(message: string, partNumber: number, uploadId: string);
|
|
317
|
+
}
|
|
318
|
+
/**
|
|
319
|
+
* The upload would require more than the S3 hard limit of 10 000 multipart
|
|
320
|
+
* parts at the server-provided chunk size. Client-side guard (Model A: the
|
|
321
|
+
* server computes the part plan; the SDK asserts the ceiling). Subclasses
|
|
322
|
+
* `GislError` for the same reason as `GislMultipartPartError`.
|
|
323
|
+
*/
|
|
324
|
+
export declare class GislMultipartPartCountError extends GislError {
|
|
325
|
+
readonly requiredParts: number;
|
|
326
|
+
readonly maxParts: number;
|
|
327
|
+
constructor(message: string, requiredParts: number, maxParts: number);
|
|
328
|
+
}
|