ocel 0.0.1-alpha.1 → 0.0.1
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/LICENSE +202 -0
- package/NOTICE +2 -0
- package/README.md +98 -0
- package/dist/binding/binding.d.ts +22 -0
- package/dist/binding/binding.js +60 -0
- package/dist/binding/unprovisioned.d.ts +17 -0
- package/dist/binding/unprovisioned.js +25 -0
- package/dist/bucket/bucket-client.d.ts +4 -0
- package/dist/bucket/bucket-client.js +5 -0
- package/dist/bucket/bucket-context.d.ts +8 -0
- package/dist/bucket/bucket-context.js +10 -0
- package/dist/bucket/bucket.d.ts +60 -0
- package/dist/bucket/bucket.js +91 -0
- package/dist/bucket/client.d.ts +49 -0
- package/dist/bucket/client.js +95 -0
- package/dist/bucket/errors.d.ts +12 -0
- package/dist/bucket/errors.js +20 -0
- package/dist/bucket/express.d.ts +10 -0
- package/dist/bucket/express.js +24 -0
- package/dist/bucket/hono.d.ts +18 -0
- package/dist/bucket/hono.js +13 -0
- package/dist/bucket/index.d.ts +8 -0
- package/dist/bucket/index.js +6 -0
- package/dist/bucket/keys.d.ts +5 -0
- package/dist/bucket/keys.js +24 -0
- package/dist/bucket/metadata.d.ts +6 -0
- package/dist/bucket/metadata.js +6 -0
- package/dist/bucket/next.d.ts +15 -0
- package/dist/bucket/next.js +11 -0
- package/dist/bucket/objects.d.ts +130 -0
- package/dist/bucket/objects.js +350 -0
- package/dist/bucket/route.d.ts +13 -0
- package/dist/bucket/route.js +247 -0
- package/dist/bucket/server-only.js +5 -0
- package/dist/bucket/types.d.ts +63 -0
- package/dist/bucket/uploader.d.ts +3 -0
- package/dist/bucket/uploader.js +6 -0
- package/dist/build-env.d.ts +17 -0
- package/dist/build-env.js +41 -0
- package/dist/config.d.ts +30 -0
- package/dist/config.js +9 -0
- package/dist/declaration/callsite.d.ts +15 -0
- package/dist/declaration/callsite.js +43 -0
- package/dist/declaration/component.d.ts +4 -0
- package/dist/declaration/component.js +1 -0
- package/dist/declaration/defer.d.ts +5 -0
- package/dist/declaration/defer.js +9 -0
- package/dist/delivery/duration.d.ts +13 -0
- package/dist/delivery/duration.js +36 -0
- package/dist/delivery/lane.d.ts +4 -0
- package/dist/delivery/lane.js +15 -0
- package/dist/delivery/payload.d.ts +6 -0
- package/dist/delivery/payload.js +14 -0
- package/dist/delivery/retry.d.ts +16 -0
- package/dist/delivery/retry.js +10 -0
- package/dist/delivery/schema.d.ts +10 -0
- package/dist/delivery/schema.js +20 -0
- package/dist/dns.d.ts +11 -0
- package/dist/dns.js +4 -0
- package/dist/edge.d.ts +4 -0
- package/dist/edge.js +4 -0
- package/dist/env/access.d.ts +22 -0
- package/dist/env/access.js +49 -0
- package/dist/env/client.d.ts +5 -0
- package/dist/env/client.js +10 -0
- package/dist/env/declare.d.ts +2 -0
- package/dist/env/declare.js +83 -0
- package/dist/env/definition.d.ts +46 -0
- package/dist/env/definition.js +164 -0
- package/dist/env/deployment.d.ts +23 -0
- package/dist/env/deployment.js +13 -0
- package/dist/env/edge.d.ts +10 -0
- package/dist/env/edge.js +30 -0
- package/dist/env/errors.d.ts +9 -0
- package/dist/env/errors.js +9 -0
- package/dist/env/file.d.ts +1 -0
- package/dist/env/file.js +27 -0
- package/dist/env/index.d.ts +10 -0
- package/dist/env/index.js +63 -0
- package/dist/env/live.d.ts +3 -0
- package/dist/env/live.js +12 -0
- package/dist/env/schema.d.ts +27 -0
- package/dist/env/schema.js +43 -0
- package/dist/env/scope.d.ts +7 -0
- package/dist/env/scope.js +45 -0
- package/dist/env/standard.d.ts +10 -0
- package/dist/env/standard.js +21 -0
- package/dist/env/value.d.ts +5 -0
- package/dist/env/value.js +26 -0
- package/dist/env-source.d.ts +17 -0
- package/dist/env-source.js +16 -0
- package/dist/gen/proto/app/bucket/v1/bucket_pb.d.ts +911 -0
- package/dist/gen/proto/app/bucket/v1/bucket_pb.js +253 -0
- package/dist/gen/proto/app/realtime/v1/realtime_pb.d.ts +50 -0
- package/dist/gen/proto/app/realtime/v1/realtime_pb.js +23 -0
- package/dist/gen/proto/app/resources/v1/resources_pb.d.ts +554 -0
- package/dist/gen/proto/app/resources/v1/resources_pb.js +214 -0
- package/dist/gen/proto/app/resources/v1/variables_pb.d.ts +231 -0
- package/dist/gen/proto/app/resources/v1/variables_pb.js +101 -0
- package/dist/gen/proto/app/task/v1/task_pb.d.ts +498 -0
- package/dist/gen/proto/app/task/v1/task_pb.js +151 -0
- package/dist/gen/proto/app/topic/v1/topic_pb.d.ts +456 -0
- package/dist/gen/proto/app/topic/v1/topic_pb.js +125 -0
- package/dist/gen/proto/buf/validate/validate_pb.d.ts +4833 -0
- package/dist/gen/proto/buf/validate/validate_pb.js +356 -0
- package/dist/gen/proto/common/bindings/v1/bindings_pb.d.ts +378 -0
- package/dist/gen/proto/common/bindings/v1/bindings_pb.js +140 -0
- package/dist/generated/config.d.ts +428 -0
- package/dist/generated/config.js +2 -0
- package/dist/kv/entries.d.ts +193 -0
- package/dist/kv/entries.js +325 -0
- package/dist/kv/errors.d.ts +12 -0
- package/dist/kv/errors.js +14 -0
- package/dist/kv/index.d.ts +6 -0
- package/dist/kv/index.js +3 -0
- package/dist/kv/ioredis.d.ts +2 -0
- package/dist/kv/ioredis.js +20 -0
- package/dist/kv/kv.d.ts +84 -0
- package/dist/kv/kv.js +177 -0
- package/dist/kv/pattern.d.ts +27 -0
- package/dist/kv/pattern.js +73 -0
- package/dist/kv/ttl.d.ts +22 -0
- package/dist/kv/ttl.js +21 -0
- package/dist/postgres/index.d.ts +21 -2
- package/dist/postgres/index.js +73 -2
- package/dist/postgres/pg.d.ts +5 -4
- package/dist/postgres/pg.js +16 -12
- package/dist/providers/aws/dns.d.ts +11 -0
- package/dist/providers/aws/dns.js +4 -0
- package/dist/providers/aws/edge.d.ts +6 -0
- package/dist/providers/aws/edge.js +8 -0
- package/dist/providers/aws/index.d.ts +4 -0
- package/dist/providers/aws/index.js +4 -0
- package/dist/providers/gcp/edge.d.ts +14 -0
- package/dist/providers/gcp/edge.js +14 -0
- package/dist/providers/gcp/index.d.ts +9 -0
- package/dist/providers/gcp/index.js +9 -0
- package/dist/providers/vps/index.d.ts +4 -0
- package/dist/providers/vps/index.js +4 -0
- package/dist/realtime/client-error.d.ts +30 -0
- package/dist/realtime/client-error.js +17 -0
- package/dist/realtime/client-event-socket.d.ts +8 -0
- package/dist/realtime/client-event-socket.js +169 -0
- package/dist/realtime/client-transport.d.ts +29 -0
- package/dist/realtime/client-transport.js +13 -0
- package/dist/realtime/client.d.ts +150 -0
- package/dist/realtime/client.js +345 -0
- package/dist/realtime/express.d.ts +18 -0
- package/dist/realtime/express.js +83 -0
- package/dist/realtime/handler.d.ts +56 -0
- package/dist/realtime/handler.js +287 -0
- package/dist/realtime/hono.d.ts +19 -0
- package/dist/realtime/hono.js +24 -0
- package/dist/realtime/index.d.ts +2 -0
- package/dist/realtime/index.js +2 -0
- package/dist/realtime/next.d.ts +26 -0
- package/dist/realtime/next.js +16 -0
- package/dist/realtime/realtime.d.ts +181 -0
- package/dist/realtime/realtime.js +205 -0
- package/dist/realtime/token.d.ts +20 -0
- package/dist/realtime/token.js +45 -0
- package/dist/realtime/transport.d.ts +11 -0
- package/dist/realtime/transport.js +15 -0
- package/dist/realtime/wire.d.ts +30 -0
- package/dist/realtime/wire.js +104 -0
- package/dist/runtime/dev-server.d.ts +8 -0
- package/dist/runtime/dev-server.js +8 -0
- package/dist/runtime/rpc.d.ts +23 -0
- package/dist/runtime/rpc.js +24 -0
- package/dist/runtime/transport.d.ts +11 -0
- package/dist/runtime/transport.js +35 -0
- package/dist/task/errors.d.ts +7 -0
- package/dist/task/errors.js +7 -0
- package/dist/task/hooks.d.ts +57 -0
- package/dist/task/hooks.js +1 -0
- package/dist/task/index.d.ts +9 -0
- package/dist/task/index.js +4 -0
- package/dist/task/runs.d.ts +74 -0
- package/dist/task/runs.js +82 -0
- package/dist/task/task.d.ts +117 -0
- package/dist/task/task.js +109 -0
- package/dist/topic/dead-letters.d.ts +53 -0
- package/dist/topic/dead-letters.js +62 -0
- package/dist/topic/index.d.ts +8 -0
- package/dist/topic/index.js +4 -0
- package/dist/topic/topic.d.ts +85 -0
- package/dist/topic/topic.js +117 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.js +2 -0
- package/dist/worker/context.d.ts +36 -0
- package/dist/worker/context.js +1 -0
- package/dist/worker/deliver.d.ts +13 -0
- package/dist/worker/deliver.js +258 -0
- package/dist/worker/index.d.ts +4 -0
- package/dist/worker/index.js +2 -0
- package/dist/worker/registry.d.ts +28 -0
- package/dist/worker/registry.js +22 -0
- package/dist/worker/semaphore.d.ts +7 -0
- package/dist/worker/semaphore.js +36 -0
- package/dist/worker/worker.d.ts +21 -0
- package/dist/worker/worker.js +32 -0
- package/package.json +158 -57
- package/bin/run.js +0 -39
- package/dist/blob/bucket.d.ts +0 -55
- package/dist/blob/bucket.js +0 -65
- package/dist/blob/index.d.ts +0 -8
- package/dist/blob/index.js +0 -13
- package/dist/blob/integrations/client.d.ts +0 -25
- package/dist/blob/integrations/client.js +0 -71
- package/dist/blob/integrations/hono.d.ts +0 -31
- package/dist/blob/integrations/hono.js +0 -11
- package/dist/blob/mime-types.d.ts +0 -1
- package/dist/blob/parse.d.ts +0 -16
- package/dist/blob/parse.js +0 -69
- package/dist/blob/s3-listener.d.ts +0 -7
- package/dist/blob/s3-listener.js +0 -35
- package/dist/blob/types.d.ts +0 -128
- package/dist/blob/types.js +0 -1
- package/dist/blob/upload-error.d.ts +0 -35
- package/dist/blob/upload-error.js +0 -54
- package/dist/blob/uploader.d.ts +0 -67
- package/dist/blob/uploader.js +0 -323
- package/dist/internal/db/index.d.ts +0 -68
- package/dist/internal/db/index.js +0 -73
- package/dist/lambda/index.d.ts +0 -2
- package/dist/lambda/index.js +0 -4
- package/dist/lambda/integrations/express.d.ts +0 -3
- package/dist/lambda/integrations/express.js +0 -13
- package/dist/lambda/integrations/hono.d.ts +0 -3
- package/dist/lambda/integrations/hono.js +0 -13
- package/dist/lambda/lambda.d.ts +0 -43
- package/dist/lambda/lambda.js +0 -30
- package/dist/utils/component.d.ts +0 -3
- package/dist/utils/constants.d.ts +0 -2
- package/dist/utils/constants.js +0 -2
- package/dist/utils/nanoid.d.ts +0 -1
- package/dist/utils/nanoid.js +0 -6
- package/dist/utils/rpc.d.ts +0 -11
- package/dist/utils/rpc.js +0 -17
- package/dist/utils/stack.d.ts +0 -4
- package/dist/utils/stack.js +0 -23
- package/dist/workflow/index.d.ts +0 -3
- package/dist/workflow/index.js +0 -4
- package/dist/workflow/workflow.d.ts +0 -34
- package/dist/workflow/workflow.js +0 -146
- package/src/blob/bucket.ts +0 -92
- package/src/blob/index.ts +0 -34
- package/src/blob/integrations/client.ts +0 -127
- package/src/blob/integrations/hono.ts +0 -16
- package/src/blob/mime-types.ts +0 -68
- package/src/blob/parse.ts +0 -93
- package/src/blob/s3-listener.ts +0 -48
- package/src/blob/types.ts +0 -142
- package/src/blob/upload-error.ts +0 -67
- package/src/blob/uploader.ts +0 -426
- package/src/internal/db/index.ts +0 -78
- package/src/lambda/index.ts +0 -8
- package/src/lambda/integrations/express.ts +0 -25
- package/src/lambda/integrations/hono.ts +0 -25
- package/src/lambda/lambda.ts +0 -94
- package/src/postgres/index.ts +0 -5
- package/src/postgres/pg.ts +0 -33
- package/src/utils/component.ts +0 -3
- package/src/utils/constants.ts +0 -2
- package/src/utils/nanoid.ts +0 -9
- package/src/utils/rpc.ts +0 -28
- package/src/utils/stack.ts +0 -26
- package/src/workflow/index.ts +0 -9
- package/src/workflow/workflow.ts +0 -235
- /package/dist/{blob/mime-types.js → bucket/server-only.d.ts} +0 -0
- /package/dist/{utils/component.js → bucket/types.js} +0 -0
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import { EnvDefinitionError } from "./errors.js";
|
|
2
|
+
import { scopeProblem } from "./scope.js";
|
|
3
|
+
import { parse } from "./standard.js";
|
|
4
|
+
/** A set of variables an app takes together: every member is reached through the group and
|
|
5
|
+
* nowhere else, and `{ optional: true }` reads the whole group as `undefined` until a value
|
|
6
|
+
* is delivered for one of its members. */
|
|
7
|
+
export function group(definitions, options) {
|
|
8
|
+
return {
|
|
9
|
+
definitions,
|
|
10
|
+
optional: (options?.optional === true),
|
|
11
|
+
...(options?.description === undefined ? {} : { description: options.description }),
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
export function flattenDefinitions(definitions) {
|
|
15
|
+
const flat = {};
|
|
16
|
+
for (const [key, definition] of Object.entries(definitions)) {
|
|
17
|
+
if ("definitions" in definition) {
|
|
18
|
+
for (const [member, nested] of Object.entries(definition.definitions)) {
|
|
19
|
+
if ("definitions" in nested)
|
|
20
|
+
throw new EnvDefinitionError(`group '${key}' nests another group. Groups nest one level only.`);
|
|
21
|
+
claim(flat, member, key);
|
|
22
|
+
flat[member] = {
|
|
23
|
+
...nested,
|
|
24
|
+
group: key,
|
|
25
|
+
groupOptional: definition.optional,
|
|
26
|
+
groupDescription: definition.description,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
claim(flat, key);
|
|
32
|
+
flat[key] = definition;
|
|
33
|
+
}
|
|
34
|
+
return flat;
|
|
35
|
+
}
|
|
36
|
+
function claim(flat, key, group) {
|
|
37
|
+
const existing = flat[key];
|
|
38
|
+
if (!existing)
|
|
39
|
+
return;
|
|
40
|
+
const inside = [existing.group, group].filter((name) => name !== undefined);
|
|
41
|
+
if (inside.length === 0) {
|
|
42
|
+
throw new EnvDefinitionError(`'${key}' is declared twice in the same call.`);
|
|
43
|
+
}
|
|
44
|
+
throw new EnvDefinitionError(`'${key}' is declared twice in the same call, once inside ${inside
|
|
45
|
+
.map((name) => `group '${name}'`)
|
|
46
|
+
.join(" and once inside ")}.`);
|
|
47
|
+
}
|
|
48
|
+
const LIVE_CLASSES = new Set(["secret"]);
|
|
49
|
+
export function isLive(definition) {
|
|
50
|
+
return LIVE_CLASSES.has(definition.class);
|
|
51
|
+
}
|
|
52
|
+
const BARE_KEY_CLASSES = new Set(["plain"]);
|
|
53
|
+
const RESERVED_PREFIXES = ["OCEL_"];
|
|
54
|
+
export const URL_KEY = "OCEL_URL";
|
|
55
|
+
export const CLIENT_URL_KEY = "NEXT_PUBLIC_OCEL_URL";
|
|
56
|
+
const RESERVED_KEYS = new Map([
|
|
57
|
+
[URL_KEY, "every app"],
|
|
58
|
+
[CLIENT_URL_KEY, "every JavaScript app"],
|
|
59
|
+
]);
|
|
60
|
+
const KEY_PATTERN = /^[A-Z_][A-Z0-9_]*$/;
|
|
61
|
+
export function isUsableKey(key) {
|
|
62
|
+
return KEY_PATTERN.test(key);
|
|
63
|
+
}
|
|
64
|
+
const owner = new Map();
|
|
65
|
+
export function validateDefinitions(definitions, source) {
|
|
66
|
+
for (const [key, definition] of Object.entries(definitions)) {
|
|
67
|
+
if ("definitions" in definition)
|
|
68
|
+
validateGroup(key, definition);
|
|
69
|
+
}
|
|
70
|
+
const flat = flattenDefinitions(definitions);
|
|
71
|
+
for (const [key, definition] of Object.entries(flat)) {
|
|
72
|
+
validateDefinition(key, definition, source);
|
|
73
|
+
owner.set(key, source);
|
|
74
|
+
}
|
|
75
|
+
return flat;
|
|
76
|
+
}
|
|
77
|
+
function validateGroup(key, definition) {
|
|
78
|
+
if (key === "" || key.includes("#") || /\p{Cc}/u.test(key)) {
|
|
79
|
+
throw new EnvDefinitionError(`'${key}' is not a usable group name: a group name is one line and has no '#'.`);
|
|
80
|
+
}
|
|
81
|
+
if (Object.keys(definition.definitions).length === 0) {
|
|
82
|
+
throw new EnvDefinitionError(`'${key}' declares no variables. A group contains the variables an app takes together, so it has at least one.`);
|
|
83
|
+
}
|
|
84
|
+
const problem = descriptionProblem(definition.description);
|
|
85
|
+
if (problem) {
|
|
86
|
+
throw new EnvDefinitionError(`'${key}' has an unusable description: ${problem}`);
|
|
87
|
+
}
|
|
88
|
+
const unsatisfiable = unsharedScopes(definition.definitions);
|
|
89
|
+
if (unsatisfiable) {
|
|
90
|
+
throw new EnvDefinitionError(`'${key}' is read as one, and no folder satisfies every member: ${unsatisfiable}.`);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
function unsharedScopes(definitions) {
|
|
94
|
+
let shared;
|
|
95
|
+
const scoped = [];
|
|
96
|
+
for (const [key, definition] of Object.entries(definitions)) {
|
|
97
|
+
const folders = definition.folders;
|
|
98
|
+
if (!folders || folders.length === 0)
|
|
99
|
+
continue;
|
|
100
|
+
scoped.push(`${key} (${folders.join(", ")})`);
|
|
101
|
+
shared = shared === undefined ? folders : shared.filter((folder) => folders.includes(folder));
|
|
102
|
+
}
|
|
103
|
+
if (shared === undefined || shared.length > 0)
|
|
104
|
+
return undefined;
|
|
105
|
+
return scoped.join(", ");
|
|
106
|
+
}
|
|
107
|
+
function descriptionProblem(description) {
|
|
108
|
+
if (description === undefined)
|
|
109
|
+
return "";
|
|
110
|
+
if (new TextEncoder().encode(description).length > 120) {
|
|
111
|
+
return "a description is at most 120 bytes.";
|
|
112
|
+
}
|
|
113
|
+
if (/\p{Cc}/u.test(description)) {
|
|
114
|
+
return "a description is one line and has no control characters.";
|
|
115
|
+
}
|
|
116
|
+
return "";
|
|
117
|
+
}
|
|
118
|
+
function validateDefinition(key, definition, source) {
|
|
119
|
+
if (!KEY_PATTERN.test(key)) {
|
|
120
|
+
throw new EnvDefinitionError(`'${key}' is not a usable variable name: use upper-case letters, digits and underscores, starting with a letter or underscore.`);
|
|
121
|
+
}
|
|
122
|
+
const writtenFor = RESERVED_KEYS.get(key);
|
|
123
|
+
if (writtenFor !== undefined) {
|
|
124
|
+
throw new EnvDefinitionError(`'${key}' is written by Ocel for ${writtenFor}, from the hostname the deploy serves it on, so a declared one would be overwritten before anything read it. Read it as \`deployment.url\` from 'ocel/env'.`);
|
|
125
|
+
}
|
|
126
|
+
const claimed = owner.get(key);
|
|
127
|
+
if (claimed !== undefined && claimed !== source) {
|
|
128
|
+
throw new EnvDefinitionError(`'${key}' is already declared in ${claimed}. A key may be defined by exactly one definitions file.`);
|
|
129
|
+
}
|
|
130
|
+
const variableClass = definition.class;
|
|
131
|
+
if (definition.client && variableClass !== "plain") {
|
|
132
|
+
throw new EnvDefinitionError(`'${key}' is client-accessible and class '${variableClass}'. A value the browser can read cannot be an encrypted class.`);
|
|
133
|
+
}
|
|
134
|
+
if (BARE_KEY_CLASSES.has(variableClass) &&
|
|
135
|
+
RESERVED_PREFIXES.some((prefix) => key.startsWith(prefix))) {
|
|
136
|
+
throw new EnvDefinitionError(`'${key}' starts with a reserved prefix (${RESERVED_PREFIXES.join(", ")}). A '${variableClass}' variable is delivered under its own name, so Ocel would overwrite it.`);
|
|
137
|
+
}
|
|
138
|
+
if (definition.client && !isRequired(definition)) {
|
|
139
|
+
throw new EnvDefinitionError(`'${key}' is client-accessible and its schema accepts a missing value. A client value is inlined into the browser bundle at build time, so a default or an optional could not be told apart from a value the bundler never inlined.`);
|
|
140
|
+
}
|
|
141
|
+
if (definition.folders) {
|
|
142
|
+
const problem = scopeProblem(definition.folders);
|
|
143
|
+
if (problem) {
|
|
144
|
+
throw new EnvDefinitionError(`'${key}' has an unusable folder scope: ${problem}`);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
const described = descriptionProblem(definition.description);
|
|
148
|
+
if (described) {
|
|
149
|
+
throw new EnvDefinitionError(`'${key}' has an unusable description: ${described}`);
|
|
150
|
+
}
|
|
151
|
+
if (LIVE_CLASSES.has(definition.class) && !isRequired(definition)) {
|
|
152
|
+
throw new EnvDefinitionError(`'${key}' is class '${definition.class}' and its schema supplies a default. A live value must fail loudly when it is missing rather than fall back.`);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
export function isRequired(definition) {
|
|
156
|
+
if (!definition.schema)
|
|
157
|
+
return true;
|
|
158
|
+
return parse(definition.schema, undefined).ok === false;
|
|
159
|
+
}
|
|
160
|
+
export function complaint(definition, message) {
|
|
161
|
+
if (definition.class === "plain")
|
|
162
|
+
return message;
|
|
163
|
+
return `withheld, because a '${definition.class}' value's schema message can quote the value itself`;
|
|
164
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/** What this deployment knows about itself. Ocel writes it; nothing declares it. */
|
|
2
|
+
export interface Deployment {
|
|
3
|
+
/**
|
|
4
|
+
* The absolute url this app is served on, scheme and all —
|
|
5
|
+
* `https://web-j-1.ocel.site` deployed, `http://localhost:3000` under
|
|
6
|
+
* `ocel dev`. It is the first production hostname the app declares, and
|
|
7
|
+
* the project's own hostnames where the app is the first one `apps`
|
|
8
|
+
* names — the deploy serves those on that app alone. On a preview it is
|
|
9
|
+
* the derived preview hostname.
|
|
10
|
+
*
|
|
11
|
+
* Present under `ocel dev` always, and on a deploy that gives this app a
|
|
12
|
+
* hostname. An app past the first that declares none of its own is served
|
|
13
|
+
* on no hostname, and is handed no url: reading it then throws
|
|
14
|
+
* {@link EnvValueError}. Declare `domains.production` on the app.
|
|
15
|
+
*
|
|
16
|
+
* A client bundle reads the value inlined at build time, so adding a
|
|
17
|
+
* hostname with `ocel domain add` and not deploying again leaves the browser
|
|
18
|
+
* reading the hostname the last build was given. Deploy to move it.
|
|
19
|
+
*/
|
|
20
|
+
readonly url: string;
|
|
21
|
+
}
|
|
22
|
+
/** This deployment, as the running app sees it. */
|
|
23
|
+
export declare const deployment: Deployment;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { URL_KEY } from "./definition.js";
|
|
2
|
+
import { EnvValueError } from "./errors.js";
|
|
3
|
+
import { readDelivered } from "./value.js";
|
|
4
|
+
/** This deployment, as the running app sees it. */
|
|
5
|
+
export const deployment = {
|
|
6
|
+
get url() {
|
|
7
|
+
const url = readDelivered(URL_KEY);
|
|
8
|
+
if (url === undefined) {
|
|
9
|
+
throw new EnvValueError(`'${URL_KEY}' was not delivered to this app. Ocel writes it from the hostname the deploy serves the app on, and this app is served on none: add one under \`domains.production\` on the app, or on the project if this is the first app it names, and deploy again.`);
|
|
10
|
+
}
|
|
11
|
+
return url;
|
|
12
|
+
},
|
|
13
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type Env } from "./access.js";
|
|
2
|
+
import { type EnvDefinitions } from "./definition.js";
|
|
3
|
+
export type { Env } from "./access.js";
|
|
4
|
+
export { EnvClientError } from "./client.js";
|
|
5
|
+
export type { Definitions, EnvDefinitions, GroupDefinition, GroupOptions, VariableClass, VariableDefinition, } from "./definition.js";
|
|
6
|
+
export { group } from "./definition.js";
|
|
7
|
+
export { type Deployment, deployment } from "./deployment.js";
|
|
8
|
+
export { EnvDefinitionError, EnvEdgeError, EnvValueError } from "./errors.js";
|
|
9
|
+
export { EnvScopeError } from "./scope.js";
|
|
10
|
+
export declare function defineEnv<const TDefinitions extends EnvDefinitions>(definitions: TDefinitions): Env<TDefinitions>;
|
package/dist/env/edge.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { callSiteFile } from "../declaration/callsite.js";
|
|
2
|
+
import { envAccessor, FIXED } from "./access.js";
|
|
3
|
+
import { isLive, validateDefinitions, } from "./definition.js";
|
|
4
|
+
import { EnvEdgeError } from "./errors.js";
|
|
5
|
+
import { assertInScope } from "./scope.js";
|
|
6
|
+
import { coerce, readDelivered } from "./value.js";
|
|
7
|
+
export { EnvClientError } from "./client.js";
|
|
8
|
+
export { group } from "./definition.js";
|
|
9
|
+
export { deployment } from "./deployment.js";
|
|
10
|
+
export { EnvDefinitionError, EnvEdgeError, EnvValueError } from "./errors.js";
|
|
11
|
+
export { EnvScopeError } from "./scope.js";
|
|
12
|
+
const ENTRY_GLOBAL = "__OCEL_EDGE_ENTRY";
|
|
13
|
+
export function defineEnv(definitions) {
|
|
14
|
+
validateDefinitions(definitions, callSiteFile());
|
|
15
|
+
return envAccessor(definitions, { resolve, delivered, generationOf: () => FIXED });
|
|
16
|
+
}
|
|
17
|
+
function delivered(key) {
|
|
18
|
+
return readDelivered(key) !== undefined;
|
|
19
|
+
}
|
|
20
|
+
function resolve(key, definition) {
|
|
21
|
+
assertInScope(key, definition.folders ?? []);
|
|
22
|
+
if (isLive(definition))
|
|
23
|
+
throw notLive(key, definition);
|
|
24
|
+
return coerce(key, definition, readDelivered(key));
|
|
25
|
+
}
|
|
26
|
+
function notLive(key, definition) {
|
|
27
|
+
const entry = globalThis[ENTRY_GLOBAL];
|
|
28
|
+
const where = typeof entry === "string" && entry !== "" ? `edge entry '${entry}'` : "an edge entry";
|
|
29
|
+
return new EnvEdgeError(`'${key}' is class '${definition.class}' and cannot be read from ${where}: a '${definition.class}' value is read live on every request, and the edge tier has no live channel to read it over. Move this entry to the nodejs runtime, or declare '${key}' as 'sensitive'.`);
|
|
30
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function readLiveFile(key: string): string | undefined;
|
package/dist/env/file.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
const LIVE_DIR = "OCEL_LIVE_DIR";
|
|
2
|
+
function host() {
|
|
3
|
+
return globalThis.process;
|
|
4
|
+
}
|
|
5
|
+
function fileSystem(on) {
|
|
6
|
+
const loaded = on.getBuiltinModule?.("node:fs");
|
|
7
|
+
if (loaded)
|
|
8
|
+
return loaded;
|
|
9
|
+
if (!on.versions?.node)
|
|
10
|
+
return undefined;
|
|
11
|
+
throw new Error(`${LIVE_DIR} is set, and reading the bindings it projects needs node 22.3 or newer. This app runs on node ${on.versions.node}.`);
|
|
12
|
+
}
|
|
13
|
+
export function readLiveFile(key) {
|
|
14
|
+
const on = host();
|
|
15
|
+
const dir = on?.env?.[LIVE_DIR];
|
|
16
|
+
if (!on || !dir)
|
|
17
|
+
return undefined;
|
|
18
|
+
const fs = fileSystem(on);
|
|
19
|
+
if (!fs)
|
|
20
|
+
return undefined;
|
|
21
|
+
try {
|
|
22
|
+
return fs.readFileSync(`${dir}/${key}`, "utf8");
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
return undefined;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type Env } from "./access.js";
|
|
2
|
+
import { type EnvDefinitions } from "./definition.js";
|
|
3
|
+
export type { Env } from "./access.js";
|
|
4
|
+
export { EnvClientError } from "./client.js";
|
|
5
|
+
export type { Definitions, EnvDefinitions, GroupDefinition, GroupOptions, VariableClass, VariableDefinition, } from "./definition.js";
|
|
6
|
+
export { group } from "./definition.js";
|
|
7
|
+
export { type Deployment, deployment } from "./deployment.js";
|
|
8
|
+
export { EnvDefinitionError, EnvEdgeError, EnvValueError } from "./errors.js";
|
|
9
|
+
export { EnvScopeError } from "./scope.js";
|
|
10
|
+
export declare function defineEnv<const TDefinitions extends EnvDefinitions>(definitions: TDefinitions): Env<TDefinitions>;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { callSiteFile } from "../declaration/callsite.js";
|
|
2
|
+
import { defer } from "../declaration/defer.js";
|
|
3
|
+
import { envAccessor, FIXED, UNCACHED } from "./access.js";
|
|
4
|
+
import { declareEnv } from "./declare.js";
|
|
5
|
+
import { isLive, validateDefinitions, } from "./definition.js";
|
|
6
|
+
import { EnvValueError } from "./errors.js";
|
|
7
|
+
import { readLiveFile } from "./file.js";
|
|
8
|
+
import { liveGeneration, NO_GENERATION, readLive } from "./live.js";
|
|
9
|
+
import { sourceOf } from "./schema.js";
|
|
10
|
+
import { assertInScope, inScope } from "./scope.js";
|
|
11
|
+
import { coerce, readDelivered } from "./value.js";
|
|
12
|
+
export { EnvClientError } from "./client.js";
|
|
13
|
+
export { group } from "./definition.js";
|
|
14
|
+
export { deployment } from "./deployment.js";
|
|
15
|
+
export { EnvDefinitionError, EnvEdgeError, EnvValueError } from "./errors.js";
|
|
16
|
+
export { EnvScopeError } from "./scope.js";
|
|
17
|
+
export function defineEnv(definitions) {
|
|
18
|
+
const source = callSiteFile();
|
|
19
|
+
const flat = validateDefinitions(definitions, source);
|
|
20
|
+
if (process.env.OCEL_PHASE === "discovery") {
|
|
21
|
+
defer(declareEnv(flat, source, sourceOf(definitions)));
|
|
22
|
+
}
|
|
23
|
+
const env = envAccessor(definitions, { resolve, delivered, generationOf });
|
|
24
|
+
validateLiveValues(flat, env);
|
|
25
|
+
return env;
|
|
26
|
+
}
|
|
27
|
+
function delivered(key, definition) {
|
|
28
|
+
return read(key, definition) !== undefined;
|
|
29
|
+
}
|
|
30
|
+
function generationOf(definition) {
|
|
31
|
+
if (!isLive(definition))
|
|
32
|
+
return FIXED;
|
|
33
|
+
const generation = liveGeneration();
|
|
34
|
+
return generation === NO_GENERATION ? UNCACHED : generation;
|
|
35
|
+
}
|
|
36
|
+
function validateLiveValues(definitions, env) {
|
|
37
|
+
if (liveGeneration() === NO_GENERATION)
|
|
38
|
+
return;
|
|
39
|
+
if (process.env.OCEL_PHASE === "discovery")
|
|
40
|
+
return;
|
|
41
|
+
for (const [key, definition] of Object.entries(definitions)) {
|
|
42
|
+
if (!isLive(definition))
|
|
43
|
+
continue;
|
|
44
|
+
if (!inScope(definition.folders ?? []))
|
|
45
|
+
continue;
|
|
46
|
+
void env[definition.group ?? key];
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
function resolve(key, definition) {
|
|
50
|
+
if (process.env.OCEL_PHASE === "discovery") {
|
|
51
|
+
throw new EnvValueError(`'${key}' cannot be read during discovery: values are resolved after the requirements are declared.`);
|
|
52
|
+
}
|
|
53
|
+
assertInScope(key, definition.folders ?? []);
|
|
54
|
+
return coerce(key, definition, read(key, definition));
|
|
55
|
+
}
|
|
56
|
+
function read(key, definition) {
|
|
57
|
+
if (isLive(definition)) {
|
|
58
|
+
const pushed = readLive(key);
|
|
59
|
+
if (pushed !== undefined)
|
|
60
|
+
return pushed;
|
|
61
|
+
}
|
|
62
|
+
return readDelivered(key) ?? readLiveFile(key);
|
|
63
|
+
}
|
package/dist/env/live.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
const LIVE_VALUES = Symbol.for("ocel.env.liveValues");
|
|
2
|
+
export const NO_GENERATION = 0;
|
|
3
|
+
function published() {
|
|
4
|
+
return globalThis[LIVE_VALUES];
|
|
5
|
+
}
|
|
6
|
+
export function liveGeneration() {
|
|
7
|
+
return published()?.generation ?? NO_GENERATION;
|
|
8
|
+
}
|
|
9
|
+
export function readLive(key) {
|
|
10
|
+
const value = published()?.values?.[key];
|
|
11
|
+
return typeof value === "string" ? value : undefined;
|
|
12
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { StandardSchemaV1 } from "@standard-schema/spec";
|
|
2
|
+
import type { Definitions, EnvDefinitions } from "./definition.js";
|
|
3
|
+
declare const SOURCE: unique symbol;
|
|
4
|
+
/** Definitions handed back by {@link envSchema}, marked with the module they were declared in. */
|
|
5
|
+
export type EnvSchema<TDefinitions extends Definitions> = TDefinitions & {
|
|
6
|
+
readonly [SOURCE]: string;
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* Declares variables without reading, declaring or resolving anything, so a
|
|
10
|
+
* browser bundle can import the module for its schemas. Hand the result to
|
|
11
|
+
* `defineEnv` on the server.
|
|
12
|
+
*/
|
|
13
|
+
export declare function envSchema<const TDefinitions extends Definitions>(definitions: TDefinitions): EnvSchema<TDefinitions>;
|
|
14
|
+
/** The module a set of definitions was declared in through {@link envSchema}, or `""`. */
|
|
15
|
+
export declare function sourceOf(definitions: EnvDefinitions): string;
|
|
16
|
+
/** The {@link envSchema} export of a module, whatever it is named. */
|
|
17
|
+
export type Declared<TModule> = Extract<TModule[keyof TModule], {
|
|
18
|
+
readonly [SOURCE]: string;
|
|
19
|
+
}>;
|
|
20
|
+
type ExportingSchema<TModule> = [Declared<TModule>] extends [never] ? "this module exports nothing made by envSchema()" : unknown;
|
|
21
|
+
/** Picks the {@link envSchema} export out of a module; a module without one fails at typecheck and at runtime. */
|
|
22
|
+
export declare function declared<TModule extends object>(module: TModule & ExportingSchema<TModule>): Declared<TModule>;
|
|
23
|
+
/** What the client accessor hands back for a key: the schema's output where one was declared, otherwise `string`. */
|
|
24
|
+
export type ClientValue<TSchema extends Definitions, TKey extends string> = TKey extends keyof TSchema ? TSchema[TKey]["schema"] extends StandardSchemaV1 ? StandardSchemaV1.InferOutput<TSchema[TKey]["schema"]> : string : string;
|
|
25
|
+
/** Parses a value the bundler inlined through the key's schema; a missing or failing value throws {@link EnvClientError}. */
|
|
26
|
+
export declare function inlined<TSchema extends Definitions, TKey extends string>(schema: TSchema, key: TKey, value: string | undefined): ClientValue<TSchema, TKey>;
|
|
27
|
+
export {};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { callSiteFile } from "../declaration/callsite.js";
|
|
2
|
+
import { EnvClientError } from "./client.js";
|
|
3
|
+
import { parse } from "./standard.js";
|
|
4
|
+
const SOURCE = Symbol.for("ocel.env.schema");
|
|
5
|
+
/**
|
|
6
|
+
* Declares variables without reading, declaring or resolving anything, so a
|
|
7
|
+
* browser bundle can import the module for its schemas. Hand the result to
|
|
8
|
+
* `defineEnv` on the server.
|
|
9
|
+
*/
|
|
10
|
+
export function envSchema(definitions) {
|
|
11
|
+
return Object.defineProperty(definitions, SOURCE, {
|
|
12
|
+
value: callSiteFile(),
|
|
13
|
+
enumerable: false,
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
/** The module a set of definitions was declared in through {@link envSchema}, or `""`. */
|
|
17
|
+
export function sourceOf(definitions) {
|
|
18
|
+
const source = definitions[SOURCE];
|
|
19
|
+
return typeof source === "string" ? source : "";
|
|
20
|
+
}
|
|
21
|
+
/** Picks the {@link envSchema} export out of a module; a module without one fails at typecheck and at runtime. */
|
|
22
|
+
export function declared(module) {
|
|
23
|
+
for (const exported of Object.values(module)) {
|
|
24
|
+
if (exported !== null && typeof exported === "object" && SOURCE in exported) {
|
|
25
|
+
return exported;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
throw new EnvClientError("The module the client accessor imports its schemas from exports nothing made by envSchema(). Declare the variables with envSchema from 'ocel/env/schema' in a module that does not call defineEnv, and hand that to defineEnv.");
|
|
29
|
+
}
|
|
30
|
+
/** Parses a value the bundler inlined through the key's schema; a missing or failing value throws {@link EnvClientError}. */
|
|
31
|
+
export function inlined(schema, key, value) {
|
|
32
|
+
if (value === undefined) {
|
|
33
|
+
throw new EnvClientError(`'${key}' is client-accessible, but no value was inlined into this bundle. A bundler inlines only the names matching its own public convention (NEXT_PUBLIC_* under Next, VITE_* under Vite); rename the variable to one of those, or read it on the server instead.`);
|
|
34
|
+
}
|
|
35
|
+
const definition = schema[key];
|
|
36
|
+
if (!definition?.schema)
|
|
37
|
+
return value;
|
|
38
|
+
const result = parse(definition.schema, value);
|
|
39
|
+
if (!result.ok) {
|
|
40
|
+
throw new EnvClientError(`'${key}' is set but does not satisfy its schema: ${result.message}. Fix it with \`ocel env set ${key}=<VALUE>\`.`);
|
|
41
|
+
}
|
|
42
|
+
return result.value;
|
|
43
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare class EnvScopeError extends Error {
|
|
2
|
+
name: string;
|
|
3
|
+
}
|
|
4
|
+
export declare const APP_FOLDER_ENV_VAR = "OCEL_APP_FOLDER";
|
|
5
|
+
export declare function scopeProblem(folders: readonly string[]): string | undefined;
|
|
6
|
+
export declare function inScope(folders: readonly string[]): boolean;
|
|
7
|
+
export declare function assertInScope(key: string, folders: readonly string[]): void;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
export class EnvScopeError extends Error {
|
|
2
|
+
name = "EnvScopeError";
|
|
3
|
+
}
|
|
4
|
+
export const APP_FOLDER_ENV_VAR = "OCEL_APP_FOLDER";
|
|
5
|
+
const KEY_DELIMITER = "#";
|
|
6
|
+
export function scopeProblem(folders) {
|
|
7
|
+
if (folders.length === 0) {
|
|
8
|
+
return "an empty folder scope says nothing. Leave 'folders' off to keep the variable at the project root.";
|
|
9
|
+
}
|
|
10
|
+
const seen = new Set();
|
|
11
|
+
for (const folder of folders) {
|
|
12
|
+
if (seen.has(folder)) {
|
|
13
|
+
return `folder '${folder}' is named twice. A scoped variable has one value per folder it names.`;
|
|
14
|
+
}
|
|
15
|
+
seen.add(folder);
|
|
16
|
+
const problem = folderProblem(folder);
|
|
17
|
+
if (problem)
|
|
18
|
+
return `folder '${folder}': ${problem}`;
|
|
19
|
+
}
|
|
20
|
+
return undefined;
|
|
21
|
+
}
|
|
22
|
+
function folderProblem(folder) {
|
|
23
|
+
if (!folder.startsWith("/"))
|
|
24
|
+
return "a folder path must start with '/'.";
|
|
25
|
+
if (folder === "/")
|
|
26
|
+
return "'/' is the project root, which is what an unscoped variable already uses. Leave 'folders' off instead.";
|
|
27
|
+
if (folder.endsWith("/"))
|
|
28
|
+
return "a folder path must not end with '/'.";
|
|
29
|
+
if (folder.includes("//"))
|
|
30
|
+
return "a folder path has no empty segments.";
|
|
31
|
+
if (folder.includes(KEY_DELIMITER))
|
|
32
|
+
return `a folder path may not contain '${KEY_DELIMITER}'.`;
|
|
33
|
+
return undefined;
|
|
34
|
+
}
|
|
35
|
+
export function inScope(folders) {
|
|
36
|
+
if (folders.length === 0)
|
|
37
|
+
return true;
|
|
38
|
+
return folders.includes(process.env[APP_FOLDER_ENV_VAR] ?? "");
|
|
39
|
+
}
|
|
40
|
+
export function assertInScope(key, folders) {
|
|
41
|
+
if (inScope(folders))
|
|
42
|
+
return;
|
|
43
|
+
const binding = process.env[APP_FOLDER_ENV_VAR] ?? "";
|
|
44
|
+
throw new EnvScopeError(`'${key}' is scoped to ${folders.join(", ")}, but this app is bound to ${binding === "" ? "the project root" : binding}. Bind this app to one of those folders in ocel.json, or widen the variable's scope.`);
|
|
45
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { StandardSchemaV1 } from "@standard-schema/spec";
|
|
2
|
+
export type ParseResult = {
|
|
3
|
+
ok: true;
|
|
4
|
+
value: unknown;
|
|
5
|
+
} | {
|
|
6
|
+
ok: false;
|
|
7
|
+
message: string;
|
|
8
|
+
};
|
|
9
|
+
export declare function parse(schema: StandardSchemaV1, value: unknown): ParseResult;
|
|
10
|
+
export declare function describeIssues(issues: ReadonlyArray<StandardSchemaV1.Issue>): string;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { EnvDefinitionError } from "./errors.js";
|
|
2
|
+
export function parse(schema, value) {
|
|
3
|
+
const result = schema["~standard"].validate(value);
|
|
4
|
+
if (result instanceof Promise) {
|
|
5
|
+
throw new EnvDefinitionError("A variable's schema must validate synchronously: variables are read as plain properties.");
|
|
6
|
+
}
|
|
7
|
+
if (result.issues) {
|
|
8
|
+
return { ok: false, message: describeIssues(result.issues) };
|
|
9
|
+
}
|
|
10
|
+
return { ok: true, value: result.value };
|
|
11
|
+
}
|
|
12
|
+
export function describeIssues(issues) {
|
|
13
|
+
return issues
|
|
14
|
+
.map((issue) => {
|
|
15
|
+
const path = (issue.path ?? [])
|
|
16
|
+
.map((segment) => (typeof segment === "object" ? String(segment.key) : String(segment)))
|
|
17
|
+
.join(".");
|
|
18
|
+
return path ? `${path}: ${issue.message}` : issue.message;
|
|
19
|
+
})
|
|
20
|
+
.join("; ");
|
|
21
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { type VariableDefinition } from "./definition.js";
|
|
2
|
+
import { EnvValueError } from "./errors.js";
|
|
3
|
+
export declare function readDelivered(key: string): string | undefined;
|
|
4
|
+
export declare function coerce(key: string, definition: VariableDefinition, raw: string | undefined): unknown;
|
|
5
|
+
export declare function undeclared(key: string): EnvValueError;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { complaint } from "./definition.js";
|
|
2
|
+
import { EnvValueError } from "./errors.js";
|
|
3
|
+
import { parse } from "./standard.js";
|
|
4
|
+
const BAKED_PREFIX = "OCEL_VAR_";
|
|
5
|
+
export function readDelivered(key) {
|
|
6
|
+
return process.env[BAKED_PREFIX + key] ?? process.env[key];
|
|
7
|
+
}
|
|
8
|
+
export function coerce(key, definition, raw) {
|
|
9
|
+
if (!definition.schema) {
|
|
10
|
+
if (raw === undefined)
|
|
11
|
+
throw unset(key);
|
|
12
|
+
return raw;
|
|
13
|
+
}
|
|
14
|
+
const result = parse(definition.schema, raw);
|
|
15
|
+
if (result.ok)
|
|
16
|
+
return result.value;
|
|
17
|
+
if (raw === undefined)
|
|
18
|
+
throw unset(key);
|
|
19
|
+
throw new EnvValueError(`'${key}' is set but does not satisfy its schema: ${complaint(definition, result.message)}. Fix it with \`ocel env set ${key}=<VALUE>\`.`);
|
|
20
|
+
}
|
|
21
|
+
function unset(key) {
|
|
22
|
+
return new EnvValueError(`'${key}' has no value. Set one with \`ocel env set ${key}=<VALUE>\`.`);
|
|
23
|
+
}
|
|
24
|
+
export function undeclared(key) {
|
|
25
|
+
return new EnvValueError(`'${key}' is not a declared variable. Add it to a defineEnv call.`);
|
|
26
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { ExecOptions, InfisicalOptions } from "./config.js";
|
|
2
|
+
/**
|
|
3
|
+
* Declares Infisical as where a tier's values are read from. Production and
|
|
4
|
+
* preview sign in as the machine identity `auth` names; `ocel dev` signs in as
|
|
5
|
+
* you, from `INFISICAL_TOKEN` or else the `infisical` CLI you are logged in to.
|
|
6
|
+
*/
|
|
7
|
+
export declare function infisical(options: InfisicalOptions): {
|
|
8
|
+
infisical: InfisicalOptions;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Declares a command whose output is a tier's values. It runs on the machine
|
|
12
|
+
* running ocel, once per variables folder with `{folder}` replaced, at each
|
|
13
|
+
* deploy and each `ocel dev`, and never on a schedule.
|
|
14
|
+
*/
|
|
15
|
+
export declare function exec(options: ExecOptions): {
|
|
16
|
+
exec: ExecOptions;
|
|
17
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Declares Infisical as where a tier's values are read from. Production and
|
|
3
|
+
* preview sign in as the machine identity `auth` names; `ocel dev` signs in as
|
|
4
|
+
* you, from `INFISICAL_TOKEN` or else the `infisical` CLI you are logged in to.
|
|
5
|
+
*/
|
|
6
|
+
export function infisical(options) {
|
|
7
|
+
return { infisical: options };
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Declares a command whose output is a tier's values. It runs on the machine
|
|
11
|
+
* running ocel, once per variables folder with `{folder}` replaced, at each
|
|
12
|
+
* deploy and each `ocel dev`, and never on a schedule.
|
|
13
|
+
*/
|
|
14
|
+
export function exec(options) {
|
|
15
|
+
return { exec: options };
|
|
16
|
+
}
|