@cedarjs/api-server 6.0.0-rc.189 → 6.0.0-rc.221
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +0 -1
- package/dist/apiCLIConfig.d.ts.map +1 -1
- package/dist/apiCLIConfig.js +1 -1
- package/dist/apiCLIConfigHandler.d.ts.map +1 -1
- package/dist/apiCLIConfigHandler.js +5 -0
- package/dist/bin.js +121 -39
- package/dist/bothCLIConfig.d.ts.map +1 -1
- package/dist/bothCLIConfig.js +2 -2
- package/dist/bothCLIConfigHandler.d.ts.map +1 -1
- package/dist/bothCLIConfigHandler.js +8 -2
- package/dist/cliHelpers.d.ts +21 -4
- package/dist/cliHelpers.d.ts.map +1 -1
- package/dist/cliHelpers.js +39 -11
- package/dist/createServer.d.ts.map +1 -1
- package/dist/createServer.js +4 -4
- package/dist/createServerHelpers.d.ts.map +1 -1
- package/dist/createServerHelpers.js +6 -2
- package/dist/plugins/api.d.ts +1 -1
- package/dist/plugins/api.d.ts.map +1 -1
- package/dist/plugins/api.js +1 -1
- package/dist/plugins/graphql.d.ts +3 -3
- package/dist/plugins/graphql.d.ts.map +1 -1
- package/dist/plugins/graphql.js +12 -10
- package/dist/serverFile.d.ts +23 -0
- package/dist/serverFile.d.ts.map +1 -0
- package/dist/serverFile.js +35 -0
- package/dist/types.d.ts +3 -3
- package/dist/types.d.ts.map +1 -1
- package/dist/utils.d.ts +0 -3
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +0 -20
- package/package.json +9 -19
- package/dist/buildManager.d.ts +0 -15
- package/dist/buildManager.d.ts.map +0 -1
- package/dist/buildManager.js +0 -55
- package/dist/serverManager.d.ts +0 -8
- package/dist/serverManager.d.ts.map +0 -1
- package/dist/serverManager.js +0 -102
- package/dist/watch.d.ts +0 -10
- package/dist/watch.d.ts.map +0 -1
- package/dist/watch.js +0 -375
- package/dist/watchPaths.d.ts +0 -3
- package/dist/watchPaths.d.ts.map +0 -1
- package/dist/watchPaths.js +0 -109
package/README.md
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"apiCLIConfig.d.ts","sourceRoot":"","sources":["../src/apiCLIConfig.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,OAAO,CAAA;AAEjC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAElD,eAAO,MAAM,WAAW,4CAA4C,CAAA;AAEpE,wBAAgB,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,gBAAgB,CAAC,
|
|
1
|
+
{"version":3,"file":"apiCLIConfig.d.ts","sourceRoot":"","sources":["../src/apiCLIConfig.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,OAAO,CAAA;AAEjC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAElD,eAAO,MAAM,WAAW,4CAA4C,CAAA;AAEpE,wBAAgB,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,gBAAgB,CAAC,QAwBpD;AAED,wBAAsB,OAAO,CAAC,OAAO,EAAE,gBAAgB,iBAGtD"}
|
package/dist/apiCLIConfig.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"apiCLIConfigHandler.d.ts","sourceRoot":"","sources":["../src/apiCLIConfigHandler.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"apiCLIConfigHandler.d.ts","sourceRoot":"","sources":["../src/apiCLIConfigHandler.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAElD,wBAAsB,OAAO,CAAC,OAAO,GAAE,gBAAqB,iBA4C3D"}
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
import ansis from "ansis";
|
|
2
2
|
import { coerceRootPath } from "@cedarjs/fastify-web";
|
|
3
3
|
import { createServer } from "./createServer.js";
|
|
4
|
+
import { apiDistServerFileExists, runApiDistServerFile } from "./serverFile.js";
|
|
4
5
|
async function handler(options = {}) {
|
|
6
|
+
if (apiDistServerFileExists()) {
|
|
7
|
+
await runApiDistServerFile(options);
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
5
10
|
const timeStart = Date.now();
|
|
6
11
|
console.log(ansis.dim.italic("Starting API Server..."));
|
|
7
12
|
options.apiRootPath = coerceRootPath(options.apiRootPath ?? "/");
|
package/dist/bin.js
CHANGED
|
@@ -15,27 +15,55 @@ var __export = (target, all) => {
|
|
|
15
15
|
};
|
|
16
16
|
|
|
17
17
|
// src/cliHelpers.ts
|
|
18
|
-
import { getConfig } from "@cedarjs/project-config";
|
|
19
|
-
function getAPIHost() {
|
|
20
|
-
let host =
|
|
18
|
+
import { getConfig, parsePort, readEnvVar } from "@cedarjs/project-config";
|
|
19
|
+
function getAPIHost({ isPublicSide = false } = {}) {
|
|
20
|
+
let host = readEnvVar("CEDAR_API_HOST", {
|
|
21
|
+
deprecatedAlias: "REDWOOD_API_HOST"
|
|
22
|
+
});
|
|
23
|
+
if (isPublicSide) {
|
|
24
|
+
host ??= process.env.HOST;
|
|
25
|
+
}
|
|
21
26
|
host ??= getConfig().api.host;
|
|
22
|
-
host ??=
|
|
27
|
+
host ??= "::";
|
|
23
28
|
return host;
|
|
24
29
|
}
|
|
25
|
-
function getAPIPort() {
|
|
26
|
-
|
|
30
|
+
function getAPIPort({ isPublicSide = false } = {}) {
|
|
31
|
+
const apiPort = readEnvVar("CEDAR_API_PORT", {
|
|
32
|
+
deprecatedAlias: "REDWOOD_API_PORT"
|
|
33
|
+
});
|
|
34
|
+
if (apiPort) {
|
|
35
|
+
return parsePort(apiPort, "CEDAR_API_PORT");
|
|
36
|
+
}
|
|
37
|
+
if (isPublicSide && process.env.PORT) {
|
|
38
|
+
return parsePort(process.env.PORT, "PORT");
|
|
39
|
+
}
|
|
40
|
+
return getConfig().api.port;
|
|
27
41
|
}
|
|
28
42
|
function getAPIRootPath() {
|
|
29
43
|
return process.env.CEDAR_API_ROOT_PATH ?? "/";
|
|
30
44
|
}
|
|
31
|
-
function getWebHost() {
|
|
32
|
-
let host =
|
|
45
|
+
function getWebHost({ isPublicSide = false } = {}) {
|
|
46
|
+
let host = readEnvVar("CEDAR_WEB_HOST", {
|
|
47
|
+
deprecatedAlias: "REDWOOD_WEB_HOST"
|
|
48
|
+
});
|
|
49
|
+
if (isPublicSide) {
|
|
50
|
+
host ??= process.env.HOST;
|
|
51
|
+
}
|
|
33
52
|
host ??= getConfig().web.host;
|
|
34
|
-
host ??=
|
|
53
|
+
host ??= "::";
|
|
35
54
|
return host;
|
|
36
55
|
}
|
|
37
|
-
function getWebPort() {
|
|
38
|
-
|
|
56
|
+
function getWebPort({ isPublicSide = false } = {}) {
|
|
57
|
+
const webPort = readEnvVar("CEDAR_WEB_PORT", {
|
|
58
|
+
deprecatedAlias: "REDWOOD_WEB_PORT"
|
|
59
|
+
});
|
|
60
|
+
if (webPort) {
|
|
61
|
+
return parsePort(webPort, "CEDAR_WEB_PORT");
|
|
62
|
+
}
|
|
63
|
+
if (isPublicSide && process.env.PORT) {
|
|
64
|
+
return parsePort(process.env.PORT, "PORT");
|
|
65
|
+
}
|
|
66
|
+
return getConfig().web.port;
|
|
39
67
|
}
|
|
40
68
|
var init_cliHelpers = __esm({
|
|
41
69
|
"src/cliHelpers.ts"() {
|
|
@@ -128,8 +156,12 @@ var init_createServerHelpers = __esm({
|
|
|
128
156
|
configureApiServer: () => {
|
|
129
157
|
},
|
|
130
158
|
parseArgs: true,
|
|
131
|
-
|
|
132
|
-
|
|
159
|
+
// `createServer()`'s only callers are `cedarjs-server api` and custom
|
|
160
|
+
// `api/src/server.ts` files — both only ever run with the api side
|
|
161
|
+
// serving public traffic on its own, so they get to use the host's
|
|
162
|
+
// `HOST`/`PORT` env vars.
|
|
163
|
+
apiHost: getAPIHost({ isPublicSide: true }),
|
|
164
|
+
apiPort: getAPIPort({ isPublicSide: true })
|
|
133
165
|
});
|
|
134
166
|
}
|
|
135
167
|
});
|
|
@@ -496,7 +528,7 @@ import fastifyRawBody from "fastify-raw-body";
|
|
|
496
528
|
import { getAsyncStoreInstance as getAsyncStoreInstance2 } from "@cedarjs/context/dist/store";
|
|
497
529
|
import { coerceRootPath as coerceRootPath2 } from "@cedarjs/fastify-web/dist/helpers.js";
|
|
498
530
|
async function cedarFastifyAPI(fastify2, opts) {
|
|
499
|
-
const cedarOptions = opts.
|
|
531
|
+
const cedarOptions = opts.cedar ?? {};
|
|
500
532
|
cedarOptions.apiRootPath ??= "/";
|
|
501
533
|
cedarOptions.apiRootPath = coerceRootPath2(cedarOptions.apiRootPath);
|
|
502
534
|
cedarOptions.fastGlobOptions ??= {};
|
|
@@ -541,7 +573,7 @@ var init_api = __esm({
|
|
|
541
573
|
// src/plugins/graphql.ts
|
|
542
574
|
var graphql_exports = {};
|
|
543
575
|
__export(graphql_exports, {
|
|
544
|
-
|
|
576
|
+
cedarFastifyGraphQLServer: () => cedarFastifyGraphQLServer
|
|
545
577
|
});
|
|
546
578
|
import { pathToFileURL as pathToFileURL3 } from "node:url";
|
|
547
579
|
import fastifyMultiPart from "@fastify/multipart";
|
|
@@ -552,10 +584,10 @@ import { getAsyncStoreInstance as getAsyncStoreInstance3 } from "@cedarjs/contex
|
|
|
552
584
|
import { coerceRootPath as coerceRootPath3 } from "@cedarjs/fastify-web/dist/helpers.js";
|
|
553
585
|
import { createGraphQLYoga } from "@cedarjs/graphql-server";
|
|
554
586
|
import { getPaths as getPaths3 } from "@cedarjs/project-config";
|
|
555
|
-
async function
|
|
556
|
-
const
|
|
557
|
-
|
|
558
|
-
|
|
587
|
+
async function cedarFastifyGraphQLServer(fastify2, options) {
|
|
588
|
+
const cedarOptions = options.cedar ?? {};
|
|
589
|
+
cedarOptions.apiRootPath ??= "/";
|
|
590
|
+
cedarOptions.apiRootPath = coerceRootPath3(cedarOptions.apiRootPath);
|
|
559
591
|
fastify2.register(fastifyUrlData2);
|
|
560
592
|
fastify2.register(fastifyMultiPart);
|
|
561
593
|
const method = ["GET", "POST", "OPTIONS"];
|
|
@@ -563,7 +595,7 @@ async function redwoodFastifyGraphQLServer(fastify2, options) {
|
|
|
563
595
|
getAsyncStoreInstance3().run(/* @__PURE__ */ new Map(), done);
|
|
564
596
|
});
|
|
565
597
|
try {
|
|
566
|
-
if (!
|
|
598
|
+
if (!cedarOptions.graphql) {
|
|
567
599
|
const [graphqlFunctionPath] = await fg2("dist/functions/graphql.{ts,js}", {
|
|
568
600
|
cwd: getPaths3().api.base,
|
|
569
601
|
absolute: true
|
|
@@ -573,9 +605,9 @@ async function redwoodFastifyGraphQLServer(fastify2, options) {
|
|
|
573
605
|
if (!__cedar_graphqlOptions) {
|
|
574
606
|
return;
|
|
575
607
|
}
|
|
576
|
-
|
|
608
|
+
cedarOptions.graphql = __cedar_graphqlOptions;
|
|
577
609
|
}
|
|
578
|
-
const graphqlOptions =
|
|
610
|
+
const graphqlOptions = cedarOptions.graphql;
|
|
579
611
|
if (graphqlOptions?.realtime?.subscriptions) {
|
|
580
612
|
method.push("PUT");
|
|
581
613
|
}
|
|
@@ -584,7 +616,7 @@ async function redwoodFastifyGraphQLServer(fastify2, options) {
|
|
|
584
616
|
const routePaths = ["", "/health", "/readiness", "/stream"];
|
|
585
617
|
for (const routePath of routePaths) {
|
|
586
618
|
fastify2.route({
|
|
587
|
-
url: `${
|
|
619
|
+
url: `${cedarOptions.apiRootPath}${graphqlEndpoint}${routePath}`,
|
|
588
620
|
method,
|
|
589
621
|
handler: async (req, reply) => {
|
|
590
622
|
const request = createFetchRequest(req, reply);
|
|
@@ -618,11 +650,13 @@ async function redwoodFastifyGraphQLServer(fastify2, options) {
|
|
|
618
650
|
done();
|
|
619
651
|
});
|
|
620
652
|
} catch (e) {
|
|
621
|
-
|
|
653
|
+
const message = e instanceof Error ? e.message : String(e);
|
|
654
|
+
fastify2.log.error(e, `Failed to set up the GraphQL server: ${message}`);
|
|
655
|
+
throw e;
|
|
622
656
|
}
|
|
623
657
|
}
|
|
624
|
-
function trimSlashes(
|
|
625
|
-
return
|
|
658
|
+
function trimSlashes(path6) {
|
|
659
|
+
return path6.replace(/^\/|\/$/g, "");
|
|
626
660
|
}
|
|
627
661
|
function createFetchRequest(req, reply) {
|
|
628
662
|
const controller = new AbortController();
|
|
@@ -702,7 +736,7 @@ async function createServer(options = {}) {
|
|
|
702
736
|
getAsyncStoreInstance4().run(/* @__PURE__ */ new Map(), done);
|
|
703
737
|
});
|
|
704
738
|
await server.register(cedarFastifyAPI, {
|
|
705
|
-
|
|
739
|
+
cedar: {
|
|
706
740
|
apiRootPath,
|
|
707
741
|
fastGlobOptions: {
|
|
708
742
|
ignore: ["**/dist/functions/graphql.js"]
|
|
@@ -716,10 +750,10 @@ async function createServer(options = {}) {
|
|
|
716
750
|
absolute: true
|
|
717
751
|
});
|
|
718
752
|
if (graphqlFunctionPath) {
|
|
719
|
-
const {
|
|
753
|
+
const { cedarFastifyGraphQLServer: cedarFastifyGraphQLServer2 } = await Promise.resolve().then(() => (init_graphql(), graphql_exports));
|
|
720
754
|
const { __cedar_graphqlOptions } = await import(pathToFileURL4(graphqlFunctionPath).href);
|
|
721
|
-
await server.register(
|
|
722
|
-
|
|
755
|
+
await server.register(cedarFastifyGraphQLServer2, {
|
|
756
|
+
cedar: {
|
|
723
757
|
apiRootPath,
|
|
724
758
|
graphql: __cedar_graphqlOptions
|
|
725
759
|
}
|
|
@@ -762,10 +796,51 @@ var init_createServer = __esm({
|
|
|
762
796
|
}
|
|
763
797
|
});
|
|
764
798
|
|
|
799
|
+
// src/serverFile.ts
|
|
800
|
+
import { spawn } from "node:child_process";
|
|
801
|
+
import fs3 from "node:fs";
|
|
802
|
+
import path4 from "node:path";
|
|
803
|
+
import { getPaths as getPaths5 } from "@cedarjs/project-config";
|
|
804
|
+
function apiDistServerFilePath() {
|
|
805
|
+
return path4.join(getPaths5().api.dist, "server.js");
|
|
806
|
+
}
|
|
807
|
+
function apiDistServerFileExists() {
|
|
808
|
+
return fs3.existsSync(apiDistServerFilePath());
|
|
809
|
+
}
|
|
810
|
+
async function runApiDistServerFile(options = {}) {
|
|
811
|
+
const args = ["--apiRootPath", options.apiRootPath ?? "/"];
|
|
812
|
+
if (options.port !== void 0) {
|
|
813
|
+
args.push("--apiPort", String(options.port));
|
|
814
|
+
}
|
|
815
|
+
await new Promise((resolve, reject) => {
|
|
816
|
+
const child = spawn(process.execPath, [apiDistServerFilePath(), ...args], {
|
|
817
|
+
cwd: getPaths5().api.dist,
|
|
818
|
+
stdio: "inherit"
|
|
819
|
+
});
|
|
820
|
+
child.on("error", reject);
|
|
821
|
+
child.on("exit", (code, signal) => {
|
|
822
|
+
if (signal || code === 0) {
|
|
823
|
+
resolve();
|
|
824
|
+
return;
|
|
825
|
+
}
|
|
826
|
+
reject(new Error(`api/dist/server.js exited with code ${code}`));
|
|
827
|
+
});
|
|
828
|
+
});
|
|
829
|
+
}
|
|
830
|
+
var init_serverFile = __esm({
|
|
831
|
+
"src/serverFile.ts"() {
|
|
832
|
+
"use strict";
|
|
833
|
+
}
|
|
834
|
+
});
|
|
835
|
+
|
|
765
836
|
// src/apiCLIConfigHandler.ts
|
|
766
837
|
import ansis3 from "ansis";
|
|
767
838
|
import { coerceRootPath as coerceRootPath4 } from "@cedarjs/fastify-web";
|
|
768
839
|
async function handler(options = {}) {
|
|
840
|
+
if (apiDistServerFileExists()) {
|
|
841
|
+
await runApiDistServerFile(options);
|
|
842
|
+
return;
|
|
843
|
+
}
|
|
769
844
|
const timeStart = Date.now();
|
|
770
845
|
console.log(ansis3.dim.italic("Starting API Server..."));
|
|
771
846
|
options.apiRootPath = coerceRootPath4(options.apiRootPath ?? "/");
|
|
@@ -796,6 +871,7 @@ var init_apiCLIConfigHandler = __esm({
|
|
|
796
871
|
"src/apiCLIConfigHandler.ts"() {
|
|
797
872
|
"use strict";
|
|
798
873
|
init_createServer();
|
|
874
|
+
init_serverFile();
|
|
799
875
|
}
|
|
800
876
|
});
|
|
801
877
|
|
|
@@ -803,10 +879,15 @@ var init_apiCLIConfigHandler = __esm({
|
|
|
803
879
|
import ansis4 from "ansis";
|
|
804
880
|
import { redwoodFastifyWeb, coerceRootPath as coerceRootPath5 } from "@cedarjs/fastify-web";
|
|
805
881
|
async function handler2(options) {
|
|
882
|
+
if (apiDistServerFileExists()) {
|
|
883
|
+
throw new Error(
|
|
884
|
+
"api/dist/server.js was found, but a custom server file is not supported when serving both sides from one process (`cedarjs-server` / `cedar serve`). It is a Fastify concept. Anything registered there (Realtime, custom plugins, custom middleware) would silently be skipped if this continued.\n\nRun the api and web sides as separate processes instead, so the api side goes through `cedarjs-server api`, which does run your server file:\n\n cedarjs-server api\n cedarjs-server web"
|
|
885
|
+
);
|
|
886
|
+
}
|
|
806
887
|
const timeStart = Date.now();
|
|
807
888
|
console.log(ansis4.dim.italic("Starting API and Web Servers..."));
|
|
808
|
-
options.webHost ??= getWebHost();
|
|
809
|
-
options.webPort ??= getWebPort();
|
|
889
|
+
options.webHost ??= getWebHost({ isPublicSide: true });
|
|
890
|
+
options.webPort ??= getWebPort({ isPublicSide: true });
|
|
810
891
|
options.apiHost ??= getAPIHost();
|
|
811
892
|
options.apiPort ??= getAPIPort();
|
|
812
893
|
options.apiRootPath = coerceRootPath5(options.apiRootPath ?? "/");
|
|
@@ -873,15 +954,16 @@ var init_bothCLIConfigHandler = __esm({
|
|
|
873
954
|
init_cliHelpers();
|
|
874
955
|
init_createServer();
|
|
875
956
|
init_fastify();
|
|
957
|
+
init_serverFile();
|
|
876
958
|
}
|
|
877
959
|
});
|
|
878
960
|
|
|
879
961
|
// src/bin.ts
|
|
880
|
-
import
|
|
962
|
+
import path5 from "path";
|
|
881
963
|
import { config as config2 } from "dotenv-defaults";
|
|
882
964
|
import { hideBin } from "yargs/helpers";
|
|
883
965
|
import yargs from "yargs/yargs";
|
|
884
|
-
import { getPaths as
|
|
966
|
+
import { getPaths as getPaths6 } from "@cedarjs/project-config";
|
|
885
967
|
import {
|
|
886
968
|
description as webDescription,
|
|
887
969
|
builder as webBuilder,
|
|
@@ -898,7 +980,7 @@ function builder(yargs2) {
|
|
|
898
980
|
alias: "p"
|
|
899
981
|
},
|
|
900
982
|
host: {
|
|
901
|
-
description: "The host to listen at
|
|
983
|
+
description: "The host to listen at",
|
|
902
984
|
type: "string"
|
|
903
985
|
},
|
|
904
986
|
apiRootPath: {
|
|
@@ -929,7 +1011,7 @@ function builder2(yargs2) {
|
|
|
929
1011
|
alias: ["web-port"]
|
|
930
1012
|
},
|
|
931
1013
|
webHost: {
|
|
932
|
-
description: "The host for the web server to listen on
|
|
1014
|
+
description: "The host for the web server to listen on",
|
|
933
1015
|
type: "string",
|
|
934
1016
|
alias: ["web-host"]
|
|
935
1017
|
},
|
|
@@ -939,7 +1021,7 @@ function builder2(yargs2) {
|
|
|
939
1021
|
alias: ["api-port"]
|
|
940
1022
|
},
|
|
941
1023
|
apiHost: {
|
|
942
|
-
description: "The host for the api server to listen on
|
|
1024
|
+
description: "The host for the api server to listen on",
|
|
943
1025
|
type: "string",
|
|
944
1026
|
alias: ["api-host"]
|
|
945
1027
|
},
|
|
@@ -956,8 +1038,8 @@ function builder2(yargs2) {
|
|
|
956
1038
|
init_bothCLIConfigHandler();
|
|
957
1039
|
if (!process.env.CEDAR_ENV_FILES_LOADED) {
|
|
958
1040
|
config2({
|
|
959
|
-
path:
|
|
960
|
-
defaults:
|
|
1041
|
+
path: path5.join(getPaths6().base, ".env"),
|
|
1042
|
+
defaults: path5.join(getPaths6().base, ".env.defaults"),
|
|
961
1043
|
multiline: true
|
|
962
1044
|
});
|
|
963
1045
|
process.env.CEDAR_ENV_FILES_LOADED = "true";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bothCLIConfig.d.ts","sourceRoot":"","sources":["../src/bothCLIConfig.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,OAAO,CAAA;AAEjC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAEnD,eAAO,MAAM,WAAW,qDAAqD,CAAA;AAE7E,wBAAgB,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,iBAAiB,CAAC,
|
|
1
|
+
{"version":3,"file":"bothCLIConfig.d.ts","sourceRoot":"","sources":["../src/bothCLIConfig.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,OAAO,CAAA;AAEjC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAEnD,eAAO,MAAM,WAAW,qDAAqD,CAAA;AAE7E,wBAAgB,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,iBAAiB,CAAC,QA6BrD;AAED,wBAAsB,OAAO,CAAC,OAAO,EAAE,iBAAiB,iBAGvD"}
|
package/dist/bothCLIConfig.js
CHANGED
|
@@ -7,7 +7,7 @@ function builder(yargs) {
|
|
|
7
7
|
alias: ["web-port"]
|
|
8
8
|
},
|
|
9
9
|
webHost: {
|
|
10
|
-
description: "The host for the web server to listen on
|
|
10
|
+
description: "The host for the web server to listen on",
|
|
11
11
|
type: "string",
|
|
12
12
|
alias: ["web-host"]
|
|
13
13
|
},
|
|
@@ -17,7 +17,7 @@ function builder(yargs) {
|
|
|
17
17
|
alias: ["api-port"]
|
|
18
18
|
},
|
|
19
19
|
apiHost: {
|
|
20
|
-
description: "The host for the api server to listen on
|
|
20
|
+
description: "The host for the api server to listen on",
|
|
21
21
|
type: "string",
|
|
22
22
|
alias: ["api-host"]
|
|
23
23
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bothCLIConfigHandler.d.ts","sourceRoot":"","sources":["../src/bothCLIConfigHandler.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"bothCLIConfigHandler.d.ts","sourceRoot":"","sources":["../src/bothCLIConfigHandler.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAEnD,wBAAsB,OAAO,CAAC,OAAO,EAAE,iBAAiB,iBA0FvD"}
|
|
@@ -3,11 +3,17 @@ import { redwoodFastifyWeb, coerceRootPath } from "@cedarjs/fastify-web";
|
|
|
3
3
|
import { getWebHost, getWebPort, getAPIHost, getAPIPort } from "./cliHelpers.js";
|
|
4
4
|
import { createServer as createApiServer } from "./createServer.js";
|
|
5
5
|
import { createFastifyInstance } from "./fastify.js";
|
|
6
|
+
import { apiDistServerFileExists } from "./serverFile.js";
|
|
6
7
|
async function handler(options) {
|
|
8
|
+
if (apiDistServerFileExists()) {
|
|
9
|
+
throw new Error(
|
|
10
|
+
"api/dist/server.js was found, but a custom server file is not supported when serving both sides from one process (`cedarjs-server` / `cedar serve`). It is a Fastify concept. Anything registered there (Realtime, custom plugins, custom middleware) would silently be skipped if this continued.\n\nRun the api and web sides as separate processes instead, so the api side goes through `cedarjs-server api`, which does run your server file:\n\n cedarjs-server api\n cedarjs-server web"
|
|
11
|
+
);
|
|
12
|
+
}
|
|
7
13
|
const timeStart = Date.now();
|
|
8
14
|
console.log(ansis.dim.italic("Starting API and Web Servers..."));
|
|
9
|
-
options.webHost ??= getWebHost();
|
|
10
|
-
options.webPort ??= getWebPort();
|
|
15
|
+
options.webHost ??= getWebHost({ isPublicSide: true });
|
|
16
|
+
options.webPort ??= getWebPort({ isPublicSide: true });
|
|
11
17
|
options.apiHost ??= getAPIHost();
|
|
12
18
|
options.apiPort ??= getAPIPort();
|
|
13
19
|
options.apiRootPath = coerceRootPath(options.apiRootPath ?? "/");
|
package/dist/cliHelpers.d.ts
CHANGED
|
@@ -1,6 +1,23 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
interface SideOptions {
|
|
2
|
+
/**
|
|
3
|
+
* Whether this side receives the deployment's public traffic.
|
|
4
|
+
*
|
|
5
|
+
* Container hosts (Railway, Render, Fly.io, Cloud Run, Heroku) tell an app
|
|
6
|
+
* which host and port to bind with the `HOST` and `PORT` env vars. Only the
|
|
7
|
+
* side serving public traffic falls back to them — when the api and web
|
|
8
|
+
* servers run in the same deployment they would otherwise both bind to
|
|
9
|
+
* `PORT` and collide.
|
|
10
|
+
*
|
|
11
|
+
* The web side is the public one whenever both sides are served together,
|
|
12
|
+
* because it proxies api requests. The api side is only public when it is
|
|
13
|
+
* served on its own.
|
|
14
|
+
*/
|
|
15
|
+
isPublicSide?: boolean;
|
|
16
|
+
}
|
|
17
|
+
export declare function getAPIHost({ isPublicSide }?: SideOptions): string;
|
|
18
|
+
export declare function getAPIPort({ isPublicSide }?: SideOptions): number;
|
|
3
19
|
export declare function getAPIRootPath(): string;
|
|
4
|
-
export declare function getWebHost(): string;
|
|
5
|
-
export declare function getWebPort(): number;
|
|
20
|
+
export declare function getWebHost({ isPublicSide }?: SideOptions): string;
|
|
21
|
+
export declare function getWebPort({ isPublicSide }?: SideOptions): number;
|
|
22
|
+
export {};
|
|
6
23
|
//# sourceMappingURL=cliHelpers.d.ts.map
|
package/dist/cliHelpers.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cliHelpers.d.ts","sourceRoot":"","sources":["../src/cliHelpers.ts"],"names":[],"mappings":"AAEA,wBAAgB,UAAU,
|
|
1
|
+
{"version":3,"file":"cliHelpers.d.ts","sourceRoot":"","sources":["../src/cliHelpers.ts"],"names":[],"mappings":"AAEA,UAAU,WAAW;IACnB;;;;;;;;;;;;OAYG;IACH,YAAY,CAAC,EAAE,OAAO,CAAA;CACvB;AAED,wBAAgB,UAAU,CAAC,EAAE,YAAoB,EAAE,GAAE,WAAgB,UAepE;AAED,wBAAgB,UAAU,CAAC,EAAE,YAAoB,EAAE,GAAE,WAAgB,UAcpE;AAED,wBAAgB,cAAc,WAE7B;AAED,wBAAgB,UAAU,CAAC,EAAE,YAAoB,EAAE,GAAE,WAAgB,UAepE;AAED,wBAAgB,UAAU,CAAC,EAAE,YAAoB,EAAE,GAAE,WAAgB,UAcpE"}
|
package/dist/cliHelpers.js
CHANGED
|
@@ -1,24 +1,52 @@
|
|
|
1
|
-
import { getConfig } from "@cedarjs/project-config";
|
|
2
|
-
function getAPIHost() {
|
|
3
|
-
let host =
|
|
1
|
+
import { getConfig, parsePort, readEnvVar } from "@cedarjs/project-config";
|
|
2
|
+
function getAPIHost({ isPublicSide = false } = {}) {
|
|
3
|
+
let host = readEnvVar("CEDAR_API_HOST", {
|
|
4
|
+
deprecatedAlias: "REDWOOD_API_HOST"
|
|
5
|
+
});
|
|
6
|
+
if (isPublicSide) {
|
|
7
|
+
host ??= process.env.HOST;
|
|
8
|
+
}
|
|
4
9
|
host ??= getConfig().api.host;
|
|
5
|
-
host ??=
|
|
10
|
+
host ??= "::";
|
|
6
11
|
return host;
|
|
7
12
|
}
|
|
8
|
-
function getAPIPort() {
|
|
9
|
-
|
|
13
|
+
function getAPIPort({ isPublicSide = false } = {}) {
|
|
14
|
+
const apiPort = readEnvVar("CEDAR_API_PORT", {
|
|
15
|
+
deprecatedAlias: "REDWOOD_API_PORT"
|
|
16
|
+
});
|
|
17
|
+
if (apiPort) {
|
|
18
|
+
return parsePort(apiPort, "CEDAR_API_PORT");
|
|
19
|
+
}
|
|
20
|
+
if (isPublicSide && process.env.PORT) {
|
|
21
|
+
return parsePort(process.env.PORT, "PORT");
|
|
22
|
+
}
|
|
23
|
+
return getConfig().api.port;
|
|
10
24
|
}
|
|
11
25
|
function getAPIRootPath() {
|
|
12
26
|
return process.env.CEDAR_API_ROOT_PATH ?? "/";
|
|
13
27
|
}
|
|
14
|
-
function getWebHost() {
|
|
15
|
-
let host =
|
|
28
|
+
function getWebHost({ isPublicSide = false } = {}) {
|
|
29
|
+
let host = readEnvVar("CEDAR_WEB_HOST", {
|
|
30
|
+
deprecatedAlias: "REDWOOD_WEB_HOST"
|
|
31
|
+
});
|
|
32
|
+
if (isPublicSide) {
|
|
33
|
+
host ??= process.env.HOST;
|
|
34
|
+
}
|
|
16
35
|
host ??= getConfig().web.host;
|
|
17
|
-
host ??=
|
|
36
|
+
host ??= "::";
|
|
18
37
|
return host;
|
|
19
38
|
}
|
|
20
|
-
function getWebPort() {
|
|
21
|
-
|
|
39
|
+
function getWebPort({ isPublicSide = false } = {}) {
|
|
40
|
+
const webPort = readEnvVar("CEDAR_WEB_PORT", {
|
|
41
|
+
deprecatedAlias: "REDWOOD_WEB_PORT"
|
|
42
|
+
});
|
|
43
|
+
if (webPort) {
|
|
44
|
+
return parsePort(webPort, "CEDAR_WEB_PORT");
|
|
45
|
+
}
|
|
46
|
+
if (isPublicSide && process.env.PORT) {
|
|
47
|
+
return parsePort(process.env.PORT, "PORT");
|
|
48
|
+
}
|
|
49
|
+
return getConfig().web.port;
|
|
22
50
|
}
|
|
23
51
|
export {
|
|
24
52
|
getAPIHost,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createServer.d.ts","sourceRoot":"","sources":["../src/createServer.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EACV,mBAAmB,EACnB,MAAM,EAEP,MAAM,0BAA0B,CAAA;AAsBjC;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAsB,YAAY,CAAC,OAAO,GAAE,mBAAwB,
|
|
1
|
+
{"version":3,"file":"createServer.d.ts","sourceRoot":"","sources":["../src/createServer.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EACV,mBAAmB,EACnB,MAAM,EAEP,MAAM,0BAA0B,CAAA;AAsBjC;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAsB,YAAY,CAAC,OAAO,GAAE,mBAAwB,mBAqHnE"}
|
package/dist/createServer.js
CHANGED
|
@@ -62,7 +62,7 @@ async function createServer(options = {}) {
|
|
|
62
62
|
getAsyncStoreInstance().run(/* @__PURE__ */ new Map(), done);
|
|
63
63
|
});
|
|
64
64
|
await server.register(cedarFastifyAPI, {
|
|
65
|
-
|
|
65
|
+
cedar: {
|
|
66
66
|
apiRootPath,
|
|
67
67
|
fastGlobOptions: {
|
|
68
68
|
ignore: ["**/dist/functions/graphql.js"]
|
|
@@ -76,10 +76,10 @@ async function createServer(options = {}) {
|
|
|
76
76
|
absolute: true
|
|
77
77
|
});
|
|
78
78
|
if (graphqlFunctionPath) {
|
|
79
|
-
const {
|
|
79
|
+
const { cedarFastifyGraphQLServer } = await import("./plugins/graphql.js");
|
|
80
80
|
const { __cedar_graphqlOptions } = await import(pathToFileURL(graphqlFunctionPath).href);
|
|
81
|
-
await server.register(
|
|
82
|
-
|
|
81
|
+
await server.register(cedarFastifyGraphQLServer, {
|
|
82
|
+
cedar: {
|
|
83
83
|
apiRootPath,
|
|
84
84
|
graphql: __cedar_graphqlOptions
|
|
85
85
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createServerHelpers.d.ts","sourceRoot":"","sources":["../src/createServerHelpers.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,oBAAoB,EACpB,oBAAoB,EACpB,eAAe,EAChB,MAAM,SAAS,CAAA;AAMhB,MAAM,MAAM,YAAY,GAAG,IAAI,CAAC,oBAAoB,EAAE,MAAM,GAAG,MAAM,CAAC,CAAA;AAEtE,MAAM,WAAW,MAAO,SAAQ,eAAe;IAC7C,KAAK,EAAE,CAAC,OAAO,CAAC,EAAE,YAAY,KAAK,OAAO,CAAC,MAAM,CAAC,CAAA;CACnD;AAED,MAAM,WAAW,mBAAmB;IAClC,iDAAiD;IACjD,WAAW,CAAC,EAAE,MAAM,CAAA;IAGpB,iCAAiC;IACjC,MAAM,CAAC,EACH,oBAAoB,CAAC,QAAQ,CAAC,GAC9B,oBAAoB,CAAC,gBAAgB,CAAC,CAAA;IAE1C;;;OAGG;IACH,oBAAoB,CAAC,EAAE,IAAI,CAAC,oBAAoB,EAAE,QAAQ,CAAC,CAAA;IAE3D;;;OAGG;IACH,qBAAqB,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;IAEzC,sEAAsE;IACtE,kBAAkB,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAE7D,uDAAuD;IACvD,SAAS,CAAC,EAAE,OAAO,CAAA;IAEnB,yEAAyE;IACzE,OAAO,CAAC,EAAE,MAAM,CAAA;IAEhB,uEAAuE;IACvE,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED,KAAK,0BAA0B,GAAG,QAAQ,CACxC,IAAI,CAAC,mBAAmB,EAAE,sBAAsB,CAAC,GAAG;IAClD,oBAAoB,EAAE,oBAAoB,CAAA;CAC3C,CACF,CAAA;AAID,eAAO,MAAM,6BAA6B,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"createServerHelpers.d.ts","sourceRoot":"","sources":["../src/createServerHelpers.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,oBAAoB,EACpB,oBAAoB,EACpB,eAAe,EAChB,MAAM,SAAS,CAAA;AAMhB,MAAM,MAAM,YAAY,GAAG,IAAI,CAAC,oBAAoB,EAAE,MAAM,GAAG,MAAM,CAAC,CAAA;AAEtE,MAAM,WAAW,MAAO,SAAQ,eAAe;IAC7C,KAAK,EAAE,CAAC,OAAO,CAAC,EAAE,YAAY,KAAK,OAAO,CAAC,MAAM,CAAC,CAAA;CACnD;AAED,MAAM,WAAW,mBAAmB;IAClC,iDAAiD;IACjD,WAAW,CAAC,EAAE,MAAM,CAAA;IAGpB,iCAAiC;IACjC,MAAM,CAAC,EACH,oBAAoB,CAAC,QAAQ,CAAC,GAC9B,oBAAoB,CAAC,gBAAgB,CAAC,CAAA;IAE1C;;;OAGG;IACH,oBAAoB,CAAC,EAAE,IAAI,CAAC,oBAAoB,EAAE,QAAQ,CAAC,CAAA;IAE3D;;;OAGG;IACH,qBAAqB,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;IAEzC,sEAAsE;IACtE,kBAAkB,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAE7D,uDAAuD;IACvD,SAAS,CAAC,EAAE,OAAO,CAAA;IAEnB,yEAAyE;IACzE,OAAO,CAAC,EAAE,MAAM,CAAA;IAEhB,uEAAuE;IACvE,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED,KAAK,0BAA0B,GAAG,QAAQ,CACxC,IAAI,CAAC,mBAAmB,EAAE,sBAAsB,CAAC,GAAG;IAClD,oBAAoB,EAAE,oBAAoB,CAAA;CAC3C,CACF,CAAA;AAID,eAAO,MAAM,6BAA6B,EAAE,MAAM,0BAqB9C,CAAA;AAgBJ,wBAAgB,cAAc,CAC5B,OAAO,GAAE,mBAAwB,EACjC,IAAI,CAAC,EAAE,MAAM,EAAE;0BAdS,oBAAoB;GA4F7C"}
|
|
@@ -15,8 +15,12 @@ const getDefaultCreateServerOptions = () => ({
|
|
|
15
15
|
configureApiServer: () => {
|
|
16
16
|
},
|
|
17
17
|
parseArgs: true,
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
// `createServer()`'s only callers are `cedarjs-server api` and custom
|
|
19
|
+
// `api/src/server.ts` files — both only ever run with the api side
|
|
20
|
+
// serving public traffic on its own, so they get to use the host's
|
|
21
|
+
// `HOST`/`PORT` env vars.
|
|
22
|
+
apiHost: getAPIHost({ isPublicSide: true }),
|
|
23
|
+
apiPort: getAPIPort({ isPublicSide: true })
|
|
20
24
|
});
|
|
21
25
|
function isCustomLoggerInstance(logger) {
|
|
22
26
|
return !!logger && typeof logger === "object" && "info" in logger;
|
package/dist/plugins/api.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import type { Options as FastGlobOptions } from 'fast-glob';
|
|
|
2
2
|
import type { FastifyInstance } from 'fastify';
|
|
3
3
|
import type { Server } from '../createServerHelpers.js';
|
|
4
4
|
export interface CedarFastifyAPIOptions {
|
|
5
|
-
|
|
5
|
+
cedar: {
|
|
6
6
|
apiRootPath?: string;
|
|
7
7
|
fastGlobOptions?: FastGlobOptions;
|
|
8
8
|
discoverFunctionsGlob?: string | string[];
|
|
@@ -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;
|
|
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;IACrC,KAAK,EAAE;QACL,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"}
|
package/dist/plugins/api.js
CHANGED
|
@@ -5,7 +5,7 @@ import { coerceRootPath } from "@cedarjs/fastify-web/dist/helpers.js";
|
|
|
5
5
|
import { loadFastifyConfig } from "../fastify.js";
|
|
6
6
|
import { lambdaRequestHandler, loadFunctionsFromDist } from "./lambdaLoader.js";
|
|
7
7
|
async function cedarFastifyAPI(fastify, opts) {
|
|
8
|
-
const cedarOptions = opts.
|
|
8
|
+
const cedarOptions = opts.cedar ?? {};
|
|
9
9
|
cedarOptions.apiRootPath ??= "/";
|
|
10
10
|
cedarOptions.apiRootPath = coerceRootPath(cedarOptions.apiRootPath);
|
|
11
11
|
cedarOptions.fastGlobOptions ??= {};
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import type { FastifyInstance } from 'fastify';
|
|
2
2
|
import type { GraphQLYogaOptions } from '@cedarjs/graphql-server';
|
|
3
|
-
export interface
|
|
4
|
-
|
|
3
|
+
export interface CedarFastifyGraphQLOptions {
|
|
4
|
+
cedar: {
|
|
5
5
|
apiRootPath?: string;
|
|
6
6
|
graphql?: GraphQLYogaOptions;
|
|
7
7
|
};
|
|
8
8
|
}
|
|
9
|
-
export declare function
|
|
9
|
+
export declare function cedarFastifyGraphQLServer(fastify: FastifyInstance, options: CedarFastifyGraphQLOptions): Promise<void>;
|
|
10
10
|
//# sourceMappingURL=graphql.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"graphql.d.ts","sourceRoot":"","sources":["../../src/plugins/graphql.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,eAAe,EAIhB,MAAM,SAAS,CAAA;AAOhB,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAKjE,MAAM,WAAW,
|
|
1
|
+
{"version":3,"file":"graphql.d.ts","sourceRoot":"","sources":["../../src/plugins/graphql.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,eAAe,EAIhB,MAAM,SAAS,CAAA;AAOhB,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAKjE,MAAM,WAAW,0BAA0B;IACzC,KAAK,EAAE;QACL,WAAW,CAAC,EAAE,MAAM,CAAA;QACpB,OAAO,CAAC,EAAE,kBAAkB,CAAA;KAC7B,CAAA;CACF;AAED,wBAAsB,yBAAyB,CAC7C,OAAO,EAAE,eAAe,EACxB,OAAO,EAAE,0BAA0B,iBA+HpC"}
|