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,17 @@
|
|
|
1
|
+
import type { StandardSchemaV1 } from "@standard-schema/spec";
|
|
2
|
+
export declare class BuildEnvError extends Error {
|
|
3
|
+
name: string;
|
|
4
|
+
}
|
|
5
|
+
export type BuildEnv<TSchemas extends Record<string, StandardSchemaV1>> = {
|
|
6
|
+
readonly [K in keyof TSchemas]: StandardSchemaV1.InferOutput<TSchemas[K]>;
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* Declares the environment the config itself needs while it is being evaluated
|
|
10
|
+
* — values read from the shell or the project's `.env` — and validates them
|
|
11
|
+
* before they reach provider options, so a missing or malformed value fails at
|
|
12
|
+
* the config rather than mid-deploy.
|
|
13
|
+
*
|
|
14
|
+
* Anything returned here can end up in deployment records. A real secret
|
|
15
|
+
* belongs in the runtime `secret` env class instead.
|
|
16
|
+
*/
|
|
17
|
+
export declare function buildEnv<const TSchemas extends Record<string, StandardSchemaV1>>(schemas: TSchemas): BuildEnv<TSchemas>;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { isUsableKey } from "./env/definition.js";
|
|
2
|
+
import { parse } from "./env/standard.js";
|
|
3
|
+
export class BuildEnvError extends Error {
|
|
4
|
+
name = "BuildEnvError";
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Declares the environment the config itself needs while it is being evaluated
|
|
8
|
+
* — values read from the shell or the project's `.env` — and validates them
|
|
9
|
+
* before they reach provider options, so a missing or malformed value fails at
|
|
10
|
+
* the config rather than mid-deploy.
|
|
11
|
+
*
|
|
12
|
+
* Anything returned here can end up in deployment records. A real secret
|
|
13
|
+
* belongs in the runtime `secret` env class instead.
|
|
14
|
+
*/
|
|
15
|
+
export function buildEnv(schemas) {
|
|
16
|
+
for (const key of Object.keys(schemas)) {
|
|
17
|
+
if (!isUsableKey(key)) {
|
|
18
|
+
throw new BuildEnvError(`'${key}' is not a usable variable name: use upper-case letters, digits and underscores, starting with a letter or underscore.`);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
const resolved = new Map();
|
|
22
|
+
return new Proxy({}, {
|
|
23
|
+
get(_target, property) {
|
|
24
|
+
if (typeof property === "symbol")
|
|
25
|
+
return undefined;
|
|
26
|
+
const key = property;
|
|
27
|
+
const schema = schemas[key];
|
|
28
|
+
if (!schema) {
|
|
29
|
+
throw new BuildEnvError(`'${key}' is not declared in the buildEnv call. Add it there before reading it.`);
|
|
30
|
+
}
|
|
31
|
+
if (resolved.has(key))
|
|
32
|
+
return resolved.get(key);
|
|
33
|
+
const result = parse(schema, process.env[key]);
|
|
34
|
+
if (!result.ok) {
|
|
35
|
+
throw new BuildEnvError(`'${key}' ${result.message} — set it in your shell or in the project's .env`);
|
|
36
|
+
}
|
|
37
|
+
resolved.set(key, result.value);
|
|
38
|
+
return result.value;
|
|
39
|
+
},
|
|
40
|
+
});
|
|
41
|
+
}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export { type BuildEnv, BuildEnvError, buildEnv } from "./build-env.js";
|
|
2
|
+
export type { AppConfig, AppDomainConfig, AwsProviderOptions, BuildConfig, DevEnvSourceDescriptor, DiscoveryConfig, DNSDescriptor, EdgeDescriptor, EnvSourceConfig, EnvSourceDescriptor, ExecOptions, GcpProviderOptions, HealthConfig, InfisicalOptions, OcelConfig, ProjectDomainConfig, ProviderDescriptor, RegistryConfig, VpsProviderOptions, VpsTarget, } from "./generated/config.js";
|
|
3
|
+
import type { OcelConfig } from "./generated/config.js";
|
|
4
|
+
/**
|
|
5
|
+
* Something an app needs of wherever it is served. A need listed in
|
|
6
|
+
* `allowDegraded` is waived, and the deploy proceeds without it; an unwaived
|
|
7
|
+
* need the deploy cannot meet refuses the deploy instead of silently serving
|
|
8
|
+
* less than the app asks for.
|
|
9
|
+
*/
|
|
10
|
+
export type Need = NonNullable<OcelConfig["allowDegraded"]>[number];
|
|
11
|
+
/** What an app runs on. */
|
|
12
|
+
export type Compute = NonNullable<AppComputeOf<OcelConfig>>;
|
|
13
|
+
type AppComputeOf<T> = T extends {
|
|
14
|
+
apps?: (infer A)[];
|
|
15
|
+
} ? A extends {
|
|
16
|
+
compute?: infer C;
|
|
17
|
+
} ? C : never : never;
|
|
18
|
+
/** What a serverless app is built with. */
|
|
19
|
+
export type Framework = NonNullable<AppFrameworkOf<OcelConfig>>;
|
|
20
|
+
type AppFrameworkOf<T> = T extends {
|
|
21
|
+
apps?: (infer A)[];
|
|
22
|
+
} ? A extends {
|
|
23
|
+
framework?: infer F;
|
|
24
|
+
} ? F : never : never;
|
|
25
|
+
/**
|
|
26
|
+
* Declares a project. The object it takes is the same document `ocel.json`
|
|
27
|
+
* contains, so a TypeScript config is an authoring surface over data and nothing
|
|
28
|
+
* more: nothing in it is evaluated at deploy time.
|
|
29
|
+
*/
|
|
30
|
+
export declare function defineConfig(config: OcelConfig): OcelConfig;
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export { BuildEnvError, buildEnv } from "./build-env.js";
|
|
2
|
+
/**
|
|
3
|
+
* Declares a project. The object it takes is the same document `ocel.json`
|
|
4
|
+
* contains, so a TypeScript config is an authoring surface over data and nothing
|
|
5
|
+
* more: nothing in it is evaluated at deploy time.
|
|
6
|
+
*/
|
|
7
|
+
export function defineConfig(config) {
|
|
8
|
+
return config;
|
|
9
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
interface Site {
|
|
2
|
+
file: string;
|
|
3
|
+
line: number;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* The file and line of the innermost frame outside this package and outside
|
|
7
|
+
* `node_modules` — the user code whose call reached the SDK. Undefined when the
|
|
8
|
+
* stack names no such frame.
|
|
9
|
+
*/
|
|
10
|
+
export declare function callSite(): Site | undefined;
|
|
11
|
+
/** The {@link callSite} as `file:line`, or `""`. */
|
|
12
|
+
export declare function declarationSite(): string;
|
|
13
|
+
/** The file of the {@link callSite}, or `""`. */
|
|
14
|
+
export declare function callSiteFile(): string;
|
|
15
|
+
export {};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
const frameRE = /\(?((?:\/|file:|[A-Za-z]:\\)[^()]+?):(\d+):\d+\)?$/;
|
|
2
|
+
function parseFrame(frame) {
|
|
3
|
+
const at = frameRE.exec(frame.trim());
|
|
4
|
+
if (!at?.[1] || !at[2])
|
|
5
|
+
return undefined;
|
|
6
|
+
return { file: at[1].replace(/^file:\/\//, ""), line: Number(at[2]) };
|
|
7
|
+
}
|
|
8
|
+
function parentOf(file) {
|
|
9
|
+
return file.slice(0, Math.max(file.lastIndexOf("/"), file.lastIndexOf("\\")));
|
|
10
|
+
}
|
|
11
|
+
function isUnder(file, dir) {
|
|
12
|
+
return dir !== "" && (file.startsWith(`${dir}/`) || file.startsWith(`${dir}\\`));
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* The file and line of the innermost frame outside this package and outside
|
|
16
|
+
* `node_modules` — the user code whose call reached the SDK. Undefined when the
|
|
17
|
+
* stack names no such frame.
|
|
18
|
+
*/
|
|
19
|
+
export function callSite() {
|
|
20
|
+
let ownRoot;
|
|
21
|
+
for (const frame of (new Error().stack ?? "").split("\n").slice(1)) {
|
|
22
|
+
const site = parseFrame(frame);
|
|
23
|
+
if (!site)
|
|
24
|
+
continue;
|
|
25
|
+
if (ownRoot === undefined) {
|
|
26
|
+
ownRoot = parentOf(parentOf(site.file));
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
if (isUnder(site.file, ownRoot) || /[/\\]node_modules[/\\]/.test(site.file))
|
|
30
|
+
continue;
|
|
31
|
+
return site;
|
|
32
|
+
}
|
|
33
|
+
return undefined;
|
|
34
|
+
}
|
|
35
|
+
/** The {@link callSite} as `file:line`, or `""`. */
|
|
36
|
+
export function declarationSite() {
|
|
37
|
+
const site = callSite();
|
|
38
|
+
return site ? `${site.file}:${site.line}` : "";
|
|
39
|
+
}
|
|
40
|
+
/** The file of the {@link callSite}, or `""`. */
|
|
41
|
+
export function callSiteFile() {
|
|
42
|
+
return callSite()?.file ?? "";
|
|
43
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { OCEL_DEV_SERVER } from "../runtime/dev-server.js";
|
|
2
|
+
/** Holds a registration with the dev server until the app's declarations are collected. Throws when no dev server is running. */
|
|
3
|
+
export function defer(p) {
|
|
4
|
+
if (!OCEL_DEV_SERVER) {
|
|
5
|
+
throw new Error("OCEL_DEV_SERVER environment variable is not set");
|
|
6
|
+
}
|
|
7
|
+
globalThis.__ocelRegister ??= [];
|
|
8
|
+
globalThis.__ocelRegister.push(p);
|
|
9
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type Timestamp } from "@bufbuild/protobuf/wkt";
|
|
2
|
+
/**
|
|
3
|
+
* A length of time: a number of seconds, or a string such as `"500ms"`, `"30s"`, `"5m"`,
|
|
4
|
+
* `"2h"` or `"1d"`.
|
|
5
|
+
*/
|
|
6
|
+
export type Duration = number | `${number}ms` | `${number}s` | `${number}m` | `${number}h` | `${number}d`;
|
|
7
|
+
export declare function parseDurationMilliseconds(duration: Duration): number;
|
|
8
|
+
export interface DurationFields {
|
|
9
|
+
seconds: bigint;
|
|
10
|
+
nanos: number;
|
|
11
|
+
}
|
|
12
|
+
export declare function encodeDuration(duration: Duration | undefined): DurationFields | undefined;
|
|
13
|
+
export declare function encodeDueAt(delay: Duration | Date | undefined): Timestamp | undefined;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { timestampFromMs } from "@bufbuild/protobuf/wkt";
|
|
2
|
+
const millisecondsPerUnit = {
|
|
3
|
+
ms: 1,
|
|
4
|
+
s: 1_000,
|
|
5
|
+
m: 60_000,
|
|
6
|
+
h: 3_600_000,
|
|
7
|
+
d: 86_400_000,
|
|
8
|
+
};
|
|
9
|
+
const durationPattern = /^(\d+(?:\.\d+)?)(ms|s|m|h|d)$/;
|
|
10
|
+
export function parseDurationMilliseconds(duration) {
|
|
11
|
+
if (typeof duration === "number") {
|
|
12
|
+
if (!Number.isFinite(duration) || duration < 0) {
|
|
13
|
+
throw new Error(`a duration is a non-negative number of seconds, not ${duration}`);
|
|
14
|
+
}
|
|
15
|
+
return duration * 1_000;
|
|
16
|
+
}
|
|
17
|
+
const match = durationPattern.exec(duration);
|
|
18
|
+
if (!match?.[1] || !match[2]) {
|
|
19
|
+
throw new Error(`"${duration}" is not a duration: write a number of seconds, or a string such as "500ms", "30s", "5m", "2h" or "1d"`);
|
|
20
|
+
}
|
|
21
|
+
return Number(match[1]) * millisecondsPerUnit[match[2]];
|
|
22
|
+
}
|
|
23
|
+
export function encodeDuration(duration) {
|
|
24
|
+
if (duration === undefined)
|
|
25
|
+
return undefined;
|
|
26
|
+
const milliseconds = Math.round(parseDurationMilliseconds(duration));
|
|
27
|
+
return {
|
|
28
|
+
seconds: BigInt(Math.floor(milliseconds / 1_000)),
|
|
29
|
+
nanos: (milliseconds % 1_000) * 1_000_000,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
export function encodeDueAt(delay) {
|
|
33
|
+
if (delay === undefined)
|
|
34
|
+
return undefined;
|
|
35
|
+
return timestampFromMs(delay instanceof Date ? delay.getTime() : Date.now() + parseDurationMilliseconds(delay));
|
|
36
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { Lane as ProtoLane } from "../gen/proto/app/topic/v1/topic_pb.js";
|
|
2
|
+
/** The lane a message waits in: `high`, `default` and `low` are read in a 6:3:1 ratio. */
|
|
3
|
+
export type Lane = "high" | "default" | "low";
|
|
4
|
+
export declare function encodeLane(lane: Lane | undefined): ProtoLane;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Lane as ProtoLane } from "../gen/proto/app/topic/v1/topic_pb.js";
|
|
2
|
+
const protoLanes = {
|
|
3
|
+
high: ProtoLane.HIGH,
|
|
4
|
+
default: ProtoLane.DEFAULT,
|
|
5
|
+
low: ProtoLane.LOW,
|
|
6
|
+
};
|
|
7
|
+
export function encodeLane(lane) {
|
|
8
|
+
if (lane === undefined)
|
|
9
|
+
return ProtoLane.UNSPECIFIED;
|
|
10
|
+
const value = protoLanes[lane];
|
|
11
|
+
if (value === undefined) {
|
|
12
|
+
throw new Error(`"${lane}" is not a lane: use "high", "default" or "low"`);
|
|
13
|
+
}
|
|
14
|
+
return value;
|
|
15
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/** The most bytes of JSON a payload may take. */
|
|
2
|
+
export declare const PAYLOAD_LIMIT_BYTES = 262144;
|
|
3
|
+
/** A payload's JSON text as bytes, with `undefined` sent as `null`. Throws over {@link PAYLOAD_LIMIT_BYTES}. */
|
|
4
|
+
export declare function encodePayload(payload: unknown): Uint8Array;
|
|
5
|
+
/** The value JSON text holds; `null` when there is no text. */
|
|
6
|
+
export declare function decodeJson(bytes: Uint8Array): unknown;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** The most bytes of JSON a payload may take. */
|
|
2
|
+
export const PAYLOAD_LIMIT_BYTES = 262_144;
|
|
3
|
+
/** A payload's JSON text as bytes, with `undefined` sent as `null`. Throws over {@link PAYLOAD_LIMIT_BYTES}. */
|
|
4
|
+
export function encodePayload(payload) {
|
|
5
|
+
const bytes = new TextEncoder().encode(JSON.stringify(payload ?? null));
|
|
6
|
+
if (bytes.byteLength > PAYLOAD_LIMIT_BYTES) {
|
|
7
|
+
throw new Error(`a payload is at most ${PAYLOAD_LIMIT_BYTES} bytes (256 KiB) of JSON, and this one is ${bytes.byteLength} bytes`);
|
|
8
|
+
}
|
|
9
|
+
return bytes;
|
|
10
|
+
}
|
|
11
|
+
/** The value JSON text holds; `null` when there is no text. */
|
|
12
|
+
export function decodeJson(bytes) {
|
|
13
|
+
return bytes.byteLength > 0 ? JSON.parse(new TextDecoder().decode(bytes)) : null;
|
|
14
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type Duration, type DurationFields } from "./duration.js";
|
|
2
|
+
/** How a failed attempt is retried. */
|
|
3
|
+
export interface RetryOptions {
|
|
4
|
+
/** Attempts made before the run fails, the first included. */
|
|
5
|
+
maxAttempts?: number;
|
|
6
|
+
/** The backoff before the first retry. */
|
|
7
|
+
minDelay?: Duration;
|
|
8
|
+
/** The longest backoff between two attempts. */
|
|
9
|
+
maxDelay?: Duration;
|
|
10
|
+
}
|
|
11
|
+
export interface RetryPolicyFields {
|
|
12
|
+
maxAttempts: number;
|
|
13
|
+
minDelay: DurationFields | undefined;
|
|
14
|
+
maxDelay: DurationFields | undefined;
|
|
15
|
+
}
|
|
16
|
+
export declare function encodeRetryPolicy(retry: RetryOptions | undefined): RetryPolicyFields | undefined;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { encodeDuration } from "./duration.js";
|
|
2
|
+
export function encodeRetryPolicy(retry) {
|
|
3
|
+
if (retry === undefined)
|
|
4
|
+
return undefined;
|
|
5
|
+
return {
|
|
6
|
+
maxAttempts: retry.maxAttempts ?? 0,
|
|
7
|
+
minDelay: encodeDuration(retry.minDelay),
|
|
8
|
+
maxDelay: encodeDuration(retry.maxDelay),
|
|
9
|
+
};
|
|
10
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { StandardSchemaV1 } from "@standard-schema/spec";
|
|
2
|
+
export declare function encodeJsonSchema(schema: StandardSchemaV1 | undefined): string;
|
|
3
|
+
export type Validation = {
|
|
4
|
+
ok: true;
|
|
5
|
+
value: unknown;
|
|
6
|
+
} | {
|
|
7
|
+
ok: false;
|
|
8
|
+
message: string;
|
|
9
|
+
};
|
|
10
|
+
export declare function validatePayload(schema: StandardSchemaV1, payload: unknown): Promise<Validation>;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { describeIssues } from "../env/standard.js";
|
|
2
|
+
export function encodeJsonSchema(schema) {
|
|
3
|
+
const converter = schema?.["~standard"]
|
|
4
|
+
?.jsonSchema;
|
|
5
|
+
if (!converter)
|
|
6
|
+
return "";
|
|
7
|
+
try {
|
|
8
|
+
return JSON.stringify(converter.input({ target: "draft-2020-12" }));
|
|
9
|
+
}
|
|
10
|
+
catch {
|
|
11
|
+
return "";
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
export async function validatePayload(schema, payload) {
|
|
15
|
+
const result = await schema["~standard"].validate(payload);
|
|
16
|
+
if (result.issues) {
|
|
17
|
+
return { ok: false, message: describeIssues(result.issues) };
|
|
18
|
+
}
|
|
19
|
+
return { ok: true, value: result.value };
|
|
20
|
+
}
|
package/dist/dns.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { DNSDescriptor } from "./config.js";
|
|
2
|
+
/** Options for Cloudflare DNS. */
|
|
3
|
+
export interface CloudflareDnsOptions {
|
|
4
|
+
/**
|
|
5
|
+
* The zone the records are written into. Omit it and ocel picks the zone
|
|
6
|
+
* that covers the hostname.
|
|
7
|
+
*/
|
|
8
|
+
zone?: string;
|
|
9
|
+
}
|
|
10
|
+
/** Declares Cloudflare as the DNS the project's records are written into. */
|
|
11
|
+
export declare function cloudflareDns(options?: CloudflareDnsOptions): DNSDescriptor;
|
package/dist/dns.js
ADDED
package/dist/edge.d.ts
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { CloudflareEdgeOptions, EdgeDescriptor } from "./generated/config.js";
|
|
2
|
+
export type { CloudflareEdgeOptions } from "./generated/config.js";
|
|
3
|
+
/** Declares Cloudflare as the edge the project's hostnames are served from. */
|
|
4
|
+
export declare function cloudflare(options?: CloudflareEdgeOptions): EdgeDescriptor;
|
package/dist/edge.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { StandardSchemaV1 } from "@standard-schema/spec";
|
|
2
|
+
import type { EnvDefinitions, GroupDefinition, VariableDefinition } from "./definition.js";
|
|
3
|
+
type EnvValue<T> = T extends GroupDefinition<infer TDefinitions, infer TOptional> ? Env<TDefinitions> | (TOptional extends true ? undefined : never) : T extends VariableDefinition ? T["schema"] extends StandardSchemaV1 ? StandardSchemaV1.InferOutput<T["schema"]> : string : never;
|
|
4
|
+
/** The object a `defineEnv` call hands back: one property per declared variable or group. */
|
|
5
|
+
export type Env<TDefinitions extends EnvDefinitions> = {
|
|
6
|
+
readonly [K in keyof TDefinitions]: EnvValue<TDefinitions[K]>;
|
|
7
|
+
};
|
|
8
|
+
/** What a tier supplies so the shared accessor can read its variables. */
|
|
9
|
+
export interface Access {
|
|
10
|
+
resolve(key: string, definition: VariableDefinition): unknown;
|
|
11
|
+
delivered(key: string, definition: VariableDefinition): boolean;
|
|
12
|
+
generationOf(definition: VariableDefinition): number;
|
|
13
|
+
}
|
|
14
|
+
export declare const FIXED = -1;
|
|
15
|
+
/**
|
|
16
|
+
* The generation of a value nothing marks the freshness of, which is read
|
|
17
|
+
* again on every access. It is `NaN`, so it equals no generation — its own
|
|
18
|
+
* included — and `Math.max` passes it on to a group containing such a member.
|
|
19
|
+
*/
|
|
20
|
+
export declare const UNCACHED: number;
|
|
21
|
+
export declare function envAccessor<TDefinitions extends EnvDefinitions>(definitions: TDefinitions, access: Access): Env<TDefinitions>;
|
|
22
|
+
export {};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { undeclared } from "./value.js";
|
|
2
|
+
export const FIXED = -1;
|
|
3
|
+
/**
|
|
4
|
+
* The generation of a value nothing marks the freshness of, which is read
|
|
5
|
+
* again on every access. It is `NaN`, so it equals no generation — its own
|
|
6
|
+
* included — and `Math.max` passes it on to a group containing such a member.
|
|
7
|
+
*/
|
|
8
|
+
export const UNCACHED = Number.NaN;
|
|
9
|
+
export function envAccessor(definitions, access) {
|
|
10
|
+
const resolved = new Map();
|
|
11
|
+
return new Proxy({}, {
|
|
12
|
+
get(_target, property) {
|
|
13
|
+
if (typeof property === "symbol")
|
|
14
|
+
return undefined;
|
|
15
|
+
const key = property;
|
|
16
|
+
const definition = definitions[key];
|
|
17
|
+
if (!definition)
|
|
18
|
+
throw undeclared(key);
|
|
19
|
+
const generation = generationOf(definition, access);
|
|
20
|
+
const memo = resolved.get(key);
|
|
21
|
+
if (memo?.generation === generation)
|
|
22
|
+
return memo.value;
|
|
23
|
+
const value = "definitions" in definition
|
|
24
|
+
? resolveGroup(definition, access)
|
|
25
|
+
: access.resolve(key, definition);
|
|
26
|
+
resolved.set(key, { generation, value });
|
|
27
|
+
return value;
|
|
28
|
+
},
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
function generationOf(definition, access) {
|
|
32
|
+
if (!("definitions" in definition))
|
|
33
|
+
return access.generationOf(definition);
|
|
34
|
+
let generation = FIXED;
|
|
35
|
+
for (const member of Object.values(definition.definitions)) {
|
|
36
|
+
generation = Math.max(generation, access.generationOf(member));
|
|
37
|
+
}
|
|
38
|
+
return generation;
|
|
39
|
+
}
|
|
40
|
+
function resolveGroup(definition, access) {
|
|
41
|
+
const members = Object.entries(definition.definitions);
|
|
42
|
+
if (definition.optional && !members.some(([key, member]) => access.delivered(key, member))) {
|
|
43
|
+
return undefined;
|
|
44
|
+
}
|
|
45
|
+
const value = {};
|
|
46
|
+
for (const [key, member] of members)
|
|
47
|
+
value[key] = access.resolve(key, member);
|
|
48
|
+
return value;
|
|
49
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export class EnvClientError extends Error {
|
|
2
|
+
name = "EnvClientError";
|
|
3
|
+
}
|
|
4
|
+
export const clientEnv = new Proxy({}, {
|
|
5
|
+
get(_target, property) {
|
|
6
|
+
if (typeof property === "symbol")
|
|
7
|
+
return undefined;
|
|
8
|
+
throw new EnvClientError(`'${property}' cannot be read: 'ocel/env/client' resolved to its unresolved fallback, because no client accessor is mapped for this app. Run \`ocel dev\` or \`ocel deploy\`: each writes the app's own 'env-client.ts' under the project's '.ocel' directory and points 'ocel/env/client' at it from the app's tsconfig.json or jsconfig.json, one of which the app must have for the mapping to be stated. Where that config is one ocel cannot write the entry into, the command refuses and names the entry to add by hand.`);
|
|
9
|
+
},
|
|
10
|
+
});
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { VariableProblem_Kind, VariableClass as WireClass, } from "../gen/proto/app/resources/v1/variables_pb.js";
|
|
2
|
+
import { rpc } from "../runtime/rpc.js";
|
|
3
|
+
import { complaint, isRequired, } from "./definition.js";
|
|
4
|
+
import { parse } from "./standard.js";
|
|
5
|
+
const WIRE_CLASS = {
|
|
6
|
+
plain: WireClass.PLAIN,
|
|
7
|
+
sensitive: WireClass.SENSITIVE,
|
|
8
|
+
secret: WireClass.SECRET,
|
|
9
|
+
};
|
|
10
|
+
export async function declareEnv(definitions, source, schemaSource) {
|
|
11
|
+
const groups = Object.values(Object.entries(definitions).reduce((all, [, definition]) => {
|
|
12
|
+
if (definition.group) {
|
|
13
|
+
all[definition.group] = {
|
|
14
|
+
key: definition.group,
|
|
15
|
+
required: !definition.groupOptional,
|
|
16
|
+
description: definition.groupDescription ?? "",
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
return all;
|
|
20
|
+
}, {}));
|
|
21
|
+
const { cells } = await rpc.resource.declareEnv({
|
|
22
|
+
definitions: Object.entries(definitions).map(([key, definition]) => ({
|
|
23
|
+
key,
|
|
24
|
+
class: WIRE_CLASS[definition.class],
|
|
25
|
+
clientAccessible: definition.client === true,
|
|
26
|
+
required: isRequired(definition),
|
|
27
|
+
folders: [...(definition.folders ?? [])],
|
|
28
|
+
source,
|
|
29
|
+
schemaSource,
|
|
30
|
+
hasSchema: definition.schema !== undefined,
|
|
31
|
+
...(definition.description === undefined ? {} : { description: definition.description }),
|
|
32
|
+
...(definition.group === undefined ? {} : { group: definition.group }),
|
|
33
|
+
})),
|
|
34
|
+
groups,
|
|
35
|
+
});
|
|
36
|
+
const problems = validate(definitions, cells);
|
|
37
|
+
if (problems.length > 0) {
|
|
38
|
+
await rpc.resource.reportEnvProblems({ problems });
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
function validate(definitions, cells) {
|
|
42
|
+
const problems = [];
|
|
43
|
+
for (const [key, definition] of Object.entries(definitions)) {
|
|
44
|
+
const stored = cells.filter((c) => c.key === key);
|
|
45
|
+
if (isRequired(definition)) {
|
|
46
|
+
for (const folder of requiredFolders(definition)) {
|
|
47
|
+
if (definition.groupOptional &&
|
|
48
|
+
definition.group &&
|
|
49
|
+
!switchedOn(definitions, cells, definition.group, folder))
|
|
50
|
+
continue;
|
|
51
|
+
if (!stored.some((c) => c.folder === folder)) {
|
|
52
|
+
problems.push(problem(key, folder, VariableProblem_Kind.MISSING, ""));
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
if (definition.class === "secret" || !definition.schema)
|
|
57
|
+
continue;
|
|
58
|
+
for (const cell of stored) {
|
|
59
|
+
const result = parse(definition.schema, cell.value);
|
|
60
|
+
if (!result.ok) {
|
|
61
|
+
problems.push(problem(key, cell.folder, VariableProblem_Kind.INVALID, complaint(definition, result.message)));
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return problems;
|
|
66
|
+
}
|
|
67
|
+
function switchedOn(definitions, cells, group, folder) {
|
|
68
|
+
return Object.entries(definitions).some(([key, definition]) => definition.group === group && hasCell(cells, key, definition, folder));
|
|
69
|
+
}
|
|
70
|
+
function hasCell(cells, key, definition, folder) {
|
|
71
|
+
const at = (where) => cells.some((cell) => cell.key === key && cell.folder === where);
|
|
72
|
+
const scope = definition.folders ?? [];
|
|
73
|
+
if (scope.length > 0) {
|
|
74
|
+
return folder !== "" && scope.includes(folder) && at(folder);
|
|
75
|
+
}
|
|
76
|
+
return (folder !== "" && at(folder)) || at("");
|
|
77
|
+
}
|
|
78
|
+
function requiredFolders(definition) {
|
|
79
|
+
return definition.folders?.length ? definition.folders : [""];
|
|
80
|
+
}
|
|
81
|
+
function problem(key, folder, kind, detail) {
|
|
82
|
+
return { key, folder, kind, detail };
|
|
83
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { StandardSchemaV1 } from "@standard-schema/spec";
|
|
2
|
+
export type VariableClass = "plain" | "sensitive" | "secret";
|
|
3
|
+
export type ConfidentialClass = Exclude<VariableClass, "plain">;
|
|
4
|
+
interface VariableOptions<TSchema extends StandardSchemaV1 = StandardSchemaV1> {
|
|
5
|
+
schema?: TSchema;
|
|
6
|
+
folders?: readonly string[];
|
|
7
|
+
description?: string;
|
|
8
|
+
}
|
|
9
|
+
export type VariableDefinition<TSchema extends StandardSchemaV1 = StandardSchemaV1> = (VariableOptions<TSchema> & {
|
|
10
|
+
class: "plain";
|
|
11
|
+
client?: boolean;
|
|
12
|
+
}) | (VariableOptions<TSchema> & {
|
|
13
|
+
class: ConfidentialClass;
|
|
14
|
+
client?: false;
|
|
15
|
+
});
|
|
16
|
+
export interface GroupOptions {
|
|
17
|
+
readonly optional?: boolean;
|
|
18
|
+
readonly description?: string;
|
|
19
|
+
}
|
|
20
|
+
export interface GroupDefinition<TDefinitions extends Definitions = Definitions, TOptional extends boolean = boolean> {
|
|
21
|
+
readonly definitions: TDefinitions;
|
|
22
|
+
readonly optional: TOptional;
|
|
23
|
+
readonly description?: string;
|
|
24
|
+
}
|
|
25
|
+
type IsOptional<TOptions extends GroupOptions> = TOptions["optional"] extends true ? true : false;
|
|
26
|
+
export type Definitions = Record<string, VariableDefinition>;
|
|
27
|
+
export type EnvDefinitions = Record<string, VariableDefinition | GroupDefinition>;
|
|
28
|
+
export type FlatDefinition = VariableDefinition & {
|
|
29
|
+
readonly group?: string;
|
|
30
|
+
readonly groupOptional?: boolean;
|
|
31
|
+
readonly groupDescription?: string;
|
|
32
|
+
};
|
|
33
|
+
export type FlatDefinitions = Record<string, FlatDefinition>;
|
|
34
|
+
/** A set of variables an app takes together: every member is reached through the group and
|
|
35
|
+
* nowhere else, and `{ optional: true }` reads the whole group as `undefined` until a value
|
|
36
|
+
* is delivered for one of its members. */
|
|
37
|
+
export declare function group<const TDefinitions extends Definitions, const TOptions extends GroupOptions = GroupOptions>(definitions: TDefinitions, options?: TOptions): GroupDefinition<TDefinitions, IsOptional<TOptions>>;
|
|
38
|
+
export declare function flattenDefinitions(definitions: EnvDefinitions): FlatDefinitions;
|
|
39
|
+
export declare function isLive(definition: VariableDefinition): boolean;
|
|
40
|
+
export declare const URL_KEY = "OCEL_URL";
|
|
41
|
+
export declare const CLIENT_URL_KEY = "NEXT_PUBLIC_OCEL_URL";
|
|
42
|
+
export declare function isUsableKey(key: string): boolean;
|
|
43
|
+
export declare function validateDefinitions(definitions: EnvDefinitions, source: string): FlatDefinitions;
|
|
44
|
+
export declare function isRequired(definition: VariableDefinition): boolean;
|
|
45
|
+
export declare function complaint(definition: VariableDefinition, message: string): string;
|
|
46
|
+
export {};
|