akanjs 3.0.0-alpha.71 → 3.0.0-alpha.73
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/client/cookie.ts +21 -34
- package/client/csrTypes.ts +0 -12
- package/client/frameConfig.ts +13 -0
- package/common/Logger.ts +13 -6
- package/common/TrustedProxy.ts +134 -0
- package/common/clamp.ts +2 -0
- package/common/dynamicRecord.ts +12 -0
- package/common/index.ts +5 -1
- package/common/isValidDate.ts +1 -1
- package/common/requestOrigin.ts +32 -0
- package/common/{httpClient.ts → restClient.ts} +16 -9
- package/constant/types.ts +22 -0
- package/dictionary/base.dictionary.ts +4 -0
- package/dictionary/trans.ts +24 -5
- package/document/dataLoader.ts +0 -4
- package/document/filterMeta.ts +2 -2
- package/document/loaderInfo.ts +4 -1
- package/fetch/client/fetchClient.ts +65 -88
- package/fetch/client/fetchHandle.ts +57 -0
- package/fetch/client/httpClient.ts +42 -14
- package/fetch/client/sliceInitHandle.ts +101 -0
- package/fetch/fetchType/appliedReturn.type.ts +64 -1
- package/fetch/fetchType/sliceFetch.type.ts +5 -5
- package/fetch/requestStorage.ts +19 -5
- package/index.ts +16 -2
- package/local/apps/serverLifecycle/serverLifecycle-local.db-shm +0 -0
- package/local/apps/serverLifecycle/serverLifecycle-local_solid.db-shm +0 -0
- package/package.json +1 -1
- package/server/akanApp.ts +3 -19
- package/server/akanAppHeaders.ts +10 -4
- package/server/akanOption.ts +14 -1
- package/server/akanServer.ts +3 -0
- package/server/cachePolicy.ts +2 -11
- package/server/decorators.ts +12 -3
- package/server/devtools/constantSerializer.ts +8 -1
- package/server/di/diLifecycle.ts +21 -1
- package/server/di/resolveHierarchy.ts +3 -3
- package/server/imageOptimizer.ts +2 -17
- package/server/mcp/McpDispatcher.ts +8 -2
- package/server/resolver/database.resolver.ts +13 -8
- package/server/resolver/signal.resolver.ts +3 -3
- package/server/routeTreeBuilder.ts +1 -15
- package/server/routing/apiRouter.ts +4 -5
- package/server/routing/appWsData.ts +9 -6
- package/server/staticPath.ts +34 -0
- package/server/webRouter.ts +35 -41
- package/service/adapt.ts +1 -5
- package/service/predefinedAdaptor/cache.adaptor.ts +8 -4
- package/service/predefinedAdaptor/database.adaptor.ts +37 -1766
- package/service/predefinedAdaptor/sql/PendingStoreEnsures.ts +22 -0
- package/service/predefinedAdaptor/sql/QueryCompiler.ts +225 -0
- package/service/predefinedAdaptor/sql/SqlDocumentStore.ts +812 -0
- package/service/predefinedAdaptor/sql/UpdateCompiler.ts +67 -0
- package/service/predefinedAdaptor/sql/dialect/postgres.ts +151 -0
- package/service/predefinedAdaptor/sql/dialect/sqlite.ts +134 -0
- package/service/predefinedAdaptor/sql/driver/bunSqlite.ts +29 -0
- package/service/predefinedAdaptor/sql/driver/libsql.ts +37 -0
- package/service/predefinedAdaptor/sql/driver/postgres.ts +42 -0
- package/service/predefinedAdaptor/sql/types.ts +251 -0
- package/service/predefinedAdaptor/sql/values.ts +91 -0
- package/signal/CrossSiteGuard.ts +71 -0
- package/signal/SignalFailure.ts +51 -0
- package/signal/endpoint.ts +2 -2
- package/signal/exception.ts +43 -6
- package/signal/index.ts +2 -0
- package/signal/intercept.ts +5 -2
- package/signal/internal.ts +10 -2
- package/signal/serializer/fetch.serializer.ts +11 -1
- package/signal/signalContext.ts +25 -28
- package/signal/slice.ts +1 -1
- package/store/SliceRequest.ts +23 -0
- package/store/action.ts +177 -114
- package/store/agent/AgentBridge.ts +3 -1
- package/store/agentic/StExposeBuilder.ts +7 -4
- package/store/agentic/StStateBuilder.ts +9 -4
- package/store/agentic/StToolBuilder.ts +21 -7
- package/store/store.ts +1 -1
- package/store/storeInstance.ts +3 -3
- package/store/storeRegistry.ts +1 -1
- package/types/client/cookie.d.ts +13 -2
- package/types/client/csrTypes.d.ts +0 -1
- package/types/client/frameConfig.d.ts +1 -0
- package/types/common/TrustedProxy.d.ts +24 -0
- package/types/common/clamp.d.ts +2 -0
- package/types/common/dynamicRecord.d.ts +14 -0
- package/types/common/index.d.ts +5 -1
- package/types/common/requestOrigin.d.ts +14 -0
- package/types/common/restClient.d.ts +27 -0
- package/types/constant/types.d.ts +13 -0
- package/types/dictionary/base.dictionary.d.ts +1 -1
- package/types/dictionary/dictionary.d.ts +8 -8
- package/types/document/dataLoader.d.ts +0 -3
- package/types/document/filterMeta.d.ts +2 -2
- package/types/document/loaderInfo.d.ts +2 -2
- package/types/fetch/client/fetchHandle.d.ts +24 -0
- package/types/fetch/client/httpClient.d.ts +2 -0
- package/types/fetch/client/sliceInitHandle.d.ts +29 -0
- package/types/fetch/fetchType/appliedReturn.type.d.ts +38 -1
- package/types/fetch/fetchType/sliceFetch.type.d.ts +5 -5
- package/types/fetch/requestStorage.d.ts +14 -0
- package/types/index.d.ts +17 -2
- package/types/server/akanOption.d.ts +8 -1
- package/types/server/decorators.d.ts +12 -2
- package/types/server/di/diLifecycle.d.ts +9 -1
- package/types/server/routeTreeBuilder.d.ts +1 -2
- package/types/server/routing/appWsData.d.ts +7 -3
- package/types/server/staticPath.d.ts +17 -0
- package/types/service/adapt.d.ts +1 -1
- package/types/service/predefinedAdaptor/database.adaptor.d.ts +15 -407
- package/types/service/predefinedAdaptor/sql/PendingStoreEnsures.d.ts +6 -0
- package/types/service/predefinedAdaptor/sql/QueryCompiler.d.ts +28 -0
- package/types/service/predefinedAdaptor/sql/SqlDocumentStore.d.ts +127 -0
- package/types/service/predefinedAdaptor/sql/UpdateCompiler.d.ts +17 -0
- package/types/service/predefinedAdaptor/sql/dialect/postgres.d.ts +27 -0
- package/types/service/predefinedAdaptor/sql/dialect/sqlite.d.ts +27 -0
- package/types/service/predefinedAdaptor/sql/driver/bunSqlite.d.ts +16 -0
- package/types/service/predefinedAdaptor/sql/driver/libsql.d.ts +17 -0
- package/types/service/predefinedAdaptor/sql/driver/postgres.d.ts +17 -0
- package/types/service/predefinedAdaptor/sql/types.d.ts +226 -0
- package/types/service/predefinedAdaptor/sql/values.d.ts +13 -0
- package/types/signal/CrossSiteGuard.d.ts +44 -0
- package/types/signal/SignalFailure.d.ts +28 -0
- package/types/signal/exception.d.ts +38 -54774
- package/types/signal/index.d.ts +2 -0
- package/types/signal/intercept.d.ts +3 -3
- package/types/signal/internal.d.ts +5 -1
- package/types/signal/serializer/fetch.serializer.d.ts +7 -1
- package/types/store/SliceRequest.d.ts +16 -0
- package/types/store/agentic/StToolBuilder.d.ts +10 -1
- package/types/ui/Agent/Menu.d.ts +1 -1
- package/types/ui/Field/Choice.d.ts +52 -0
- package/types/ui/Field/Collection.d.ts +51 -0
- package/types/ui/Field/DateField.d.ts +32 -0
- package/types/ui/Field/Label.d.ts +9 -0
- package/types/ui/Field/NumberField.d.ts +43 -0
- package/types/ui/Field/Relation.d.ts +80 -0
- package/types/ui/Field/Text.d.ts +101 -0
- package/types/ui/Field/index.d.ts +50 -0
- package/types/ui/Field.d.ts +1 -412
- package/types/ui/Load/Edit_Client.d.ts +3 -1
- package/types/ui/Load/Stream.d.ts +22 -0
- package/types/ui/Load/index.d.ts +2 -0
- package/types/ui/System/Root.d.ts +4 -0
- package/types/ui/index.d.ts +1 -1
- package/types/ui/recipe/badgeRecipe.d.ts +2 -2
- package/types/ui/recipe/buttonRecipe.d.ts +2 -2
- package/types/webkit/useCamera.d.ts +10 -1
- package/types/webkit/usePurchase.d.ts +4 -0
- package/ui/Agent/Menu.tsx +2 -2
- package/ui/Data/TableList.tsx +1 -1
- package/ui/DraggableList.tsx +1 -2
- package/ui/Field/Choice.tsx +172 -0
- package/ui/Field/Collection.tsx +293 -0
- package/ui/Field/DateField.tsx +138 -0
- package/ui/Field/Label.tsx +31 -0
- package/ui/Field/NumberField.tsx +169 -0
- package/ui/Field/Relation.tsx +387 -0
- package/ui/Field/Text.tsx +360 -0
- package/ui/Field/index.tsx +70 -0
- package/ui/Input.tsx +3 -3
- package/ui/Load/Edit.tsx +2 -2
- package/ui/Load/Edit_Client.tsx +11 -3
- package/ui/Load/Pagination.tsx +25 -25
- package/ui/Load/Stream.tsx +38 -0
- package/ui/Load/Units.tsx +50 -37
- package/ui/Load/View.tsx +25 -17
- package/ui/Load/index.ts +2 -0
- package/ui/Model/EditModal.tsx +7 -7
- package/ui/Signal/Message.tsx +7 -7
- package/ui/Signal/PubSub.tsx +4 -1
- package/ui/System/Client.tsx +0 -2
- package/ui/System/Gtag.tsx +1 -1
- package/ui/System/Root.tsx +4 -0
- package/ui/index.ts +1 -1
- package/ui/overlayPosition.ts +1 -2
- package/webkit/useCamera.tsx +22 -6
- package/webkit/useCodepush.tsx +2 -2
- package/webkit/useCsrValues.ts +1 -3
- package/webkit/useFetch.ts +4 -3
- package/webkit/useFrameRuntime.ts +14 -7
- package/webkit/usePurchase.tsx +4 -1
- package/fetch/serializer/fetch.serializer.ts +0 -142
- package/fetch/serializer/index.ts +0 -1
- package/types/common/httpClient.d.ts +0 -20
- package/types/fetch/serializer/fetch.serializer.d.ts +0 -14
- package/types/fetch/serializer/index.d.ts +0 -1
- package/types/fetch/serializer.d.ts +0 -1
- package/ui/Field.tsx +0 -1639
package/server/webRouter.ts
CHANGED
|
@@ -55,6 +55,7 @@ import { type RscRedirectMethod, type RscRedirectStatus, type RscRenderResult, R
|
|
|
55
55
|
import { createDefaultSitemapXml, getSitemapBasePath } from "./sitemap";
|
|
56
56
|
import { SsrFromRscRenderer } from "./ssrFromRscRenderer";
|
|
57
57
|
import type { RscTraceMetadata, SsrManifest } from "./ssrTypes";
|
|
58
|
+
import { resolveStaticPath } from "./staticPath";
|
|
58
59
|
import { createSubRouteIndexResponse, createSystemPageResponse, getSystemPageHomeHref } from "./systemPages";
|
|
59
60
|
import { type BaseBuildArtifact, type HttpRoutes, type RenderState, resolveWebConfig } from "./types";
|
|
60
61
|
|
|
@@ -411,16 +412,14 @@ export class WebRouter {
|
|
|
411
412
|
<script type="module" src="/csr.js"></script>
|
|
412
413
|
</body>
|
|
413
414
|
</html>`;
|
|
414
|
-
return new Response(this.#withCsrHmr(htmlText), {
|
|
415
|
-
headers: { "Content-Type": "text/html; charset=utf-8" },
|
|
416
|
-
});
|
|
415
|
+
return new Response(this.#withCsrHmr(htmlText), { headers: WebRouter.#htmlResponseHeaders(200) });
|
|
417
416
|
},
|
|
418
417
|
}
|
|
419
418
|
: {}),
|
|
420
419
|
[`${clientServePrefix}/*`]: async (req) => {
|
|
421
420
|
this.#requestStats.staticAsset += 1;
|
|
422
421
|
const url = new URL(req.url);
|
|
423
|
-
const filePath =
|
|
422
|
+
const filePath = resolveStaticPath(clientOutputDir, url.pathname.slice(clientServePrefix.length + 1));
|
|
424
423
|
if (!filePath) return new Response("Not Found", { status: 404 });
|
|
425
424
|
return WebRouter.#fileResponse(req, filePath, {
|
|
426
425
|
contentType: Bun.file(filePath).type || "application/javascript",
|
|
@@ -431,7 +430,7 @@ export class WebRouter {
|
|
|
431
430
|
this.#requestStats.staticAsset += 1;
|
|
432
431
|
const url = new URL(req.url);
|
|
433
432
|
if (this.#prodMode) {
|
|
434
|
-
const filePath =
|
|
433
|
+
const filePath = resolveStaticPath(this.#artifactDir, url.pathname.slice("/_akan/".length));
|
|
435
434
|
if (filePath) {
|
|
436
435
|
return WebRouter.#fileResponse(req, filePath, {
|
|
437
436
|
contentType: "text/css; charset=utf-8",
|
|
@@ -449,7 +448,7 @@ export class WebRouter {
|
|
|
449
448
|
"/_akan/fonts/*": (req) => {
|
|
450
449
|
this.#requestStats.staticAsset += 1;
|
|
451
450
|
const url = new URL(req.url);
|
|
452
|
-
const filePath =
|
|
451
|
+
const filePath = resolveStaticPath(this.#artifactDir, url.pathname.slice("/_akan/".length));
|
|
453
452
|
if (!filePath) return new Response("Not Found", { status: 404 });
|
|
454
453
|
return WebRouter.#fileResponse(req, filePath, {
|
|
455
454
|
contentType: Bun.file(filePath).type || "font/woff2",
|
|
@@ -524,10 +523,10 @@ export class WebRouter {
|
|
|
524
523
|
this.#requestStats.staticAsset += 1;
|
|
525
524
|
const firebaseConfig = await WebRouter.#resolveFirebaseClientConfig();
|
|
526
525
|
return new Response(WebRouter.#createFirebaseMessagingServiceWorker(firebaseConfig), {
|
|
527
|
-
headers: {
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
},
|
|
526
|
+
headers: WebRouter.#baseAssetHeaders({
|
|
527
|
+
contentType: "application/javascript; charset=utf-8",
|
|
528
|
+
cacheControl: "no-store",
|
|
529
|
+
}),
|
|
531
530
|
});
|
|
532
531
|
},
|
|
533
532
|
"/*": async (req) => {
|
|
@@ -544,12 +543,10 @@ export class WebRouter {
|
|
|
544
543
|
const csrHtml = await this.#resolveCsrHtml(csrOutputDir, url.pathname);
|
|
545
544
|
if (!csrHtml) return this.#csrUnavailableResponse(url.pathname);
|
|
546
545
|
const html = await Bun.file(csrHtml).text();
|
|
547
|
-
return new Response(this.#withCsrHmr(html), {
|
|
548
|
-
headers: { "Content-Type": "text/html; charset=utf-8" },
|
|
549
|
-
});
|
|
546
|
+
return new Response(this.#withCsrHmr(html), { headers: WebRouter.#htmlResponseHeaders(200) });
|
|
550
547
|
}
|
|
551
548
|
|
|
552
|
-
const csrAssetPath = path.extname(url.pathname) ?
|
|
549
|
+
const csrAssetPath = path.extname(url.pathname) ? resolveStaticPath(csrOutputDir, url.pathname) : null;
|
|
553
550
|
if (csrAssetPath && (await Bun.file(csrAssetPath).exists())) {
|
|
554
551
|
this.#requestStats.staticAsset += 1;
|
|
555
552
|
return WebRouter.#fileResponse(req, csrAssetPath, {
|
|
@@ -559,7 +556,7 @@ export class WebRouter {
|
|
|
559
556
|
}
|
|
560
557
|
}
|
|
561
558
|
|
|
562
|
-
const filePath =
|
|
559
|
+
const filePath = resolveStaticPath(publicDir, url.pathname);
|
|
563
560
|
if (filePath) {
|
|
564
561
|
if (await Bun.file(filePath).exists()) {
|
|
565
562
|
this.#requestStats.staticAsset += 1;
|
|
@@ -607,12 +604,9 @@ export class WebRouter {
|
|
|
607
604
|
const htmlCacheEntry = htmlCacheDecision.entry;
|
|
608
605
|
const cachedHtml = htmlCacheEntry ? this.#getCachedHtml(htmlCacheEntry.key) : null;
|
|
609
606
|
if (cachedHtml) {
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
"X-Akan-Cache": "HIT",
|
|
614
|
-
},
|
|
615
|
-
});
|
|
607
|
+
const cachedHeaders = WebRouter.#htmlResponseHeaders(200);
|
|
608
|
+
cachedHeaders.set("X-Akan-Cache", "HIT");
|
|
609
|
+
return new Response(cachedHtml, { headers: cachedHeaders });
|
|
616
610
|
}
|
|
617
611
|
const rscResult = await this.#rsc.renderWithMeta(req, {
|
|
618
612
|
clientManifest: manifest.clientManifest,
|
|
@@ -993,7 +987,7 @@ export class WebRouter {
|
|
|
993
987
|
static #htmlResponseHeaders(status: number): Headers {
|
|
994
988
|
const headers = new Headers({ "Content-Type": "text/html; charset=utf-8" });
|
|
995
989
|
if (status >= 400) headers.set("Cache-Control", "no-store");
|
|
996
|
-
return headers;
|
|
990
|
+
return WebRouter.#applySecurityHeaders(headers, { html: true });
|
|
997
991
|
}
|
|
998
992
|
#withCsrHmr(html: string): string {
|
|
999
993
|
if (this.#prodMode) return html;
|
|
@@ -1249,7 +1243,7 @@ self.addEventListener("notificationclick", (event) => {
|
|
|
1249
1243
|
i18n: artifact.i18n,
|
|
1250
1244
|
});
|
|
1251
1245
|
const filename = basePath ? `${basePath}.html` : "index.html";
|
|
1252
|
-
const filePath =
|
|
1246
|
+
const filePath = resolveStaticPath(csrOutputDir, filename);
|
|
1253
1247
|
return filePath && fs.existsSync(filePath) ? filePath : null;
|
|
1254
1248
|
}
|
|
1255
1249
|
|
|
@@ -1334,10 +1328,27 @@ self.addEventListener("notificationclick", (event) => {
|
|
|
1334
1328
|
return bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength) as ArrayBuffer;
|
|
1335
1329
|
}
|
|
1336
1330
|
|
|
1331
|
+
/**
|
|
1332
|
+
* Headers every response carries, whatever it is.
|
|
1333
|
+
*
|
|
1334
|
+
* `nosniff` because `Bun.file().type` falls back to `application/octet-stream` for an extension it does not
|
|
1335
|
+
* know, and a sniffing browser then guesses again — on a `public/` tree the app serves from its own origin,
|
|
1336
|
+
* that guess is script execution. `Referrer-Policy` because route paths carry ids.
|
|
1337
|
+
*
|
|
1338
|
+
* `X-Frame-Options` is on the HTML only: framing an image or a stylesheet means nothing, and the header is
|
|
1339
|
+
* what stops a page authenticated by a `SameSite=None` cookie from being clickjacked inside somebody else's.
|
|
1340
|
+
*/
|
|
1341
|
+
static #applySecurityHeaders(headers: Headers, { html = false } = {}): Headers {
|
|
1342
|
+
headers.set("X-Content-Type-Options", "nosniff");
|
|
1343
|
+
headers.set("Referrer-Policy", "strict-origin-when-cross-origin");
|
|
1344
|
+
if (html) headers.set("X-Frame-Options", "SAMEORIGIN");
|
|
1345
|
+
return headers;
|
|
1346
|
+
}
|
|
1347
|
+
|
|
1337
1348
|
static #baseAssetHeaders(options: { contentType: string; cacheControl?: string }): Headers {
|
|
1338
1349
|
const headers = new Headers({ "Content-Type": options.contentType });
|
|
1339
1350
|
if (options.cacheControl) headers.set("Cache-Control", options.cacheControl);
|
|
1340
|
-
return headers;
|
|
1351
|
+
return WebRouter.#applySecurityHeaders(headers);
|
|
1341
1352
|
}
|
|
1342
1353
|
|
|
1343
1354
|
static #weakEtag(size: number, mtimeMs: number): string {
|
|
@@ -1359,21 +1370,4 @@ self.addEventListener("notificationclick", (event) => {
|
|
|
1359
1370
|
const sinceMs = Date.parse(ifModifiedSince);
|
|
1360
1371
|
return Number.isFinite(sinceMs) && sinceMs >= lastModifiedMs;
|
|
1361
1372
|
}
|
|
1362
|
-
|
|
1363
|
-
static #safeResolve(baseDir: string, urlPath: string): string | null {
|
|
1364
|
-
let decoded: string;
|
|
1365
|
-
try {
|
|
1366
|
-
decoded = decodeURIComponent(urlPath);
|
|
1367
|
-
} catch {
|
|
1368
|
-
return null;
|
|
1369
|
-
}
|
|
1370
|
-
if (decoded.includes("\0")) return null;
|
|
1371
|
-
const normalizedBase = path.resolve(baseDir);
|
|
1372
|
-
const rel = decoded.replace(/^[/\\]+/, "");
|
|
1373
|
-
const resolved = path.resolve(normalizedBase, rel);
|
|
1374
|
-
if (resolved === normalizedBase) return resolved;
|
|
1375
|
-
const baseWithSep = normalizedBase.endsWith(path.sep) ? normalizedBase : normalizedBase + path.sep;
|
|
1376
|
-
if (!resolved.startsWith(baseWithSep)) return null;
|
|
1377
|
-
return resolved;
|
|
1378
|
-
}
|
|
1379
1373
|
}
|
package/service/adapt.ts
CHANGED
|
@@ -8,11 +8,7 @@ export interface Adaptor {
|
|
|
8
8
|
onDestroy(): Promise<void> | void;
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
export type AdaptorCls<
|
|
12
|
-
Methods = any,
|
|
13
|
-
|
|
14
|
-
InjectMap extends Record<string, InjectInfo> = {},
|
|
15
|
-
> = Cls<
|
|
11
|
+
export type AdaptorCls<Methods = any, InjectMap extends Record<string, InjectInfo> = Record<never, never>> = Cls<
|
|
16
12
|
Methods & ExtractInjectInfoObject<InjectMap> & Adaptor,
|
|
17
13
|
{ readonly [INJECT_META]: InjectMap; readonly refName: string }
|
|
18
14
|
>;
|
|
@@ -39,7 +39,6 @@ export class RedisCache
|
|
|
39
39
|
operationMode,
|
|
40
40
|
repoName,
|
|
41
41
|
redis = {
|
|
42
|
-
|
|
43
42
|
sshOptions: {
|
|
44
43
|
host: `${appName}-${environment}.${serveDomain}`,
|
|
45
44
|
port: 32767,
|
|
@@ -51,9 +50,14 @@ export class RedisCache
|
|
|
51
50
|
}: RedisEnv) => {
|
|
52
51
|
const createRedis = async (url: string) => {
|
|
53
52
|
const { Redis } = await import("ioredis");
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
53
|
+
|
|
54
|
+
const client = new Redis(url, {
|
|
55
|
+
lazyConnect: true,
|
|
56
|
+
...(redis.username ? { username: redis.username } : {}),
|
|
57
|
+
...(redis.password ? { password: redis.password } : {}),
|
|
58
|
+
});
|
|
59
|
+
await client.connect();
|
|
60
|
+
return client;
|
|
57
61
|
};
|
|
58
62
|
if (process.env.REDIS_URI) return await createRedis(process.env.REDIS_URI);
|
|
59
63
|
else if (environment === "local") return await createRedis("redis://localhost:6379");
|