@formfeed/sdk 0.1.0 → 0.2.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/index.cjs +61 -4
- package/index.js +61 -4
- package/package.json +1 -1
- package/types/index.d.cts +1 -1
- package/types/index.d.ts +1 -1
- package/types/lib/client.d.cts +147 -0
- package/types/lib/client.d.ts +147 -0
package/index.cjs
CHANGED
|
@@ -54,6 +54,8 @@ function randomKey() {
|
|
|
54
54
|
if (c?.randomUUID) return c.randomUUID();
|
|
55
55
|
return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`;
|
|
56
56
|
}
|
|
57
|
+
var withKey = (options) => ({ ...options, idempotencyKey: options.idempotencyKey ?? randomKey() });
|
|
58
|
+
var idOf = (source) => typeof source === "string" ? source : source.id;
|
|
57
59
|
var Formfeed = class {
|
|
58
60
|
baseUrl;
|
|
59
61
|
apiKey;
|
|
@@ -122,6 +124,54 @@ var Formfeed = class {
|
|
|
122
124
|
idempotencyKey: options.idempotencyKey ?? randomKey()
|
|
123
125
|
})
|
|
124
126
|
};
|
|
127
|
+
/**
|
|
128
|
+
* PDF tools on the outputs of earlier renders (a `Render` or its id) and on PDFs of the file library
|
|
129
|
+
* (a `LibraryFile`, its id or its name). merge, protect and watermark return a new render and cost
|
|
130
|
+
* 0.5 units each on live keys; info is free.
|
|
131
|
+
*/
|
|
132
|
+
pdf = {
|
|
133
|
+
merge: (sources, output = {}, options = {}) => this.request("POST", "/pdf/merge", { ...output, sources: sources.map(idOf) }, withKey(options)),
|
|
134
|
+
protect: (source, protect, options = {}) => this.request("POST", "/pdf/protect", { ...protect, source: idOf(source) }, withKey(options)),
|
|
135
|
+
watermark: (source, watermark, options = {}) => this.request("POST", "/pdf/watermark", { ...watermark, source: idOf(source) }, withKey(options)),
|
|
136
|
+
info: (source, options = {}) => this.request("POST", "/pdf/info", { source: idOf(source) }, options)
|
|
137
|
+
};
|
|
138
|
+
/**
|
|
139
|
+
* The workspace file library (`/files`): images and PDFs a template references by name with
|
|
140
|
+
* `asset('logo.png')`, and the sources of image watermarks and merges. Needs `file:read`,
|
|
141
|
+
* `file:write` or `file:delete`. Files are served without a signature, so keep confidential
|
|
142
|
+
* documents out of it.
|
|
143
|
+
*/
|
|
144
|
+
files = {
|
|
145
|
+
/** Uploads a file; the same name replaces the existing file in place and keeps its URL. */
|
|
146
|
+
upload: (file, options = {}) => {
|
|
147
|
+
const blob = file.data instanceof Blob ? file.data : new Blob([file.data], file.contentType ? { type: file.contentType } : {});
|
|
148
|
+
const form = new FormData();
|
|
149
|
+
form.set("file", blob, file.name);
|
|
150
|
+
form.set("name", file.name);
|
|
151
|
+
return this.request("POST", "/files", form, options);
|
|
152
|
+
},
|
|
153
|
+
/** Page of files, newest first. */
|
|
154
|
+
list: (query = {}, options = {}) => {
|
|
155
|
+
const params = new URLSearchParams();
|
|
156
|
+
for (const [k, v] of Object.entries(query)) if (v !== void 0 && v !== null && v !== "") params.set(k, String(v));
|
|
157
|
+
const qs = params.toString();
|
|
158
|
+
return this.request("GET", `/files${qs ? `?${qs}` : ""}`, void 0, options);
|
|
159
|
+
},
|
|
160
|
+
/** Every file matching the query, following the cursor. */
|
|
161
|
+
all: async (query = {}, options = {}) => {
|
|
162
|
+
const out = [];
|
|
163
|
+
let cursor = null;
|
|
164
|
+
do {
|
|
165
|
+
const page = await this.files.list({ ...query, cursor }, options);
|
|
166
|
+
out.push(...page.data);
|
|
167
|
+
cursor = page.next_cursor;
|
|
168
|
+
} while (cursor);
|
|
169
|
+
return out;
|
|
170
|
+
},
|
|
171
|
+
get: (id, options = {}) => this.request("GET", `/files/${encodeURIComponent(id)}`, void 0, options),
|
|
172
|
+
/** Removes the file and its bytes; templates that name it render a missing image afterwards. */
|
|
173
|
+
delete: (file, options = {}) => this.request("DELETE", `/files/${encodeURIComponent(idOf(file))}`, void 0, options)
|
|
174
|
+
};
|
|
125
175
|
jobs = {
|
|
126
176
|
get: (id, options = {}) => this.request("GET", `/jobs/${encodeURIComponent(id)}`, void 0, options),
|
|
127
177
|
waitFor: async (id, options = {}) => {
|
|
@@ -172,7 +222,13 @@ var Formfeed = class {
|
|
|
172
222
|
create: (idOrSlug, input, options = {}) => this.request("POST", `/templates/${encodeURIComponent(idOrSlug)}/versions`, input, options),
|
|
173
223
|
publish: (idOrSlug, number, options = {}) => this.request("POST", `/templates/${encodeURIComponent(idOrSlug)}/versions/${number}/publish`, void 0, options)
|
|
174
224
|
},
|
|
175
|
-
schema: (idOrSlug, options = {}) => this.request("GET", `/templates/${encodeURIComponent(idOrSlug)}/schema`, void 0, options)
|
|
225
|
+
schema: (idOrSlug, options = {}) => this.request("GET", `/templates/${encodeURIComponent(idOrSlug)}/schema`, void 0, options),
|
|
226
|
+
/**
|
|
227
|
+
* Checks a version with data without rendering: syntax, header and footer, missing partials,
|
|
228
|
+
* runtime errors and the data against the stored schema. Free. Without `data`, the version's
|
|
229
|
+
* sample data is checked.
|
|
230
|
+
*/
|
|
231
|
+
validate: (idOrSlug, input = {}, options = {}) => this.request("POST", `/templates/${encodeURIComponent(idOrSlug)}/validate`, input, options)
|
|
176
232
|
};
|
|
177
233
|
account = {
|
|
178
234
|
get: (options = {}) => this.request("GET", "/account", void 0, options),
|
|
@@ -185,9 +241,10 @@ var Formfeed = class {
|
|
|
185
241
|
const headers = {
|
|
186
242
|
authorization: `Bearer ${this.apiKey}`,
|
|
187
243
|
accept: "application/json",
|
|
188
|
-
"user-agent": "formfeed-sdk-ts/0.
|
|
244
|
+
"user-agent": "formfeed-sdk-ts/0.2"
|
|
189
245
|
};
|
|
190
|
-
|
|
246
|
+
const isForm = typeof FormData !== "undefined" && body instanceof FormData;
|
|
247
|
+
if (body !== void 0 && !isForm) headers["content-type"] = "application/json";
|
|
191
248
|
if (options.idempotencyKey) headers["idempotency-key"] = options.idempotencyKey;
|
|
192
249
|
let attempt = 0;
|
|
193
250
|
for (; ; ) {
|
|
@@ -199,7 +256,7 @@ var Formfeed = class {
|
|
|
199
256
|
res = await this.fetchImpl(url, {
|
|
200
257
|
method,
|
|
201
258
|
headers,
|
|
202
|
-
body: body === void 0 ? void 0 : JSON.stringify(body),
|
|
259
|
+
body: body === void 0 ? void 0 : isForm ? body : JSON.stringify(body),
|
|
203
260
|
signal: controller.signal
|
|
204
261
|
});
|
|
205
262
|
} catch (e) {
|
package/index.js
CHANGED
|
@@ -25,6 +25,8 @@ function randomKey() {
|
|
|
25
25
|
if (c?.randomUUID) return c.randomUUID();
|
|
26
26
|
return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`;
|
|
27
27
|
}
|
|
28
|
+
var withKey = (options) => ({ ...options, idempotencyKey: options.idempotencyKey ?? randomKey() });
|
|
29
|
+
var idOf = (source) => typeof source === "string" ? source : source.id;
|
|
28
30
|
var Formfeed = class {
|
|
29
31
|
baseUrl;
|
|
30
32
|
apiKey;
|
|
@@ -93,6 +95,54 @@ var Formfeed = class {
|
|
|
93
95
|
idempotencyKey: options.idempotencyKey ?? randomKey()
|
|
94
96
|
})
|
|
95
97
|
};
|
|
98
|
+
/**
|
|
99
|
+
* PDF tools on the outputs of earlier renders (a `Render` or its id) and on PDFs of the file library
|
|
100
|
+
* (a `LibraryFile`, its id or its name). merge, protect and watermark return a new render and cost
|
|
101
|
+
* 0.5 units each on live keys; info is free.
|
|
102
|
+
*/
|
|
103
|
+
pdf = {
|
|
104
|
+
merge: (sources, output = {}, options = {}) => this.request("POST", "/pdf/merge", { ...output, sources: sources.map(idOf) }, withKey(options)),
|
|
105
|
+
protect: (source, protect, options = {}) => this.request("POST", "/pdf/protect", { ...protect, source: idOf(source) }, withKey(options)),
|
|
106
|
+
watermark: (source, watermark, options = {}) => this.request("POST", "/pdf/watermark", { ...watermark, source: idOf(source) }, withKey(options)),
|
|
107
|
+
info: (source, options = {}) => this.request("POST", "/pdf/info", { source: idOf(source) }, options)
|
|
108
|
+
};
|
|
109
|
+
/**
|
|
110
|
+
* The workspace file library (`/files`): images and PDFs a template references by name with
|
|
111
|
+
* `asset('logo.png')`, and the sources of image watermarks and merges. Needs `file:read`,
|
|
112
|
+
* `file:write` or `file:delete`. Files are served without a signature, so keep confidential
|
|
113
|
+
* documents out of it.
|
|
114
|
+
*/
|
|
115
|
+
files = {
|
|
116
|
+
/** Uploads a file; the same name replaces the existing file in place and keeps its URL. */
|
|
117
|
+
upload: (file, options = {}) => {
|
|
118
|
+
const blob = file.data instanceof Blob ? file.data : new Blob([file.data], file.contentType ? { type: file.contentType } : {});
|
|
119
|
+
const form = new FormData();
|
|
120
|
+
form.set("file", blob, file.name);
|
|
121
|
+
form.set("name", file.name);
|
|
122
|
+
return this.request("POST", "/files", form, options);
|
|
123
|
+
},
|
|
124
|
+
/** Page of files, newest first. */
|
|
125
|
+
list: (query = {}, options = {}) => {
|
|
126
|
+
const params = new URLSearchParams();
|
|
127
|
+
for (const [k, v] of Object.entries(query)) if (v !== void 0 && v !== null && v !== "") params.set(k, String(v));
|
|
128
|
+
const qs = params.toString();
|
|
129
|
+
return this.request("GET", `/files${qs ? `?${qs}` : ""}`, void 0, options);
|
|
130
|
+
},
|
|
131
|
+
/** Every file matching the query, following the cursor. */
|
|
132
|
+
all: async (query = {}, options = {}) => {
|
|
133
|
+
const out = [];
|
|
134
|
+
let cursor = null;
|
|
135
|
+
do {
|
|
136
|
+
const page = await this.files.list({ ...query, cursor }, options);
|
|
137
|
+
out.push(...page.data);
|
|
138
|
+
cursor = page.next_cursor;
|
|
139
|
+
} while (cursor);
|
|
140
|
+
return out;
|
|
141
|
+
},
|
|
142
|
+
get: (id, options = {}) => this.request("GET", `/files/${encodeURIComponent(id)}`, void 0, options),
|
|
143
|
+
/** Removes the file and its bytes; templates that name it render a missing image afterwards. */
|
|
144
|
+
delete: (file, options = {}) => this.request("DELETE", `/files/${encodeURIComponent(idOf(file))}`, void 0, options)
|
|
145
|
+
};
|
|
96
146
|
jobs = {
|
|
97
147
|
get: (id, options = {}) => this.request("GET", `/jobs/${encodeURIComponent(id)}`, void 0, options),
|
|
98
148
|
waitFor: async (id, options = {}) => {
|
|
@@ -143,7 +193,13 @@ var Formfeed = class {
|
|
|
143
193
|
create: (idOrSlug, input, options = {}) => this.request("POST", `/templates/${encodeURIComponent(idOrSlug)}/versions`, input, options),
|
|
144
194
|
publish: (idOrSlug, number, options = {}) => this.request("POST", `/templates/${encodeURIComponent(idOrSlug)}/versions/${number}/publish`, void 0, options)
|
|
145
195
|
},
|
|
146
|
-
schema: (idOrSlug, options = {}) => this.request("GET", `/templates/${encodeURIComponent(idOrSlug)}/schema`, void 0, options)
|
|
196
|
+
schema: (idOrSlug, options = {}) => this.request("GET", `/templates/${encodeURIComponent(idOrSlug)}/schema`, void 0, options),
|
|
197
|
+
/**
|
|
198
|
+
* Checks a version with data without rendering: syntax, header and footer, missing partials,
|
|
199
|
+
* runtime errors and the data against the stored schema. Free. Without `data`, the version's
|
|
200
|
+
* sample data is checked.
|
|
201
|
+
*/
|
|
202
|
+
validate: (idOrSlug, input = {}, options = {}) => this.request("POST", `/templates/${encodeURIComponent(idOrSlug)}/validate`, input, options)
|
|
147
203
|
};
|
|
148
204
|
account = {
|
|
149
205
|
get: (options = {}) => this.request("GET", "/account", void 0, options),
|
|
@@ -156,9 +212,10 @@ var Formfeed = class {
|
|
|
156
212
|
const headers = {
|
|
157
213
|
authorization: `Bearer ${this.apiKey}`,
|
|
158
214
|
accept: "application/json",
|
|
159
|
-
"user-agent": "formfeed-sdk-ts/0.
|
|
215
|
+
"user-agent": "formfeed-sdk-ts/0.2"
|
|
160
216
|
};
|
|
161
|
-
|
|
217
|
+
const isForm = typeof FormData !== "undefined" && body instanceof FormData;
|
|
218
|
+
if (body !== void 0 && !isForm) headers["content-type"] = "application/json";
|
|
162
219
|
if (options.idempotencyKey) headers["idempotency-key"] = options.idempotencyKey;
|
|
163
220
|
let attempt = 0;
|
|
164
221
|
for (; ; ) {
|
|
@@ -170,7 +227,7 @@ var Formfeed = class {
|
|
|
170
227
|
res = await this.fetchImpl(url, {
|
|
171
228
|
method,
|
|
172
229
|
headers,
|
|
173
|
-
body: body === void 0 ? void 0 : JSON.stringify(body),
|
|
230
|
+
body: body === void 0 ? void 0 : isForm ? body : JSON.stringify(body),
|
|
174
231
|
signal: controller.signal
|
|
175
232
|
});
|
|
176
233
|
} catch (e) {
|
package/package.json
CHANGED
package/types/index.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { Formfeed, FormfeedError } from './lib/client.cjs';
|
|
2
|
-
export type { Template, TemplateCreate, TemplateFiles, TemplateKind, TemplateListOptions, TemplateVersion, TemplateVersionCreate, VersionStatus, BatchRequest, Engine, FormfeedOptions, Job, OutputFormat, Problem, Region, Render, RenderListOptions, RenderRequest, RenderStatus, RequestOptions, Usage, WaitOptions, WebhookEndpoint, } from './lib/client.cjs';
|
|
2
|
+
export type { Template, TemplateCreate, TemplateFiles, TemplateKind, TemplateListOptions, TemplateValidation, TemplateVersion, TemplateVersionCreate, VersionStatus, BatchRequest, Diagnostic, Engine, FileListOptions, FileUpload, FormfeedOptions, Job, LibraryFile, OutputFormat, PdfInfo, PdfOutputOptions, PdfPermission, PostProcessing, Problem, ProtectOptions, Region, Render, RenderListOptions, RenderRequest, RenderStatus, RequestOptions, Usage, WaitOptions, WatermarkOptions, WebhookEndpoint, } from './lib/client.cjs';
|
|
3
3
|
export { parseWebhookEvent, verifyWebhookSignature } from './lib/webhooks.cjs';
|
|
4
4
|
export type { VerifyOptions } from './lib/webhooks.cjs';
|
package/types/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { Formfeed, FormfeedError } from './lib/client.js';
|
|
2
|
-
export type { Template, TemplateCreate, TemplateFiles, TemplateKind, TemplateListOptions, TemplateVersion, TemplateVersionCreate, VersionStatus, BatchRequest, Engine, FormfeedOptions, Job, OutputFormat, Problem, Region, Render, RenderListOptions, RenderRequest, RenderStatus, RequestOptions, Usage, WaitOptions, WebhookEndpoint, } from './lib/client.js';
|
|
2
|
+
export type { Template, TemplateCreate, TemplateFiles, TemplateKind, TemplateListOptions, TemplateValidation, TemplateVersion, TemplateVersionCreate, VersionStatus, BatchRequest, Diagnostic, Engine, FileListOptions, FileUpload, FormfeedOptions, Job, LibraryFile, OutputFormat, PdfInfo, PdfOutputOptions, PdfPermission, PostProcessing, Problem, ProtectOptions, Region, Render, RenderListOptions, RenderRequest, RenderStatus, RequestOptions, Usage, WaitOptions, WatermarkOptions, WebhookEndpoint, } from './lib/client.js';
|
|
3
3
|
export { parseWebhookEvent, verifyWebhookSignature } from './lib/webhooks.js';
|
|
4
4
|
export type { VerifyOptions } from './lib/webhooks.js';
|
package/types/lib/client.d.cts
CHANGED
|
@@ -34,9 +34,65 @@ export interface RenderRequest {
|
|
|
34
34
|
mode?: 'sync' | 'async';
|
|
35
35
|
locale?: string | null;
|
|
36
36
|
webhook_url?: string | null;
|
|
37
|
+
/** Signs the deliveries to `webhook_url`, the way an endpoint secret does; 16 to 200 characters. */
|
|
38
|
+
webhook_secret?: string | null;
|
|
37
39
|
meta?: Record<string, unknown>;
|
|
38
40
|
region?: Region;
|
|
39
41
|
dedupe?: boolean;
|
|
42
|
+
/** PDF post-processing: merge, watermark, password, applied in that order (0.5 units each). */
|
|
43
|
+
post?: PostProcessing | null;
|
|
44
|
+
/** Check `data` against the template's stored schema first; a mismatch throws `data_validation_error`. */
|
|
45
|
+
validate_data?: boolean;
|
|
46
|
+
}
|
|
47
|
+
export type PdfPermission = 'print' | 'copy' | 'modify' | 'annotate';
|
|
48
|
+
/** A text or an image watermark; pass one of `text` and `image`. */
|
|
49
|
+
export interface WatermarkOptions {
|
|
50
|
+
text?: string;
|
|
51
|
+
/** A PNG or JPEG of the workspace file library: its id (`fil_…`) or its name. */
|
|
52
|
+
image?: string;
|
|
53
|
+
/** 0 to 1, default 0.2. */
|
|
54
|
+
opacity?: number;
|
|
55
|
+
/** Degrees clockwise as in CSS, default -45 (bottom left to top right). */
|
|
56
|
+
rotation?: number;
|
|
57
|
+
/** Hex colour such as `#cc0000`; grey by default. Text only. */
|
|
58
|
+
color?: string;
|
|
59
|
+
}
|
|
60
|
+
export interface PostProcessing {
|
|
61
|
+
/** PDFs appended after this document, in order: render ids, or file ids and names of library PDFs. */
|
|
62
|
+
merge_after?: string[];
|
|
63
|
+
watermark?: WatermarkOptions;
|
|
64
|
+
password?: {
|
|
65
|
+
user?: string;
|
|
66
|
+
owner?: string;
|
|
67
|
+
permissions?: PdfPermission[];
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
/** Where the result of a PDF tool is stored, as for a render. */
|
|
71
|
+
export interface PdfOutputOptions {
|
|
72
|
+
filename?: string;
|
|
73
|
+
expires_in?: number | null;
|
|
74
|
+
access?: 'public' | 'signed';
|
|
75
|
+
meta?: Record<string, unknown>;
|
|
76
|
+
}
|
|
77
|
+
export interface ProtectOptions extends PdfOutputOptions {
|
|
78
|
+
/** Needed to open the document. */
|
|
79
|
+
user_password?: string;
|
|
80
|
+
/** Lifts the restrictions; random when omitted. */
|
|
81
|
+
owner_password?: string;
|
|
82
|
+
/** What readers may do; everything not listed is forbidden. */
|
|
83
|
+
permissions?: PdfPermission[];
|
|
84
|
+
}
|
|
85
|
+
export interface PdfInfo {
|
|
86
|
+
source: string;
|
|
87
|
+
page_count: number;
|
|
88
|
+
pages: Array<{
|
|
89
|
+
width_pt: number;
|
|
90
|
+
height_pt: number;
|
|
91
|
+
width_mm: number;
|
|
92
|
+
height_mm: number;
|
|
93
|
+
}>;
|
|
94
|
+
encrypted: boolean;
|
|
95
|
+
metadata: Record<string, unknown>;
|
|
40
96
|
}
|
|
41
97
|
export interface Render {
|
|
42
98
|
id: string;
|
|
@@ -73,6 +129,7 @@ export interface BatchRequest {
|
|
|
73
129
|
items: RenderRequest[];
|
|
74
130
|
zip?: boolean;
|
|
75
131
|
webhook_url?: string | null;
|
|
132
|
+
webhook_secret?: string | null;
|
|
76
133
|
meta?: Record<string, unknown>;
|
|
77
134
|
}
|
|
78
135
|
export interface Job {
|
|
@@ -89,6 +146,32 @@ export interface Job {
|
|
|
89
146
|
created_at: string;
|
|
90
147
|
completed_at: string | null;
|
|
91
148
|
}
|
|
149
|
+
/** A file of the workspace library (`/files`); a template reaches it with `asset(name)`. */
|
|
150
|
+
export interface LibraryFile {
|
|
151
|
+
id: string;
|
|
152
|
+
name: string;
|
|
153
|
+
content_type: string;
|
|
154
|
+
bytes: number;
|
|
155
|
+
sha256: string;
|
|
156
|
+
/** The CDN URL, the same one `asset(name)` produces. */
|
|
157
|
+
url: string;
|
|
158
|
+
created_at: string;
|
|
159
|
+
updated_at: string;
|
|
160
|
+
}
|
|
161
|
+
export interface FileUpload {
|
|
162
|
+
/** The bytes: a Blob or File, a Uint8Array (Node's Buffer is one) or an ArrayBuffer. */
|
|
163
|
+
data: Blob | Uint8Array | ArrayBuffer;
|
|
164
|
+
/** The library name, e.g. `logo.png` or `brand/header.svg`. Uploading a name again replaces it. */
|
|
165
|
+
name: string;
|
|
166
|
+
/** Sent with the bytes; the API also goes by the extension when it is missing. */
|
|
167
|
+
contentType?: string;
|
|
168
|
+
}
|
|
169
|
+
export interface FileListOptions {
|
|
170
|
+
/** Only names starting with this, e.g. `brand/`. */
|
|
171
|
+
prefix?: string;
|
|
172
|
+
limit?: number;
|
|
173
|
+
cursor?: string | null;
|
|
174
|
+
}
|
|
92
175
|
export interface WebhookEndpoint {
|
|
93
176
|
id: string;
|
|
94
177
|
url: string;
|
|
@@ -116,6 +199,28 @@ export interface Template {
|
|
|
116
199
|
created_at: string;
|
|
117
200
|
updated_at: string;
|
|
118
201
|
}
|
|
202
|
+
/** One finding of `templates.validate`. */
|
|
203
|
+
export interface Diagnostic {
|
|
204
|
+
severity: 'error' | 'warning' | 'info';
|
|
205
|
+
code: string;
|
|
206
|
+
message: string;
|
|
207
|
+
location?: {
|
|
208
|
+
line: number;
|
|
209
|
+
column: number;
|
|
210
|
+
};
|
|
211
|
+
/** Data errors only: where in the data, e.g. `data.invoice.lines[0].qty`. */
|
|
212
|
+
path?: string;
|
|
213
|
+
}
|
|
214
|
+
export interface TemplateValidation {
|
|
215
|
+
/** `false` when at least one diagnostic is an error. */
|
|
216
|
+
ok: boolean;
|
|
217
|
+
template: {
|
|
218
|
+
id: string;
|
|
219
|
+
slug: string;
|
|
220
|
+
version: number;
|
|
221
|
+
};
|
|
222
|
+
diagnostics: Diagnostic[];
|
|
223
|
+
}
|
|
119
224
|
/** The files of a version as the editor and the CLI keep them. */
|
|
120
225
|
export interface TemplateFiles {
|
|
121
226
|
html: string;
|
|
@@ -127,6 +232,8 @@ export interface TemplateFiles {
|
|
|
127
232
|
data_sets?: Record<string, unknown> | null;
|
|
128
233
|
data_schema?: Record<string, unknown> | null;
|
|
129
234
|
i18n?: Record<string, unknown> | null;
|
|
235
|
+
/** Partials the template includes (`name` → source); `formfeed templates push` sends them. */
|
|
236
|
+
partials?: Record<string, string> | null;
|
|
130
237
|
}
|
|
131
238
|
export interface TemplateVersion extends Partial<TemplateFiles> {
|
|
132
239
|
id: string;
|
|
@@ -238,6 +345,37 @@ export declare class Formfeed {
|
|
|
238
345
|
deleteOutputs: (id: string, options?: RequestOptions) => Promise<void>;
|
|
239
346
|
batch: (request: BatchRequest, options?: RequestOptions) => Promise<Job>;
|
|
240
347
|
};
|
|
348
|
+
/**
|
|
349
|
+
* PDF tools on the outputs of earlier renders (a `Render` or its id) and on PDFs of the file library
|
|
350
|
+
* (a `LibraryFile`, its id or its name). merge, protect and watermark return a new render and cost
|
|
351
|
+
* 0.5 units each on live keys; info is free.
|
|
352
|
+
*/
|
|
353
|
+
readonly pdf: {
|
|
354
|
+
merge: (sources: Array<Render | LibraryFile | string>, output?: PdfOutputOptions, options?: RequestOptions) => Promise<Render>;
|
|
355
|
+
protect: (source: Render | string, protect: ProtectOptions, options?: RequestOptions) => Promise<Render>;
|
|
356
|
+
watermark: (source: Render | string, watermark: WatermarkOptions & PdfOutputOptions, options?: RequestOptions) => Promise<Render>;
|
|
357
|
+
info: (source: Render | string, options?: RequestOptions) => Promise<PdfInfo>;
|
|
358
|
+
};
|
|
359
|
+
/**
|
|
360
|
+
* The workspace file library (`/files`): images and PDFs a template references by name with
|
|
361
|
+
* `asset('logo.png')`, and the sources of image watermarks and merges. Needs `file:read`,
|
|
362
|
+
* `file:write` or `file:delete`. Files are served without a signature, so keep confidential
|
|
363
|
+
* documents out of it.
|
|
364
|
+
*/
|
|
365
|
+
readonly files: {
|
|
366
|
+
/** Uploads a file; the same name replaces the existing file in place and keeps its URL. */
|
|
367
|
+
upload: (file: FileUpload, options?: RequestOptions) => Promise<LibraryFile>;
|
|
368
|
+
/** Page of files, newest first. */
|
|
369
|
+
list: (query?: FileListOptions, options?: RequestOptions) => Promise<{
|
|
370
|
+
data: LibraryFile[];
|
|
371
|
+
next_cursor: string | null;
|
|
372
|
+
}>;
|
|
373
|
+
/** Every file matching the query, following the cursor. */
|
|
374
|
+
all: (query?: Omit<FileListOptions, "cursor">, options?: RequestOptions) => Promise<LibraryFile[]>;
|
|
375
|
+
get: (id: string, options?: RequestOptions) => Promise<LibraryFile>;
|
|
376
|
+
/** Removes the file and its bytes; templates that name it render a missing image afterwards. */
|
|
377
|
+
delete: (file: LibraryFile | string, options?: RequestOptions) => Promise<void>;
|
|
378
|
+
};
|
|
241
379
|
readonly jobs: {
|
|
242
380
|
get: (id: string, options?: RequestOptions) => Promise<Job>;
|
|
243
381
|
waitFor: (id: string, options?: WaitOptions) => Promise<Job>;
|
|
@@ -283,6 +421,15 @@ export declare class Formfeed {
|
|
|
283
421
|
publish: (idOrSlug: string, number: number, options?: RequestOptions) => Promise<TemplateVersion>;
|
|
284
422
|
};
|
|
285
423
|
schema: (idOrSlug: string, options?: RequestOptions) => Promise<Record<string, unknown>>;
|
|
424
|
+
/**
|
|
425
|
+
* Checks a version with data without rendering: syntax, header and footer, missing partials,
|
|
426
|
+
* runtime errors and the data against the stored schema. Free. Without `data`, the version's
|
|
427
|
+
* sample data is checked.
|
|
428
|
+
*/
|
|
429
|
+
validate: (idOrSlug: string, input?: {
|
|
430
|
+
version?: "published" | "latest" | number;
|
|
431
|
+
data?: Record<string, unknown>;
|
|
432
|
+
}, options?: RequestOptions) => Promise<TemplateValidation>;
|
|
286
433
|
};
|
|
287
434
|
readonly account: {
|
|
288
435
|
get: (options?: RequestOptions) => Promise<Record<string, unknown>>;
|
package/types/lib/client.d.ts
CHANGED
|
@@ -34,9 +34,65 @@ export interface RenderRequest {
|
|
|
34
34
|
mode?: 'sync' | 'async';
|
|
35
35
|
locale?: string | null;
|
|
36
36
|
webhook_url?: string | null;
|
|
37
|
+
/** Signs the deliveries to `webhook_url`, the way an endpoint secret does; 16 to 200 characters. */
|
|
38
|
+
webhook_secret?: string | null;
|
|
37
39
|
meta?: Record<string, unknown>;
|
|
38
40
|
region?: Region;
|
|
39
41
|
dedupe?: boolean;
|
|
42
|
+
/** PDF post-processing: merge, watermark, password, applied in that order (0.5 units each). */
|
|
43
|
+
post?: PostProcessing | null;
|
|
44
|
+
/** Check `data` against the template's stored schema first; a mismatch throws `data_validation_error`. */
|
|
45
|
+
validate_data?: boolean;
|
|
46
|
+
}
|
|
47
|
+
export type PdfPermission = 'print' | 'copy' | 'modify' | 'annotate';
|
|
48
|
+
/** A text or an image watermark; pass one of `text` and `image`. */
|
|
49
|
+
export interface WatermarkOptions {
|
|
50
|
+
text?: string;
|
|
51
|
+
/** A PNG or JPEG of the workspace file library: its id (`fil_…`) or its name. */
|
|
52
|
+
image?: string;
|
|
53
|
+
/** 0 to 1, default 0.2. */
|
|
54
|
+
opacity?: number;
|
|
55
|
+
/** Degrees clockwise as in CSS, default -45 (bottom left to top right). */
|
|
56
|
+
rotation?: number;
|
|
57
|
+
/** Hex colour such as `#cc0000`; grey by default. Text only. */
|
|
58
|
+
color?: string;
|
|
59
|
+
}
|
|
60
|
+
export interface PostProcessing {
|
|
61
|
+
/** PDFs appended after this document, in order: render ids, or file ids and names of library PDFs. */
|
|
62
|
+
merge_after?: string[];
|
|
63
|
+
watermark?: WatermarkOptions;
|
|
64
|
+
password?: {
|
|
65
|
+
user?: string;
|
|
66
|
+
owner?: string;
|
|
67
|
+
permissions?: PdfPermission[];
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
/** Where the result of a PDF tool is stored, as for a render. */
|
|
71
|
+
export interface PdfOutputOptions {
|
|
72
|
+
filename?: string;
|
|
73
|
+
expires_in?: number | null;
|
|
74
|
+
access?: 'public' | 'signed';
|
|
75
|
+
meta?: Record<string, unknown>;
|
|
76
|
+
}
|
|
77
|
+
export interface ProtectOptions extends PdfOutputOptions {
|
|
78
|
+
/** Needed to open the document. */
|
|
79
|
+
user_password?: string;
|
|
80
|
+
/** Lifts the restrictions; random when omitted. */
|
|
81
|
+
owner_password?: string;
|
|
82
|
+
/** What readers may do; everything not listed is forbidden. */
|
|
83
|
+
permissions?: PdfPermission[];
|
|
84
|
+
}
|
|
85
|
+
export interface PdfInfo {
|
|
86
|
+
source: string;
|
|
87
|
+
page_count: number;
|
|
88
|
+
pages: Array<{
|
|
89
|
+
width_pt: number;
|
|
90
|
+
height_pt: number;
|
|
91
|
+
width_mm: number;
|
|
92
|
+
height_mm: number;
|
|
93
|
+
}>;
|
|
94
|
+
encrypted: boolean;
|
|
95
|
+
metadata: Record<string, unknown>;
|
|
40
96
|
}
|
|
41
97
|
export interface Render {
|
|
42
98
|
id: string;
|
|
@@ -73,6 +129,7 @@ export interface BatchRequest {
|
|
|
73
129
|
items: RenderRequest[];
|
|
74
130
|
zip?: boolean;
|
|
75
131
|
webhook_url?: string | null;
|
|
132
|
+
webhook_secret?: string | null;
|
|
76
133
|
meta?: Record<string, unknown>;
|
|
77
134
|
}
|
|
78
135
|
export interface Job {
|
|
@@ -89,6 +146,32 @@ export interface Job {
|
|
|
89
146
|
created_at: string;
|
|
90
147
|
completed_at: string | null;
|
|
91
148
|
}
|
|
149
|
+
/** A file of the workspace library (`/files`); a template reaches it with `asset(name)`. */
|
|
150
|
+
export interface LibraryFile {
|
|
151
|
+
id: string;
|
|
152
|
+
name: string;
|
|
153
|
+
content_type: string;
|
|
154
|
+
bytes: number;
|
|
155
|
+
sha256: string;
|
|
156
|
+
/** The CDN URL, the same one `asset(name)` produces. */
|
|
157
|
+
url: string;
|
|
158
|
+
created_at: string;
|
|
159
|
+
updated_at: string;
|
|
160
|
+
}
|
|
161
|
+
export interface FileUpload {
|
|
162
|
+
/** The bytes: a Blob or File, a Uint8Array (Node's Buffer is one) or an ArrayBuffer. */
|
|
163
|
+
data: Blob | Uint8Array | ArrayBuffer;
|
|
164
|
+
/** The library name, e.g. `logo.png` or `brand/header.svg`. Uploading a name again replaces it. */
|
|
165
|
+
name: string;
|
|
166
|
+
/** Sent with the bytes; the API also goes by the extension when it is missing. */
|
|
167
|
+
contentType?: string;
|
|
168
|
+
}
|
|
169
|
+
export interface FileListOptions {
|
|
170
|
+
/** Only names starting with this, e.g. `brand/`. */
|
|
171
|
+
prefix?: string;
|
|
172
|
+
limit?: number;
|
|
173
|
+
cursor?: string | null;
|
|
174
|
+
}
|
|
92
175
|
export interface WebhookEndpoint {
|
|
93
176
|
id: string;
|
|
94
177
|
url: string;
|
|
@@ -116,6 +199,28 @@ export interface Template {
|
|
|
116
199
|
created_at: string;
|
|
117
200
|
updated_at: string;
|
|
118
201
|
}
|
|
202
|
+
/** One finding of `templates.validate`. */
|
|
203
|
+
export interface Diagnostic {
|
|
204
|
+
severity: 'error' | 'warning' | 'info';
|
|
205
|
+
code: string;
|
|
206
|
+
message: string;
|
|
207
|
+
location?: {
|
|
208
|
+
line: number;
|
|
209
|
+
column: number;
|
|
210
|
+
};
|
|
211
|
+
/** Data errors only: where in the data, e.g. `data.invoice.lines[0].qty`. */
|
|
212
|
+
path?: string;
|
|
213
|
+
}
|
|
214
|
+
export interface TemplateValidation {
|
|
215
|
+
/** `false` when at least one diagnostic is an error. */
|
|
216
|
+
ok: boolean;
|
|
217
|
+
template: {
|
|
218
|
+
id: string;
|
|
219
|
+
slug: string;
|
|
220
|
+
version: number;
|
|
221
|
+
};
|
|
222
|
+
diagnostics: Diagnostic[];
|
|
223
|
+
}
|
|
119
224
|
/** The files of a version as the editor and the CLI keep them. */
|
|
120
225
|
export interface TemplateFiles {
|
|
121
226
|
html: string;
|
|
@@ -127,6 +232,8 @@ export interface TemplateFiles {
|
|
|
127
232
|
data_sets?: Record<string, unknown> | null;
|
|
128
233
|
data_schema?: Record<string, unknown> | null;
|
|
129
234
|
i18n?: Record<string, unknown> | null;
|
|
235
|
+
/** Partials the template includes (`name` → source); `formfeed templates push` sends them. */
|
|
236
|
+
partials?: Record<string, string> | null;
|
|
130
237
|
}
|
|
131
238
|
export interface TemplateVersion extends Partial<TemplateFiles> {
|
|
132
239
|
id: string;
|
|
@@ -238,6 +345,37 @@ export declare class Formfeed {
|
|
|
238
345
|
deleteOutputs: (id: string, options?: RequestOptions) => Promise<void>;
|
|
239
346
|
batch: (request: BatchRequest, options?: RequestOptions) => Promise<Job>;
|
|
240
347
|
};
|
|
348
|
+
/**
|
|
349
|
+
* PDF tools on the outputs of earlier renders (a `Render` or its id) and on PDFs of the file library
|
|
350
|
+
* (a `LibraryFile`, its id or its name). merge, protect and watermark return a new render and cost
|
|
351
|
+
* 0.5 units each on live keys; info is free.
|
|
352
|
+
*/
|
|
353
|
+
readonly pdf: {
|
|
354
|
+
merge: (sources: Array<Render | LibraryFile | string>, output?: PdfOutputOptions, options?: RequestOptions) => Promise<Render>;
|
|
355
|
+
protect: (source: Render | string, protect: ProtectOptions, options?: RequestOptions) => Promise<Render>;
|
|
356
|
+
watermark: (source: Render | string, watermark: WatermarkOptions & PdfOutputOptions, options?: RequestOptions) => Promise<Render>;
|
|
357
|
+
info: (source: Render | string, options?: RequestOptions) => Promise<PdfInfo>;
|
|
358
|
+
};
|
|
359
|
+
/**
|
|
360
|
+
* The workspace file library (`/files`): images and PDFs a template references by name with
|
|
361
|
+
* `asset('logo.png')`, and the sources of image watermarks and merges. Needs `file:read`,
|
|
362
|
+
* `file:write` or `file:delete`. Files are served without a signature, so keep confidential
|
|
363
|
+
* documents out of it.
|
|
364
|
+
*/
|
|
365
|
+
readonly files: {
|
|
366
|
+
/** Uploads a file; the same name replaces the existing file in place and keeps its URL. */
|
|
367
|
+
upload: (file: FileUpload, options?: RequestOptions) => Promise<LibraryFile>;
|
|
368
|
+
/** Page of files, newest first. */
|
|
369
|
+
list: (query?: FileListOptions, options?: RequestOptions) => Promise<{
|
|
370
|
+
data: LibraryFile[];
|
|
371
|
+
next_cursor: string | null;
|
|
372
|
+
}>;
|
|
373
|
+
/** Every file matching the query, following the cursor. */
|
|
374
|
+
all: (query?: Omit<FileListOptions, "cursor">, options?: RequestOptions) => Promise<LibraryFile[]>;
|
|
375
|
+
get: (id: string, options?: RequestOptions) => Promise<LibraryFile>;
|
|
376
|
+
/** Removes the file and its bytes; templates that name it render a missing image afterwards. */
|
|
377
|
+
delete: (file: LibraryFile | string, options?: RequestOptions) => Promise<void>;
|
|
378
|
+
};
|
|
241
379
|
readonly jobs: {
|
|
242
380
|
get: (id: string, options?: RequestOptions) => Promise<Job>;
|
|
243
381
|
waitFor: (id: string, options?: WaitOptions) => Promise<Job>;
|
|
@@ -283,6 +421,15 @@ export declare class Formfeed {
|
|
|
283
421
|
publish: (idOrSlug: string, number: number, options?: RequestOptions) => Promise<TemplateVersion>;
|
|
284
422
|
};
|
|
285
423
|
schema: (idOrSlug: string, options?: RequestOptions) => Promise<Record<string, unknown>>;
|
|
424
|
+
/**
|
|
425
|
+
* Checks a version with data without rendering: syntax, header and footer, missing partials,
|
|
426
|
+
* runtime errors and the data against the stored schema. Free. Without `data`, the version's
|
|
427
|
+
* sample data is checked.
|
|
428
|
+
*/
|
|
429
|
+
validate: (idOrSlug: string, input?: {
|
|
430
|
+
version?: "published" | "latest" | number;
|
|
431
|
+
data?: Record<string, unknown>;
|
|
432
|
+
}, options?: RequestOptions) => Promise<TemplateValidation>;
|
|
286
433
|
};
|
|
287
434
|
readonly account: {
|
|
288
435
|
get: (options?: RequestOptions) => Promise<Record<string, unknown>>;
|