@etohq/framework 1.0.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (132) hide show
  1. package/dist/build-tools/compiler.d.ts.map +1 -1
  2. package/dist/build-tools/compiler.js +38 -32
  3. package/dist/build-tools/compiler.js.map +1 -1
  4. package/dist/config/config.d.ts.map +1 -1
  5. package/dist/config/config.js +1 -0
  6. package/dist/config/config.js.map +1 -1
  7. package/dist/config/loader.d.ts +7 -2
  8. package/dist/config/loader.d.ts.map +1 -1
  9. package/dist/config/loader.js +28 -6
  10. package/dist/config/loader.js.map +1 -1
  11. package/dist/config/types.d.ts +4 -166
  12. package/dist/config/types.d.ts.map +1 -1
  13. package/dist/context/index.d.ts +6 -0
  14. package/dist/context/index.d.ts.map +1 -0
  15. package/dist/context/index.js +50 -0
  16. package/dist/context/index.js.map +1 -0
  17. package/dist/error/index.d.ts +205 -0
  18. package/dist/error/index.d.ts.map +1 -0
  19. package/dist/error/index.js +273 -0
  20. package/dist/error/index.js.map +1 -0
  21. package/dist/eto-app-loader.d.ts +6 -4
  22. package/dist/eto-app-loader.d.ts.map +1 -1
  23. package/dist/eto-app-loader.js +53 -11
  24. package/dist/eto-app-loader.js.map +1 -1
  25. package/dist/eto.d.ts +39 -0
  26. package/dist/eto.d.ts.map +1 -0
  27. package/dist/eto.js +148 -0
  28. package/dist/eto.js.map +1 -0
  29. package/dist/feature-flags/feature-flag-loader.d.ts +4 -3
  30. package/dist/feature-flags/feature-flag-loader.d.ts.map +1 -1
  31. package/dist/feature-flags/feature-flag-loader.js +36 -25
  32. package/dist/feature-flags/feature-flag-loader.js.map +1 -1
  33. package/dist/http/encore.d.ts +191 -0
  34. package/dist/http/encore.d.ts.map +1 -0
  35. package/dist/http/encore.js +3 -0
  36. package/dist/http/encore.js.map +1 -0
  37. package/dist/http/index.d.ts +1 -3
  38. package/dist/http/index.d.ts.map +1 -1
  39. package/dist/http/index.js +1 -3
  40. package/dist/http/index.js.map +1 -1
  41. package/dist/http/middlewares/apply-default-filters.d.ts +2 -2
  42. package/dist/http/middlewares/apply-default-filters.d.ts.map +1 -1
  43. package/dist/http/middlewares/apply-default-filters.js +8 -6
  44. package/dist/http/middlewares/apply-default-filters.js.map +1 -1
  45. package/dist/http/middlewares/apply-params-as-filters.d.ts +2 -2
  46. package/dist/http/middlewares/apply-params-as-filters.d.ts.map +1 -1
  47. package/dist/http/middlewares/apply-params-as-filters.js +7 -4
  48. package/dist/http/middlewares/apply-params-as-filters.js.map +1 -1
  49. package/dist/http/middlewares/authenticate-middleware.d.ts +2 -2
  50. package/dist/http/middlewares/authenticate-middleware.d.ts.map +1 -1
  51. package/dist/http/middlewares/authenticate-middleware.js +25 -22
  52. package/dist/http/middlewares/authenticate-middleware.js.map +1 -1
  53. package/dist/http/middlewares/clear-filters-by-key.d.ts +2 -2
  54. package/dist/http/middlewares/clear-filters-by-key.d.ts.map +1 -1
  55. package/dist/http/middlewares/clear-filters-by-key.js +2 -2
  56. package/dist/http/middlewares/clear-filters-by-key.js.map +1 -1
  57. package/dist/http/middlewares/ensure-publishable-api-key.d.ts +2 -2
  58. package/dist/http/middlewares/ensure-publishable-api-key.d.ts.map +1 -1
  59. package/dist/http/middlewares/ensure-publishable-api-key.js +7 -5
  60. package/dist/http/middlewares/ensure-publishable-api-key.js.map +1 -1
  61. package/dist/http/middlewares/error-handler.d.ts +2 -3
  62. package/dist/http/middlewares/error-handler.d.ts.map +1 -1
  63. package/dist/http/middlewares/error-handler.js +6 -3
  64. package/dist/http/middlewares/error-handler.js.map +1 -1
  65. package/dist/http/middlewares/set-context.d.ts +2 -2
  66. package/dist/http/middlewares/set-context.d.ts.map +1 -1
  67. package/dist/http/middlewares/set-context.js +4 -4
  68. package/dist/http/middlewares/set-context.js.map +1 -1
  69. package/dist/http/types.d.ts +41 -31
  70. package/dist/http/types.d.ts.map +1 -1
  71. package/dist/http/types.js.map +1 -1
  72. package/dist/http/utils/http-compression.d.ts +1 -4
  73. package/dist/http/utils/http-compression.d.ts.map +1 -1
  74. package/dist/http/utils/http-compression.js +35 -30
  75. package/dist/http/utils/http-compression.js.map +1 -1
  76. package/dist/http/utils/maybe-apply-link-filter.d.ts +2 -2
  77. package/dist/http/utils/maybe-apply-link-filter.d.ts.map +1 -1
  78. package/dist/http/utils/maybe-apply-link-filter.js +7 -6
  79. package/dist/http/utils/maybe-apply-link-filter.js.map +1 -1
  80. package/dist/http/utils/refetch-entities.d.ts +2 -2
  81. package/dist/http/utils/refetch-entities.d.ts.map +1 -1
  82. package/dist/http/utils/refetch-entities.js.map +1 -1
  83. package/dist/http/utils/unless-path.d.ts +4 -4
  84. package/dist/http/utils/unless-path.d.ts.map +1 -1
  85. package/dist/http/utils/unless-path.js +20 -11
  86. package/dist/http/utils/unless-path.js.map +1 -1
  87. package/dist/http/utils/validate-body.d.ts +1 -4
  88. package/dist/http/utils/validate-body.d.ts.map +1 -1
  89. package/dist/http/utils/validate-body.js +31 -20
  90. package/dist/http/utils/validate-body.js.map +1 -1
  91. package/dist/http/utils/validate-query.d.ts +9 -4
  92. package/dist/http/utils/validate-query.d.ts.map +1 -1
  93. package/dist/http/utils/validate-query.js +63 -20
  94. package/dist/http/utils/validate-query.js.map +1 -1
  95. package/dist/index.d.ts +4 -0
  96. package/dist/index.d.ts.map +1 -1
  97. package/dist/index.js +4 -0
  98. package/dist/index.js.map +1 -1
  99. package/dist/jobs/job-loader.d.ts +12 -4
  100. package/dist/jobs/job-loader.d.ts.map +1 -1
  101. package/dist/jobs/job-loader.js +56 -38
  102. package/dist/jobs/job-loader.js.map +1 -1
  103. package/dist/link-modules-sdk/index.d.ts +2 -0
  104. package/dist/link-modules-sdk/index.d.ts.map +1 -0
  105. package/dist/link-modules-sdk/index.js +18 -0
  106. package/dist/link-modules-sdk/index.js.map +1 -0
  107. package/dist/loader.d.ts +24 -0
  108. package/dist/loader.d.ts.map +1 -0
  109. package/dist/loader.js +104 -0
  110. package/dist/loader.js.map +1 -0
  111. package/dist/mikro-orm-cli/bin.js +0 -0
  112. package/dist/subscribers/subscriber-loader.d.ts +15 -1
  113. package/dist/subscribers/subscriber-loader.d.ts.map +1 -1
  114. package/dist/subscribers/subscriber-loader.js +44 -17
  115. package/dist/subscribers/subscriber-loader.js.map +1 -1
  116. package/dist/types/container.d.ts +2 -23
  117. package/dist/types/container.d.ts.map +1 -1
  118. package/dist/zod/zod-helpers.js +1 -1
  119. package/dist/zod/zod-helpers.js.map +1 -1
  120. package/package.json +12 -9
  121. package/dist/http/express-loader.d.ts +0 -8
  122. package/dist/http/express-loader.d.ts.map +0 -1
  123. package/dist/http/express-loader.js +0 -85
  124. package/dist/http/express-loader.js.map +0 -1
  125. package/dist/http/router.d.ts +0 -100
  126. package/dist/http/router.d.ts.map +0 -1
  127. package/dist/http/router.js +0 -764
  128. package/dist/http/router.js.map +0 -1
  129. package/dist/http/utils/define-middlewares.d.ts +0 -18
  130. package/dist/http/utils/define-middlewares.d.ts.map +0 -1
  131. package/dist/http/utils/define-middlewares.js +0 -40
  132. package/dist/http/utils/define-middlewares.js.map +0 -1
@@ -1,764 +0,0 @@
1
- "use strict";
2
- var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
3
- if (kind === "m") throw new TypeError("Private method is not writable");
4
- if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
5
- if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
6
- return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
7
- };
8
- var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
9
- if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
10
- if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
11
- return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
12
- };
13
- var __importDefault = (this && this.__importDefault) || function (mod) {
14
- return (mod && mod.__esModule) ? mod : { "default": mod };
15
- };
16
- var _ApiRoutesLoader_routesMap, _ApiRoutesLoader_globalMiddlewaresDescriptor, _ApiRoutesLoader_app, _ApiRoutesLoader_router, _ApiRoutesLoader_activityId, _ApiRoutesLoader_excludes, _ApiRoutesLoader_sourceDir, _RoutesLoader_instances, _RoutesLoader_app, _RoutesLoader_activityId, _RoutesLoader_sourceDir, _RoutesLoader_assignRestrictedFields;
17
- Object.defineProperty(exports, "__esModule", { value: true });
18
- exports.RoutesLoader = exports.ApiRoutesLoader = void 0;
19
- const utils_1 = require("@etohq/utils");
20
- const cors_1 = __importDefault(require("cors"));
21
- const express_1 = require("express");
22
- const promises_1 = require("fs/promises");
23
- const path_1 = require("path");
24
- const config_1 = require("../config");
25
- const logger_1 = require("../logger");
26
- const middlewares_1 = require("./middlewares");
27
- const ensure_publishable_api_key_1 = require("./middlewares/ensure-publishable-api-key");
28
- const types_1 = require("./types");
29
- const restricted_fields_1 = require("./utils/restricted-fields");
30
- const log = ({ activityId, message, }) => {
31
- if (activityId) {
32
- logger_1.logger.progress(activityId, message);
33
- return;
34
- }
35
- logger_1.logger.debug(message);
36
- };
37
- /**
38
- * File name that is used to indicate that the file is a route file
39
- */
40
- const ROUTE_NAME = "route";
41
- /**
42
- * Flag that developers can export from their route files to indicate
43
- * whether or not the route should be authenticated or not.
44
- */
45
- const AUTHTHENTICATE = "AUTHENTICATE";
46
- /**
47
- * File name for the global middlewares file
48
- */
49
- const MIDDLEWARES_NAME = "middlewares";
50
- const pathSegmentReplacer = {
51
- "\\[\\.\\.\\.\\]": () => `*`,
52
- "\\[(\\w+)?": (param) => `:${param}`,
53
- "\\]": () => ``,
54
- };
55
- /**
56
- * @param routes - The routes to prioritize
57
- *
58
- * @return An array of sorted
59
- * routes based on their priority
60
- */
61
- const prioritize = (routes) => {
62
- return routes.sort((a, b) => {
63
- return a.priority - b.priority;
64
- });
65
- };
66
- /**
67
- * The smaller the number the higher the priority with zero indicating
68
- * highest priority
69
- *
70
- * @param path - The path to calculate the priority for
71
- *
72
- * @return An integer ranging from `0` to `Infinity`
73
- */
74
- function calculatePriority(path) {
75
- const depth = path.match(/\/.+?/g)?.length || 0;
76
- const specifity = path.match(/\/:.+?/g)?.length || 0;
77
- const catchall = (path.match(/\/\*/g)?.length || 0) > 0 ? Infinity : 0;
78
- return depth + specifity + catchall;
79
- }
80
- function matchMethod(method, configMethod) {
81
- if (!configMethod || configMethod === "USE" || configMethod === "ALL") {
82
- return true;
83
- }
84
- else if (Array.isArray(configMethod)) {
85
- return (configMethod.includes(method) ||
86
- configMethod.includes("ALL") ||
87
- configMethod.includes("USE"));
88
- }
89
- else {
90
- return method === configMethod;
91
- }
92
- }
93
- /**
94
- * Function that looks though the global middlewares and returns the first
95
- * complete match for the given path and method.
96
- *
97
- * @param path - The path to match
98
- * @param method - The method to match
99
- * @param routes - The routes to match against
100
- * @returns The first complete match or undefined if no match is found
101
- */
102
- function findMatch(path, method, routes) {
103
- for (const route of routes) {
104
- const { matcher, method: configMethod } = route;
105
- if (matchMethod(method, configMethod)) {
106
- let isMatch = false;
107
- if (typeof matcher === "string") {
108
- // Convert wildcard expressions to proper regex for matching entire path
109
- // The '.*' will match any character sequence including '/'
110
- const regex = new RegExp(`^${matcher.split("*").join(".*")}$`);
111
- isMatch = regex.test(path);
112
- }
113
- else if (matcher instanceof RegExp) {
114
- // Ensure that the regex matches the entire path
115
- const match = path.match(matcher);
116
- isMatch = match !== null && match[0] === path;
117
- }
118
- if (isMatch) {
119
- return route; // Return the first complete match
120
- }
121
- }
122
- }
123
- return undefined; // Return undefined if no complete match is found
124
- }
125
- /**
126
- * Returns an array of body parser middlewares that are applied on routes
127
- * out-of-the-box.
128
- */
129
- function getBodyParserMiddleware(args) {
130
- const sizeLimit = args?.sizeLimit;
131
- const preserveRawBody = args?.preserveRawBody;
132
- return [
133
- (0, express_1.json)({
134
- limit: sizeLimit,
135
- verify: preserveRawBody
136
- ? (req, res, buf) => {
137
- req.rawBody = buf;
138
- }
139
- : undefined,
140
- }),
141
- (0, express_1.text)({ limit: sizeLimit }),
142
- (0, express_1.urlencoded)({ limit: sizeLimit, extended: true }),
143
- ];
144
- }
145
- function createCorsOptions(origin) {
146
- return {
147
- origin: (0, utils_1.parseCorsOrigins)(origin),
148
- credentials: true,
149
- };
150
- }
151
- function applyCors(router, route, corsConfig) {
152
- router.use(route, (0, cors_1.default)(corsConfig));
153
- }
154
- function getRouteContext(path) {
155
- /**
156
- * We cannot reliably guess the route context from a regex, so we skip it.
157
- */
158
- if (path instanceof RegExp) {
159
- return null;
160
- }
161
- if (path.startsWith("/admin")) {
162
- return "admin";
163
- }
164
- if (path.startsWith("/store")) {
165
- return "store";
166
- }
167
- if (path.startsWith("/auth")) {
168
- return "auth";
169
- }
170
- return null;
171
- }
172
- // TODO this router would need a proper rework, but it is out of scope right now
173
- class ApiRoutesLoader {
174
- constructor({ app, activityId, sourceDir, }) {
175
- /**
176
- * Map of router path and its descriptor
177
- * @private
178
- */
179
- _ApiRoutesLoader_routesMap.set(this, new Map()
180
- /**
181
- * Global middleware descriptors
182
- * @private
183
- */
184
- );
185
- /**
186
- * Global middleware descriptors
187
- * @private
188
- */
189
- _ApiRoutesLoader_globalMiddlewaresDescriptor.set(this, void 0);
190
- /**
191
- * An express instance
192
- * @private
193
- */
194
- _ApiRoutesLoader_app.set(this, void 0);
195
- /**
196
- * A router to assign the route to
197
- * @private
198
- */
199
- _ApiRoutesLoader_router.set(this, void 0);
200
- /**
201
- * An eventual activity id for information tracking
202
- * @private
203
- */
204
- _ApiRoutesLoader_activityId.set(this, void 0);
205
- /**
206
- * The list of file names to exclude from the routes scan
207
- * @private
208
- */
209
- _ApiRoutesLoader_excludes.set(this, [
210
- /\.DS_Store/,
211
- /(\.ts\.map|\.js\.map|\.d\.ts|\.md)/,
212
- /^_[^/\\]*(\.[^/\\]+)?$/,
213
- ]
214
- /**
215
- * Path from where to load the routes from
216
- * @private
217
- */
218
- );
219
- /**
220
- * Path from where to load the routes from
221
- * @private
222
- */
223
- _ApiRoutesLoader_sourceDir.set(this, void 0);
224
- __classPrivateFieldSet(this, _ApiRoutesLoader_app, app, "f");
225
- __classPrivateFieldSet(this, _ApiRoutesLoader_router, (0, express_1.Router)(), "f");
226
- __classPrivateFieldSet(this, _ApiRoutesLoader_activityId, activityId, "f");
227
- __classPrivateFieldSet(this, _ApiRoutesLoader_sourceDir, sourceDir, "f");
228
- }
229
- /**
230
- * Validate the route config and display a log info if
231
- * it should be ignored or skipped.
232
- *
233
- * @param {GlobalMiddlewareDescriptor} descriptor
234
- * @param {MiddlewaresConfig} config
235
- *
236
- * @return {void}
237
- */
238
- validateMiddlewaresConfig({ config, }) {
239
- if (!config?.routes && !config?.errorHandler) {
240
- log({
241
- activityId: __classPrivateFieldGet(this, _ApiRoutesLoader_activityId, "f"),
242
- message: `Empty middleware config. Skipping middleware application.`,
243
- });
244
- return;
245
- }
246
- for (const route of config.routes ?? []) {
247
- if (!route.matcher) {
248
- throw new Error(`Route is missing a \`matcher\` field. The 'matcher' field is required when applying middleware to this route.`);
249
- }
250
- }
251
- }
252
- /**
253
- * Take care of replacing the special path segments
254
- * to an express specific path segment
255
- *
256
- * @param route - The route to parse
257
- *
258
- * @example
259
- * "/admin/orders/[id]/route.ts => "/admin/orders/:id/route.ts"
260
- */
261
- parseRoute(route) {
262
- let route_ = route;
263
- for (const config of Object.entries(pathSegmentReplacer)) {
264
- const [searchFor, replacedByFn] = config;
265
- const replacer = new RegExp(searchFor, "g");
266
- const matches = [...route_.matchAll(replacer)];
267
- const parameters = new Set();
268
- for (const match of matches) {
269
- if (match?.[1] && !Number.isInteger(match?.[1])) {
270
- if (parameters.has(match?.[1])) {
271
- log({
272
- activityId: __classPrivateFieldGet(this, _ApiRoutesLoader_activityId, "f"),
273
- message: `Duplicate parameters found in route ${route} (${match?.[1]})`,
274
- });
275
- throw new Error(`Duplicate parameters found in route ${route} (${match?.[1]}). Make sure that all parameters are unique.`);
276
- }
277
- parameters.add(match?.[1]);
278
- }
279
- route_ = route_.replace(match[0], replacedByFn(match?.[1]));
280
- }
281
- const extension = (0, path_1.extname)(route_);
282
- if (extension) {
283
- route_ = route_.replace(extension, "");
284
- }
285
- }
286
- route = route_;
287
- return route;
288
- }
289
- /**
290
- * Load the file content from a descriptor and retrieve the verbs and handlers
291
- * to be assigned to the descriptor
292
- *
293
- * @return {Promise<void>}
294
- */
295
- async createRoutesConfig() {
296
- await (0, utils_1.promiseAll)([...__classPrivateFieldGet(this, _ApiRoutesLoader_routesMap, "f").values()].map(async (descriptor) => {
297
- const absolutePath = descriptor.absolutePath;
298
- const route = descriptor.route;
299
- return await (0, utils_1.dynamicImport)(absolutePath).then((import_) => {
300
- const map = __classPrivateFieldGet(this, _ApiRoutesLoader_routesMap, "f");
301
- const config = {
302
- routes: [],
303
- };
304
- /**
305
- * If the developer has not exported the
306
- * AUTHENTICATE flag we default to true.
307
- */
308
- const shouldRequireAuth = import_[AUTHTHENTICATE] !== undefined
309
- ? import_[AUTHTHENTICATE]
310
- : true;
311
- config.optedOutOfAuth = !shouldRequireAuth;
312
- /**
313
- * If the developer has not exported the
314
- * CORS flag we default to true.
315
- */
316
- const shouldAddCors = import_["CORS"] !== undefined ? import_["CORS"] : true;
317
- if (route.startsWith("/admin")) {
318
- config.routeType = "admin";
319
- if (shouldAddCors) {
320
- config.shouldAppendAdminCors = true;
321
- }
322
- }
323
- if (route.startsWith("/store")) {
324
- config.routeType = "store";
325
- if (shouldAddCors) {
326
- config.shouldAppendStoreCors = true;
327
- }
328
- }
329
- if (route.startsWith("/auth") && shouldAddCors) {
330
- config.routeType = "auth";
331
- if (shouldAddCors) {
332
- config.shouldAppendAuthCors = true;
333
- }
334
- }
335
- const handlers = Object.keys(import_).filter((key) => {
336
- /**
337
- * Filter out any export that is not a function
338
- */
339
- return typeof import_[key] === "function";
340
- });
341
- for (const handler of handlers) {
342
- if (types_1.HTTP_METHODS.includes(handler)) {
343
- config.routes?.push({
344
- method: handler,
345
- handler: import_[handler],
346
- });
347
- }
348
- else {
349
- log({
350
- activityId: __classPrivateFieldGet(this, _ApiRoutesLoader_activityId, "f"),
351
- message: `Skipping handler ${handler} in ${absolutePath}. Invalid HTTP method: ${handler}.`,
352
- });
353
- }
354
- }
355
- if (!config.routes?.length) {
356
- log({
357
- activityId: __classPrivateFieldGet(this, _ApiRoutesLoader_activityId, "f"),
358
- message: `No valid route handlers detected in ${absolutePath}. Skipping route configuration.`,
359
- });
360
- map.delete(absolutePath);
361
- return;
362
- }
363
- descriptor.config = config;
364
- map.set(absolutePath, descriptor);
365
- });
366
- }));
367
- }
368
- createRoutesDescriptor(path) {
369
- const descriptor = {
370
- absolutePath: path,
371
- relativePath: path,
372
- route: "",
373
- priority: Infinity,
374
- };
375
- const childPath = path.replace(__classPrivateFieldGet(this, _ApiRoutesLoader_sourceDir, "f"), "");
376
- descriptor.relativePath = childPath;
377
- let routeToParse = childPath;
378
- const pathSegments = routeToParse.split(path_1.sep);
379
- const lastSegment = pathSegments[pathSegments.length - 1];
380
- if (lastSegment.startsWith("route")) {
381
- pathSegments.pop();
382
- routeToParse = pathSegments.join("/");
383
- }
384
- descriptor.route = this.parseRoute(routeToParse);
385
- descriptor.priority = calculatePriority(descriptor.route);
386
- __classPrivateFieldGet(this, _ApiRoutesLoader_routesMap, "f").set(path, descriptor);
387
- }
388
- async createMiddlewaresDescriptor() {
389
- const filePaths = await (0, promises_1.readdir)(__classPrivateFieldGet(this, _ApiRoutesLoader_sourceDir, "f"));
390
- const filteredFilePaths = filePaths.filter((path) => {
391
- const pathToCheck = path.replace(__classPrivateFieldGet(this, _ApiRoutesLoader_sourceDir, "f"), "");
392
- return !pathToCheck
393
- .split(path_1.sep)
394
- .some((segment) => __classPrivateFieldGet(this, _ApiRoutesLoader_excludes, "f").some((exclude) => exclude.test(segment)));
395
- });
396
- const middlewareFilePath = filteredFilePaths.find((file) => {
397
- return file.replace(/\.[^/.]+$/, "") === MIDDLEWARES_NAME;
398
- });
399
- if (!middlewareFilePath) {
400
- log({
401
- activityId: __classPrivateFieldGet(this, _ApiRoutesLoader_activityId, "f"),
402
- message: `No middleware files found in ${__classPrivateFieldGet(this, _ApiRoutesLoader_sourceDir, "f")}. Skipping middleware configuration.`,
403
- });
404
- return;
405
- }
406
- const absolutePath = (0, path_1.join)(__classPrivateFieldGet(this, _ApiRoutesLoader_sourceDir, "f"), middlewareFilePath);
407
- await (0, utils_1.dynamicImport)(absolutePath).then((import_) => {
408
- const middlewaresConfig = (0, utils_1.resolveExports)(import_).default;
409
- if (!middlewaresConfig) {
410
- log({
411
- activityId: __classPrivateFieldGet(this, _ApiRoutesLoader_activityId, "f"),
412
- message: `No middleware configuration found in ${absolutePath}. Skipping middleware configuration.`,
413
- });
414
- return;
415
- }
416
- middlewaresConfig.routes = middlewaresConfig.routes?.map((route) => {
417
- return {
418
- ...route,
419
- method: route.method ?? "USE",
420
- };
421
- });
422
- const descriptor = {
423
- config: middlewaresConfig,
424
- };
425
- this.validateMiddlewaresConfig(descriptor);
426
- __classPrivateFieldSet(this, _ApiRoutesLoader_globalMiddlewaresDescriptor, descriptor, "f");
427
- });
428
- }
429
- async createRoutesMap() {
430
- await (0, utils_1.promiseAll)(await (0, utils_1.readDirRecursive)(__classPrivateFieldGet(this, _ApiRoutesLoader_sourceDir, "f")).then((entries) => {
431
- const fileEntries = entries.filter((entry) => {
432
- const fullPathFromSource = (0, path_1.join)(entry.path, entry.name).replace(__classPrivateFieldGet(this, _ApiRoutesLoader_sourceDir, "f"), "");
433
- const isExcluded = fullPathFromSource
434
- .split(path_1.sep)
435
- .some((segment) => __classPrivateFieldGet(this, _ApiRoutesLoader_excludes, "f").some((exclude) => exclude.test(segment)));
436
- return (!entry.isDirectory() &&
437
- !isExcluded &&
438
- (0, path_1.parse)(entry.name).name === ROUTE_NAME);
439
- });
440
- return fileEntries.map(async (entry) => {
441
- const path = (0, path_1.join)(entry.path, entry.name);
442
- return this.createRoutesDescriptor(path);
443
- });
444
- }));
445
- }
446
- /**
447
- * Apply the most specific body parser middleware to the router
448
- */
449
- applyBodyParserMiddleware(path, method) {
450
- const middlewareDescriptor = __classPrivateFieldGet(this, _ApiRoutesLoader_globalMiddlewaresDescriptor, "f");
451
- const mostSpecificConfig = findMatch(path, method, middlewareDescriptor?.config?.routes ?? []);
452
- if (!mostSpecificConfig || mostSpecificConfig?.bodyParser === undefined) {
453
- __classPrivateFieldGet(this, _ApiRoutesLoader_router, "f")[method.toLowerCase()](path, ...getBodyParserMiddleware());
454
- return;
455
- }
456
- if (mostSpecificConfig?.bodyParser) {
457
- __classPrivateFieldGet(this, _ApiRoutesLoader_router, "f")[method.toLowerCase()](path, ...getBodyParserMiddleware(mostSpecificConfig?.bodyParser));
458
- return;
459
- }
460
- return;
461
- }
462
- /**
463
- * Applies middleware that checks if a valid publishable key is set on store request
464
- */
465
- applyStorePublishableKeyMiddleware(route) {
466
- let middleware = ensure_publishable_api_key_1.ensurePublishableApiKeyMiddleware;
467
- if (ApiRoutesLoader.traceMiddleware) {
468
- middleware = ApiRoutesLoader.traceMiddleware(middleware, {
469
- route: String(route),
470
- });
471
- }
472
- __classPrivateFieldGet(this, _ApiRoutesLoader_router, "f").use(route, middleware);
473
- }
474
- /**
475
- * Applies the route middleware on a route. Encapsulates the logic
476
- * needed to pass the middleware via the trace calls
477
- */
478
- applyAuthMiddleware(route, actorType, authType, options) {
479
- let authenticateMiddleware = (0, middlewares_1.authenticate)(actorType, authType, options);
480
- if (ApiRoutesLoader.traceMiddleware) {
481
- authenticateMiddleware = ApiRoutesLoader.traceMiddleware(authenticateMiddleware, { route: String(route) });
482
- }
483
- __classPrivateFieldGet(this, _ApiRoutesLoader_router, "f").use(route, authenticateMiddleware);
484
- }
485
- /**
486
- * Apply the route specific middlewares to the router,
487
- * this includes the cors, authentication and
488
- * body parsing. These are applied first to ensure
489
- * that they are applied before any other middleware.
490
- */
491
- applyRouteSpecificMiddlewares() {
492
- const prioritizedRoutes = prioritize([...__classPrivateFieldGet(this, _ApiRoutesLoader_routesMap, "f").values()]);
493
- const handledPaths = new Set();
494
- const middlewarePaths = new Set();
495
- const globalRoutes = __classPrivateFieldGet(this, _ApiRoutesLoader_globalMiddlewaresDescriptor, "f")?.config?.routes ?? [];
496
- for (const route of globalRoutes) {
497
- middlewarePaths.add(route.matcher);
498
- }
499
- for (const descriptor of prioritizedRoutes) {
500
- if (!descriptor.config?.routes?.length) {
501
- continue;
502
- }
503
- const config = descriptor.config;
504
- handledPaths.add(descriptor.route);
505
- if (config.shouldAppendAdminCors) {
506
- applyCors(__classPrivateFieldGet(this, _ApiRoutesLoader_router, "f"), descriptor.route, createCorsOptions(config_1.configManager.config.projectConfig.http.adminCors));
507
- }
508
- if (config.shouldAppendAuthCors) {
509
- applyCors(__classPrivateFieldGet(this, _ApiRoutesLoader_router, "f"), descriptor.route, createCorsOptions(config_1.configManager.config.projectConfig.http.authCors));
510
- }
511
- if (config.shouldAppendStoreCors) {
512
- applyCors(__classPrivateFieldGet(this, _ApiRoutesLoader_router, "f"), descriptor.route, createCorsOptions(config_1.configManager.config.projectConfig.http.storeCors));
513
- }
514
- // Apply other middlewares
515
- if (config.routeType === "store") {
516
- this.applyStorePublishableKeyMiddleware(descriptor.route);
517
- }
518
- // We only apply the auth middleware to store routes to populate the auth context. For actual authentication, users can just reapply the middleware.
519
- if (!config.optedOutOfAuth && config.routeType === "store") {
520
- this.applyAuthMiddleware(descriptor.route, "customer", ["bearer", "session"], {
521
- allowUnauthenticated: true,
522
- });
523
- }
524
- if (!config.optedOutOfAuth && config.routeType === "admin") {
525
- this.applyAuthMiddleware(descriptor.route, "user", [
526
- "bearer",
527
- "session",
528
- "api-key",
529
- ]);
530
- }
531
- for (const route of descriptor.config.routes) {
532
- /**
533
- * Apply the body parser middleware if the route
534
- * has not opted out of it.
535
- */
536
- this.applyBodyParserMiddleware(descriptor.route, route.method);
537
- }
538
- }
539
- /**
540
- * Apply CORS and auth middleware for paths defined in global middleware but not already handled by routes.
541
- */
542
- for (const path of middlewarePaths) {
543
- if (typeof path === "string" && handledPaths.has(path)) {
544
- continue;
545
- }
546
- const context = getRouteContext(path);
547
- if (!context) {
548
- continue;
549
- }
550
- switch (context) {
551
- case "admin":
552
- applyCors(__classPrivateFieldGet(this, _ApiRoutesLoader_router, "f"), path, createCorsOptions(config_1.configManager.config.projectConfig.http.adminCors));
553
- this.applyAuthMiddleware(path, "user", [
554
- "bearer",
555
- "session",
556
- "api-key",
557
- ]);
558
- break;
559
- case "store":
560
- applyCors(__classPrivateFieldGet(this, _ApiRoutesLoader_router, "f"), path, createCorsOptions(config_1.configManager.config.projectConfig.http.storeCors));
561
- this.applyStorePublishableKeyMiddleware(path);
562
- break;
563
- case "auth":
564
- applyCors(__classPrivateFieldGet(this, _ApiRoutesLoader_router, "f"), path, createCorsOptions(config_1.configManager.config.projectConfig.http.authCors));
565
- break;
566
- }
567
- }
568
- }
569
- /**
570
- * Apply the error handler middleware to the router
571
- */
572
- applyErrorHandlerMiddleware() {
573
- const middlewareDescriptor = __classPrivateFieldGet(this, _ApiRoutesLoader_globalMiddlewaresDescriptor, "f");
574
- const errorHandlerFn = middlewareDescriptor?.config?.errorHandler;
575
- /**
576
- * If the user has opted out of the error handler then return
577
- */
578
- if (errorHandlerFn === false) {
579
- return;
580
- }
581
- /**
582
- * If the user has provided a custom error handler then use it
583
- */
584
- if (errorHandlerFn) {
585
- __classPrivateFieldGet(this, _ApiRoutesLoader_router, "f").use(errorHandlerFn);
586
- return;
587
- }
588
- /**
589
- * If the user has not provided a custom error handler then use the
590
- * default one.
591
- */
592
- __classPrivateFieldGet(this, _ApiRoutesLoader_router, "f").use((0, middlewares_1.errorHandler)());
593
- }
594
- async registerRoutes() {
595
- const middlewareDescriptor = __classPrivateFieldGet(this, _ApiRoutesLoader_globalMiddlewaresDescriptor, "f");
596
- const shouldWrapHandler = middlewareDescriptor?.config
597
- ? middlewareDescriptor.config.errorHandler !== false
598
- : true;
599
- const prioritizedRoutes = prioritize([...__classPrivateFieldGet(this, _ApiRoutesLoader_routesMap, "f").values()]);
600
- for (const descriptor of prioritizedRoutes) {
601
- if (!descriptor.config?.routes?.length) {
602
- continue;
603
- }
604
- const routes = descriptor.config.routes;
605
- for (const route of routes) {
606
- log({
607
- activityId: __classPrivateFieldGet(this, _ApiRoutesLoader_activityId, "f"),
608
- message: `Registering route [${route.method?.toUpperCase()}] - ${descriptor.route}`,
609
- });
610
- let handler = route.handler;
611
- /**
612
- * Give handler to the trace route handler for instrumentation
613
- * from outside-in.
614
- */
615
- if (ApiRoutesLoader.traceRoute) {
616
- handler = ApiRoutesLoader.traceRoute(handler, {
617
- method: route.method,
618
- route: descriptor.route,
619
- });
620
- }
621
- /**
622
- * If the user hasn't opted out of error handling then
623
- * we wrap the handler in a try/catch block.
624
- */
625
- if (shouldWrapHandler) {
626
- handler = (0, utils_1.wrapHandler)(handler);
627
- }
628
- __classPrivateFieldGet(this, _ApiRoutesLoader_router, "f")[route.method.toLowerCase()](descriptor.route, handler);
629
- }
630
- }
631
- }
632
- async registerMiddlewares() {
633
- const descriptor = __classPrivateFieldGet(this, _ApiRoutesLoader_globalMiddlewaresDescriptor, "f");
634
- if (!descriptor) {
635
- return;
636
- }
637
- if (!descriptor.config?.routes?.length) {
638
- return;
639
- }
640
- const routes = descriptor.config.routes;
641
- /**
642
- * We don't prioritize the middlewares to preserve the order
643
- * in which they are defined in the 'middlewares.ts'. This is to
644
- * maintain the same behavior as how middleware is applied
645
- * in Express.
646
- */
647
- for (const route of routes) {
648
- if (!route.middlewares || !route.middlewares.length) {
649
- continue;
650
- }
651
- const methods = (Array.isArray(route.method) ? route.method : [route.method]).filter(Boolean);
652
- for (const method of methods) {
653
- log({
654
- activityId: __classPrivateFieldGet(this, _ApiRoutesLoader_activityId, "f"),
655
- message: `Registering middleware [${method}] - ${route.matcher}`,
656
- });
657
- let middlewares = route.middlewares;
658
- if (ApiRoutesLoader.traceMiddleware) {
659
- middlewares = middlewares.map((middleware) => ApiRoutesLoader.traceMiddleware(middleware, {
660
- route: String(route.matcher),
661
- method,
662
- }));
663
- }
664
- __classPrivateFieldGet(this, _ApiRoutesLoader_router, "f")[method.toLowerCase()](route.matcher, ...middlewares);
665
- }
666
- }
667
- }
668
- async load() {
669
- performance && performance.mark("file-base-routing-start" + __classPrivateFieldGet(this, _ApiRoutesLoader_sourceDir, "f"));
670
- let apiExists = true;
671
- /**
672
- * Since the file based routing does not require a index file
673
- * we can't check if it exists using require. Instead we try
674
- * to read the directory and if it fails we know that the
675
- * directory does not exist.
676
- */
677
- try {
678
- await (0, promises_1.readdir)(__classPrivateFieldGet(this, _ApiRoutesLoader_sourceDir, "f"));
679
- }
680
- catch (_error) {
681
- apiExists = false;
682
- }
683
- if (apiExists) {
684
- await this.createMiddlewaresDescriptor();
685
- await this.createRoutesMap();
686
- await this.createRoutesConfig();
687
- this.applyRouteSpecificMiddlewares();
688
- await this.registerMiddlewares();
689
- await this.registerRoutes();
690
- this.applyErrorHandlerMiddleware();
691
- /**
692
- * Apply the router to the app.
693
- *
694
- * This prevents middleware from a plugin from
695
- * bleeding into the global middleware stack.
696
- */
697
- __classPrivateFieldGet(this, _ApiRoutesLoader_app, "f").use("/", __classPrivateFieldGet(this, _ApiRoutesLoader_router, "f"));
698
- }
699
- performance && performance.mark("file-base-routing-end" + __classPrivateFieldGet(this, _ApiRoutesLoader_sourceDir, "f"));
700
- const timeSpent = performance &&
701
- performance
702
- .measure("file-base-routing-measure" + __classPrivateFieldGet(this, _ApiRoutesLoader_sourceDir, "f"), "file-base-routing-start" + __classPrivateFieldGet(this, _ApiRoutesLoader_sourceDir, "f"), "file-base-routing-end" + __classPrivateFieldGet(this, _ApiRoutesLoader_sourceDir, "f"))
703
- ?.duration?.toFixed(2);
704
- log({
705
- activityId: __classPrivateFieldGet(this, _ApiRoutesLoader_activityId, "f"),
706
- message: `Routes loaded in ${timeSpent} ms`,
707
- });
708
- __classPrivateFieldGet(this, _ApiRoutesLoader_routesMap, "f").clear();
709
- __classPrivateFieldSet(this, _ApiRoutesLoader_globalMiddlewaresDescriptor, undefined, "f");
710
- }
711
- }
712
- exports.ApiRoutesLoader = ApiRoutesLoader;
713
- _ApiRoutesLoader_routesMap = new WeakMap(), _ApiRoutesLoader_globalMiddlewaresDescriptor = new WeakMap(), _ApiRoutesLoader_app = new WeakMap(), _ApiRoutesLoader_router = new WeakMap(), _ApiRoutesLoader_activityId = new WeakMap(), _ApiRoutesLoader_excludes = new WeakMap(), _ApiRoutesLoader_sourceDir = new WeakMap();
714
- class RoutesLoader {
715
- constructor({ app, activityId, sourceDir, baseRestrictedFields = [], }) {
716
- _RoutesLoader_instances.add(this);
717
- /**
718
- * An express instance
719
- * @private
720
- */
721
- _RoutesLoader_app.set(this, void 0);
722
- /**
723
- * An eventual activity id for information tracking
724
- * @private
725
- */
726
- _RoutesLoader_activityId.set(this, void 0);
727
- /**
728
- * Path from where to load the routes from
729
- * @private
730
- */
731
- _RoutesLoader_sourceDir.set(this, void 0);
732
- __classPrivateFieldSet(this, _RoutesLoader_app, app, "f");
733
- __classPrivateFieldSet(this, _RoutesLoader_activityId, activityId, "f");
734
- __classPrivateFieldSet(this, _RoutesLoader_sourceDir, sourceDir, "f");
735
- __classPrivateFieldGet(this, _RoutesLoader_instances, "m", _RoutesLoader_assignRestrictedFields).call(this, baseRestrictedFields);
736
- }
737
- async load() {
738
- const normalizedSourcePath = Array.isArray(__classPrivateFieldGet(this, _RoutesLoader_sourceDir, "f"))
739
- ? __classPrivateFieldGet(this, _RoutesLoader_sourceDir, "f")
740
- : [__classPrivateFieldGet(this, _RoutesLoader_sourceDir, "f")];
741
- const promises = normalizedSourcePath.map(async (sourcePath) => {
742
- const apiRoutesLoader = new ApiRoutesLoader({
743
- app: __classPrivateFieldGet(this, _RoutesLoader_app, "f"),
744
- activityId: __classPrivateFieldGet(this, _RoutesLoader_activityId, "f"),
745
- sourceDir: sourcePath,
746
- });
747
- await apiRoutesLoader.load();
748
- });
749
- await (0, utils_1.promiseAll)(promises);
750
- }
751
- }
752
- exports.RoutesLoader = RoutesLoader;
753
- _RoutesLoader_app = new WeakMap(), _RoutesLoader_activityId = new WeakMap(), _RoutesLoader_sourceDir = new WeakMap(), _RoutesLoader_instances = new WeakSet(), _RoutesLoader_assignRestrictedFields = function _RoutesLoader_assignRestrictedFields(baseRestrictedFields) {
754
- __classPrivateFieldGet(this, _RoutesLoader_app, "f").use("/store", ((req, _, next) => {
755
- req.restrictedFields = new restricted_fields_1.RestrictedFields();
756
- req.restrictedFields.add(baseRestrictedFields);
757
- next();
758
- }));
759
- __classPrivateFieldGet(this, _RoutesLoader_app, "f").use("/admin", ((req, _, next) => {
760
- req.restrictedFields = new restricted_fields_1.RestrictedFields();
761
- next();
762
- }));
763
- };
764
- //# sourceMappingURL=router.js.map