@giveitsmaller/sdk 0.20.0 → 0.22.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/LICENSE +202 -0
- package/README.md +55 -14
- package/dist/_audit.js +2 -4
- package/dist/builder.d.ts +4 -4
- package/dist/builder.js +47 -22
- package/dist/client.d.ts +9 -6
- package/dist/client.js +90 -31
- package/dist/ergonomic/image_output_routes.d.ts +97 -0
- package/dist/ergonomic/image_output_routes.js +227 -25
- package/dist/ergonomic/option_types.d.ts +11 -2
- package/dist/ergonomic/preset_resolver.d.ts +24 -2
- package/dist/ergonomic/preset_resolver.js +100 -10
- package/dist/ergonomic/presets/image_compress.js +16 -4
- package/dist/ergonomic/presets/index.d.ts +9 -8
- package/dist/ergonomic/presets/index.js +1 -9
- package/dist/ergonomic/presets/video_compress.d.ts +14 -0
- package/dist/errors.d.ts +101 -2
- package/dist/errors.js +108 -1
- package/dist/file-first.d.ts +81 -13
- package/dist/file-first.js +329 -69
- package/dist/generated/sdk_spec/enums.d.ts +0 -26
- package/dist/generated/sdk_spec/enums.js +0 -16
- package/dist/generated/sdk_spec/errors.d.ts +1 -1
- package/dist/generated/sdk_spec/errors.js +159 -1
- package/dist/generated/sdk_spec/presets.js +0 -14
- package/dist/generated/sdk_spec/version.d.ts +2 -2
- package/dist/generated/sdk_spec/version.js +2 -2
- package/dist/gisl.d.ts +21 -2
- package/dist/handle.d.ts +6 -1
- package/dist/handle.js +42 -13
- package/dist/index.core.d.ts +4 -4
- package/dist/index.core.js +6 -3
- package/dist/merge.d.ts +23 -0
- package/dist/merge.js +2 -2
- package/dist/sse.js +49 -1
- package/dist/types.d.ts +11 -3
- package/dist/types.js +1 -0
- package/package.json +3 -3
- package/dist/ergonomic/presets/document_pdf_compress.d.ts +0 -12
- package/dist/ergonomic/presets/document_pdf_compress.js +0 -33
package/dist/merge.js
CHANGED
|
@@ -128,14 +128,14 @@ export class MergeBuilder {
|
|
|
128
128
|
});
|
|
129
129
|
// 5. Fetch downloads + project.
|
|
130
130
|
if (Date.now() >= deadline) {
|
|
131
|
-
throw new GislTimeoutError(`Merge workflow ${created.workflowId} reached terminal status but maxWait elapsed before downloads could be fetched
|
|
131
|
+
throw new GislTimeoutError(`Merge workflow ${created.workflowId} reached terminal status but maxWait elapsed before downloads could be fetched`, created.workflowId);
|
|
132
132
|
}
|
|
133
133
|
const downloads = await this.client.getWorkflowDownloads(created.workflowId);
|
|
134
134
|
// TDqmkWpX: the maxWait deadline also covers the downloads fetch itself —
|
|
135
135
|
// re-check AFTER the call so a slow getWorkflowDownloads cannot return a
|
|
136
136
|
// success past the advertised whole-run deadline.
|
|
137
137
|
if (Date.now() >= deadline) {
|
|
138
|
-
throw new GislTimeoutError(`Merge workflow ${created.workflowId} downloads fetch completed after maxWait elapsed
|
|
138
|
+
throw new GislTimeoutError(`Merge workflow ${created.workflowId} downloads fetch completed after maxWait elapsed`, created.workflowId);
|
|
139
139
|
}
|
|
140
140
|
// p0SuJEeK — project ONLY the merge job's output. getWorkflowDownloads
|
|
141
141
|
// returns a download group per terminal job, which now INCLUDES the
|
package/dist/sse.js
CHANGED
|
@@ -105,7 +105,55 @@ export async function* parseSseStream(response, opts = {}) {
|
|
|
105
105
|
continue;
|
|
106
106
|
}
|
|
107
107
|
if (line.startsWith(':')) {
|
|
108
|
-
// Comment line (keep-alive), skip
|
|
108
|
+
// Comment line (keep-alive), skip.
|
|
109
|
+
//
|
|
110
|
+
// ⚠️ DO NOT "FIX" THIS INTO SURFACING COMMENT FRAMES WITHOUT READING
|
|
111
|
+
// THIS. Dropping them is CORRECT per the SSE spec — a comment carries
|
|
112
|
+
// no event — but it is also LOAD-BEARING FOR A CONSUMER, and that
|
|
113
|
+
// consumer is in another repo.
|
|
114
|
+
//
|
|
115
|
+
// The frontend does NOT close its SSE reader on the terminal event:
|
|
116
|
+
// `workflow_completed` patches status and breaks WITHOUT aborting.
|
|
117
|
+
// What actually closes the stream is an IDLE WATCHDOG at 20s. That
|
|
118
|
+
// watchdog only fires because heartbeats are never yielded here, so
|
|
119
|
+
// they never re-arm it — roughly 20s after the last real event the
|
|
120
|
+
// reader closes and the PHP worker is released.
|
|
121
|
+
//
|
|
122
|
+
// HEARTBEAT ~16s vs IDLE TIMEOUT 20s: a FOUR-SECOND MARGIN that holds
|
|
123
|
+
// only while the heartbeats are invisible. Surfacing comment frames —
|
|
124
|
+
// a completely reasonable change, since EventSource semantics treat
|
|
125
|
+
// keep-alive comments as liveness signals that legitimately reset
|
|
126
|
+
// timeouts — would CONTINUOUSLY re-arm the watchdog. The stream would
|
|
127
|
+
// never go idle, and every completed job left on screen would hold a
|
|
128
|
+
// PHP worker for the full 570s. That is worker exhaustion from
|
|
129
|
+
// ordinary users leaving tabs open.
|
|
130
|
+
//
|
|
131
|
+
// A ONE-LINE CHANGE HERE SILENTLY CONVERTS THE FRONTEND FROM BOUNDED
|
|
132
|
+
// TO UNBOUNDED, and nothing on either side would flag it.
|
|
133
|
+
//
|
|
134
|
+
// ⚠️ THIS NOTE IS PERMANENT. DO NOT DELETE IT WHEN THE FRONTEND
|
|
135
|
+
// ADDS AN EXPLICIT CLOSE-ON-TERMINAL. That fix removes the TERMINAL
|
|
136
|
+
// case and does NOT remove the dependency, because closing finished
|
|
137
|
+
// streams was never the watchdog's job — that was a side effect
|
|
138
|
+
// nobody knew about until 2026-08-12.
|
|
139
|
+
//
|
|
140
|
+
// THE WATCHDOG'S ACTUAL JOB IS DETECTING A STREAM THAT HAS GONE
|
|
141
|
+
// SILENT WHILE THE WORKFLOW IS STILL RUNNING, and resuming the
|
|
142
|
+
// fallback poll. That case survives every fix in flight, and it is
|
|
143
|
+
// not exotic: a long operation between progress events produces it
|
|
144
|
+
// exactly — heartbeats flowing, no data frames, job still running.
|
|
145
|
+
//
|
|
146
|
+
// If this parser surfaced comment frames, heartbeats at ~16s would
|
|
147
|
+
// re-arm the 20s watchdog FOREVER and STALL DETECTION WOULD NEVER
|
|
148
|
+
// FIRE AT ALL, on a stream that is genuinely stuck. The UI would go
|
|
149
|
+
// on believing a dead job is fine. That is worse than the worker
|
|
150
|
+
// leak: a leak is bounded by 570s, a missed stall is not bounded at
|
|
151
|
+
// all.
|
|
152
|
+
//
|
|
153
|
+
// The PHP SDK does the same thing at GislClient.php (`$line[0] === ':'`),
|
|
154
|
+
// verified 2026-08-12 — the two languages agree on this axis, and
|
|
155
|
+
// they must stay agreed: this property governs whether a stuck
|
|
156
|
+
// stream is EVER detected, so a divergence here is not cosmetic.
|
|
109
157
|
continue;
|
|
110
158
|
}
|
|
111
159
|
const colonIndex = line.indexOf(':');
|
package/dist/types.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { OperationType, OperationsSchemaResponse, OperationCapability, OutputProperties, ImageEncodeCapabilities, CallbackEventType, SseEventType, SseOperationProgressData, SseOperationCompletedData, SseOperationFailedData, SseJobCompletedData, SseJobFailedData, SseWorkflowTerminalData, MultipartInitiateRequestMetadataHint, UploadProbeResponse } from '@giveitsmaller/contracts/openapi';
|
|
2
|
-
import type { JobInputV2RoleEnum } from '@giveitsmaller/contracts/openapi';
|
|
2
|
+
import type { JobInputV2RoleEnum, NotifyConfig } from '@giveitsmaller/contracts/openapi';
|
|
3
3
|
export interface GislClientConfig {
|
|
4
4
|
baseUrl: string;
|
|
5
5
|
apiKey?: string;
|
|
@@ -188,6 +188,14 @@ export interface WorkflowCreatePayload {
|
|
|
188
188
|
export?: ExternalDestinationPayload;
|
|
189
189
|
delivery?: DeliveryPayload;
|
|
190
190
|
processing?: WorkflowProcessingPayload;
|
|
191
|
+
/**
|
|
192
|
+
* Per-job completion notification (contracts v2.164.0, `notify.email`).
|
|
193
|
+
* Opaque passthrough wire shape — the ergonomic `notifyEmail` surface
|
|
194
|
+
* (SubmitOptions/RunOptions + builder convenience) is a separate follow-up
|
|
195
|
+
* (card y6jsQCpb); this field only acknowledges the wire key so a
|
|
196
|
+
* hand-built payload can carry it. Mirrors `export`/`delivery`/`processing`.
|
|
197
|
+
*/
|
|
198
|
+
notify?: NotifyConfig;
|
|
191
199
|
}
|
|
192
200
|
/**
|
|
193
201
|
* Single source of truth for WorkflowCreatePayload's top-level wire keys.
|
|
@@ -196,7 +204,7 @@ export interface WorkflowCreatePayload {
|
|
|
196
204
|
* only via deep imports and should not be treated as public API.
|
|
197
205
|
* @internal
|
|
198
206
|
*/
|
|
199
|
-
export declare const WORKFLOW_CREATE_PAYLOAD_KEYS: readonly ["jobs", "source", "operations", "workflow_edges", "callback_url", "callback_events", "export", "delivery", "processing"];
|
|
207
|
+
export declare const WORKFLOW_CREATE_PAYLOAD_KEYS: readonly ["jobs", "source", "operations", "workflow_edges", "callback_url", "callback_events", "export", "delivery", "processing", "notify"];
|
|
200
208
|
export interface GetSchemaOptions {
|
|
201
209
|
/** Filter the schema to operations that accept this MIME type (e.g. `image/jpeg`). */
|
|
202
210
|
mimeType?: string;
|
|
@@ -322,7 +330,7 @@ export interface ReadCapabilityOptions {
|
|
|
322
330
|
export interface WaitOptions {
|
|
323
331
|
/** Poll interval in milliseconds (default: 2000) */
|
|
324
332
|
intervalMs?: number;
|
|
325
|
-
/** Maximum wait time in milliseconds (default:
|
|
333
|
+
/** Maximum wait time in milliseconds (default: 600000 = 10 min) */
|
|
326
334
|
timeoutMs?: number;
|
|
327
335
|
/** Called after each poll with current status */
|
|
328
336
|
onPoll?: (status: string) => void;
|
package/dist/types.js
CHANGED
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@giveitsmaller/sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.22.0",
|
|
4
4
|
"description": "Node.js SDK for the GISL (Give It Smaller) file compression and processing API",
|
|
5
|
-
"license": "
|
|
5
|
+
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "./dist/index.js",
|
|
8
8
|
"exports": {
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"node": ">=18"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@giveitsmaller/contracts": "^0.
|
|
34
|
+
"@giveitsmaller/contracts": "^0.65.0"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
37
|
"@types/node": "^22",
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { PdfProfile, OptimizeFor } from '../../generated/sdk_spec/enums.js';
|
|
2
|
-
export interface DocumentPdfCompressPresetOptionsInput {
|
|
3
|
-
readonly profile?: PdfProfile;
|
|
4
|
-
readonly grayscale?: boolean;
|
|
5
|
-
}
|
|
6
|
-
export declare class DocumentPdfCompressPresetOptions {
|
|
7
|
-
readonly profile?: PdfProfile;
|
|
8
|
-
readonly grayscale?: boolean;
|
|
9
|
-
private constructor();
|
|
10
|
-
static from(input: DocumentPdfCompressPresetOptionsInput): DocumentPdfCompressPresetOptions;
|
|
11
|
-
static shippedDefaultsFor(level: OptimizeFor): DocumentPdfCompressPresetOptions;
|
|
12
|
-
}
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
// T4a — DocumentPdfCompressPresetOptions leaf DTO.
|
|
2
|
-
//
|
|
3
|
-
// Field set (2): profile, grayscale — the worker-honored stable PDF controls
|
|
4
|
-
// (contracts v2.96.0 Acrobat-PDF realignment Lw1LseYr). The earlier
|
|
5
|
-
// {profile, colorspace, flattenForms} set was retired: colorspace + flatten_forms
|
|
6
|
-
// are `planned` (not read by the worker) so presets never emit them, and
|
|
7
|
-
// `image_dpi` + `pages` are per-call knobs, not preset cells.
|
|
8
|
-
import { shippedDefaultsFor as f3ShippedDefaultsFor } from '../../generated/sdk_spec/presets.js';
|
|
9
|
-
import { translateEnum } from './_translate.js';
|
|
10
|
-
export class DocumentPdfCompressPresetOptions {
|
|
11
|
-
profile;
|
|
12
|
-
grayscale;
|
|
13
|
-
constructor(input) {
|
|
14
|
-
if (input.profile !== undefined)
|
|
15
|
-
this.profile = input.profile;
|
|
16
|
-
if (input.grayscale !== undefined)
|
|
17
|
-
this.grayscale = input.grayscale;
|
|
18
|
-
Object.freeze(this);
|
|
19
|
-
}
|
|
20
|
-
static from(input) {
|
|
21
|
-
return new DocumentPdfCompressPresetOptions(input);
|
|
22
|
-
}
|
|
23
|
-
static shippedDefaultsFor(level) {
|
|
24
|
-
const cell = f3ShippedDefaultsFor('document_pdf_compress', level);
|
|
25
|
-
const input = {};
|
|
26
|
-
const mut = input;
|
|
27
|
-
if ('profile' in cell)
|
|
28
|
-
mut.profile = translateEnum('PdfProfile', cell.profile);
|
|
29
|
-
if ('grayscale' in cell)
|
|
30
|
-
mut.grayscale = cell.grayscale;
|
|
31
|
-
return new DocumentPdfCompressPresetOptions(input);
|
|
32
|
-
}
|
|
33
|
-
}
|