@cedarjs/api-server 4.0.0 → 4.0.1-next.67

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 (39) hide show
  1. package/dist/bin.js +112 -38
  2. package/dist/cjs/bin.js +122 -48
  3. package/dist/cjs/createServer.d.ts.map +1 -1
  4. package/dist/cjs/createServer.js +6 -5
  5. package/dist/cjs/fastify.d.ts.map +1 -1
  6. package/dist/cjs/fastify.js +5 -0
  7. package/dist/cjs/plugins/api.d.ts.map +1 -1
  8. package/dist/cjs/plugins/graphql.d.ts.map +1 -1
  9. package/dist/cjs/plugins/graphql.js +27 -21
  10. package/dist/cjs/plugins/lambdaLoader.d.ts +16 -6
  11. package/dist/cjs/plugins/lambdaLoader.d.ts.map +1 -1
  12. package/dist/cjs/plugins/lambdaLoader.js +76 -12
  13. package/dist/cjs/requestHandlers/awsLambdaFastify.d.ts.map +1 -1
  14. package/dist/cjs/requestHandlers/awsLambdaFastify.js +6 -2
  15. package/dist/cjs/udDispatcher.d.ts +28 -0
  16. package/dist/cjs/udDispatcher.d.ts.map +1 -0
  17. package/dist/cjs/udDispatcher.js +192 -0
  18. package/dist/cjs/udFetchable.d.ts +12 -0
  19. package/dist/cjs/udFetchable.d.ts.map +1 -0
  20. package/dist/cjs/udFetchable.js +36 -0
  21. package/dist/createServer.d.ts.map +1 -1
  22. package/dist/createServer.js +3 -2
  23. package/dist/fastify.d.ts.map +1 -1
  24. package/dist/fastify.js +5 -0
  25. package/dist/plugins/api.d.ts.map +1 -1
  26. package/dist/plugins/graphql.d.ts.map +1 -1
  27. package/dist/plugins/graphql.js +27 -21
  28. package/dist/plugins/lambdaLoader.d.ts +16 -6
  29. package/dist/plugins/lambdaLoader.d.ts.map +1 -1
  30. package/dist/plugins/lambdaLoader.js +72 -10
  31. package/dist/requestHandlers/awsLambdaFastify.d.ts.map +1 -1
  32. package/dist/requestHandlers/awsLambdaFastify.js +6 -2
  33. package/dist/udDispatcher.d.ts +28 -0
  34. package/dist/udDispatcher.d.ts.map +1 -0
  35. package/dist/udDispatcher.js +158 -0
  36. package/dist/udFetchable.d.ts +12 -0
  37. package/dist/udFetchable.d.ts.map +1 -0
  38. package/dist/udFetchable.js +12 -0
  39. package/package.json +40 -11
@@ -32,7 +32,8 @@ __export(createServer_exports, {
32
32
  });
33
33
  module.exports = __toCommonJS(createServer_exports);
34
34
  var import_node_fs = __toESM(require("node:fs"), 1);
35
- var import_path = __toESM(require("path"), 1);
35
+ var import_node_path = __toESM(require("node:path"), 1);
36
+ var import_node_url = require("node:url");
36
37
  var import_ansis = __toESM(require("ansis"), 1);
37
38
  var import_dotenv_defaults = require("dotenv-defaults");
38
39
  var import_fast_glob = __toESM(require("fast-glob"), 1);
@@ -43,8 +44,8 @@ var import_createServerHelpers = require("./createServerHelpers.js");
43
44
  var import_api = require("./plugins/api.js");
44
45
  if (!process.env.CEDAR_ENV_FILES_LOADED) {
45
46
  (0, import_dotenv_defaults.config)({
46
- path: import_path.default.join((0, import_project_config.getPaths)().base, ".env"),
47
- defaults: import_path.default.join((0, import_project_config.getPaths)().base, ".env.defaults"),
47
+ path: import_node_path.default.join((0, import_project_config.getPaths)().base, ".env"),
48
+ defaults: import_node_path.default.join((0, import_project_config.getPaths)().base, ".env.defaults"),
48
49
  multiline: true
49
50
  });
50
51
  process.env.CEDAR_ENV_FILES_LOADED = "true";
@@ -58,7 +59,7 @@ async function createServer(options = {}) {
58
59
  apiPort,
59
60
  apiHost
60
61
  } = (0, import_createServerHelpers.resolveOptions)(options);
61
- const serverConfigPath = import_path.default.join(
62
+ const serverConfigPath = import_node_path.default.join(
62
63
  (0, import_project_config.getPaths)().base,
63
64
  (0, import_project_config.getConfig)().api.serverConfig
64
65
  );
@@ -109,7 +110,7 @@ async function createServer(options = {}) {
109
110
  });
110
111
  if (graphqlFunctionPath) {
111
112
  const { redwoodFastifyGraphQLServer } = await import("./plugins/graphql.js");
112
- const { __rw_graphqlOptions } = await import(`file://${graphqlFunctionPath}`);
113
+ const { __rw_graphqlOptions } = await import((0, import_node_url.pathToFileURL)(graphqlFunctionPath).href);
113
114
  await server.register(redwoodFastifyGraphQLServer, {
114
115
  redwood: {
115
116
  apiRootPath,
@@ -1 +1 @@
1
- {"version":3,"file":"fastify.d.ts","sourceRoot":"","sources":["../../src/fastify.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAA;AAOpE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAA;AAGrD,eAAO,MAAM,eAAe;;;;CAI3B,CAAA;AAiBD,wBAAsB,iBAAiB;YAb7B,oBAAoB;sBACV,mBAAmB;GAsCtC;AAED,eAAO,MAAM,qBAAqB,GAChC,UAAU,oBAAoB,KAC7B,OAAO,CAAC,eAAe,CAWzB,CAAA"}
1
+ {"version":3,"file":"fastify.d.ts","sourceRoot":"","sources":["../../src/fastify.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAA;AAOpE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAA;AAGrD,eAAO,MAAM,eAAe;;;;CAI3B,CAAA;AAkBD,wBAAsB,iBAAiB;YAb7B,oBAAoB;sBACV,mBAAmB;GA2CtC;AAED,eAAO,MAAM,qBAAqB,GAChC,UAAU,oBAAoB,KAC7B,OAAO,CAAC,eAAe,CAWzB,CAAA"}
@@ -45,6 +45,7 @@ const DEFAULT_OPTIONS = {
45
45
  }
46
46
  };
47
47
  let isServerConfigLoaded = false;
48
+ let loadedServerConfigPath;
48
49
  let serverConfigFile = {
49
50
  config: DEFAULT_OPTIONS,
50
51
  configureFastify: async (fastify, options) => {
@@ -63,6 +64,9 @@ async function loadFastifyConfig() {
63
64
  if (!import_node_fs.default.existsSync(serverConfigPath)) {
64
65
  return serverConfigFile;
65
66
  }
67
+ if (loadedServerConfigPath !== serverConfigPath) {
68
+ isServerConfigLoaded = false;
69
+ }
66
70
  if (!isServerConfigLoaded) {
67
71
  console.log(`Loading server config from ${serverConfigPath}`);
68
72
  console.log(`Loading server config from URL file://${serverConfigPath}`);
@@ -71,6 +75,7 @@ async function loadFastifyConfig() {
71
75
  );
72
76
  const config = await import((0, import_url.pathToFileURL)(serverConfigPath).href);
73
77
  serverConfigFile = { ...config.default };
78
+ loadedServerConfigPath = serverConfigPath;
74
79
  isServerConfigLoaded = true;
75
80
  }
76
81
  return serverConfigFile;
@@ -1 +1 @@
1
- {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../../src/plugins/api.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,WAAW,CAAA;AAC3D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAO9C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,2BAA2B,CAAA;AAKvD,MAAM,WAAW,sBAAsB;IAErC,OAAO,EAAE;QACP,WAAW,CAAC,EAAE,MAAM,CAAA;QACpB,eAAe,CAAC,EAAE,eAAe,CAAA;QACjC,qBAAqB,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;QACzC,cAAc,CAAC,EAAE,OAAO,CAAA;QACxB,eAAe,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;KAC3D,CAAA;CACF;AAED,wBAAsB,eAAe,CACnC,OAAO,EAAE,eAAe,EACxB,IAAI,EAAE,sBAAsB,iBA4C7B"}
1
+ {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../../src/plugins/api.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,WAAW,CAAA;AAC3D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAO9C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,2BAA2B,CAAA;AAKvD,MAAM,WAAW,sBAAsB;IAErC,OAAO,EAAE;QACP,WAAW,CAAC,EAAE,MAAM,CAAA;QACpB,eAAe,CAAC,EAAE,eAAe,CAAA;QACjC,qBAAqB,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;QACzC,cAAc,CAAC,EAAE,OAAO,CAAA;QACxB,eAAe,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;KAI3D,CAAA;CACF;AAED,wBAAsB,eAAe,CACnC,OAAO,EAAE,eAAe,EACxB,IAAI,EAAE,sBAAsB,iBA4C7B"}
@@ -1 +1 @@
1
- {"version":3,"file":"graphql.d.ts","sourceRoot":"","sources":["../../../src/plugins/graphql.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAe,MAAM,SAAS,CAAA;AAO3D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAKjE,MAAM,WAAW,4BAA4B;IAC3C,OAAO,EAAE;QACP,WAAW,CAAC,EAAE,MAAM,CAAA;QACpB,OAAO,CAAC,EAAE,kBAAkB,CAAA;KAC7B,CAAA;CACF;AAED,wBAAsB,2BAA2B,CAC/C,OAAO,EAAE,eAAe,EACxB,OAAO,EAAE,4BAA4B,iBAmGtC"}
1
+ {"version":3,"file":"graphql.d.ts","sourceRoot":"","sources":["../../../src/plugins/graphql.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,eAAe,EAA+B,MAAM,SAAS,CAAA;AAO3E,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAKjE,MAAM,WAAW,4BAA4B;IAC3C,OAAO,EAAE;QACP,WAAW,CAAC,EAAE,MAAM,CAAA;QACpB,OAAO,CAAC,EAAE,kBAAkB,CAAA;KAC7B,CAAA;CACF;AAED,wBAAsB,2BAA2B,CAC/C,OAAO,EAAE,eAAe,EACxB,OAAO,EAAE,4BAA4B,iBAuGtC"}
@@ -31,9 +31,11 @@ __export(graphql_exports, {
31
31
  redwoodFastifyGraphQLServer: () => redwoodFastifyGraphQLServer
32
32
  });
33
33
  module.exports = __toCommonJS(graphql_exports);
34
+ var import_node_url = require("node:url");
34
35
  var import_multipart = __toESM(require("@fastify/multipart"), 1);
35
36
  var import_url_data = __toESM(require("@fastify/url-data"), 1);
36
37
  var import_fast_glob = __toESM(require("fast-glob"), 1);
38
+ var import_runtime = require("@cedarjs/api/runtime");
37
39
  var import_store = require("@cedarjs/context/dist/store");
38
40
  var import_helpers = require("@cedarjs/fastify-web/dist/helpers.js");
39
41
  var import_graphql_server = require("@cedarjs/graphql-server");
@@ -55,7 +57,7 @@ async function redwoodFastifyGraphQLServer(fastify, options) {
55
57
  cwd: (0, import_project_config.getPaths)().api.base,
56
58
  absolute: true
57
59
  });
58
- const filePath = `file://${graphqlFunctionPath}`;
60
+ const filePath = (0, import_node_url.pathToFileURL)(graphqlFunctionPath).href;
59
61
  const { __rw_graphqlOptions } = await import(filePath);
60
62
  if (!__rw_graphqlOptions) {
61
63
  return;
@@ -63,33 +65,28 @@ async function redwoodFastifyGraphQLServer(fastify, options) {
63
65
  redwoodOptions.graphql = __rw_graphqlOptions;
64
66
  }
65
67
  const graphqlOptions = redwoodOptions.graphql;
66
- if (graphqlOptions?.realtime) {
67
- const { useCedarRealtime } = await import("@cedarjs/realtime");
68
- const originalExtraPlugins = graphqlOptions.extraPlugins ?? [];
69
- originalExtraPlugins.push(
70
- // This type cast is needed because useCedarRealtime returns an
71
- // EnvelopPlugin and here we need a YogaPlugin. I can't change the
72
- // return type of `useCedarRealtime` yet, because it'd be a breaking
73
- // change.
74
- useCedarRealtime(graphqlOptions.realtime)
75
- );
76
- graphqlOptions.extraPlugins = originalExtraPlugins;
77
- if (graphqlOptions.realtime.subscriptions) {
78
- method.push("PUT");
79
- }
68
+ if (graphqlOptions?.realtime?.subscriptions) {
69
+ method.push("PUT");
80
70
  }
81
- const { yoga } = (0, import_graphql_server.createGraphQLYoga)(graphqlOptions);
71
+ const { yoga } = await (0, import_graphql_server.createGraphQLYoga)(graphqlOptions);
82
72
  const graphqlEndpoint = trimSlashes(yoga.graphqlEndpoint);
83
73
  const routePaths = ["", "/health", "/readiness", "/stream"];
84
74
  for (const routePath of routePaths) {
85
75
  fastify.route({
86
76
  url: `${redwoodOptions.apiRootPath}${graphqlEndpoint}${routePath}`,
87
77
  method,
88
- handler: (req, reply) => yoga.handleNodeRequestAndResponse(req, reply, {
89
- req,
90
- reply,
91
- event: (0, import_awsLambdaFastify.lambdaEventForFastifyRequest)(req)
92
- })
78
+ handler: async (req, _reply) => {
79
+ const request = createFetchRequest(req);
80
+ const cedarContext = await (0, import_runtime.buildCedarContext)(request, {
81
+ authDecoder: graphqlOptions.authDecoder
82
+ });
83
+ return yoga.handle(request, {
84
+ request,
85
+ cedarContext,
86
+ event: (0, import_awsLambdaFastify.lambdaEventForFastifyRequest)(req),
87
+ requestContext: void 0
88
+ });
89
+ }
93
90
  });
94
91
  }
95
92
  fastify.addHook("onReady", (done) => {
@@ -109,6 +106,15 @@ async function redwoodFastifyGraphQLServer(fastify, options) {
109
106
  function trimSlashes(path) {
110
107
  return path.replace(/^\/|\/$/g, "");
111
108
  }
109
+ function createFetchRequest(req) {
110
+ const requestBody = req.method === "GET" || req.method === "HEAD" ? void 0 : typeof req.body === "string" ? req.body : req.body ? JSON.stringify(req.body) : void 0;
111
+ const href = `${req.protocol}://${req.hostname}${req.raw.url ?? "/"}`;
112
+ return new Request(href, {
113
+ method: req.method,
114
+ headers: req.headers,
115
+ body: requestBody
116
+ });
117
+ }
112
118
  // Annotate the CommonJS export names for ESM import in node:
113
119
  0 && (module.exports = {
114
120
  redwoodFastifyGraphQLServer
@@ -1,8 +1,16 @@
1
1
  import type { Handler } from 'aws-lambda';
2
2
  import type { Options as FastGlobOptions } from 'fast-glob';
3
3
  import type { FastifyReply, FastifyRequest, RequestGenericInterface } from 'fastify';
4
- export type Lambdas = Record<string, Handler>;
5
- export declare const LAMBDA_FUNCTIONS: Lambdas;
4
+ import type { CedarHandler, CedarRouteRecord } from '@cedarjs/api/runtime';
5
+ export declare const LAMBDA_FUNCTIONS: Map<string, Handler>;
6
+ export declare const CEDAR_HANDLERS: Map<string, CedarHandler>;
7
+ /**
8
+ * Exports a copy of the Cedar route manifest.
9
+ *
10
+ * This is intended to be used to later build WinterTC compatible `fetch`
11
+ * exports
12
+ */
13
+ export declare const getCedarRouteManifest: () => CedarRouteRecord[];
6
14
  export declare const setLambdaFunctions: (foundFunctions: string[]) => Promise<void>;
7
15
  type LoadFunctionsFromDistOptions = {
8
16
  fastGlobOptions?: FastGlobOptions;
@@ -15,10 +23,12 @@ interface LambdaHandlerRequest extends RequestGenericInterface {
15
23
  };
16
24
  }
17
25
  /**
18
- This will take a fastify request
19
- Then convert it to a lambdaEvent, and pass it to the the appropriate handler for the routeName
20
- The LAMBDA_FUNCTIONS lookup has been populated already by this point
21
- **/
26
+ * This will take a fastify request
27
+ * Then convert it to a lambdaEvent, and pass it to the the appropriate handler
28
+ * for the routeName
29
+ * The CEDAR_HANDLERS and LAMBDA_FUNCTIONS maps have been populated already by
30
+ * this point
31
+ */
22
32
  export declare const lambdaRequestHandler: (req: FastifyRequest<LambdaHandlerRequest>, reply: FastifyReply) => Promise<void>;
23
33
  export {};
24
34
  //# sourceMappingURL=lambdaLoader.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"lambdaLoader.d.ts","sourceRoot":"","sources":["../../../src/plugins/lambdaLoader.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAA;AAEzC,OAAO,KAAK,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,WAAW,CAAA;AAC3D,OAAO,KAAK,EACV,YAAY,EACZ,cAAc,EACd,uBAAuB,EACxB,MAAM,SAAS,CAAA;AAOhB,MAAM,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;AAC7C,eAAO,MAAM,gBAAgB,EAAE,OAAY,CAAA;AAI3C,eAAO,MAAM,kBAAkB,GAAU,gBAAgB,MAAM,EAAE,kBAsDhE,CAAA;AAED,KAAK,4BAA4B,GAAG;IAClC,eAAe,CAAC,EAAE,eAAe,CAAA;IACjC,qBAAqB,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;CAC1C,CAAA;AAGD,eAAO,MAAM,qBAAqB,GAChC,UAAS,4BAAiC,kBAe3C,CAAA;AA0BD,UAAU,oBAAqB,SAAQ,uBAAuB;IAC5D,MAAM,EAAE;QACN,SAAS,EAAE,MAAM,CAAA;KAClB,CAAA;CACF;AAED;;;;IAII;AACJ,eAAO,MAAM,oBAAoB,GAC/B,KAAK,cAAc,CAAC,oBAAoB,CAAC,EACzC,OAAO,YAAY,kBAsBpB,CAAA"}
1
+ {"version":3,"file":"lambdaLoader.d.ts","sourceRoot":"","sources":["../../../src/plugins/lambdaLoader.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAA;AAEzC,OAAO,KAAK,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,WAAW,CAAA;AAC3D,OAAO,KAAK,EACV,YAAY,EACZ,cAAc,EACd,uBAAuB,EACxB,MAAM,SAAS,CAAA;AAGhB,OAAO,KAAK,EACV,YAAY,EACZ,gBAAgB,EAEjB,MAAM,sBAAsB,CAAA;AAO7B,eAAO,MAAM,gBAAgB,sBAA6B,CAAA;AAC1D,eAAO,MAAM,cAAc,2BAAkC,CAAA;AAG7D;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,0BAAgC,CAAA;AAIlE,eAAO,MAAM,kBAAkB,GAAU,gBAAgB,MAAM,EAAE,kBAuGhE,CAAA;AAED,KAAK,4BAA4B,GAAG;IAClC,eAAe,CAAC,EAAE,eAAe,CAAA;IACjC,qBAAqB,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;CAC1C,CAAA;AAGD,eAAO,MAAM,qBAAqB,GAChC,UAAS,4BAAiC,kBAe3C,CAAA;AA0BD,UAAU,oBAAqB,SAAQ,uBAAuB;IAC5D,MAAM,EAAE;QACN,SAAS,EAAE,MAAM,CAAA;KAClB,CAAA;CACF;AAED;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,GAC/B,KAAK,cAAc,CAAC,oBAAoB,CAAC,EACzC,OAAO,YAAY,kBAqEpB,CAAA"}
@@ -28,26 +28,38 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
28
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
29
  var lambdaLoader_exports = {};
30
30
  __export(lambdaLoader_exports, {
31
+ CEDAR_HANDLERS: () => CEDAR_HANDLERS,
31
32
  LAMBDA_FUNCTIONS: () => LAMBDA_FUNCTIONS,
33
+ getCedarRouteManifest: () => getCedarRouteManifest,
32
34
  lambdaRequestHandler: () => lambdaRequestHandler,
33
35
  loadFunctionsFromDist: () => loadFunctionsFromDist,
34
36
  setLambdaFunctions: () => setLambdaFunctions
35
37
  });
36
38
  module.exports = __toCommonJS(lambdaLoader_exports);
37
- var import_path = __toESM(require("path"), 1);
39
+ var import_node_path = __toESM(require("node:path"), 1);
40
+ var import_node_url = require("node:url");
38
41
  var import_ansis = __toESM(require("ansis"), 1);
39
42
  var import_fast_glob = __toESM(require("fast-glob"), 1);
43
+ var import_termi_link = require("termi-link");
44
+ var import_runtime = require("@cedarjs/api/runtime");
40
45
  var import_project_config = require("@cedarjs/project-config");
41
46
  var import_awsLambdaFastify = require("../requestHandlers/awsLambdaFastify.js");
42
47
  var import_utils = require("../utils.js");
43
- const LAMBDA_FUNCTIONS = {};
48
+ const LAMBDA_FUNCTIONS = /* @__PURE__ */ new Map();
49
+ const CEDAR_HANDLERS = /* @__PURE__ */ new Map();
50
+ const cedarRouteManifest = [];
51
+ const getCedarRouteManifest = () => [...cedarRouteManifest];
44
52
  const setLambdaFunctions = async (foundFunctions) => {
45
53
  const tsImport = Date.now();
46
54
  console.log(import_ansis.default.dim.italic("Importing Server Functions... "));
55
+ cedarRouteManifest.length = 0;
56
+ LAMBDA_FUNCTIONS.clear();
57
+ CEDAR_HANDLERS.clear();
47
58
  const imports = foundFunctions.map(async (fnPath) => {
48
59
  const ts = Date.now();
49
- const routeName = import_path.default.basename(fnPath).replace(".js", "");
50
- const fnImport = await import(`file://${fnPath}`);
60
+ const routeName = import_node_path.default.basename(fnPath).replace(".js", "");
61
+ const routePath = routeName === "graphql" ? "/graphql" : `/${routeName}`;
62
+ const fnImport = await import((0, import_node_url.pathToFileURL)(fnPath).href);
51
63
  const handler = (() => {
52
64
  if ("handler" in fnImport) {
53
65
  return fnImport.handler;
@@ -59,17 +71,39 @@ const setLambdaFunctions = async (foundFunctions) => {
59
71
  }
60
72
  return void 0;
61
73
  })();
62
- LAMBDA_FUNCTIONS[routeName] = handler;
63
- if (!handler) {
74
+ const cedarHandler = (() => {
75
+ if ("handleRequest" in fnImport && typeof fnImport.handleRequest === "function") {
76
+ return fnImport.handleRequest;
77
+ }
78
+ if ("default" in fnImport && fnImport.default && "handleRequest" in fnImport.default && typeof fnImport.default.handleRequest === "function") {
79
+ return fnImport.default.handleRequest;
80
+ }
81
+ return void 0;
82
+ })();
83
+ if (handler) {
84
+ LAMBDA_FUNCTIONS.set(routeName, handler);
85
+ }
86
+ if (cedarHandler) {
87
+ CEDAR_HANDLERS.set(routeName, cedarHandler);
88
+ } else if (handler) {
89
+ CEDAR_HANDLERS.set(routeName, (0, import_runtime.wrapLegacyHandler)(handler));
90
+ }
91
+ if (!handler && !cedarHandler) {
64
92
  console.warn(
65
93
  routeName,
66
94
  "at",
67
95
  fnPath,
68
- "does not have a function called handler defined."
96
+ "does not have a function called handler or handleRequest defined."
69
97
  );
70
98
  }
99
+ cedarRouteManifest.push({
100
+ path: routePath,
101
+ methods: routeName === "graphql" ? ["GET", "POST", "OPTIONS"] : ["GET", "POST"],
102
+ type: routeName === "graphql" ? "graphql" : routeName === "health" ? "health" : routeName.toLowerCase().includes("auth") ? "auth" : "function",
103
+ entry: fnPath
104
+ });
71
105
  console.log(
72
- import_ansis.default.magenta("/" + routeName),
106
+ (0, import_termi_link.terminalLink)(import_ansis.default.magenta("/" + routeName), (0, import_node_url.pathToFileURL)(fnPath).href),
73
107
  import_ansis.default.dim.italic(Date.now() - ts + " ms")
74
108
  );
75
109
  });
@@ -84,7 +118,7 @@ const loadFunctionsFromDist = async (options = {}) => {
84
118
  options: options?.fastGlobOptions,
85
119
  discoverFunctionsGlob: options?.discoverFunctionsGlob
86
120
  });
87
- const i = serverFunctions.findIndex((x) => import_path.default.basename(x) === "graphql.js");
121
+ const i = serverFunctions.findIndex((x) => import_node_path.default.basename(x) === "graphql.js");
88
122
  if (i >= 0) {
89
123
  const graphQLFn = serverFunctions.splice(i, 1)[0];
90
124
  serverFunctions.unshift(graphQLFn);
@@ -108,14 +142,43 @@ const findApiDistFunctions = (params) => {
108
142
  };
109
143
  const lambdaRequestHandler = async (req, reply) => {
110
144
  const { routeName } = req.params;
111
- if (!LAMBDA_FUNCTIONS[routeName]) {
145
+ const cedarHandlerCandidate = CEDAR_HANDLERS.get(routeName);
146
+ const cedarHandler = typeof cedarHandlerCandidate === "function" ? cedarHandlerCandidate : void 0;
147
+ if (cedarHandler) {
148
+ const requestBody = req.method === "GET" || req.method === "HEAD" ? void 0 : typeof req.rawBody === "string" ? req.rawBody : req.rawBody ? Buffer.from(req.rawBody).toString() : void 0;
149
+ const href = `${req.protocol}://${req.hostname}${req.raw.url ?? "/"}`;
150
+ const request = new Request(href, {
151
+ method: req.method,
152
+ headers: req.headers,
153
+ body: requestBody
154
+ });
155
+ const ctx = await (0, import_runtime.buildCedarContext)(request, {
156
+ params: {
157
+ routeName
158
+ }
159
+ });
160
+ const response = await cedarHandler(request, ctx);
161
+ reply.status(response.status);
162
+ response.headers.forEach((value, name) => {
163
+ reply.header(name, value);
164
+ });
165
+ const body = await response.arrayBuffer();
166
+ reply.send(Buffer.from(body));
167
+ return;
168
+ }
169
+ const handler = LAMBDA_FUNCTIONS.get(routeName);
170
+ if (handler) {
171
+ return (0, import_awsLambdaFastify.requestHandler)(req, reply, handler);
172
+ } else {
112
173
  const errorMessage = `Function "${routeName}" was not found.`;
113
174
  req.log.error(errorMessage);
114
175
  reply.status(404);
115
176
  if (process.env.NODE_ENV === "development") {
116
177
  const devError = {
117
178
  error: errorMessage,
118
- availableFunctions: Object.keys(LAMBDA_FUNCTIONS)
179
+ availableFunctions: [
180
+ .../* @__PURE__ */ new Set([...LAMBDA_FUNCTIONS.keys(), ...CEDAR_HANDLERS.keys()])
181
+ ]
119
182
  };
120
183
  reply.send(devError);
121
184
  } else {
@@ -123,11 +186,12 @@ const lambdaRequestHandler = async (req, reply) => {
123
186
  }
124
187
  return;
125
188
  }
126
- return (0, import_awsLambdaFastify.requestHandler)(req, reply, LAMBDA_FUNCTIONS[routeName]);
127
189
  };
128
190
  // Annotate the CommonJS export names for ESM import in node:
129
191
  0 && (module.exports = {
192
+ CEDAR_HANDLERS,
130
193
  LAMBDA_FUNCTIONS,
194
+ getCedarRouteManifest,
131
195
  lambdaRequestHandler,
132
196
  loadFunctionsFromDist,
133
197
  setLambdaFunctions
@@ -1 +1 @@
1
- {"version":3,"file":"awsLambdaFastify.d.ts","sourceRoot":"","sources":["../../../src/requestHandlers/awsLambdaFastify.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,oBAAoB,EACpB,OAAO,EAER,MAAM,YAAY,CAAA;AACnB,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAK3D,eAAO,MAAM,4BAA4B,GACvC,SAAS,cAAc,KACtB,oBAyBF,CAAA;AAoCD,eAAO,MAAM,cAAc,GACzB,KAAK,cAAc,EACnB,OAAO,YAAY,EACnB,SAAS,OAAO,kBAmCjB,CAAA"}
1
+ {"version":3,"file":"awsLambdaFastify.d.ts","sourceRoot":"","sources":["../../../src/requestHandlers/awsLambdaFastify.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,oBAAoB,EACpB,OAAO,EAGR,MAAM,YAAY,CAAA;AACnB,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAK3D,eAAO,MAAM,4BAA4B,GACvC,SAAS,cAAc,KACtB,oBA6BF,CAAA;AAoCD,eAAO,MAAM,cAAc,GACzB,KAAK,cAAc,EACnB,OAAO,YAAY,EACnB,SAAS,OAAO,kBAmCjB,CAAA"}
@@ -35,14 +35,18 @@ const lambdaEventForFastifyRequest = (request) => {
35
35
  );
36
36
  return {
37
37
  httpMethod: request.method,
38
- headers: request.headers,
38
+ headers: {
39
+ "x-forwarded-proto": request.protocol,
40
+ ...request.headers
41
+ },
39
42
  path: request.urlData("path"),
40
43
  queryStringParameters: qsParams,
41
44
  requestContext: {
42
45
  requestId: request.id,
43
46
  identity: {
44
47
  sourceIp: request.ip
45
- }
48
+ },
49
+ domainName: request.hostname
46
50
  },
47
51
  ...(0, import_utils.parseBody)(request.rawBody || "")
48
52
  // adds `body` and `isBase64Encoded`
@@ -0,0 +1,28 @@
1
+ import type { EntryMeta } from '@universal-deploy/store';
2
+ import type { Fetchable } from './udFetchable.js';
3
+ export interface CedarDispatcherOptions {
4
+ apiRootPath?: string;
5
+ discoverFunctionsGlob?: string | string[];
6
+ /**
7
+ * Cache-bust token appended to dynamic ESM imports. Use this in dev to
8
+ * bypass Node.js's ESM module cache after a rebuild. Production builds
9
+ * should omit this.
10
+ */
11
+ cacheBust?: string | number;
12
+ }
13
+ export interface CedarDispatcherResult {
14
+ fetchable: Fetchable;
15
+ registrations: EntryMeta[];
16
+ }
17
+ /**
18
+ * Shared aggregate Cedar API dispatcher used by
19
+ * `cedarUniversalDeployPlugin` (via `virtual:cedar-api`).
20
+ *
21
+ * Discovers Cedar API functions in `api/dist/functions/`, builds a rou3 router
22
+ * and a map of route names to Fetchables, then returns a single Fetchable that
23
+ * routes incoming Fetch-API requests to the correct per-function handler.
24
+ * Also returns the list of `EntryMeta` registrations so callers can forward
25
+ * them to `@universal-deploy/store` via `addEntry()`.
26
+ */
27
+ export declare function buildCedarDispatcher(options?: CedarDispatcherOptions): Promise<CedarDispatcherResult>;
28
+ //# sourceMappingURL=udDispatcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"udDispatcher.d.ts","sourceRoot":"","sources":["../../src/udDispatcher.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AAUxD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AAgBjD,MAAM,WAAW,sBAAsB;IACrC,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,qBAAqB,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;IACzC;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;CAC5B;AAED,MAAM,WAAW,qBAAqB;IACpC,SAAS,EAAE,SAAS,CAAA;IACpB,aAAa,EAAE,SAAS,EAAE,CAAA;CAC3B;AA6BD;;;;;;;;;GASG;AACH,wBAAsB,oBAAoB,CACxC,OAAO,CAAC,EAAE,sBAAsB,GAC/B,OAAO,CAAC,qBAAqB,CAAC,CAmNhC"}
@@ -0,0 +1,192 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+ var udDispatcher_exports = {};
30
+ __export(udDispatcher_exports, {
31
+ buildCedarDispatcher: () => buildCedarDispatcher
32
+ });
33
+ module.exports = __toCommonJS(udDispatcher_exports);
34
+ var import_node_path = __toESM(require("node:path"), 1);
35
+ var import_node_url = require("node:url");
36
+ var import_fast_glob = __toESM(require("fast-glob"), 1);
37
+ var import_rou3 = require("rou3");
38
+ var import_runtime = require("@cedarjs/api/runtime");
39
+ var import_store = require("@cedarjs/context/dist/store");
40
+ var import_project_config = require("@cedarjs/project-config");
41
+ var import_udFetchable = require("./udFetchable.js");
42
+ const ALL_HTTP_METHODS = [
43
+ "GET",
44
+ "HEAD",
45
+ "POST",
46
+ "PUT",
47
+ "DELETE",
48
+ "PATCH",
49
+ "OPTIONS",
50
+ "CONNECT",
51
+ "TRACE"
52
+ ];
53
+ const GRAPHQL_METHODS = ["GET", "POST", "OPTIONS"];
54
+ function normalizeApiRootPath(rootPath) {
55
+ let normalized = rootPath;
56
+ if (!normalized.startsWith("/")) {
57
+ normalized = "/" + normalized;
58
+ }
59
+ if (!normalized.endsWith("/")) {
60
+ normalized = normalized + "/";
61
+ }
62
+ return normalized;
63
+ }
64
+ async function buildCedarDispatcher(options) {
65
+ const normalizedApiRootPath = normalizeApiRootPath(
66
+ options?.apiRootPath ?? "/"
67
+ );
68
+ const discoverFunctionsGlob = options?.discoverFunctionsGlob ?? "dist/functions/**/*.{ts,js}";
69
+ const serverFunctions = import_fast_glob.default.sync(discoverFunctionsGlob, {
70
+ cwd: (0, import_project_config.getPaths)().api.base,
71
+ deep: 2,
72
+ absolute: true
73
+ });
74
+ const graphqlIdx = serverFunctions.findIndex(
75
+ (x) => import_node_path.default.basename(x, import_node_path.default.extname(x)) === "graphql"
76
+ );
77
+ if (graphqlIdx >= 0) {
78
+ const [graphqlFn] = serverFunctions.splice(graphqlIdx, 1);
79
+ serverFunctions.unshift(graphqlFn);
80
+ }
81
+ const fetchableMap = /* @__PURE__ */ new Map();
82
+ const router = (0, import_rou3.createRouter)();
83
+ const registrations = [];
84
+ for (const fnPath of serverFunctions) {
85
+ const routeName = import_node_path.default.basename(fnPath, import_node_path.default.extname(fnPath));
86
+ const routePath = routeName === "graphql" ? "/graphql" : `/${routeName}`;
87
+ const importUrl = options?.cacheBust ? `${(0, import_node_url.pathToFileURL)(fnPath).href}?t=${options.cacheBust}` : (0, import_node_url.pathToFileURL)(fnPath).href;
88
+ const fnImport = await import(importUrl);
89
+ if ("__rw_graphqlOptions" in fnImport && fnImport.__rw_graphqlOptions != null) {
90
+ const { createGraphQLYoga } = await import("@cedarjs/graphql-server");
91
+ const graphqlOptions = fnImport.__rw_graphqlOptions;
92
+ const { yoga } = await createGraphQLYoga(graphqlOptions);
93
+ const graphqlFetchable = {
94
+ async fetch(request) {
95
+ const cedarContext = await (0, import_runtime.buildCedarContext)(request, {
96
+ authDecoder: graphqlOptions.authDecoder
97
+ });
98
+ const event = await (0, import_runtime.requestToLegacyEvent)(request, cedarContext);
99
+ return yoga.handle(request, {
100
+ request,
101
+ cedarContext,
102
+ event,
103
+ requestContext: void 0
104
+ });
105
+ }
106
+ };
107
+ fetchableMap.set(routeName, graphqlFetchable);
108
+ registrations.push({
109
+ id: routePath,
110
+ route: routePath,
111
+ method: [...GRAPHQL_METHODS]
112
+ });
113
+ for (const method of GRAPHQL_METHODS) {
114
+ (0, import_rou3.addRoute)(router, method, routePath, routeName);
115
+ (0, import_rou3.addRoute)(router, method, `${routePath}/**`, routeName);
116
+ }
117
+ continue;
118
+ }
119
+ const cedarHandler = (() => {
120
+ if ("handle" in fnImport && typeof fnImport.handle === "function") {
121
+ return fnImport.handle;
122
+ }
123
+ if ("default" in fnImport && fnImport.default != null && "handle" in fnImport.default && typeof fnImport.default.handle === "function") {
124
+ return fnImport.default.handle;
125
+ }
126
+ return void 0;
127
+ })();
128
+ if (!cedarHandler) {
129
+ console.warn(
130
+ routeName,
131
+ "at",
132
+ fnPath,
133
+ "does not export a Fetch-native `handle` function and will not be served by the Universal Deploy server. Migrate to `export async function handle(request, ctx)` or use `yarn cedar serve` for legacy Lambda-shaped handler support."
134
+ );
135
+ continue;
136
+ }
137
+ const handler = cedarHandler;
138
+ fetchableMap.set(routeName, (0, import_udFetchable.createCedarFetchable)(handler));
139
+ registrations.push({
140
+ id: routePath,
141
+ route: routePath
142
+ // method omitted → matches all HTTP methods per @universal-deploy/store docs
143
+ });
144
+ for (const method of ALL_HTTP_METHODS) {
145
+ (0, import_rou3.addRoute)(router, method, routePath, routeName);
146
+ (0, import_rou3.addRoute)(router, method, `${routePath}/**`, routeName);
147
+ }
148
+ }
149
+ const fetchable = {
150
+ fetch(request) {
151
+ return (0, import_store.getAsyncStoreInstance)().run(
152
+ /* @__PURE__ */ new Map(),
153
+ async () => {
154
+ const url = new URL(request.url);
155
+ let routePathname = url.pathname;
156
+ if (normalizedApiRootPath !== "/" && routePathname.startsWith(normalizedApiRootPath)) {
157
+ routePathname = routePathname.slice(
158
+ normalizedApiRootPath.length - 1
159
+ );
160
+ }
161
+ if (!routePathname.startsWith("/")) {
162
+ routePathname = "/" + routePathname;
163
+ }
164
+ const match = (0, import_rou3.findRoute)(router, request.method, routePathname);
165
+ if (!match) {
166
+ return new Response("Not Found", { status: 404 });
167
+ }
168
+ const matchedRouteName = match.data;
169
+ const fnFetchable = fetchableMap.get(matchedRouteName);
170
+ if (!fnFetchable) {
171
+ return new Response("Not Found", { status: 404 });
172
+ }
173
+ try {
174
+ return await fnFetchable.fetch(request);
175
+ } catch (err) {
176
+ console.error(
177
+ "Unhandled error in fetch handler for route",
178
+ matchedRouteName,
179
+ err
180
+ );
181
+ return new Response("Internal Server Error", { status: 500 });
182
+ }
183
+ }
184
+ );
185
+ }
186
+ };
187
+ return { fetchable, registrations };
188
+ }
189
+ // Annotate the CommonJS export names for ESM import in node:
190
+ 0 && (module.exports = {
191
+ buildCedarDispatcher
192
+ });
@@ -0,0 +1,12 @@
1
+ import type { CedarHandler } from '@cedarjs/api/runtime';
2
+ export interface Fetchable {
3
+ fetch(request: Request): Response | Promise<Response>;
4
+ }
5
+ /**
6
+ * Wraps a CedarHandler in a WinterTC-compatible Fetchable.
7
+ *
8
+ * The Fetchable calls buildCedarContext to produce a CedarRequestContext,
9
+ * then delegates to the handler.
10
+ */
11
+ export declare function createCedarFetchable(handler: CedarHandler): Fetchable;
12
+ //# sourceMappingURL=udFetchable.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"udFetchable.d.ts","sourceRoot":"","sources":["../../src/udFetchable.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AAGxD,MAAM,WAAW,SAAS;IACxB,KAAK,CAAC,OAAO,EAAE,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAA;CACtD;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,YAAY,GAAG,SAAS,CAOrE"}