forked from deco-cx/deco
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdeco.ts
139 lines (122 loc) · 3.65 KB
/
deco.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
import "./utils/patched_fetch.ts";
import { AsyncLocalStorage } from "node:async_hooks";
import type { ImportMap } from "./blocks/app.ts";
import type { ReleaseResolver } from "./engine/core/mod.ts";
import type { DecofileProvider } from "./engine/decofile/provider.ts";
import type { AppManifest } from "./types.ts";
import { randId } from "./utils/rand.ts";
export interface DecoRuntimeState<
TAppManifest extends AppManifest = AppManifest,
> {
manifest: TAppManifest;
// deno-lint-ignore no-explicit-any
resolver: ReleaseResolver<any>;
importMap: ImportMap;
}
export interface InstanceInfo {
startedAt: Date;
id: string;
readyAt?: Date;
}
export type RequestContext = {
/** Cancelation token used for early processing halt */
signal?: AbortSignal;
framework?: "fresh" | "htmx";
};
export type WellKnownHostingPlatform =
| "kubernetes"
| "denodeploy"
| "localhost";
export type DecodMode = "sidecar" | "embedded";
export const DaemonMode = {
Sidecar: "sidecar" as DecodMode,
Embedded: "embedded" as DecodMode,
};
// The global deco context
export interface DecoContext<TAppManifest extends AppManifest = AppManifest> {
deploymentId: string | undefined;
isDeploy: boolean;
decodMode?: DecodMode;
platform: WellKnownHostingPlatform;
site: string;
siteId: number;
loginUrl?: string;
base?: string;
namespace?: string;
release?: DecofileProvider;
runtime?: Promise<DecoRuntimeState<TAppManifest>>;
instance: InstanceInfo;
request?: RequestContext;
}
export interface RequestContextBinder {
active: () => RequestContext | undefined;
bind: <R, TArgs extends unknown[]>(
request: RequestContext,
f: (...args: TArgs) => R,
) => (...args: TArgs) => R;
readonly signal: AbortSignal | undefined;
readonly framework: "fresh" | "htmx";
}
const deploymentId = Deno.env.get("DENO_DEPLOYMENT_ID");
const isDeploy = Boolean(deploymentId);
const getHostingPlatform = (): WellKnownHostingPlatform => {
const kService = Deno.env.get("K_SERVICE") !== undefined;
if (kService) {
return "kubernetes";
} else if (isDeploy) {
return "denodeploy";
} else {
return "localhost";
}
};
// deno-lint-ignore no-explicit-any
let defaultContext: Omit<DecoContext<any>, "schema"> = {
deploymentId,
siteId: 0,
isDeploy: isDeploy,
decodMode: Deno.env.get("DECOD_MODE") as DecodMode | undefined,
platform: getHostingPlatform(),
site: "",
instance: {
id: randId(),
startedAt: new Date(),
},
};
const asyncLocalStorage = new AsyncLocalStorage<DecoContext>();
export const Context = {
setDefault: <T extends AppManifest = AppManifest>(
ctx: DecoContext<T>,
): void => {
defaultContext = ctx;
},
// Function to retrieve the active context
active: <T extends AppManifest = AppManifest>(): DecoContext<T> => {
// Retrieve the context associated with the async ID
return asyncLocalStorage.getStore() ?? defaultContext;
},
bind: <R, TArgs extends unknown[]>(
ctx: DecoContext,
f: (...args: TArgs) => R,
): (...args: TArgs) => R => {
return (...args: TArgs): R => {
return asyncLocalStorage.run(ctx, f, ...args);
};
},
};
export const RequestContext: RequestContextBinder = {
active: (): RequestContext | undefined => Context.active().request,
bind: <R, TArgs extends unknown[]>(
request: RequestContext,
f: (...args: TArgs) => R,
): (...args: TArgs) => R => {
return Context.bind({ ...Context.active(), request }, f);
},
get signal() {
return Context.active().request?.signal;
},
get framework() {
return Context.active().request?.framework ?? "fresh";
},
};
// deno-lint-ignore no-explicit-any
export const context: DecoContext<any> = Context.active();