@quantcdn/quant-client 1.0.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 ADDED
@@ -0,0 +1,30 @@
1
+ # QuantCDN client API
2
+
3
+ Provides a client to common API interfaces on QuantCDN.
4
+
5
+ ## Install
6
+
7
+ The preferred method for installation is via npm.
8
+
9
+ ```
10
+ npm i @quantcdn/quant-cli
11
+ ```
12
+
13
+ ## Usage
14
+
15
+ The API client expects the following environment variables are present in order to make a successful API connection:
16
+ * `QUANT_CUSTOMER`: The organization/customer identifier
17
+ * `QUANT_PROJECT`: The project identifier
18
+ * `QUANT_TOKEN`: The project token
19
+
20
+ These values can be found from the "Integrations" page of the QuantCDN Dashboard.
21
+
22
+ ```
23
+ import { QuantClient } from "@quantcdn/quant-client"
24
+
25
+ // Purge QuantCDN edge caches for a single route.
26
+ QuantClient().purge('/path/to/content')
27
+
28
+ // Purge all QuantCDN edge caches.
29
+ QuantClient().purge('/*')
30
+ ``
@@ -0,0 +1,7 @@
1
+ export interface QuantConfig {
2
+ dir: string;
3
+ endpoint: "https://api.quantcdn.io/v1";
4
+ clientid: string;
5
+ project: string;
6
+ token: string;
7
+ }
package/dist/config.js ADDED
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ ;
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Prepare URLs for quant.
3
+ */
4
+ export declare class QuantURL {
5
+ /**
6
+ * Prepare a URI to work with Quant.
7
+ *
8
+ * @param {string} uri
9
+ * The URI to prepare.
10
+ *
11
+ * @return {string}
12
+ * The prepared URI
13
+ */
14
+ static prepare(uri: any): any;
15
+ }
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ /**
3
+ * Prepare URLs for quant.
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.QuantURL = void 0;
7
+ class QuantURL {
8
+ /**
9
+ * Prepare a URI to work with Quant.
10
+ *
11
+ * @param {string} uri
12
+ * The URI to prepare.
13
+ *
14
+ * @return {string}
15
+ * The prepared URI
16
+ */
17
+ static prepare(uri) {
18
+ uri = uri.startsWith('/') ? uri : `/${uri}`;
19
+ uri = uri.toLowerCase();
20
+ uri = uri.replace(/^\/\//, '/');
21
+ uri = uri.replace(/(\/)index\.html/, '$1');
22
+ if (uri.length > 1) {
23
+ return uri.endsWith('/') ? uri.slice(0, -1) : uri;
24
+ }
25
+ return uri;
26
+ }
27
+ }
28
+ exports.QuantURL = QuantURL;
29
+ ;
@@ -0,0 +1 @@
1
+ export { QuantClient } from './quant-client';
package/dist/index.js ADDED
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.QuantClient = void 0;
4
+ var quant_client_1 = require("./quant-client");
5
+ Object.defineProperty(exports, "QuantClient", { enumerable: true, get: function () { return quant_client_1.QuantClient; } });
@@ -0,0 +1,230 @@
1
+ /**
2
+ * Quant API client.
3
+ */
4
+ export declare function QuantClient(): {
5
+ /**
6
+ * Initialize the client
7
+ */
8
+ init: () => void;
9
+ /**
10
+ * Ping the quant API.
11
+ *
12
+ * @return {object}
13
+ * The response object.
14
+ *
15
+ * @throws Error.
16
+ */
17
+ ping: () => Promise<any>;
18
+ /**
19
+ * Access the global meta for the project.
20
+ *
21
+ * @param {bool} unfold
22
+ * Unfold the record set.
23
+ * @param {bool} exclude
24
+ * Exclude delete objects from the meta result.
25
+ * @param {object} extend
26
+ * Additional query parameters to send.
27
+ *
28
+ * @return {object}
29
+ * The global meta response object.
30
+ *
31
+ * @throws Error.
32
+ *
33
+ * @TODO
34
+ * - Async iterator for memory 21k items ~ 40mb.
35
+ */
36
+ meta: (unfold?: boolean, exclude?: boolean, extend?: {}) => Promise<{
37
+ total_pages: any;
38
+ total_records: any;
39
+ records: any[];
40
+ }>;
41
+ /**
42
+ * Send a file to the server.
43
+ *
44
+ * @param {string} file
45
+ * The path to the file.
46
+ * @param {string} location
47
+ * The path the location.
48
+ * @param {bool} published
49
+ * The status.
50
+ * @param {bool} attachments
51
+ * Should quant find attachments.
52
+ * @param {bool} skipPurge
53
+ * Skip CDN cache purge.
54
+ * @param {bool} includeIndex
55
+ * Include index.html suffix on HTML assets.
56
+ * @param {object} extraHeaders
57
+ * Additional HTTP headers.
58
+ * @param {string} encoding
59
+ * The encoding type.
60
+ *
61
+ * @return {object}
62
+ * The API response.
63
+ */
64
+ send: (file: any, location: any, published?: boolean, attachments?: boolean, skipPurge?: boolean, includeIndex?: boolean, extraHeaders?: {}, encoding?: string) => Promise<any>;
65
+ /**
66
+ * Upload markup.
67
+ *
68
+ * @param {string} file
69
+ * Filepath on disk.
70
+ * @param {string} location
71
+ * The web accessible destination.
72
+ * @param {bool} published
73
+ * The status.
74
+ * @param {bool} attachments
75
+ * Quant looking for attachments.
76
+ * @param {object} extraHeaders
77
+ * Additional HTTP headers.
78
+ * @param {string} encoding
79
+ * The encoding type.
80
+ * @param {bool} skipPurge
81
+ * Skip CDN cache purge.
82
+ *
83
+ * @return {object}
84
+ * The API response.
85
+ */
86
+ markup: (file: any, location: any, published?: boolean, attachments?: boolean, extraHeaders?: {}, encoding?: string, skipPurge?: boolean) => Promise<any>;
87
+ /**
88
+ * Send a file to the Quant API.
89
+ *
90
+ * @param {string} local
91
+ * File path on disk.
92
+ * @param {string} location
93
+ * Accessible location.
94
+ * @param {bool} absolute
95
+ * If the location is an absolute path.
96
+ * @param {object} extraHeaders
97
+ * Additional HTTP headers.
98
+ * @param {bool} skipPurge
99
+ * Skip CDN cache purge.
100
+ *
101
+ * @return {object}
102
+ * The successful payload.
103
+ *
104
+ * @throws Error
105
+ */
106
+ file: (local: any, location: any, absolute?: boolean, extraHeaders?: {}, skipPurge?: boolean) => Promise<any>;
107
+ /**
108
+ * Change the status of an asset.
109
+ *
110
+ * @param {string} location
111
+ * The URL location of the content.
112
+ * @param {string} revision
113
+ * The revision to publish.
114
+ *
115
+ * @return {object}
116
+ * API payload.
117
+ *
118
+ * @throws Error.
119
+ */
120
+ publish: (location: any, revision: any) => Promise<any>;
121
+ /**
122
+ * Unpublish a URL.
123
+ *
124
+ * @param {string} url
125
+ * The URL to unpublish.
126
+ *
127
+ * @return {object}
128
+ *
129
+ * @throws Error.
130
+ */
131
+ unpublish: (url: any) => Promise<any>;
132
+ /**
133
+ *
134
+ * @param {string} from
135
+ * The URL to redirect form.
136
+ * @param {string} to
137
+ * The URL to redirect to.
138
+ * @param {string} author
139
+ * (Optional) Author.
140
+ * @param {int} status
141
+ * HTTP status code.
142
+ *
143
+ * @return {object}
144
+ * API payload.
145
+ *
146
+ * @throws Error.
147
+ */
148
+ redirect: (from: any, to: any, author: any, status?: number) => Promise<any>;
149
+ /**
150
+ * Create a proxy with the Quant API.
151
+ *
152
+ * @param {string} url
153
+ * The relative URL to proxy.
154
+ * @param {string} destination
155
+ * The absolute FQDN/path to proxy to.
156
+ * @param {bool} published
157
+ * If the proxy is published
158
+ * @param {string} username
159
+ * Basic auth user.
160
+ * @param {string} password
161
+ * Basic auth password.
162
+ *
163
+ * @return {object}
164
+ * The response.
165
+ *
166
+ * @throws Error.
167
+ */
168
+ proxy: (url: any, destination: any, published: boolean, username: any, password: any) => Promise<any>;
169
+ /**
170
+ * Delete a path from Quant.
171
+ *
172
+ * @param {string} path
173
+ *
174
+ * @return {object}
175
+ * The response object.
176
+ *
177
+ * @throw Error.
178
+ */
179
+ delete: (path: any) => Promise<any>;
180
+ /**
181
+ * Get the revision history from Quant.
182
+ *
183
+ * @param {string} url
184
+ * The URL path to get revisions for.
185
+ * @param {string|bool} revision
186
+ * Retrieve a specific revision.
187
+ *
188
+ * @return {object}
189
+ * The response.
190
+ *
191
+ * @throws Error.
192
+ */
193
+ revisions: (url: any, revision?: boolean) => Promise<any>;
194
+ /**
195
+ * Purge URL patterns from Quants Varnish.
196
+ *
197
+ * @param {string} urlPattern
198
+ *
199
+ * @throws Error
200
+ */
201
+ purge: (urlPattern: any) => Promise<any>;
202
+ /**
203
+ * Add/update items in search index.
204
+ *
205
+ * @param {string} filePath
206
+ *
207
+ * @throws Error
208
+ */
209
+ searchIndex: (filePath: any) => Promise<any>;
210
+ /**
211
+ * Remove item from search index.
212
+ *
213
+ * @param {string} url
214
+ *
215
+ * @throws Error
216
+ */
217
+ searchRemove: (url: any) => Promise<any>;
218
+ /**
219
+ * Clear search index.
220
+ *
221
+ * @throws Error
222
+ */
223
+ searchClearIndex: () => Promise<any>;
224
+ /**
225
+ * Retrieve search index status.
226
+ *
227
+ * @throws Error
228
+ */
229
+ searchStatus: () => Promise<any>;
230
+ };
@@ -0,0 +1,696 @@
1
+ "use strict";
2
+ /**
3
+ * Quant API client.
4
+ */
5
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
6
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
7
+ return new (P || (P = Promise))(function (resolve, reject) {
8
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
9
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
10
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
11
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
12
+ });
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.QuantClient = void 0;
16
+ const request = require('request');
17
+ const util = require('util');
18
+ const fs = require('fs');
19
+ const path = require('path');
20
+ const mime = require('mime-types');
21
+ const querystring = require('querystring');
22
+ const quant_url_1 = require("./helper/quant-url");
23
+ function QuantClient() {
24
+ const req = util.promisify(request); // eslint-disable-line
25
+ const get = util.promisify(request.get);
26
+ const post = util.promisify(request.post);
27
+ const patch = util.promisify(request.patch);
28
+ const del = util.promisify(request.delete);
29
+ let headers = {};
30
+ let config;
31
+ /**
32
+ * Handle the response.
33
+ *
34
+ * @param {string} response
35
+ * Response body from the Quant API.
36
+ *
37
+ * @return {object}
38
+ * The API response.
39
+ */
40
+ const handleResponse = function (response) {
41
+ const body = typeof response.body == 'string' ? JSON.parse(response.body) : response.body; // eslint-disable-line max-len
42
+ if (typeof body.errors != 'undefined') {
43
+ let msg = '';
44
+ for (const i in body.errors) { // eslint-disable-line
45
+ msg += body.errors[i].errorMsg + '\n';
46
+ }
47
+ throw new Error(msg);
48
+ }
49
+ if (response.statusCode == 400) {
50
+ // @TODO: this is generally if the content is
51
+ // streamed to the endpoint 4xx and 5xx are thrown
52
+ // similarly, the API should respond with errors
53
+ // otherwise.
54
+ if (typeof body.errorMsg != 'undefined') {
55
+ throw new Error(body.errorMsg);
56
+ }
57
+ throw new Error('Critical error...');
58
+ }
59
+ if (body.error || (typeof body.errorMsg != 'undefined' && body.errorMsg.length > 0)) { // eslint-disable-line max-len
60
+ const msg = typeof body.errorMsg != 'undefined' ? body.errorMsg : body.msg;
61
+ throw new Error(msg);
62
+ }
63
+ return body;
64
+ };
65
+ return {
66
+ /**
67
+ * Initialize the client
68
+ */
69
+ init: function () {
70
+ this.config = {
71
+ clientid: process.env.QUANT_CUSTOMER,
72
+ project: process.env.QUANT_PROJECT,
73
+ token: process.env.QUANT_TOKEN,
74
+ endpoint: 'https://api.quantcdn.io/v1'
75
+ };
76
+ this.headers = {
77
+ 'User-Agent': 'Quant (+http://api.quantcdn.io)',
78
+ 'Quant-Token': this.config.token,
79
+ 'Quant-Customer': this.config.clientid,
80
+ 'Quant-Project': this.config.project,
81
+ 'Content-Type': 'application/json',
82
+ };
83
+ },
84
+ /**
85
+ * Ping the quant API.
86
+ *
87
+ * @return {object}
88
+ * The response object.
89
+ *
90
+ * @throws Error.
91
+ */
92
+ ping: function () {
93
+ return __awaiter(this, void 0, void 0, function* () {
94
+ try {
95
+ this.init();
96
+ const options = {
97
+ url: `${this.config.endpoint}/ping`,
98
+ json: true,
99
+ headers,
100
+ };
101
+ const res = yield get(options);
102
+ return handleResponse(res);
103
+ }
104
+ catch (err) {
105
+ console.error(err);
106
+ }
107
+ });
108
+ },
109
+ /**
110
+ * Access the global meta for the project.
111
+ *
112
+ * @param {bool} unfold
113
+ * Unfold the record set.
114
+ * @param {bool} exclude
115
+ * Exclude delete objects from the meta result.
116
+ * @param {object} extend
117
+ * Additional query parameters to send.
118
+ *
119
+ * @return {object}
120
+ * The global meta response object.
121
+ *
122
+ * @throws Error.
123
+ *
124
+ * @TODO
125
+ * - Async iterator for memory 21k items ~ 40mb.
126
+ */
127
+ meta: function (unfold = false, exclude = true, extend = {}) {
128
+ return __awaiter(this, void 0, void 0, function* () {
129
+ try {
130
+ this.init();
131
+ const records = [];
132
+ const query = Object.assign({
133
+ page_size: 500,
134
+ published: true,
135
+ deleted: false,
136
+ sort_field: 'last_modified',
137
+ sort_direction: 'desc',
138
+ }, extend);
139
+ const url = `${this.config.endpoint}/global-meta?${querystring.stringify(query)}`;
140
+ const doUnfold = function (i) {
141
+ return __awaiter(this, void 0, void 0, function* () {
142
+ const res = yield get({
143
+ url: `${url}&page=${i}`,
144
+ json: true,
145
+ headers,
146
+ });
147
+ if (res.body.global_meta && res.body.global_meta.records) {
148
+ res.body.global_meta.records.map((item) => records.push({ url: item.meta.url, md5: item.meta.md5 }));
149
+ }
150
+ });
151
+ };
152
+ let page = 1;
153
+ const options = {
154
+ url: `${url}&page=${page}`,
155
+ json: true,
156
+ headers,
157
+ };
158
+ // Seed the record set.
159
+ const res = yield get(options);
160
+ if (!res.body.global_meta) {
161
+ // If no records have been published then global_meta is not
162
+ // present in the response.
163
+ return;
164
+ }
165
+ if (res.body.global_meta.records) {
166
+ res.body.global_meta.records.map((item) => records.push({ url: item.meta.url, md5: item.meta.md5 }));
167
+ }
168
+ if (unfold) {
169
+ page++;
170
+ while (res.body.global_meta.total_pages >= page) {
171
+ yield doUnfold(page);
172
+ page++;
173
+ }
174
+ }
175
+ return {
176
+ total_pages: res.body.global_meta.total_pages,
177
+ total_records: res.body.global_meta.total_records,
178
+ records,
179
+ };
180
+ }
181
+ catch (err) {
182
+ console.error(err);
183
+ }
184
+ });
185
+ },
186
+ /**
187
+ * Send a file to the server.
188
+ *
189
+ * @param {string} file
190
+ * The path to the file.
191
+ * @param {string} location
192
+ * The path the location.
193
+ * @param {bool} published
194
+ * The status.
195
+ * @param {bool} attachments
196
+ * Should quant find attachments.
197
+ * @param {bool} skipPurge
198
+ * Skip CDN cache purge.
199
+ * @param {bool} includeIndex
200
+ * Include index.html suffix on HTML assets.
201
+ * @param {object} extraHeaders
202
+ * Additional HTTP headers.
203
+ * @param {string} encoding
204
+ * The encoding type.
205
+ *
206
+ * @return {object}
207
+ * The API response.
208
+ */
209
+ send: function (file, location, published = true, attachments = false, skipPurge = false, includeIndex = false, extraHeaders = {}, encoding = 'utf-8') {
210
+ return __awaiter(this, void 0, void 0, function* () {
211
+ try {
212
+ this.init();
213
+ const mimeType = mime.lookup(file);
214
+ if (mimeType == 'text/html') {
215
+ if (!location) {
216
+ const p = path.resolve(process.cwd(), this.config.dir);
217
+ // If a location isn't given, calculate it.
218
+ location = path.relative(p, file);
219
+ }
220
+ location = quant_url_1.QuantURL.prepare(location);
221
+ if (!location.endsWith('.html') && includeIndex) {
222
+ location = `${location}/index.html`;
223
+ location = location.replace(/^\/\//, '/');
224
+ }
225
+ return yield this.markup(file, location, published, attachments, extraHeaders, encoding, skipPurge);
226
+ }
227
+ else {
228
+ return yield this.file(file, location, false, extraHeaders, skipPurge);
229
+ }
230
+ }
231
+ catch (err) {
232
+ console.error(err);
233
+ }
234
+ });
235
+ },
236
+ /**
237
+ * Upload markup.
238
+ *
239
+ * @param {string} file
240
+ * Filepath on disk.
241
+ * @param {string} location
242
+ * The web accessible destination.
243
+ * @param {bool} published
244
+ * The status.
245
+ * @param {bool} attachments
246
+ * Quant looking for attachments.
247
+ * @param {object} extraHeaders
248
+ * Additional HTTP headers.
249
+ * @param {string} encoding
250
+ * The encoding type.
251
+ * @param {bool} skipPurge
252
+ * Skip CDN cache purge.
253
+ *
254
+ * @return {object}
255
+ * The API response.
256
+ */
257
+ markup: function (file, location, published = true, attachments = false, extraHeaders = {}, encoding = 'utf-8', skipPurge = false) {
258
+ return __awaiter(this, void 0, void 0, function* () {
259
+ try {
260
+ this.init();
261
+ if (!Buffer.isBuffer(file)) {
262
+ if (!location) {
263
+ const p = path.resolve(process.cwd(), this.config.dir);
264
+ // If a location isn't given, calculate it.
265
+ location = path.relative(p, file);
266
+ }
267
+ file = fs.readFileSync(file, [encoding]);
268
+ }
269
+ const content = file.toString('utf8');
270
+ location = location.startsWith('/') ? location : `/${location}`;
271
+ if (skipPurge) {
272
+ headers['Quant-Skip-Purge'] = 'true';
273
+ }
274
+ const options = {
275
+ url: `${this.config.endpoint}`,
276
+ json: true,
277
+ body: {
278
+ url: location,
279
+ find_attachments: attachments,
280
+ content,
281
+ published,
282
+ },
283
+ headers: Object.assign({}, headers),
284
+ };
285
+ // if (Object.entries(extraHeaders).length > 0) {
286
+ // options.body.headers = extraHeaders;
287
+ // }
288
+ const res = yield post(options);
289
+ return handleResponse(res);
290
+ }
291
+ catch (err) {
292
+ console.error(err);
293
+ }
294
+ });
295
+ },
296
+ /**
297
+ * Send a file to the Quant API.
298
+ *
299
+ * @param {string} local
300
+ * File path on disk.
301
+ * @param {string} location
302
+ * Accessible location.
303
+ * @param {bool} absolute
304
+ * If the location is an absolute path.
305
+ * @param {object} extraHeaders
306
+ * Additional HTTP headers.
307
+ * @param {bool} skipPurge
308
+ * Skip CDN cache purge.
309
+ *
310
+ * @return {object}
311
+ * The successful payload.
312
+ *
313
+ * @throws Error
314
+ */
315
+ file: function (local, location, absolute = false, extraHeaders = {}, skipPurge = false) {
316
+ return __awaiter(this, void 0, void 0, function* () {
317
+ try {
318
+ this.init();
319
+ if (!Buffer.isBuffer(local)) {
320
+ if (!location) {
321
+ const p = path.resolve(process.cwd(), this.config.dir);
322
+ // If a location isn't given, calculate it.
323
+ location = path.relative(p, local);
324
+ location.replace(path.basename(location), '');
325
+ }
326
+ if (!fs.existsSync(local)) {
327
+ throw new Error('File is not accessible.');
328
+ }
329
+ local = fs.createReadStream(local);
330
+ }
331
+ const formData = {
332
+ data: local,
333
+ };
334
+ location = location.startsWith('/') ? location : `/${location}`;
335
+ if (skipPurge) {
336
+ headers['Quant-Skip-Purge'] = 'true';
337
+ }
338
+ const options = {
339
+ url: this.config.endpoint,
340
+ json: true,
341
+ headers: Object.assign(Object.assign({}, headers), { 'Content-Type': 'multipart/form-data', 'Quant-File-Url': location }),
342
+ formData,
343
+ };
344
+ if (Object.entries(extraHeaders).length > 0) {
345
+ options.headers['Quant-File-Headers'] = JSON.stringify(extraHeaders);
346
+ }
347
+ const res = yield post(options);
348
+ return handleResponse(res);
349
+ }
350
+ catch (err) {
351
+ console.error(err);
352
+ }
353
+ });
354
+ },
355
+ /**
356
+ * Change the status of an asset.
357
+ *
358
+ * @param {string} location
359
+ * The URL location of the content.
360
+ * @param {string} revision
361
+ * The revision to publish.
362
+ *
363
+ * @return {object}
364
+ * API payload.
365
+ *
366
+ * @throws Error.
367
+ */
368
+ publish: function (location, revision) {
369
+ return __awaiter(this, void 0, void 0, function* () {
370
+ try {
371
+ this.init();
372
+ const url = quant_url_1.QuantURL.prepare(location);
373
+ if (!revision) {
374
+ throw Error('Invalid revision ID provided.');
375
+ }
376
+ const options = {
377
+ url: `${this.config.endpoint}/publish/${revision}`,
378
+ headers: Object.assign(Object.assign({}, headers), { 'Quant-Url': url }),
379
+ json: true,
380
+ };
381
+ const res = yield patch(options);
382
+ return handleResponse(res);
383
+ }
384
+ catch (err) {
385
+ console.error(err);
386
+ }
387
+ });
388
+ },
389
+ /**
390
+ * Unpublish a URL.
391
+ *
392
+ * @param {string} url
393
+ * The URL to unpublish.
394
+ *
395
+ * @return {object}
396
+ *
397
+ * @throws Error.
398
+ */
399
+ unpublish: function (url) {
400
+ return __awaiter(this, void 0, void 0, function* () {
401
+ try {
402
+ this.init();
403
+ url = quant_url_1.QuantURL.prepare(url);
404
+ const options = {
405
+ url: `${this.config.endpoint}/unpublish`,
406
+ headers: Object.assign(Object.assign({}, headers), { 'Quant-Url': url }),
407
+ json: true,
408
+ };
409
+ const res = yield patch(options);
410
+ return handleResponse(res);
411
+ }
412
+ catch (err) {
413
+ console.error(err);
414
+ }
415
+ });
416
+ },
417
+ /**
418
+ *
419
+ * @param {string} from
420
+ * The URL to redirect form.
421
+ * @param {string} to
422
+ * The URL to redirect to.
423
+ * @param {string} author
424
+ * (Optional) Author.
425
+ * @param {int} status
426
+ * HTTP status code.
427
+ *
428
+ * @return {object}
429
+ * API payload.
430
+ *
431
+ * @throws Error.
432
+ */
433
+ redirect: function (from, to, author, status = 302) {
434
+ return __awaiter(this, void 0, void 0, function* () {
435
+ try {
436
+ this.init();
437
+ const options = {
438
+ url: `${this.config.endpoint}/redirect`,
439
+ headers: Object.assign({}, headers),
440
+ json: true,
441
+ body: {
442
+ url: from,
443
+ redirect_url: to,
444
+ redirect_http_code: status,
445
+ published: true,
446
+ },
447
+ };
448
+ if (status < 300 || status > 400) {
449
+ throw new Error('A valid redirect status code is required');
450
+ }
451
+ // if (author) {
452
+ // options.body.info = {author_user: author};
453
+ // }
454
+ const res = yield post(options);
455
+ return handleResponse(res);
456
+ }
457
+ catch (err) {
458
+ console.error(err);
459
+ }
460
+ });
461
+ },
462
+ /**
463
+ * Create a proxy with the Quant API.
464
+ *
465
+ * @param {string} url
466
+ * The relative URL to proxy.
467
+ * @param {string} destination
468
+ * The absolute FQDN/path to proxy to.
469
+ * @param {bool} published
470
+ * If the proxy is published
471
+ * @param {string} username
472
+ * Basic auth user.
473
+ * @param {string} password
474
+ * Basic auth password.
475
+ *
476
+ * @return {object}
477
+ * The response.
478
+ *
479
+ * @throws Error.
480
+ */
481
+ proxy: function (url, destination, published = true, username, password) {
482
+ return __awaiter(this, void 0, void 0, function* () {
483
+ try {
484
+ this.init();
485
+ const options = {
486
+ url: `${this.config.endpoint}/proxy`,
487
+ headers: Object.assign({}, headers),
488
+ json: true,
489
+ body: {
490
+ url,
491
+ destination,
492
+ published,
493
+ },
494
+ };
495
+ // if (username) {
496
+ // options.body.basic_auth_user = username;
497
+ // options.body.basic_auth_pass = password;
498
+ // }
499
+ const res = yield post(options);
500
+ return handleResponse(res);
501
+ }
502
+ catch (err) {
503
+ console.error(err);
504
+ }
505
+ });
506
+ },
507
+ /**
508
+ * Delete a path from Quant.
509
+ *
510
+ * @param {string} path
511
+ *
512
+ * @return {object}
513
+ * The response object.
514
+ *
515
+ * @throw Error.
516
+ */
517
+ delete: function (path) {
518
+ return __awaiter(this, void 0, void 0, function* () {
519
+ try {
520
+ this.init();
521
+ path = path.replace('index.html', '');
522
+ const options = {
523
+ url: `${this.config.endpoint}/delete/all`,
524
+ headers: Object.assign(Object.assign({}, headers), { 'Quant-Url': path }),
525
+ };
526
+ const res = yield del(options);
527
+ return handleResponse(res);
528
+ }
529
+ catch (err) {
530
+ console.error(err);
531
+ }
532
+ });
533
+ },
534
+ /**
535
+ * Get the revision history from Quant.
536
+ *
537
+ * @param {string} url
538
+ * The URL path to get revisions for.
539
+ * @param {string|bool} revision
540
+ * Retrieve a specific revision.
541
+ *
542
+ * @return {object}
543
+ * The response.
544
+ *
545
+ * @throws Error.
546
+ */
547
+ revisions: function (url, revision = false) {
548
+ return __awaiter(this, void 0, void 0, function* () {
549
+ try {
550
+ this.init();
551
+ const path = revision ? revision : 'published';
552
+ url = url.indexOf('/') == 0 ? url : `/${url}`;
553
+ url = url.toLowerCase();
554
+ url = url.replace(/\/?index\.html/, '');
555
+ const options = {
556
+ url: `${this.config.endpoint}/revisions/${path}`,
557
+ headers: Object.assign(Object.assign({}, headers), { 'Quant-Url': url }),
558
+ json: true,
559
+ };
560
+ const res = yield get(options);
561
+ return handleResponse(res);
562
+ }
563
+ catch (err) {
564
+ console.error(err);
565
+ }
566
+ });
567
+ },
568
+ /**
569
+ * Purge URL patterns from Quants Varnish.
570
+ *
571
+ * @param {string} urlPattern
572
+ *
573
+ * @throws Error
574
+ */
575
+ purge: function (urlPattern) {
576
+ return __awaiter(this, void 0, void 0, function* () {
577
+ try {
578
+ this.init();
579
+ const options = {
580
+ url: `${this.config.endpoint}/purge`,
581
+ headers: Object.assign(Object.assign({}, this.headers), { 'Quant-Url': urlPattern }),
582
+ };
583
+ const res = yield post(options);
584
+ return handleResponse(res);
585
+ }
586
+ catch (err) {
587
+ console.error(err);
588
+ }
589
+ });
590
+ },
591
+ /**
592
+ * Add/update items in search index.
593
+ *
594
+ * @param {string} filePath
595
+ *
596
+ * @throws Error
597
+ */
598
+ searchIndex: function (filePath) {
599
+ return __awaiter(this, void 0, void 0, function* () {
600
+ try {
601
+ this.init();
602
+ let data = '';
603
+ // filePath is a JSON file we send the raw content of.
604
+ try {
605
+ data = JSON.parse(fs.readFileSync(filePath, 'utf8'));
606
+ }
607
+ catch (err) {
608
+ console.error(err);
609
+ return;
610
+ }
611
+ const options = {
612
+ url: `${this.config.endpoint}/search`,
613
+ headers: Object.assign({}, this.headers),
614
+ json: true,
615
+ body: data,
616
+ };
617
+ const res = yield post(options);
618
+ return handleResponse(res);
619
+ }
620
+ catch (err) {
621
+ console.error(err);
622
+ }
623
+ });
624
+ },
625
+ /**
626
+ * Remove item from search index.
627
+ *
628
+ * @param {string} url
629
+ *
630
+ * @throws Error
631
+ */
632
+ searchRemove: function (url) {
633
+ return __awaiter(this, void 0, void 0, function* () {
634
+ try {
635
+ this.init();
636
+ const options = {
637
+ url: `${this.config.endpoint}/search`,
638
+ headers: Object.assign(Object.assign({}, this.headers), { 'Quant-Url': url }),
639
+ json: true,
640
+ };
641
+ const res = yield del(options);
642
+ return handleResponse(res);
643
+ }
644
+ catch (err) {
645
+ console.error(err);
646
+ }
647
+ });
648
+ },
649
+ /**
650
+ * Clear search index.
651
+ *
652
+ * @throws Error
653
+ */
654
+ searchClearIndex: function () {
655
+ return __awaiter(this, void 0, void 0, function* () {
656
+ try {
657
+ this.init();
658
+ const options = {
659
+ url: `${this.config.endpoint}/search/all`,
660
+ headers: Object.assign({}, this.headers),
661
+ json: true,
662
+ };
663
+ const res = yield del(options);
664
+ return handleResponse(res);
665
+ }
666
+ catch (err) {
667
+ console.error(err);
668
+ }
669
+ });
670
+ },
671
+ /**
672
+ * Retrieve search index status.
673
+ *
674
+ * @throws Error
675
+ */
676
+ searchStatus: function () {
677
+ return __awaiter(this, void 0, void 0, function* () {
678
+ try {
679
+ this.init();
680
+ const options = {
681
+ url: `${this.config.endpoint}/search`,
682
+ headers: Object.assign({}, this.headers),
683
+ json: true,
684
+ };
685
+ const res = yield get(options);
686
+ return handleResponse(res);
687
+ }
688
+ catch (err) {
689
+ console.error(err);
690
+ }
691
+ });
692
+ },
693
+ };
694
+ }
695
+ exports.QuantClient = QuantClient;
696
+ ;
package/package.json ADDED
@@ -0,0 +1,30 @@
1
+ {
2
+ "name": "@quantcdn/quant-client",
3
+ "version": "1.0.0",
4
+ "description": "Client library for API connectivity",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "files": [
8
+ "/dist"
9
+ ],
10
+ "scripts": {
11
+ "test": "echo \"Error: no test specified\" && exit 1"
12
+ },
13
+ "repository": {
14
+ "type": "git",
15
+ "url": "git+https://github.com/quantcdn/quant-client.git"
16
+ },
17
+ "author": "Stuart Rowlands <stuart.rowlands@quantcdn.io>",
18
+ "license": "ISC",
19
+ "bugs": {
20
+ "url": "https://github.com/quantcdn/quant-client/issues"
21
+ },
22
+ "homepage": "https://github.com/quantcdn/quant-client#readme",
23
+ "dependencies": {
24
+ "mime-types": "^2.1.27",
25
+ "request": "^2.88.2"
26
+ },
27
+ "devDependencies": {
28
+ "@types/node": "^18.16.3"
29
+ }
30
+ }