@uniformdev/mesh-edgehancer-sdk 19.121.0 → 19.122.1-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +41 -1
- package/dist/index.d.ts +41 -1
- package/dist/index.esm.js +159 -1
- package/dist/index.js +168 -2
- package/dist/index.mjs +159 -1
- package/package.json +9 -3
package/dist/index.d.mts
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
import * as zod from 'zod';
|
2
2
|
import { z } from 'zod';
|
3
3
|
import { DataType, DataSource } from '@uniformdev/canvas';
|
4
|
+
import { NextApiRequest, NextApiResponse } from 'next';
|
4
5
|
|
5
6
|
/**
|
6
7
|
* The context we are fetching the data resource in:
|
@@ -292,6 +293,45 @@ type ResolveBatchIdsResult<TID> = {
|
|
292
293
|
*/
|
293
294
|
declare function resolveBatchFetchIds<TID>(batch: readonly RequestEdgehancerDataResourceContext[], resolveBatchItemIdFn: (dataResource: RequestEdgehancerDataResourceContext) => TID | undefined): ResolveBatchIdsResult<TID>;
|
294
295
|
|
296
|
+
type InvalidationResponse = {
|
297
|
+
status: number;
|
298
|
+
text: string;
|
299
|
+
};
|
300
|
+
declare abstract class APIError extends Error {
|
301
|
+
abstract readonly status: number;
|
302
|
+
abstract readonly statusText: string;
|
303
|
+
}
|
304
|
+
declare class BadRequestError extends APIError {
|
305
|
+
status: number;
|
306
|
+
statusText: string;
|
307
|
+
constructor(message?: string);
|
308
|
+
}
|
309
|
+
declare class ForbiddenError extends APIError {
|
310
|
+
status: number;
|
311
|
+
statusText: string;
|
312
|
+
constructor(message?: string);
|
313
|
+
}
|
314
|
+
|
315
|
+
type Purger = {
|
316
|
+
purgeAllCachesForDataType(): Promise<InvalidationResponse>;
|
317
|
+
purgeBySurrogateKeys(surrogateKeys: string[]): Promise<InvalidationResponse>;
|
318
|
+
};
|
319
|
+
declare const createPurger: ({ invalidationEndpointUrl }: {
|
320
|
+
invalidationEndpointUrl: URL;
|
321
|
+
}) => Purger;
|
322
|
+
|
323
|
+
type Handler = (args: {
|
324
|
+
request: NextApiRequest;
|
325
|
+
purger: Purger;
|
326
|
+
}) => Promise<InvalidationResponse>;
|
327
|
+
declare const handleWebhookRequest: (req: NextApiRequest, res: NextApiResponse, handler: Handler) => Promise<void>;
|
328
|
+
|
329
|
+
declare function getParam(query: NextApiRequest['query'], paramName: string): string | null;
|
330
|
+
declare function getRequiredParam(query: NextApiRequest['query'], paramName: string): string;
|
331
|
+
declare function validateParams(req: NextApiRequest): {
|
332
|
+
invalidationEndpointUrl: URL;
|
333
|
+
};
|
334
|
+
|
295
335
|
declare const edgehancerMergedDataTypeSchema: z.ZodObject<Omit<{
|
296
336
|
id: z.ZodString;
|
297
337
|
displayName: z.ZodString;
|
@@ -820,4 +860,4 @@ declare function getDataResourceQueryString({ parameters, url }: EdgehancerMerge
|
|
820
860
|
/** Gets the HTTP headers for a data resource */
|
821
861
|
declare function getDataResourceHeaders({ headers }: EdgehancerMergedDataType): Headers;
|
822
862
|
|
823
|
-
export { type ConvertBatchResultsToEdgehancerResultOptions, type CustomEdgehancerDefinition, type DataResource, type DataResourceFetchContext, type EdgehancerMergedDataType, type MergedDataType, type PreRequestEdgehancerContext, type PreRequestEdgehancerDataResourceContext, type PreRequestEdgehancerDataResourceResult, type PreRequestEdgehancerResult, type PreRequestHookFn, type RequestEdgehancerContext, type RequestEdgehancerDataResourceContext, type RequestEdgehancerDataResourceResolutionResult, type RequestEdgehancerResult, type RequestHookFn, type ResolveBatchIdsResult, convertBatchResultsToEdgehancerResult, dataResourceSchema, edgehancerMergedDataTypeSchema, getDataResourceAsRequest, getDataResourceHeaders, getDataResourceQueryString, getDataResourceUrl, mergedDataTypeSchema, preRequestEdgehancerDataResourceResultSchema, preRequestEdgehancerResultSchema, requestEdgehancerDataResourceResolutionResultSchema, requestEdgehancerResultSchema, resolveBatchFetchIds };
|
863
|
+
export { APIError, BadRequestError, type ConvertBatchResultsToEdgehancerResultOptions, type CustomEdgehancerDefinition, type DataResource, type DataResourceFetchContext, type EdgehancerMergedDataType, ForbiddenError, type InvalidationResponse, type MergedDataType, type PreRequestEdgehancerContext, type PreRequestEdgehancerDataResourceContext, type PreRequestEdgehancerDataResourceResult, type PreRequestEdgehancerResult, type PreRequestHookFn, type Purger, type RequestEdgehancerContext, type RequestEdgehancerDataResourceContext, type RequestEdgehancerDataResourceResolutionResult, type RequestEdgehancerResult, type RequestHookFn, type ResolveBatchIdsResult, convertBatchResultsToEdgehancerResult, createPurger, dataResourceSchema, edgehancerMergedDataTypeSchema, getDataResourceAsRequest, getDataResourceHeaders, getDataResourceQueryString, getDataResourceUrl, getParam, getRequiredParam, handleWebhookRequest, mergedDataTypeSchema, preRequestEdgehancerDataResourceResultSchema, preRequestEdgehancerResultSchema, requestEdgehancerDataResourceResolutionResultSchema, requestEdgehancerResultSchema, resolveBatchFetchIds, validateParams };
|
package/dist/index.d.ts
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
import * as zod from 'zod';
|
2
2
|
import { z } from 'zod';
|
3
3
|
import { DataType, DataSource } from '@uniformdev/canvas';
|
4
|
+
import { NextApiRequest, NextApiResponse } from 'next';
|
4
5
|
|
5
6
|
/**
|
6
7
|
* The context we are fetching the data resource in:
|
@@ -292,6 +293,45 @@ type ResolveBatchIdsResult<TID> = {
|
|
292
293
|
*/
|
293
294
|
declare function resolveBatchFetchIds<TID>(batch: readonly RequestEdgehancerDataResourceContext[], resolveBatchItemIdFn: (dataResource: RequestEdgehancerDataResourceContext) => TID | undefined): ResolveBatchIdsResult<TID>;
|
294
295
|
|
296
|
+
type InvalidationResponse = {
|
297
|
+
status: number;
|
298
|
+
text: string;
|
299
|
+
};
|
300
|
+
declare abstract class APIError extends Error {
|
301
|
+
abstract readonly status: number;
|
302
|
+
abstract readonly statusText: string;
|
303
|
+
}
|
304
|
+
declare class BadRequestError extends APIError {
|
305
|
+
status: number;
|
306
|
+
statusText: string;
|
307
|
+
constructor(message?: string);
|
308
|
+
}
|
309
|
+
declare class ForbiddenError extends APIError {
|
310
|
+
status: number;
|
311
|
+
statusText: string;
|
312
|
+
constructor(message?: string);
|
313
|
+
}
|
314
|
+
|
315
|
+
type Purger = {
|
316
|
+
purgeAllCachesForDataType(): Promise<InvalidationResponse>;
|
317
|
+
purgeBySurrogateKeys(surrogateKeys: string[]): Promise<InvalidationResponse>;
|
318
|
+
};
|
319
|
+
declare const createPurger: ({ invalidationEndpointUrl }: {
|
320
|
+
invalidationEndpointUrl: URL;
|
321
|
+
}) => Purger;
|
322
|
+
|
323
|
+
type Handler = (args: {
|
324
|
+
request: NextApiRequest;
|
325
|
+
purger: Purger;
|
326
|
+
}) => Promise<InvalidationResponse>;
|
327
|
+
declare const handleWebhookRequest: (req: NextApiRequest, res: NextApiResponse, handler: Handler) => Promise<void>;
|
328
|
+
|
329
|
+
declare function getParam(query: NextApiRequest['query'], paramName: string): string | null;
|
330
|
+
declare function getRequiredParam(query: NextApiRequest['query'], paramName: string): string;
|
331
|
+
declare function validateParams(req: NextApiRequest): {
|
332
|
+
invalidationEndpointUrl: URL;
|
333
|
+
};
|
334
|
+
|
295
335
|
declare const edgehancerMergedDataTypeSchema: z.ZodObject<Omit<{
|
296
336
|
id: z.ZodString;
|
297
337
|
displayName: z.ZodString;
|
@@ -820,4 +860,4 @@ declare function getDataResourceQueryString({ parameters, url }: EdgehancerMerge
|
|
820
860
|
/** Gets the HTTP headers for a data resource */
|
821
861
|
declare function getDataResourceHeaders({ headers }: EdgehancerMergedDataType): Headers;
|
822
862
|
|
823
|
-
export { type ConvertBatchResultsToEdgehancerResultOptions, type CustomEdgehancerDefinition, type DataResource, type DataResourceFetchContext, type EdgehancerMergedDataType, type MergedDataType, type PreRequestEdgehancerContext, type PreRequestEdgehancerDataResourceContext, type PreRequestEdgehancerDataResourceResult, type PreRequestEdgehancerResult, type PreRequestHookFn, type RequestEdgehancerContext, type RequestEdgehancerDataResourceContext, type RequestEdgehancerDataResourceResolutionResult, type RequestEdgehancerResult, type RequestHookFn, type ResolveBatchIdsResult, convertBatchResultsToEdgehancerResult, dataResourceSchema, edgehancerMergedDataTypeSchema, getDataResourceAsRequest, getDataResourceHeaders, getDataResourceQueryString, getDataResourceUrl, mergedDataTypeSchema, preRequestEdgehancerDataResourceResultSchema, preRequestEdgehancerResultSchema, requestEdgehancerDataResourceResolutionResultSchema, requestEdgehancerResultSchema, resolveBatchFetchIds };
|
863
|
+
export { APIError, BadRequestError, type ConvertBatchResultsToEdgehancerResultOptions, type CustomEdgehancerDefinition, type DataResource, type DataResourceFetchContext, type EdgehancerMergedDataType, ForbiddenError, type InvalidationResponse, type MergedDataType, type PreRequestEdgehancerContext, type PreRequestEdgehancerDataResourceContext, type PreRequestEdgehancerDataResourceResult, type PreRequestEdgehancerResult, type PreRequestHookFn, type Purger, type RequestEdgehancerContext, type RequestEdgehancerDataResourceContext, type RequestEdgehancerDataResourceResolutionResult, type RequestEdgehancerResult, type RequestHookFn, type ResolveBatchIdsResult, convertBatchResultsToEdgehancerResult, createPurger, dataResourceSchema, edgehancerMergedDataTypeSchema, getDataResourceAsRequest, getDataResourceHeaders, getDataResourceQueryString, getDataResourceUrl, getParam, getRequiredParam, handleWebhookRequest, mergedDataTypeSchema, preRequestEdgehancerDataResourceResultSchema, preRequestEdgehancerResultSchema, requestEdgehancerDataResourceResolutionResultSchema, requestEdgehancerResultSchema, resolveBatchFetchIds, validateParams };
|
package/dist/index.esm.js
CHANGED
@@ -52,6 +52,156 @@ function resolveBatchFetchIds(batch, resolveBatchItemIdFn) {
|
|
52
52
|
return result;
|
53
53
|
}
|
54
54
|
|
55
|
+
// src/cache-purging-webhooks/purge.ts
|
56
|
+
var logger = console;
|
57
|
+
var createPurger = ({ invalidationEndpointUrl }) => {
|
58
|
+
logger.log(`[createPurger] call`, {
|
59
|
+
invalidationEndpointUrl: invalidationEndpointUrl.toString()
|
60
|
+
});
|
61
|
+
const purgeAllCachesForDataType = async () => {
|
62
|
+
logger.log(`[purgeAllCachesForDataType] call`, {
|
63
|
+
invalidationEndpointUrl: invalidationEndpointUrl.toString()
|
64
|
+
});
|
65
|
+
const res = await fetch(invalidationEndpointUrl, {
|
66
|
+
method: "GET"
|
67
|
+
});
|
68
|
+
return {
|
69
|
+
status: res.status,
|
70
|
+
text: await res.text()
|
71
|
+
};
|
72
|
+
};
|
73
|
+
const purgeBySurrogateKeys = async (surrogateKeys) => {
|
74
|
+
logger.log(`[purgeBySurrogateKeys] call`, {
|
75
|
+
invalidationEndpointUrl: invalidationEndpointUrl.toString(),
|
76
|
+
surrogateKeys
|
77
|
+
});
|
78
|
+
const body = {
|
79
|
+
surrogateKeys: surrogateKeys.filter((x) => x)
|
80
|
+
};
|
81
|
+
if (body.surrogateKeys.length > 0) {
|
82
|
+
const res = await fetch(invalidationEndpointUrl, {
|
83
|
+
method: "POST",
|
84
|
+
body: JSON.stringify(body)
|
85
|
+
});
|
86
|
+
return {
|
87
|
+
status: res.status,
|
88
|
+
text: await res.text()
|
89
|
+
};
|
90
|
+
} else {
|
91
|
+
logger.log(`[purgeBySurrogateKeys] No surrogate keys found.`, {
|
92
|
+
invalidationEndpointUrl: invalidationEndpointUrl.toString(),
|
93
|
+
surrogateKeys
|
94
|
+
});
|
95
|
+
return {
|
96
|
+
status: 200,
|
97
|
+
text: "No surrogate keys found."
|
98
|
+
};
|
99
|
+
}
|
100
|
+
};
|
101
|
+
return { purgeAllCachesForDataType, purgeBySurrogateKeys };
|
102
|
+
};
|
103
|
+
|
104
|
+
// src/cache-purging-webhooks/shared.ts
|
105
|
+
var APIError = class extends Error {
|
106
|
+
};
|
107
|
+
var BadRequestError = class _BadRequestError extends APIError {
|
108
|
+
constructor(message = "Invalid request received") {
|
109
|
+
super(message);
|
110
|
+
this.status = 400;
|
111
|
+
this.statusText = "Bad Request";
|
112
|
+
Object.setPrototypeOf(this, _BadRequestError.prototype);
|
113
|
+
}
|
114
|
+
};
|
115
|
+
var ForbiddenError = class _ForbiddenError extends APIError {
|
116
|
+
constructor(message = "This action is forbidden") {
|
117
|
+
super(message);
|
118
|
+
this.status = 403;
|
119
|
+
this.statusText = "Forbidden";
|
120
|
+
Object.setPrototypeOf(this, _ForbiddenError.prototype);
|
121
|
+
}
|
122
|
+
};
|
123
|
+
|
124
|
+
// src/cache-purging-webhooks/utils.ts
|
125
|
+
function getParam(query, paramName) {
|
126
|
+
const values = query[paramName];
|
127
|
+
if (!values) {
|
128
|
+
return null;
|
129
|
+
} else if (typeof values === "string") {
|
130
|
+
return values;
|
131
|
+
} else if (values.length === 1) {
|
132
|
+
return values[0];
|
133
|
+
} else {
|
134
|
+
throw new BadRequestError(`Multiple values for ${paramName} found in request parameters`);
|
135
|
+
}
|
136
|
+
}
|
137
|
+
function getRequiredParam(query, paramName) {
|
138
|
+
const value = getParam(query, paramName);
|
139
|
+
if (!value) {
|
140
|
+
throw new BadRequestError(`${paramName} not found in request parameters`);
|
141
|
+
}
|
142
|
+
return value;
|
143
|
+
}
|
144
|
+
function validateParams(req) {
|
145
|
+
const edgeApiHost = getParam(req.query, "edgeApiHost");
|
146
|
+
if (edgeApiHost) {
|
147
|
+
if (!isAllowedEdgeApiHost(edgeApiHost)) {
|
148
|
+
throw new ForbiddenError(`Edge API hostname is not allowed: ${edgeApiHost}`);
|
149
|
+
}
|
150
|
+
}
|
151
|
+
const projectId = getRequiredParam(req.query, "projectId");
|
152
|
+
const dataTypeId = getRequiredParam(req.query, "dataTypeId");
|
153
|
+
const purgeKey = getRequiredParam(req.query, "purgeKey");
|
154
|
+
const invalidationEndpointUrl = new URL(`https://${edgeApiHost || "uniform.global"}/api/v1/invalidation`);
|
155
|
+
invalidationEndpointUrl.searchParams.set("projectId", projectId);
|
156
|
+
invalidationEndpointUrl.searchParams.set("dataTypeId", dataTypeId);
|
157
|
+
invalidationEndpointUrl.searchParams.set("purgeKey", purgeKey);
|
158
|
+
return { invalidationEndpointUrl };
|
159
|
+
}
|
160
|
+
function isAllowedEdgeApiHost(edgeApiHost) {
|
161
|
+
if (["uniform.global", "canary.uniform.global"].includes(edgeApiHost)) {
|
162
|
+
return true;
|
163
|
+
}
|
164
|
+
if (edgeApiHost.endsWith(".uniform.rocks")) {
|
165
|
+
return true;
|
166
|
+
}
|
167
|
+
return false;
|
168
|
+
}
|
169
|
+
|
170
|
+
// src/cache-purging-webhooks/handleWebhookRequest.ts
|
171
|
+
var ALLOWED_METHODS = ["POST"];
|
172
|
+
var logger2 = console;
|
173
|
+
var handleWebhookRequest = async (req, res, handler) => {
|
174
|
+
try {
|
175
|
+
logger2.log(`request`, {
|
176
|
+
url: req.url,
|
177
|
+
method: req.method
|
178
|
+
});
|
179
|
+
if (!ALLOWED_METHODS.includes(req.method || "")) {
|
180
|
+
throw new BadRequestError(`Expected ${ALLOWED_METHODS.join(" or ")} but was called with ${req.method}`);
|
181
|
+
}
|
182
|
+
const { invalidationEndpointUrl } = validateParams(req);
|
183
|
+
const purger = createPurger({ invalidationEndpointUrl });
|
184
|
+
const { status, text } = await handler({
|
185
|
+
request: req,
|
186
|
+
purger
|
187
|
+
});
|
188
|
+
res.status(status).send(text);
|
189
|
+
} catch (err) {
|
190
|
+
if (err instanceof APIError) {
|
191
|
+
logger2.error(`APIError: [${err.status} ${err.statusText}] ${err.message}`);
|
192
|
+
res.status(err.status).json({
|
193
|
+
type: err.statusText,
|
194
|
+
errorMessage: err.message
|
195
|
+
});
|
196
|
+
} else {
|
197
|
+
logger2.error(`Error`, err);
|
198
|
+
res.status(500).json({
|
199
|
+
errorMessage: err.message || "Unknown error"
|
200
|
+
});
|
201
|
+
}
|
202
|
+
}
|
203
|
+
};
|
204
|
+
|
55
205
|
// src/fetchUtils.ts
|
56
206
|
function getDataResourceAsRequest(data) {
|
57
207
|
var _a;
|
@@ -178,17 +328,25 @@ var requestEdgehancerResultSchema = z3.strictObject({
|
|
178
328
|
results: z3.array(requestEdgehancerDataResourceResolutionResultSchema)
|
179
329
|
});
|
180
330
|
export {
|
331
|
+
APIError,
|
332
|
+
BadRequestError,
|
333
|
+
ForbiddenError,
|
181
334
|
convertBatchResultsToEdgehancerResult,
|
335
|
+
createPurger,
|
182
336
|
dataResourceSchema,
|
183
337
|
edgehancerMergedDataTypeSchema,
|
184
338
|
getDataResourceAsRequest,
|
185
339
|
getDataResourceHeaders,
|
186
340
|
getDataResourceQueryString,
|
187
341
|
getDataResourceUrl,
|
342
|
+
getParam,
|
343
|
+
getRequiredParam,
|
344
|
+
handleWebhookRequest,
|
188
345
|
mergedDataTypeSchema,
|
189
346
|
preRequestEdgehancerDataResourceResultSchema,
|
190
347
|
preRequestEdgehancerResultSchema,
|
191
348
|
requestEdgehancerDataResourceResolutionResultSchema,
|
192
349
|
requestEdgehancerResultSchema,
|
193
|
-
resolveBatchFetchIds
|
350
|
+
resolveBatchFetchIds,
|
351
|
+
validateParams
|
194
352
|
};
|
package/dist/index.js
CHANGED
@@ -20,19 +20,27 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
20
20
|
// src/index.ts
|
21
21
|
var src_exports = {};
|
22
22
|
__export(src_exports, {
|
23
|
+
APIError: () => APIError,
|
24
|
+
BadRequestError: () => BadRequestError,
|
25
|
+
ForbiddenError: () => ForbiddenError,
|
23
26
|
convertBatchResultsToEdgehancerResult: () => convertBatchResultsToEdgehancerResult,
|
27
|
+
createPurger: () => createPurger,
|
24
28
|
dataResourceSchema: () => dataResourceSchema,
|
25
29
|
edgehancerMergedDataTypeSchema: () => edgehancerMergedDataTypeSchema,
|
26
30
|
getDataResourceAsRequest: () => getDataResourceAsRequest,
|
27
31
|
getDataResourceHeaders: () => getDataResourceHeaders,
|
28
32
|
getDataResourceQueryString: () => getDataResourceQueryString,
|
29
33
|
getDataResourceUrl: () => getDataResourceUrl,
|
34
|
+
getParam: () => getParam,
|
35
|
+
getRequiredParam: () => getRequiredParam,
|
36
|
+
handleWebhookRequest: () => handleWebhookRequest,
|
30
37
|
mergedDataTypeSchema: () => mergedDataTypeSchema,
|
31
38
|
preRequestEdgehancerDataResourceResultSchema: () => preRequestEdgehancerDataResourceResultSchema,
|
32
39
|
preRequestEdgehancerResultSchema: () => preRequestEdgehancerResultSchema,
|
33
40
|
requestEdgehancerDataResourceResolutionResultSchema: () => requestEdgehancerDataResourceResolutionResultSchema,
|
34
41
|
requestEdgehancerResultSchema: () => requestEdgehancerResultSchema,
|
35
|
-
resolveBatchFetchIds: () => resolveBatchFetchIds
|
42
|
+
resolveBatchFetchIds: () => resolveBatchFetchIds,
|
43
|
+
validateParams: () => validateParams
|
36
44
|
});
|
37
45
|
module.exports = __toCommonJS(src_exports);
|
38
46
|
|
@@ -90,6 +98,156 @@ function resolveBatchFetchIds(batch, resolveBatchItemIdFn) {
|
|
90
98
|
return result;
|
91
99
|
}
|
92
100
|
|
101
|
+
// src/cache-purging-webhooks/purge.ts
|
102
|
+
var logger = console;
|
103
|
+
var createPurger = ({ invalidationEndpointUrl }) => {
|
104
|
+
logger.log(`[createPurger] call`, {
|
105
|
+
invalidationEndpointUrl: invalidationEndpointUrl.toString()
|
106
|
+
});
|
107
|
+
const purgeAllCachesForDataType = async () => {
|
108
|
+
logger.log(`[purgeAllCachesForDataType] call`, {
|
109
|
+
invalidationEndpointUrl: invalidationEndpointUrl.toString()
|
110
|
+
});
|
111
|
+
const res = await fetch(invalidationEndpointUrl, {
|
112
|
+
method: "GET"
|
113
|
+
});
|
114
|
+
return {
|
115
|
+
status: res.status,
|
116
|
+
text: await res.text()
|
117
|
+
};
|
118
|
+
};
|
119
|
+
const purgeBySurrogateKeys = async (surrogateKeys) => {
|
120
|
+
logger.log(`[purgeBySurrogateKeys] call`, {
|
121
|
+
invalidationEndpointUrl: invalidationEndpointUrl.toString(),
|
122
|
+
surrogateKeys
|
123
|
+
});
|
124
|
+
const body = {
|
125
|
+
surrogateKeys: surrogateKeys.filter((x) => x)
|
126
|
+
};
|
127
|
+
if (body.surrogateKeys.length > 0) {
|
128
|
+
const res = await fetch(invalidationEndpointUrl, {
|
129
|
+
method: "POST",
|
130
|
+
body: JSON.stringify(body)
|
131
|
+
});
|
132
|
+
return {
|
133
|
+
status: res.status,
|
134
|
+
text: await res.text()
|
135
|
+
};
|
136
|
+
} else {
|
137
|
+
logger.log(`[purgeBySurrogateKeys] No surrogate keys found.`, {
|
138
|
+
invalidationEndpointUrl: invalidationEndpointUrl.toString(),
|
139
|
+
surrogateKeys
|
140
|
+
});
|
141
|
+
return {
|
142
|
+
status: 200,
|
143
|
+
text: "No surrogate keys found."
|
144
|
+
};
|
145
|
+
}
|
146
|
+
};
|
147
|
+
return { purgeAllCachesForDataType, purgeBySurrogateKeys };
|
148
|
+
};
|
149
|
+
|
150
|
+
// src/cache-purging-webhooks/shared.ts
|
151
|
+
var APIError = class extends Error {
|
152
|
+
};
|
153
|
+
var BadRequestError = class _BadRequestError extends APIError {
|
154
|
+
constructor(message = "Invalid request received") {
|
155
|
+
super(message);
|
156
|
+
this.status = 400;
|
157
|
+
this.statusText = "Bad Request";
|
158
|
+
Object.setPrototypeOf(this, _BadRequestError.prototype);
|
159
|
+
}
|
160
|
+
};
|
161
|
+
var ForbiddenError = class _ForbiddenError extends APIError {
|
162
|
+
constructor(message = "This action is forbidden") {
|
163
|
+
super(message);
|
164
|
+
this.status = 403;
|
165
|
+
this.statusText = "Forbidden";
|
166
|
+
Object.setPrototypeOf(this, _ForbiddenError.prototype);
|
167
|
+
}
|
168
|
+
};
|
169
|
+
|
170
|
+
// src/cache-purging-webhooks/utils.ts
|
171
|
+
function getParam(query, paramName) {
|
172
|
+
const values = query[paramName];
|
173
|
+
if (!values) {
|
174
|
+
return null;
|
175
|
+
} else if (typeof values === "string") {
|
176
|
+
return values;
|
177
|
+
} else if (values.length === 1) {
|
178
|
+
return values[0];
|
179
|
+
} else {
|
180
|
+
throw new BadRequestError(`Multiple values for ${paramName} found in request parameters`);
|
181
|
+
}
|
182
|
+
}
|
183
|
+
function getRequiredParam(query, paramName) {
|
184
|
+
const value = getParam(query, paramName);
|
185
|
+
if (!value) {
|
186
|
+
throw new BadRequestError(`${paramName} not found in request parameters`);
|
187
|
+
}
|
188
|
+
return value;
|
189
|
+
}
|
190
|
+
function validateParams(req) {
|
191
|
+
const edgeApiHost = getParam(req.query, "edgeApiHost");
|
192
|
+
if (edgeApiHost) {
|
193
|
+
if (!isAllowedEdgeApiHost(edgeApiHost)) {
|
194
|
+
throw new ForbiddenError(`Edge API hostname is not allowed: ${edgeApiHost}`);
|
195
|
+
}
|
196
|
+
}
|
197
|
+
const projectId = getRequiredParam(req.query, "projectId");
|
198
|
+
const dataTypeId = getRequiredParam(req.query, "dataTypeId");
|
199
|
+
const purgeKey = getRequiredParam(req.query, "purgeKey");
|
200
|
+
const invalidationEndpointUrl = new URL(`https://${edgeApiHost || "uniform.global"}/api/v1/invalidation`);
|
201
|
+
invalidationEndpointUrl.searchParams.set("projectId", projectId);
|
202
|
+
invalidationEndpointUrl.searchParams.set("dataTypeId", dataTypeId);
|
203
|
+
invalidationEndpointUrl.searchParams.set("purgeKey", purgeKey);
|
204
|
+
return { invalidationEndpointUrl };
|
205
|
+
}
|
206
|
+
function isAllowedEdgeApiHost(edgeApiHost) {
|
207
|
+
if (["uniform.global", "canary.uniform.global"].includes(edgeApiHost)) {
|
208
|
+
return true;
|
209
|
+
}
|
210
|
+
if (edgeApiHost.endsWith(".uniform.rocks")) {
|
211
|
+
return true;
|
212
|
+
}
|
213
|
+
return false;
|
214
|
+
}
|
215
|
+
|
216
|
+
// src/cache-purging-webhooks/handleWebhookRequest.ts
|
217
|
+
var ALLOWED_METHODS = ["POST"];
|
218
|
+
var logger2 = console;
|
219
|
+
var handleWebhookRequest = async (req, res, handler) => {
|
220
|
+
try {
|
221
|
+
logger2.log(`request`, {
|
222
|
+
url: req.url,
|
223
|
+
method: req.method
|
224
|
+
});
|
225
|
+
if (!ALLOWED_METHODS.includes(req.method || "")) {
|
226
|
+
throw new BadRequestError(`Expected ${ALLOWED_METHODS.join(" or ")} but was called with ${req.method}`);
|
227
|
+
}
|
228
|
+
const { invalidationEndpointUrl } = validateParams(req);
|
229
|
+
const purger = createPurger({ invalidationEndpointUrl });
|
230
|
+
const { status, text } = await handler({
|
231
|
+
request: req,
|
232
|
+
purger
|
233
|
+
});
|
234
|
+
res.status(status).send(text);
|
235
|
+
} catch (err) {
|
236
|
+
if (err instanceof APIError) {
|
237
|
+
logger2.error(`APIError: [${err.status} ${err.statusText}] ${err.message}`);
|
238
|
+
res.status(err.status).json({
|
239
|
+
type: err.statusText,
|
240
|
+
errorMessage: err.message
|
241
|
+
});
|
242
|
+
} else {
|
243
|
+
logger2.error(`Error`, err);
|
244
|
+
res.status(500).json({
|
245
|
+
errorMessage: err.message || "Unknown error"
|
246
|
+
});
|
247
|
+
}
|
248
|
+
}
|
249
|
+
};
|
250
|
+
|
93
251
|
// src/fetchUtils.ts
|
94
252
|
function getDataResourceAsRequest(data) {
|
95
253
|
var _a;
|
@@ -217,17 +375,25 @@ var requestEdgehancerResultSchema = import_zod3.z.strictObject({
|
|
217
375
|
});
|
218
376
|
// Annotate the CommonJS export names for ESM import in node:
|
219
377
|
0 && (module.exports = {
|
378
|
+
APIError,
|
379
|
+
BadRequestError,
|
380
|
+
ForbiddenError,
|
220
381
|
convertBatchResultsToEdgehancerResult,
|
382
|
+
createPurger,
|
221
383
|
dataResourceSchema,
|
222
384
|
edgehancerMergedDataTypeSchema,
|
223
385
|
getDataResourceAsRequest,
|
224
386
|
getDataResourceHeaders,
|
225
387
|
getDataResourceQueryString,
|
226
388
|
getDataResourceUrl,
|
389
|
+
getParam,
|
390
|
+
getRequiredParam,
|
391
|
+
handleWebhookRequest,
|
227
392
|
mergedDataTypeSchema,
|
228
393
|
preRequestEdgehancerDataResourceResultSchema,
|
229
394
|
preRequestEdgehancerResultSchema,
|
230
395
|
requestEdgehancerDataResourceResolutionResultSchema,
|
231
396
|
requestEdgehancerResultSchema,
|
232
|
-
resolveBatchFetchIds
|
397
|
+
resolveBatchFetchIds,
|
398
|
+
validateParams
|
233
399
|
});
|
package/dist/index.mjs
CHANGED
@@ -52,6 +52,156 @@ function resolveBatchFetchIds(batch, resolveBatchItemIdFn) {
|
|
52
52
|
return result;
|
53
53
|
}
|
54
54
|
|
55
|
+
// src/cache-purging-webhooks/purge.ts
|
56
|
+
var logger = console;
|
57
|
+
var createPurger = ({ invalidationEndpointUrl }) => {
|
58
|
+
logger.log(`[createPurger] call`, {
|
59
|
+
invalidationEndpointUrl: invalidationEndpointUrl.toString()
|
60
|
+
});
|
61
|
+
const purgeAllCachesForDataType = async () => {
|
62
|
+
logger.log(`[purgeAllCachesForDataType] call`, {
|
63
|
+
invalidationEndpointUrl: invalidationEndpointUrl.toString()
|
64
|
+
});
|
65
|
+
const res = await fetch(invalidationEndpointUrl, {
|
66
|
+
method: "GET"
|
67
|
+
});
|
68
|
+
return {
|
69
|
+
status: res.status,
|
70
|
+
text: await res.text()
|
71
|
+
};
|
72
|
+
};
|
73
|
+
const purgeBySurrogateKeys = async (surrogateKeys) => {
|
74
|
+
logger.log(`[purgeBySurrogateKeys] call`, {
|
75
|
+
invalidationEndpointUrl: invalidationEndpointUrl.toString(),
|
76
|
+
surrogateKeys
|
77
|
+
});
|
78
|
+
const body = {
|
79
|
+
surrogateKeys: surrogateKeys.filter((x) => x)
|
80
|
+
};
|
81
|
+
if (body.surrogateKeys.length > 0) {
|
82
|
+
const res = await fetch(invalidationEndpointUrl, {
|
83
|
+
method: "POST",
|
84
|
+
body: JSON.stringify(body)
|
85
|
+
});
|
86
|
+
return {
|
87
|
+
status: res.status,
|
88
|
+
text: await res.text()
|
89
|
+
};
|
90
|
+
} else {
|
91
|
+
logger.log(`[purgeBySurrogateKeys] No surrogate keys found.`, {
|
92
|
+
invalidationEndpointUrl: invalidationEndpointUrl.toString(),
|
93
|
+
surrogateKeys
|
94
|
+
});
|
95
|
+
return {
|
96
|
+
status: 200,
|
97
|
+
text: "No surrogate keys found."
|
98
|
+
};
|
99
|
+
}
|
100
|
+
};
|
101
|
+
return { purgeAllCachesForDataType, purgeBySurrogateKeys };
|
102
|
+
};
|
103
|
+
|
104
|
+
// src/cache-purging-webhooks/shared.ts
|
105
|
+
var APIError = class extends Error {
|
106
|
+
};
|
107
|
+
var BadRequestError = class _BadRequestError extends APIError {
|
108
|
+
constructor(message = "Invalid request received") {
|
109
|
+
super(message);
|
110
|
+
this.status = 400;
|
111
|
+
this.statusText = "Bad Request";
|
112
|
+
Object.setPrototypeOf(this, _BadRequestError.prototype);
|
113
|
+
}
|
114
|
+
};
|
115
|
+
var ForbiddenError = class _ForbiddenError extends APIError {
|
116
|
+
constructor(message = "This action is forbidden") {
|
117
|
+
super(message);
|
118
|
+
this.status = 403;
|
119
|
+
this.statusText = "Forbidden";
|
120
|
+
Object.setPrototypeOf(this, _ForbiddenError.prototype);
|
121
|
+
}
|
122
|
+
};
|
123
|
+
|
124
|
+
// src/cache-purging-webhooks/utils.ts
|
125
|
+
function getParam(query, paramName) {
|
126
|
+
const values = query[paramName];
|
127
|
+
if (!values) {
|
128
|
+
return null;
|
129
|
+
} else if (typeof values === "string") {
|
130
|
+
return values;
|
131
|
+
} else if (values.length === 1) {
|
132
|
+
return values[0];
|
133
|
+
} else {
|
134
|
+
throw new BadRequestError(`Multiple values for ${paramName} found in request parameters`);
|
135
|
+
}
|
136
|
+
}
|
137
|
+
function getRequiredParam(query, paramName) {
|
138
|
+
const value = getParam(query, paramName);
|
139
|
+
if (!value) {
|
140
|
+
throw new BadRequestError(`${paramName} not found in request parameters`);
|
141
|
+
}
|
142
|
+
return value;
|
143
|
+
}
|
144
|
+
function validateParams(req) {
|
145
|
+
const edgeApiHost = getParam(req.query, "edgeApiHost");
|
146
|
+
if (edgeApiHost) {
|
147
|
+
if (!isAllowedEdgeApiHost(edgeApiHost)) {
|
148
|
+
throw new ForbiddenError(`Edge API hostname is not allowed: ${edgeApiHost}`);
|
149
|
+
}
|
150
|
+
}
|
151
|
+
const projectId = getRequiredParam(req.query, "projectId");
|
152
|
+
const dataTypeId = getRequiredParam(req.query, "dataTypeId");
|
153
|
+
const purgeKey = getRequiredParam(req.query, "purgeKey");
|
154
|
+
const invalidationEndpointUrl = new URL(`https://${edgeApiHost || "uniform.global"}/api/v1/invalidation`);
|
155
|
+
invalidationEndpointUrl.searchParams.set("projectId", projectId);
|
156
|
+
invalidationEndpointUrl.searchParams.set("dataTypeId", dataTypeId);
|
157
|
+
invalidationEndpointUrl.searchParams.set("purgeKey", purgeKey);
|
158
|
+
return { invalidationEndpointUrl };
|
159
|
+
}
|
160
|
+
function isAllowedEdgeApiHost(edgeApiHost) {
|
161
|
+
if (["uniform.global", "canary.uniform.global"].includes(edgeApiHost)) {
|
162
|
+
return true;
|
163
|
+
}
|
164
|
+
if (edgeApiHost.endsWith(".uniform.rocks")) {
|
165
|
+
return true;
|
166
|
+
}
|
167
|
+
return false;
|
168
|
+
}
|
169
|
+
|
170
|
+
// src/cache-purging-webhooks/handleWebhookRequest.ts
|
171
|
+
var ALLOWED_METHODS = ["POST"];
|
172
|
+
var logger2 = console;
|
173
|
+
var handleWebhookRequest = async (req, res, handler) => {
|
174
|
+
try {
|
175
|
+
logger2.log(`request`, {
|
176
|
+
url: req.url,
|
177
|
+
method: req.method
|
178
|
+
});
|
179
|
+
if (!ALLOWED_METHODS.includes(req.method || "")) {
|
180
|
+
throw new BadRequestError(`Expected ${ALLOWED_METHODS.join(" or ")} but was called with ${req.method}`);
|
181
|
+
}
|
182
|
+
const { invalidationEndpointUrl } = validateParams(req);
|
183
|
+
const purger = createPurger({ invalidationEndpointUrl });
|
184
|
+
const { status, text } = await handler({
|
185
|
+
request: req,
|
186
|
+
purger
|
187
|
+
});
|
188
|
+
res.status(status).send(text);
|
189
|
+
} catch (err) {
|
190
|
+
if (err instanceof APIError) {
|
191
|
+
logger2.error(`APIError: [${err.status} ${err.statusText}] ${err.message}`);
|
192
|
+
res.status(err.status).json({
|
193
|
+
type: err.statusText,
|
194
|
+
errorMessage: err.message
|
195
|
+
});
|
196
|
+
} else {
|
197
|
+
logger2.error(`Error`, err);
|
198
|
+
res.status(500).json({
|
199
|
+
errorMessage: err.message || "Unknown error"
|
200
|
+
});
|
201
|
+
}
|
202
|
+
}
|
203
|
+
};
|
204
|
+
|
55
205
|
// src/fetchUtils.ts
|
56
206
|
function getDataResourceAsRequest(data) {
|
57
207
|
var _a;
|
@@ -178,17 +328,25 @@ var requestEdgehancerResultSchema = z3.strictObject({
|
|
178
328
|
results: z3.array(requestEdgehancerDataResourceResolutionResultSchema)
|
179
329
|
});
|
180
330
|
export {
|
331
|
+
APIError,
|
332
|
+
BadRequestError,
|
333
|
+
ForbiddenError,
|
181
334
|
convertBatchResultsToEdgehancerResult,
|
335
|
+
createPurger,
|
182
336
|
dataResourceSchema,
|
183
337
|
edgehancerMergedDataTypeSchema,
|
184
338
|
getDataResourceAsRequest,
|
185
339
|
getDataResourceHeaders,
|
186
340
|
getDataResourceQueryString,
|
187
341
|
getDataResourceUrl,
|
342
|
+
getParam,
|
343
|
+
getRequiredParam,
|
344
|
+
handleWebhookRequest,
|
188
345
|
mergedDataTypeSchema,
|
189
346
|
preRequestEdgehancerDataResourceResultSchema,
|
190
347
|
preRequestEdgehancerResultSchema,
|
191
348
|
requestEdgehancerDataResourceResolutionResultSchema,
|
192
349
|
requestEdgehancerResultSchema,
|
193
|
-
resolveBatchFetchIds
|
350
|
+
resolveBatchFetchIds,
|
351
|
+
validateParams
|
194
352
|
};
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@uniformdev/mesh-edgehancer-sdk",
|
3
|
-
"version": "19.
|
3
|
+
"version": "19.122.1-alpha.0+03f737f1b5",
|
4
4
|
"description": "Uniform Mesh Edgehancer SDK",
|
5
5
|
"license": "SEE LICENSE IN LICENSE.txt",
|
6
6
|
"main": "./dist/index.js",
|
@@ -28,12 +28,18 @@
|
|
28
28
|
"/dist"
|
29
29
|
],
|
30
30
|
"dependencies": {
|
31
|
-
"@uniformdev/canvas": "19.
|
31
|
+
"@uniformdev/canvas": "19.122.1-alpha.0+03f737f1b5",
|
32
32
|
"tsafe": "1.6.5",
|
33
33
|
"zod": "3.22.4"
|
34
34
|
},
|
35
|
+
"devDependencies": {
|
36
|
+
"next": "13.4.12"
|
37
|
+
},
|
38
|
+
"peerDependencies": {
|
39
|
+
"next": ">13"
|
40
|
+
},
|
35
41
|
"publishConfig": {
|
36
42
|
"access": "public"
|
37
43
|
},
|
38
|
-
"gitHead": "
|
44
|
+
"gitHead": "03f737f1b507886971bc90dde2367d1bf85f5edf"
|
39
45
|
}
|