@vtex/api 1.9.3 → 1.9.4
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/CHANGELOG.md +2 -0
- package/lib/Apps.d.ts +66 -0
- package/lib/Apps.js +211 -0
- package/lib/Billing.d.ts +18 -0
- package/lib/Billing.js +27 -0
- package/lib/Builder.d.ts +40 -0
- package/lib/Builder.js +80 -0
- package/lib/Events.d.ts +6 -0
- package/lib/Events.js +19 -0
- package/lib/HttpClient/context.d.ts +9 -0
- package/lib/HttpClient/context.js +2 -0
- package/lib/HttpClient/index.d.ts +92 -0
- package/lib/HttpClient/index.js +121 -0
- package/lib/HttpClient/middlewares/cache.d.ts +16 -0
- package/lib/HttpClient/middlewares/cache.js +85 -0
- package/lib/HttpClient/middlewares/metrics.d.ts +3 -0
- package/lib/HttpClient/middlewares/metrics.js +41 -0
- package/lib/HttpClient/middlewares/notFound.d.ts +7 -0
- package/lib/HttpClient/middlewares/notFound.js +28 -0
- package/lib/HttpClient/middlewares/recorder.d.ts +3 -0
- package/lib/HttpClient/middlewares/recorder.js +26 -0
- package/lib/HttpClient/middlewares/request.d.ts +3 -0
- package/lib/HttpClient/middlewares/request.js +39 -0
- package/lib/ID.d.ts +23 -0
- package/lib/ID.js +46 -0
- package/lib/IODataSource.d.ts +23 -0
- package/lib/IODataSource.js +43 -0
- package/lib/Logger.d.ts +20 -0
- package/lib/Logger.js +62 -0
- package/lib/Metadata.d.ts +27 -0
- package/lib/Metadata.js +53 -0
- package/lib/Registry.d.ts +52 -0
- package/lib/Registry.js +112 -0
- package/lib/Router.d.ts +35 -0
- package/lib/Router.js +52 -0
- package/lib/VBase.d.ts +40 -0
- package/lib/VBase.js +82 -0
- package/lib/Workspaces.d.ts +17 -0
- package/lib/Workspaces.js +39 -0
- package/lib/caches/CacheLayer.d.ts +7 -0
- package/lib/caches/CacheLayer.js +2 -0
- package/lib/caches/DiskCache.d.ts +17 -0
- package/lib/caches/DiskCache.js +75 -0
- package/lib/caches/LRUCache.d.ts +16 -0
- package/lib/caches/LRUCache.js +49 -0
- package/lib/caches/LRUDiskCache.d.ts +21 -0
- package/lib/caches/LRUDiskCache.js +132 -0
- package/lib/caches/MultilayeredCache.d.ts +14 -0
- package/lib/caches/MultilayeredCache.js +76 -0
- package/lib/caches/index.d.ts +6 -0
- package/lib/caches/index.js +9 -0
- package/lib/caches/typings.d.ts +48 -0
- package/lib/caches/typings.js +2 -0
- package/lib/constants.d.ts +1 -0
- package/lib/constants.js +3 -0
- package/lib/index.d.ts +19 -0
- package/lib/index.js +21 -0
- package/lib/metrics/metricsAccumulator.d.ts +27 -0
- package/lib/metrics/metricsAccumulator.js +80 -0
- package/lib/metrics/metricsLogger.d.ts +6 -0
- package/lib/metrics/metricsLogger.js +2 -0
- package/lib/responses.d.ts +95 -0
- package/lib/responses.js +2 -0
- package/lib/runtime.d.ts +27 -0
- package/lib/runtime.js +2 -0
- package/lib/utils/AppId.d.ts +19 -0
- package/lib/utils/AppId.js +42 -0
- package/lib/utils/Time.d.ts +4 -0
- package/lib/utils/Time.js +7 -0
- package/lib/utils/index.d.ts +2 -0
- package/lib/utils/index.js +7 -0
- package/lib/utils/json.d.ts +5 -0
- package/lib/utils/json.js +18 -0
- package/lib/utils/log.d.ts +3 -0
- package/lib/utils/log.js +20 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
package/lib/Apps.d.ts
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { IncomingMessage } from 'http';
|
|
3
|
+
import { Readable, Writable } from 'stream';
|
|
4
|
+
import { ZlibOptions } from 'zlib';
|
|
5
|
+
import { IODataSource } from './IODataSource';
|
|
6
|
+
import { AppBundleLinked, AppFilesList, AppManifest } from './responses';
|
|
7
|
+
export declare class Apps extends IODataSource {
|
|
8
|
+
protected httpClientFactory: import("./IODataSource").HttpClientFactory;
|
|
9
|
+
protected service: string;
|
|
10
|
+
installApp: (descriptor: string) => Promise<void>;
|
|
11
|
+
uninstallApp: (app: string) => Promise<import("./HttpClient").IOResponse<void>>;
|
|
12
|
+
acknowledgeApp: (app: string, service: string) => Promise<void>;
|
|
13
|
+
link: (app: string, files: Change[], { zlib }?: ZipOptions) => Promise<AppBundleLinked>;
|
|
14
|
+
patch: (app: string, changes: Change[], { zlib }?: ZipOptions) => Promise<void>;
|
|
15
|
+
unlink: (app: string) => Promise<import("./HttpClient").IOResponse<void>>;
|
|
16
|
+
unlinkAll: () => Promise<import("./HttpClient").IOResponse<void>>;
|
|
17
|
+
saveAppSettings: (app: string, settings: any) => Promise<void>;
|
|
18
|
+
listApps: ({ oldVersion, context, since, service }?: ListAppsOptions) => Promise<AppsList>;
|
|
19
|
+
listAppFiles: (app: string, { prefix, context, nextMarker }?: ListFilesOptions) => Promise<AppFilesList>;
|
|
20
|
+
listLinks: () => Promise<string[]>;
|
|
21
|
+
getAppFile: (app: string, path: string, context?: string[]) => Promise<{
|
|
22
|
+
data: Buffer;
|
|
23
|
+
headers: any;
|
|
24
|
+
}>;
|
|
25
|
+
getAppFileStream: (app: string, path: string, context?: string[]) => Promise<IncomingMessage>;
|
|
26
|
+
getApp: (app: string, context?: string[]) => Promise<AppManifest>;
|
|
27
|
+
getAppSettings: (app: string) => Promise<any>;
|
|
28
|
+
getAllAppsSettings: (listAppsOptions?: ListAppsOptions) => Promise<AppsSettings>;
|
|
29
|
+
getAppBundle: (app: string, bundlePath: string, generatePackageJson: boolean) => Promise<Readable>;
|
|
30
|
+
unpackAppBundle: (app: string, bundlePath: string, unpackPath: string, generatePackageJson: boolean) => Promise<Writable>;
|
|
31
|
+
getDependencies: (filter?: string) => Promise<Record<string, string[]>>;
|
|
32
|
+
updateDependencies: () => Promise<Record<string, string[]>>;
|
|
33
|
+
updateDependency: (name: string, version: string, registry: string) => Promise<void>;
|
|
34
|
+
resolveDependencies: (apps: string[], registries: string[], filter?: string) => Promise<any>;
|
|
35
|
+
resolveDependenciesWithManifest: (manifest: AppManifest, filter?: string) => Promise<Record<string, string[]>>;
|
|
36
|
+
}
|
|
37
|
+
interface ZipOptions {
|
|
38
|
+
zlib?: ZlibOptions;
|
|
39
|
+
}
|
|
40
|
+
export interface AppsListItem {
|
|
41
|
+
app: string;
|
|
42
|
+
id: string;
|
|
43
|
+
location: string;
|
|
44
|
+
}
|
|
45
|
+
export interface AppsList {
|
|
46
|
+
data: AppsListItem[];
|
|
47
|
+
}
|
|
48
|
+
export interface Change {
|
|
49
|
+
path: string;
|
|
50
|
+
content: string | Readable | Buffer;
|
|
51
|
+
}
|
|
52
|
+
export interface ListAppsOptions {
|
|
53
|
+
oldVersion?: string;
|
|
54
|
+
context?: string[];
|
|
55
|
+
since?: string;
|
|
56
|
+
service?: string;
|
|
57
|
+
}
|
|
58
|
+
export interface ListFilesOptions {
|
|
59
|
+
prefix?: string;
|
|
60
|
+
context?: string[];
|
|
61
|
+
nextMarker?: string;
|
|
62
|
+
}
|
|
63
|
+
export interface AppsSettings {
|
|
64
|
+
[app: string]: any;
|
|
65
|
+
}
|
|
66
|
+
export {};
|
package/lib/Apps.js
ADDED
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
const archiver = require("archiver");
|
|
12
|
+
const qs_1 = require("qs");
|
|
13
|
+
const tar_fs_1 = require("tar-fs");
|
|
14
|
+
const zlib_1 = require("zlib");
|
|
15
|
+
const IODataSource_1 = require("./IODataSource");
|
|
16
|
+
const routes = {
|
|
17
|
+
Acknowledge: (app, service) => `${routes.App(app)}/acknowledge/${service}`,
|
|
18
|
+
App: (app) => `${routes.Apps}/${app}`,
|
|
19
|
+
AppBundle: (app, path) => `${routes.App(app)}/bundle/${path}`,
|
|
20
|
+
Apps: '/apps',
|
|
21
|
+
Dependencies: '/dependencies',
|
|
22
|
+
File: (app, path) => `${routes.Files(app)}/${path}`,
|
|
23
|
+
Files: (app) => `${routes.App(app)}/files`,
|
|
24
|
+
Link: (app) => `/v2/links/${app}`,
|
|
25
|
+
Links: '/links',
|
|
26
|
+
ResolveDependencies: 'dependencies/_resolve',
|
|
27
|
+
ResolveDependenciesWithManifest: '/v2/apps/_resolve',
|
|
28
|
+
Settings: (app) => `${routes.App(app)}/settings`,
|
|
29
|
+
Unlink: (app) => `${routes.Links}/${app}`,
|
|
30
|
+
};
|
|
31
|
+
const contextQuery = (context) => context ? context.join('/') : context;
|
|
32
|
+
const getVendorAndName = ({ id }) => id.split('@')[0];
|
|
33
|
+
const notFound = (e) => {
|
|
34
|
+
if (e.response && e.response.status === 404) {
|
|
35
|
+
return {};
|
|
36
|
+
}
|
|
37
|
+
throw e;
|
|
38
|
+
};
|
|
39
|
+
const zipObj = (keys, values) => {
|
|
40
|
+
let idx = 0;
|
|
41
|
+
const len = Math.min(keys.length, values.length);
|
|
42
|
+
const out = {};
|
|
43
|
+
while (idx < len) {
|
|
44
|
+
out[keys[idx]] = values[idx];
|
|
45
|
+
idx += 1;
|
|
46
|
+
}
|
|
47
|
+
return out;
|
|
48
|
+
};
|
|
49
|
+
const paramsSerializer = (params) => {
|
|
50
|
+
return qs_1.stringify(params, { arrayFormat: 'repeat' });
|
|
51
|
+
};
|
|
52
|
+
class Apps extends IODataSource_1.IODataSource {
|
|
53
|
+
constructor() {
|
|
54
|
+
super(...arguments);
|
|
55
|
+
this.httpClientFactory = IODataSource_1.forWorkspace;
|
|
56
|
+
this.service = 'apps';
|
|
57
|
+
this.installApp = (descriptor) => {
|
|
58
|
+
return this.http.post(routes.Apps, { id: descriptor });
|
|
59
|
+
};
|
|
60
|
+
this.uninstallApp = (app) => {
|
|
61
|
+
return this.http.delete(routes.App(app));
|
|
62
|
+
};
|
|
63
|
+
this.acknowledgeApp = (app, service) => {
|
|
64
|
+
return this.http.put(routes.Acknowledge(app, service));
|
|
65
|
+
};
|
|
66
|
+
this.link = (app, files, { zlib } = {}) => __awaiter(this, void 0, void 0, function* () {
|
|
67
|
+
if (!(files[0] && files[0].path)) {
|
|
68
|
+
throw new Error('Argument files must be an array of {path, content}, where content can be a String, a Buffer or a ReadableStream.');
|
|
69
|
+
}
|
|
70
|
+
const emptyChanges = files.filter(file => !file.content);
|
|
71
|
+
if (emptyChanges.length > 0) {
|
|
72
|
+
throw new Error(`Missing content for paths: ${emptyChanges.map(e => e.path).join('; ')}`);
|
|
73
|
+
}
|
|
74
|
+
const indexOfManifest = files.findIndex(({ path }) => path === 'manifest.json');
|
|
75
|
+
if (indexOfManifest === -1) {
|
|
76
|
+
throw new Error('No manifest.json file found in files.');
|
|
77
|
+
}
|
|
78
|
+
const zip = archiver('zip', { zlib });
|
|
79
|
+
// Throw stream errors so they reject the promise chain.
|
|
80
|
+
zip.on('error', (e) => {
|
|
81
|
+
throw e;
|
|
82
|
+
});
|
|
83
|
+
const request = this.http.put(routes.Link(app), zip, {
|
|
84
|
+
headers: { 'Content-Type': 'application/zip' },
|
|
85
|
+
});
|
|
86
|
+
files.forEach(({ content, path }) => zip.append(content, { name: path }));
|
|
87
|
+
const finalize = zip.finalize();
|
|
88
|
+
try {
|
|
89
|
+
const [response] = yield Promise.all([request, finalize]);
|
|
90
|
+
response.bundleSize = zip.pointer();
|
|
91
|
+
return response;
|
|
92
|
+
}
|
|
93
|
+
catch (e) {
|
|
94
|
+
e.bundleSize = zip.pointer();
|
|
95
|
+
throw e;
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
this.patch = (app, changes, { zlib } = {}) => __awaiter(this, void 0, void 0, function* () {
|
|
99
|
+
if (!(changes[0] && changes[0].path)) {
|
|
100
|
+
throw new Error('Argument changes must be an array of {path, content}, where content can be a String, a Buffer or a ReadableStream.');
|
|
101
|
+
}
|
|
102
|
+
const files = changes.filter(change => !!change.content);
|
|
103
|
+
const deletedFiles = changes
|
|
104
|
+
.filter(change => !change.content)
|
|
105
|
+
.map(change => change.path)
|
|
106
|
+
.join(':');
|
|
107
|
+
const zip = archiver('zip', { zlib });
|
|
108
|
+
// Throw stream errors so they reject the promise chain.
|
|
109
|
+
zip.on('error', (e) => {
|
|
110
|
+
throw e;
|
|
111
|
+
});
|
|
112
|
+
const request = this.http.patch(routes.Link(app), zip, {
|
|
113
|
+
headers: { 'Content-Type': 'application/zip' },
|
|
114
|
+
params: { deletedFiles },
|
|
115
|
+
});
|
|
116
|
+
files.forEach(({ content, path }) => zip.append(content, { name: path }));
|
|
117
|
+
const finalize = zip.finalize();
|
|
118
|
+
const [response] = yield Promise.all([request, finalize]);
|
|
119
|
+
return response;
|
|
120
|
+
});
|
|
121
|
+
this.unlink = (app) => {
|
|
122
|
+
return this.http.delete(routes.Unlink(app));
|
|
123
|
+
};
|
|
124
|
+
this.unlinkAll = () => {
|
|
125
|
+
return this.http.delete(routes.Links);
|
|
126
|
+
};
|
|
127
|
+
this.saveAppSettings = (app, settings) => {
|
|
128
|
+
const headers = { 'Content-Type': 'application/json' };
|
|
129
|
+
return this.http.put(routes.Settings(app), settings, { headers });
|
|
130
|
+
};
|
|
131
|
+
this.listApps = ({ oldVersion, context, since, service } = {}) => {
|
|
132
|
+
const params = {
|
|
133
|
+
context: contextQuery(context),
|
|
134
|
+
oldVersion,
|
|
135
|
+
service,
|
|
136
|
+
since,
|
|
137
|
+
};
|
|
138
|
+
return this.http.get(routes.Apps, { params });
|
|
139
|
+
};
|
|
140
|
+
this.listAppFiles = (app, { prefix, context, nextMarker } = {}) => {
|
|
141
|
+
const params = {
|
|
142
|
+
context: contextQuery(context),
|
|
143
|
+
marker: nextMarker,
|
|
144
|
+
prefix,
|
|
145
|
+
};
|
|
146
|
+
return this.http.get(routes.Files(app), { params });
|
|
147
|
+
};
|
|
148
|
+
this.listLinks = () => {
|
|
149
|
+
return this.http.get(routes.Links);
|
|
150
|
+
};
|
|
151
|
+
this.getAppFile = (app, path, context = []) => {
|
|
152
|
+
const params = { context: contextQuery(context) };
|
|
153
|
+
return this.http.getBuffer(routes.File(app, path), { params });
|
|
154
|
+
};
|
|
155
|
+
this.getAppFileStream = (app, path, context = []) => {
|
|
156
|
+
const params = { context: contextQuery(context) };
|
|
157
|
+
return this.http.getStream(routes.File(app, path), { params });
|
|
158
|
+
};
|
|
159
|
+
this.getApp = (app, context = []) => {
|
|
160
|
+
const params = { context: contextQuery(context) };
|
|
161
|
+
return this.http.get(routes.App(app), { params });
|
|
162
|
+
};
|
|
163
|
+
this.getAppSettings = (app) => {
|
|
164
|
+
return this.http.get(routes.Settings(app));
|
|
165
|
+
};
|
|
166
|
+
this.getAllAppsSettings = (listAppsOptions = {}) => {
|
|
167
|
+
return this.listApps(listAppsOptions).then(({ data: installedApps }) => {
|
|
168
|
+
const names = installedApps.map(getVendorAndName);
|
|
169
|
+
const settingsPromises = names.map(vendorAndName => this.getAppSettings(vendorAndName).catch(notFound));
|
|
170
|
+
return Promise.all(settingsPromises).then((settings) => {
|
|
171
|
+
return zipObj(names, settings);
|
|
172
|
+
});
|
|
173
|
+
});
|
|
174
|
+
};
|
|
175
|
+
this.getAppBundle = (app, bundlePath, generatePackageJson) => {
|
|
176
|
+
const params = generatePackageJson && { _packageJSONEngine: 'npm', _packageJSONFilter: 'vtex.render-builder@x' };
|
|
177
|
+
return this.http.getStream(routes.AppBundle(app, bundlePath), {
|
|
178
|
+
headers: {
|
|
179
|
+
Accept: 'application/x-gzip',
|
|
180
|
+
'Accept-Encoding': 'gzip',
|
|
181
|
+
},
|
|
182
|
+
params,
|
|
183
|
+
});
|
|
184
|
+
};
|
|
185
|
+
this.unpackAppBundle = (app, bundlePath, unpackPath, generatePackageJson) => {
|
|
186
|
+
return this.getAppBundle(app, bundlePath, generatePackageJson)
|
|
187
|
+
.then(stream => stream
|
|
188
|
+
.pipe(zlib_1.createGunzip())
|
|
189
|
+
.pipe(tar_fs_1.extract(unpackPath)));
|
|
190
|
+
};
|
|
191
|
+
this.getDependencies = (filter = '') => {
|
|
192
|
+
const params = { filter };
|
|
193
|
+
return this.http.get(routes.Dependencies, { params });
|
|
194
|
+
};
|
|
195
|
+
this.updateDependencies = () => {
|
|
196
|
+
return this.http.put(routes.Dependencies);
|
|
197
|
+
};
|
|
198
|
+
this.updateDependency = (name, version, registry) => {
|
|
199
|
+
return this.http.patch(routes.Apps, [{ name, version, registry }]);
|
|
200
|
+
};
|
|
201
|
+
this.resolveDependencies = (apps, registries, filter = '') => {
|
|
202
|
+
const params = { apps, registries, filter };
|
|
203
|
+
return this.http.get(routes.ResolveDependencies, { params, paramsSerializer });
|
|
204
|
+
};
|
|
205
|
+
this.resolveDependenciesWithManifest = (manifest, filter = '') => {
|
|
206
|
+
const params = { filter };
|
|
207
|
+
return this.http.post(routes.ResolveDependenciesWithManifest, manifest, { params, paramsSerializer });
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
exports.Apps = Apps;
|
package/lib/Billing.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { IODataSource } from './IODataSource';
|
|
2
|
+
export declare class Billing extends IODataSource {
|
|
3
|
+
protected service: string;
|
|
4
|
+
protected httpClientFactory: import("./IODataSource").HttpClientFactory;
|
|
5
|
+
contractStatus: () => Promise<ContractStatus>;
|
|
6
|
+
sendMetric: (metric: BillingMetric) => Promise<void>;
|
|
7
|
+
}
|
|
8
|
+
export declare enum ContractStatus {
|
|
9
|
+
ACTIVE = "active_contract",
|
|
10
|
+
INACTIVE = "inactive_contract",
|
|
11
|
+
NO_CONTRACT = "no_contract"
|
|
12
|
+
}
|
|
13
|
+
export interface BillingMetric {
|
|
14
|
+
value: number;
|
|
15
|
+
unit: string;
|
|
16
|
+
metricId: string;
|
|
17
|
+
timestamp?: number;
|
|
18
|
+
}
|
package/lib/Billing.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const IODataSource_1 = require("./IODataSource");
|
|
4
|
+
const metricRoute = `/metrics`;
|
|
5
|
+
const routes = {
|
|
6
|
+
contractStatus: '/_v/contractStatus',
|
|
7
|
+
};
|
|
8
|
+
class Billing extends IODataSource_1.IODataSource {
|
|
9
|
+
constructor() {
|
|
10
|
+
super(...arguments);
|
|
11
|
+
this.service = 'billing.vtex';
|
|
12
|
+
this.httpClientFactory = IODataSource_1.forWorkspace;
|
|
13
|
+
this.contractStatus = () => {
|
|
14
|
+
return this.http.get(routes.contractStatus);
|
|
15
|
+
};
|
|
16
|
+
this.sendMetric = (metric) => {
|
|
17
|
+
return this.http.post(metricRoute, metric);
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
exports.Billing = Billing;
|
|
22
|
+
var ContractStatus;
|
|
23
|
+
(function (ContractStatus) {
|
|
24
|
+
ContractStatus["ACTIVE"] = "active_contract";
|
|
25
|
+
ContractStatus["INACTIVE"] = "inactive_contract";
|
|
26
|
+
ContractStatus["NO_CONTRACT"] = "no_contract";
|
|
27
|
+
})(ContractStatus = exports.ContractStatus || (exports.ContractStatus = {}));
|
package/lib/Builder.d.ts
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { ZlibOptions } from 'zlib';
|
|
3
|
+
import { Change } from './Apps';
|
|
4
|
+
import { InstanceOptions, IOContext } from './HttpClient';
|
|
5
|
+
import { File } from './Registry';
|
|
6
|
+
export declare class Builder {
|
|
7
|
+
private account;
|
|
8
|
+
private workspace;
|
|
9
|
+
private http;
|
|
10
|
+
private stickyHost;
|
|
11
|
+
constructor(ioContext: IOContext, opts?: InstanceOptions);
|
|
12
|
+
availability: (app: string, hintIndex: number) => Promise<{
|
|
13
|
+
host: any;
|
|
14
|
+
hostname: string | undefined;
|
|
15
|
+
score: number;
|
|
16
|
+
}>;
|
|
17
|
+
clean: (app: string) => Promise<BuildResult>;
|
|
18
|
+
linkApp: (app: string, files: File[], zipOptions?: ZipOptions) => Promise<BuildResult>;
|
|
19
|
+
publishApp: (app: string, files: File[], zipOptions?: ZipOptions) => Promise<BuildResult>;
|
|
20
|
+
relinkApp: (app: string, changes: Change[]) => Promise<BuildResult>;
|
|
21
|
+
private zipAndSend;
|
|
22
|
+
}
|
|
23
|
+
interface ZipOptions {
|
|
24
|
+
sticky?: boolean;
|
|
25
|
+
stickyHint?: string;
|
|
26
|
+
tag?: string;
|
|
27
|
+
zlib?: ZlibOptions;
|
|
28
|
+
}
|
|
29
|
+
export interface BuildResult {
|
|
30
|
+
availability?: AvailabilityResponse;
|
|
31
|
+
code?: string;
|
|
32
|
+
message?: any;
|
|
33
|
+
timeNano?: number;
|
|
34
|
+
}
|
|
35
|
+
export interface AvailabilityResponse {
|
|
36
|
+
host: string | undefined;
|
|
37
|
+
hostname: string | undefined;
|
|
38
|
+
score: number;
|
|
39
|
+
}
|
|
40
|
+
export {};
|
package/lib/Builder.js
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
const archiver = require("archiver");
|
|
12
|
+
const HttpClient_1 = require("./HttpClient");
|
|
13
|
+
const EMPTY_OBJECT = {};
|
|
14
|
+
const routes = {
|
|
15
|
+
Availability: (app) => `${routes.Builder}/availability/${app}`,
|
|
16
|
+
Builder: '/_v/builder/0',
|
|
17
|
+
Clean: (app) => `${routes.Builder}/clean/${app}`,
|
|
18
|
+
Link: (app) => `${routes.Builder}/link/${app}`,
|
|
19
|
+
Publish: (app) => `${routes.Builder}/publish/${app}`,
|
|
20
|
+
Relink: (app) => `${routes.Builder}/relink/${app}`,
|
|
21
|
+
};
|
|
22
|
+
class Builder {
|
|
23
|
+
constructor(ioContext, opts = {}) {
|
|
24
|
+
this.availability = (app, hintIndex) => __awaiter(this, void 0, void 0, function* () {
|
|
25
|
+
const stickyHint = hintIndex === undefined || hintIndex === null ?
|
|
26
|
+
`request:${this.account}:${this.workspace}:${app}` :
|
|
27
|
+
`request:${this.account}:${this.workspace}:${app}:${hintIndex}`;
|
|
28
|
+
const headers = {
|
|
29
|
+
'Content-Type': 'application/json',
|
|
30
|
+
'x-vtex-sticky-host': stickyHint,
|
|
31
|
+
};
|
|
32
|
+
const { data: { availability }, headers: { 'x-vtex-sticky-host': host }, } = yield this.http.getRaw(routes.Availability(app), { headers });
|
|
33
|
+
const { hostname, score } = availability;
|
|
34
|
+
return { host, hostname, score };
|
|
35
|
+
});
|
|
36
|
+
this.clean = (app) => {
|
|
37
|
+
const headers = Object.assign({ 'Content-Type': 'application/json' }, this.stickyHost && { 'x-vtex-sticky-host': this.stickyHost });
|
|
38
|
+
return this.http.post(routes.Clean(app), { headers });
|
|
39
|
+
};
|
|
40
|
+
this.linkApp = (app, files, zipOptions = { sticky: true }) => {
|
|
41
|
+
return this.zipAndSend(routes.Link(app), app, files, zipOptions);
|
|
42
|
+
};
|
|
43
|
+
this.publishApp = (app, files, zipOptions = { sticky: true }) => {
|
|
44
|
+
return this.zipAndSend(routes.Publish(app), app, files, zipOptions);
|
|
45
|
+
};
|
|
46
|
+
this.relinkApp = (app, changes) => {
|
|
47
|
+
const headers = Object.assign({ 'Content-Type': 'application/json' }, this.stickyHost && { 'x-vtex-sticky-host': this.stickyHost });
|
|
48
|
+
return this.http.put(routes.Relink(app), changes, { headers });
|
|
49
|
+
};
|
|
50
|
+
this.zipAndSend = (route, app, files, { tag, sticky, stickyHint, zlib } = {}) => __awaiter(this, void 0, void 0, function* () {
|
|
51
|
+
if (!(files[0] && files[0].path && files[0].content)) {
|
|
52
|
+
throw new Error('Argument files must be an array of {path, content}, where content can be a String, a Buffer or a ReadableStream.');
|
|
53
|
+
}
|
|
54
|
+
const indexOfManifest = files.findIndex(({ path }) => path === 'manifest.json');
|
|
55
|
+
if (indexOfManifest === -1) {
|
|
56
|
+
throw new Error('No manifest.json file found in files.');
|
|
57
|
+
}
|
|
58
|
+
const zip = archiver('zip', { zlib });
|
|
59
|
+
// Throw stream errors so they reject the promise chain.
|
|
60
|
+
zip.on('error', (e) => {
|
|
61
|
+
throw e;
|
|
62
|
+
});
|
|
63
|
+
const hint = stickyHint || `request:${this.account}:${this.workspace}:${app}`;
|
|
64
|
+
const request = this.http.postRaw(route, zip, {
|
|
65
|
+
headers: Object.assign({ 'Content-Type': 'application/octet-stream' }, sticky && { 'x-vtex-sticky-host': this.stickyHost || hint }),
|
|
66
|
+
params: tag ? { tag } : EMPTY_OBJECT,
|
|
67
|
+
});
|
|
68
|
+
files.forEach(({ content, path }) => zip.append(content, { name: path }));
|
|
69
|
+
const finalize = zip.finalize();
|
|
70
|
+
const [response] = yield Promise.all([request, finalize]);
|
|
71
|
+
const { data, headers: { 'x-vtex-sticky-host': host } } = response;
|
|
72
|
+
this.stickyHost = host;
|
|
73
|
+
return data;
|
|
74
|
+
});
|
|
75
|
+
this.http = HttpClient_1.HttpClient.forWorkspace('builder-hub.vtex', ioContext, opts);
|
|
76
|
+
this.account = ioContext.account;
|
|
77
|
+
this.workspace = ioContext.workspace;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
exports.Builder = Builder;
|
package/lib/Events.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { HttpClientFactory, IODataSource } from './IODataSource';
|
|
2
|
+
export declare class Events extends IODataSource {
|
|
3
|
+
protected service: string;
|
|
4
|
+
protected httpClientFactory: HttpClientFactory;
|
|
5
|
+
sendEvent: (subject: string, route: string, message?: any) => Promise<void>;
|
|
6
|
+
}
|
package/lib/Events.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const HttpClient_1 = require("./HttpClient");
|
|
4
|
+
const IODataSource_1 = require("./IODataSource");
|
|
5
|
+
const eventRoute = (route) => `/events/${route}`;
|
|
6
|
+
const forWorkspaceWithoutRecorder = ({ service, context, options }) => (service && context)
|
|
7
|
+
? HttpClient_1.HttpClient.forWorkspace(service, HttpClient_1.withoutRecorder(context), options || {})
|
|
8
|
+
: undefined;
|
|
9
|
+
class Events extends IODataSource_1.IODataSource {
|
|
10
|
+
constructor() {
|
|
11
|
+
super(...arguments);
|
|
12
|
+
this.service = 'colossus';
|
|
13
|
+
this.httpClientFactory = forWorkspaceWithoutRecorder;
|
|
14
|
+
this.sendEvent = (subject, route, message) => {
|
|
15
|
+
return this.http.put(eventRoute(route), message, { params: { subject } });
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
exports.Events = Events;
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { DataSource } from 'apollo-datasource';
|
|
3
|
+
import { IncomingMessage } from 'http';
|
|
4
|
+
import { Context } from 'koa';
|
|
5
|
+
import { ParsedUrlQuery } from 'querystring';
|
|
6
|
+
import { CacheLayer } from '../caches/CacheLayer';
|
|
7
|
+
import { MetricsAccumulator } from '../metrics/metricsAccumulator';
|
|
8
|
+
import { MetricsLogger } from '../metrics/metricsLogger';
|
|
9
|
+
import { RequestConfig } from './context';
|
|
10
|
+
import { Cached } from './middlewares/cache';
|
|
11
|
+
import { Recorder } from './middlewares/recorder';
|
|
12
|
+
export declare class HttpClient {
|
|
13
|
+
static forWorkspace(service: string, context: IOContext, opts: InstanceOptions): HttpClient;
|
|
14
|
+
static forRoot(service: string, context: IOContext, opts: InstanceOptions): HttpClient;
|
|
15
|
+
static forLegacy(endpoint: string, opts: LegacyInstanceOptions): HttpClient;
|
|
16
|
+
private runMiddlewares;
|
|
17
|
+
constructor(opts: ClientOptions);
|
|
18
|
+
get: <T = any>(url: string, config?: RequestConfig) => Promise<T>;
|
|
19
|
+
getRaw: <T = any>(url: string, config?: RequestConfig) => Promise<IOResponse<T>>;
|
|
20
|
+
getBuffer: (url: string, config?: RequestConfig) => Promise<{
|
|
21
|
+
data: Buffer;
|
|
22
|
+
headers: any;
|
|
23
|
+
}>;
|
|
24
|
+
getStream: (url: string, config?: RequestConfig) => Promise<IncomingMessage>;
|
|
25
|
+
put: <T = void>(url: string, data?: any, config?: RequestConfig) => Promise<T>;
|
|
26
|
+
post: <T = void>(url: string, data?: any, config?: RequestConfig) => Promise<T>;
|
|
27
|
+
postRaw: <T = void>(url: string, data?: any, config?: RequestConfig) => Promise<IOResponse<T>>;
|
|
28
|
+
patch: <T = void>(url: string, data?: any, config?: RequestConfig) => Promise<T>;
|
|
29
|
+
delete: (url: string, config?: RequestConfig | undefined) => Promise<IOResponse<void>>;
|
|
30
|
+
private request;
|
|
31
|
+
}
|
|
32
|
+
export declare const withoutRecorder: (ioContext: IOContext) => IOContext;
|
|
33
|
+
export declare type CacheStorage = CacheLayer<string, Cached>;
|
|
34
|
+
export declare type Recorder = Recorder;
|
|
35
|
+
export interface DataSources {
|
|
36
|
+
[name: string]: DataSource<ServiceContext>;
|
|
37
|
+
}
|
|
38
|
+
export interface ServiceContext extends Context {
|
|
39
|
+
vtex: IOContext;
|
|
40
|
+
dataSources?: DataSources;
|
|
41
|
+
metricsLogger?: MetricsLogger;
|
|
42
|
+
}
|
|
43
|
+
export interface IOContext {
|
|
44
|
+
account: string;
|
|
45
|
+
authToken: string;
|
|
46
|
+
production: boolean;
|
|
47
|
+
recorder?: Recorder;
|
|
48
|
+
region: string;
|
|
49
|
+
route: {
|
|
50
|
+
declarer?: string;
|
|
51
|
+
id: string;
|
|
52
|
+
params: ParsedUrlQuery;
|
|
53
|
+
};
|
|
54
|
+
userAgent: string;
|
|
55
|
+
workspace: string;
|
|
56
|
+
segmentToken?: string;
|
|
57
|
+
sessionToken?: string;
|
|
58
|
+
}
|
|
59
|
+
export interface InstanceOptions {
|
|
60
|
+
timeout?: number;
|
|
61
|
+
cacheStorage?: CacheLayer<string, Cached>;
|
|
62
|
+
endpoint?: string;
|
|
63
|
+
}
|
|
64
|
+
export interface LegacyInstanceOptions {
|
|
65
|
+
authToken: string;
|
|
66
|
+
userAgent: string;
|
|
67
|
+
timeout?: number;
|
|
68
|
+
accept?: string;
|
|
69
|
+
cacheStorage?: CacheLayer<string, Cached>;
|
|
70
|
+
}
|
|
71
|
+
export interface IOResponse<T> {
|
|
72
|
+
data: T;
|
|
73
|
+
headers: any;
|
|
74
|
+
status: number;
|
|
75
|
+
}
|
|
76
|
+
declare enum AuthType {
|
|
77
|
+
bearer = "bearer",
|
|
78
|
+
token = "token"
|
|
79
|
+
}
|
|
80
|
+
interface ClientOptions {
|
|
81
|
+
authType?: AuthType;
|
|
82
|
+
authToken?: string;
|
|
83
|
+
userAgent: string;
|
|
84
|
+
baseURL?: string;
|
|
85
|
+
timeout?: number;
|
|
86
|
+
recorder?: Recorder;
|
|
87
|
+
metrics?: MetricsAccumulator;
|
|
88
|
+
cacheStorage?: CacheLayer<string, Cached>;
|
|
89
|
+
segmentToken?: string;
|
|
90
|
+
sessionToken?: string;
|
|
91
|
+
}
|
|
92
|
+
export {};
|