@sandbox-kit/sandbox 0.0.0-stage → 0.1.0
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 +21 -0
- package/README.md +69 -2
- package/dist/client/client.d.ts +136 -0
- package/dist/client/client.js +749 -0
- package/dist/contracts/config_paths.d.ts +44 -0
- package/dist/contracts/config_paths.js +50 -0
- package/dist/contracts/field_paths.d.ts +216 -0
- package/dist/contracts/field_paths.js +222 -0
- package/dist/contracts/sandbox_data_contracts.d.ts +203 -0
- package/dist/contracts/sandbox_data_contracts.js +22 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +5 -0
- package/dist/internal/duration_ms.d.ts +15 -0
- package/dist/internal/duration_ms.js +41 -0
- package/dist/internal/input_remap.d.ts +36 -0
- package/dist/internal/input_remap.js +1 -0
- package/dist/internal/oneof_input.d.ts +32 -0
- package/dist/internal/oneof_input.js +1 -0
- package/dist/internal/proto_enum.d.ts +25 -0
- package/dist/internal/proto_enum.js +25 -0
- package/dist/internal/strip_proto.d.ts +46 -0
- package/dist/internal/strip_proto.js +1 -0
- package/dist/metadata/metadata_object.d.ts +7 -0
- package/dist/metadata/metadata_object.js +103 -0
- package/dist/metadata/metadata_plain.d.ts +9 -0
- package/dist/metadata/metadata_plain.js +1 -0
- package/package.json +66 -4
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
import type { DurationFieldsToMs } from "#internal/duration_ms.js";
|
|
2
|
+
import type { EmptyMarkersAsTrue, FlattenAllowlistFields, PlainStringMapFields, RemapFields } from "#internal/input_remap.js";
|
|
3
|
+
import type { StripProto } from "#internal/strip_proto.js";
|
|
4
|
+
import { EgressMode as ProtoEgressMode, IsolationKind as ProtoIsolationKind, LifecycleCapability as ProtoLifecycleCapability, PolicyMode as ProtoPolicyMode, PortTransport as ProtoPortTransport, SandboxState as ProtoSandboxState, SecretInjection as ProtoSecretInjection, SnapshotKind as ProtoSnapshotKind, ValueOrigin as ProtoValueOrigin, WaitCondition as ProtoWaitCondition, type ArchiveOptions as ProtoArchiveOptions, type CreateOptions as ProtoCreateOptions, type CreateResult as ProtoCreateResult, type DeleteOptions as ProtoDeleteOptions, type ErrorInfo as ProtoErrorInfo, type ExitResult as ProtoExitResult, type IsolationConfig as ProtoIsolationConfig, type MetadataList as ProtoMetadataList, type MetadataObject as ProtoMetadataObject, type MetadataValue as ProtoMetadataValue, type ObservabilityConfig as ProtoObservabilityConfig, type PauseOptions as ProtoPauseOptions, type Placement as ProtoPlacement, type PortBinding as ProtoPortBinding, type Resources as ProtoResources, type RuntimeConfig as ProtoRuntimeConfig, type SandboxInfo as ProtoSandboxInfo, type SandboxSource as ProtoSandboxSource, type SecretReference as ProtoSecretReference, type SecurityConfig as ProtoSecurityConfig, type StartOptions as ProtoStartOptions, type StopOptions as ProtoStopOptions, type TerminateOptions as ProtoTerminateOptions, type ReadinessProbe as ProtoReadinessProbe } from "@sandbox-kit/contracts/sandbox";
|
|
5
|
+
import type { StripAndFlatten } from "#internal/oneof_input.js";
|
|
6
|
+
import type { MetadataPlain } from "#metadata/metadata_plain.js";
|
|
7
|
+
/** Public error payload; identity fields stay required after StripProto softening. */
|
|
8
|
+
export type ErrorInfo = StripProto<ProtoErrorInfo> & {
|
|
9
|
+
kind: NonNullable<StripProto<ProtoErrorInfo>["kind"]>;
|
|
10
|
+
provider: string;
|
|
11
|
+
operation: string;
|
|
12
|
+
field: string;
|
|
13
|
+
message: string;
|
|
14
|
+
};
|
|
15
|
+
export type RuntimeConfig = StripProto<ProtoRuntimeConfig>;
|
|
16
|
+
export type IsolationConfig = StripProto<ProtoIsolationConfig>;
|
|
17
|
+
export type Resources = StripProto<ProtoResources>;
|
|
18
|
+
export type Placement = StripProto<ProtoPlacement>;
|
|
19
|
+
export type PortBinding = StripProto<ProtoPortBinding>;
|
|
20
|
+
export type SecurityConfig = StripProto<ProtoSecurityConfig>;
|
|
21
|
+
export type SecretReference = StripProto<ProtoSecretReference>;
|
|
22
|
+
export type ObservabilityConfig = StripProto<ProtoObservabilityConfig>;
|
|
23
|
+
export type SandboxInfo = StripProto<ProtoSandboxInfo>;
|
|
24
|
+
export type CreateResult = StripProto<ProtoCreateResult>;
|
|
25
|
+
/** Wire lifecycle options (Duration timeouts) for providers / Backend. */
|
|
26
|
+
export type StartOptions = StripProto<ProtoStartOptions>;
|
|
27
|
+
export type StopOptions = StripProto<ProtoStopOptions>;
|
|
28
|
+
export type PauseOptions = StripProto<ProtoPauseOptions>;
|
|
29
|
+
export type TerminateOptions = StripProto<ProtoTerminateOptions>;
|
|
30
|
+
export type ArchiveOptions = StripProto<ProtoArchiveOptions>;
|
|
31
|
+
export type DeleteOptions = StripProto<ProtoDeleteOptions>;
|
|
32
|
+
export type ExitResult = StripProto<ProtoExitResult>;
|
|
33
|
+
export type MetadataValue = StripProto<ProtoMetadataValue>;
|
|
34
|
+
export type MetadataList = StripProto<ProtoMetadataList>;
|
|
35
|
+
export type MetadataObject = StripProto<ProtoMetadataObject>;
|
|
36
|
+
/**
|
|
37
|
+
* Public create request for `Client.create`.
|
|
38
|
+
* Composed from reusable input transforms: strip + flatten oneofs → plain maps /
|
|
39
|
+
* allowlists / empty markers → ms durations.
|
|
40
|
+
*/
|
|
41
|
+
export type CreateOptions = DurationFieldsToMs<EmptyMarkersAsTrue<FlattenAllowlistFields<PlainStringMapFields<RemapFields<StripAndFlatten<ProtoCreateOptions, {
|
|
42
|
+
source: NonNullable<ProtoSandboxSource["kind"]>;
|
|
43
|
+
readiness: NonNullable<ProtoReadinessProbe["check"]>;
|
|
44
|
+
}>, {
|
|
45
|
+
providerOptions: Record<string, MetadataPlain>;
|
|
46
|
+
}>>>>>;
|
|
47
|
+
/**
|
|
48
|
+
* Public network create input (allowlists are plain `string[]`).
|
|
49
|
+
* Derived from {@link CreateOptions}; present empty arrays mean deny-all.
|
|
50
|
+
*/
|
|
51
|
+
export type NetworkConfigInput = NonNullable<CreateOptions["network"]>;
|
|
52
|
+
/** Public create source: set exactly one variant (no protobuf `{ case, value }`). */
|
|
53
|
+
export type SandboxSourceInput = NonNullable<CreateOptions["source"]>;
|
|
54
|
+
/** Public readiness: set tcpPort or command (no protobuf `{ case, value }`). */
|
|
55
|
+
export type ReadinessProbeInput = NonNullable<CreateOptions["readiness"]>;
|
|
56
|
+
/**
|
|
57
|
+
* Public lifetime create input (ms durations).
|
|
58
|
+
* Derived from {@link CreateOptions}; wire `Duration` fields stay private.
|
|
59
|
+
*/
|
|
60
|
+
export type LifetimePolicyInput = NonNullable<CreateOptions["lifetime"]>;
|
|
61
|
+
/**
|
|
62
|
+
* Public idle/stopped policy leaf under {@link LifetimePolicyInput} (`after` in ms).
|
|
63
|
+
*/
|
|
64
|
+
export type AutomaticActionInput = NonNullable<LifetimePolicyInput["idleTerminate"]>;
|
|
65
|
+
/**
|
|
66
|
+
* Public provisioning create input (ms timeouts).
|
|
67
|
+
* Derived from {@link CreateOptions}; wire `Duration` fields stay private.
|
|
68
|
+
*/
|
|
69
|
+
export type ProvisioningOptionsInput = NonNullable<CreateOptions["provisioning"]>;
|
|
70
|
+
export declare const SnapshotKind: {
|
|
71
|
+
readonly Default: ProtoSnapshotKind.DEFAULT;
|
|
72
|
+
readonly Filesystem: ProtoSnapshotKind.FILESYSTEM;
|
|
73
|
+
readonly Memory: ProtoSnapshotKind.MEMORY;
|
|
74
|
+
readonly Image: ProtoSnapshotKind.IMAGE;
|
|
75
|
+
readonly Machine: ProtoSnapshotKind.MACHINE;
|
|
76
|
+
readonly Checkpoint: ProtoSnapshotKind.CHECKPOINT;
|
|
77
|
+
readonly ProviderSpecific: ProtoSnapshotKind.PROVIDER_SPECIFIC;
|
|
78
|
+
};
|
|
79
|
+
export type SnapshotKind = (typeof SnapshotKind)[keyof typeof SnapshotKind];
|
|
80
|
+
export declare const SnapshotKindNumber: {
|
|
81
|
+
readonly Default: ProtoSnapshotKind.DEFAULT;
|
|
82
|
+
readonly Filesystem: ProtoSnapshotKind.FILESYSTEM;
|
|
83
|
+
readonly Memory: ProtoSnapshotKind.MEMORY;
|
|
84
|
+
readonly Image: ProtoSnapshotKind.IMAGE;
|
|
85
|
+
readonly Machine: ProtoSnapshotKind.MACHINE;
|
|
86
|
+
readonly Checkpoint: ProtoSnapshotKind.CHECKPOINT;
|
|
87
|
+
readonly ProviderSpecific: ProtoSnapshotKind.PROVIDER_SPECIFIC;
|
|
88
|
+
};
|
|
89
|
+
export declare const IsolationKind: {
|
|
90
|
+
readonly Default: ProtoIsolationKind.DEFAULT;
|
|
91
|
+
readonly ProviderSpecific: ProtoIsolationKind.PROVIDER_SPECIFIC;
|
|
92
|
+
readonly Container: ProtoIsolationKind.CONTAINER;
|
|
93
|
+
readonly Microvm: ProtoIsolationKind.MICROVM;
|
|
94
|
+
readonly LinuxVm: ProtoIsolationKind.LINUX_VM;
|
|
95
|
+
readonly Worker: ProtoIsolationKind.WORKER;
|
|
96
|
+
};
|
|
97
|
+
export type IsolationKind = (typeof IsolationKind)[keyof typeof IsolationKind];
|
|
98
|
+
export declare const IsolationKindNumber: {
|
|
99
|
+
readonly Default: ProtoIsolationKind.DEFAULT;
|
|
100
|
+
readonly ProviderSpecific: ProtoIsolationKind.PROVIDER_SPECIFIC;
|
|
101
|
+
readonly Container: ProtoIsolationKind.CONTAINER;
|
|
102
|
+
readonly Microvm: ProtoIsolationKind.MICROVM;
|
|
103
|
+
readonly LinuxVm: ProtoIsolationKind.LINUX_VM;
|
|
104
|
+
readonly Worker: ProtoIsolationKind.WORKER;
|
|
105
|
+
};
|
|
106
|
+
export declare const EgressMode: {
|
|
107
|
+
readonly Default: ProtoEgressMode.DEFAULT;
|
|
108
|
+
readonly AllowAll: ProtoEgressMode.ALLOW_ALL;
|
|
109
|
+
readonly BlockAll: ProtoEgressMode.BLOCK_ALL;
|
|
110
|
+
readonly Restricted: ProtoEgressMode.RESTRICTED;
|
|
111
|
+
};
|
|
112
|
+
export type EgressMode = (typeof EgressMode)[keyof typeof EgressMode];
|
|
113
|
+
export declare const EgressModeNumber: {
|
|
114
|
+
readonly Default: ProtoEgressMode.DEFAULT;
|
|
115
|
+
readonly AllowAll: ProtoEgressMode.ALLOW_ALL;
|
|
116
|
+
readonly BlockAll: ProtoEgressMode.BLOCK_ALL;
|
|
117
|
+
readonly Restricted: ProtoEgressMode.RESTRICTED;
|
|
118
|
+
};
|
|
119
|
+
export declare const PortTransport: {
|
|
120
|
+
readonly Default: ProtoPortTransport.DEFAULT;
|
|
121
|
+
readonly Tls: ProtoPortTransport.TLS;
|
|
122
|
+
readonly Http2Tls: ProtoPortTransport.HTTP2_TLS;
|
|
123
|
+
readonly Plain: ProtoPortTransport.PLAIN;
|
|
124
|
+
};
|
|
125
|
+
export type PortTransport = (typeof PortTransport)[keyof typeof PortTransport];
|
|
126
|
+
export declare const PortTransportNumber: {
|
|
127
|
+
readonly Default: ProtoPortTransport.DEFAULT;
|
|
128
|
+
readonly Tls: ProtoPortTransport.TLS;
|
|
129
|
+
readonly Http2Tls: ProtoPortTransport.HTTP2_TLS;
|
|
130
|
+
readonly Plain: ProtoPortTransport.PLAIN;
|
|
131
|
+
};
|
|
132
|
+
export declare const SecretInjection: {
|
|
133
|
+
readonly Default: ProtoSecretInjection.DEFAULT;
|
|
134
|
+
readonly Environment: ProtoSecretInjection.ENVIRONMENT;
|
|
135
|
+
readonly EgressPlaceholder: ProtoSecretInjection.EGRESS_PLACEHOLDER;
|
|
136
|
+
};
|
|
137
|
+
export type SecretInjection = (typeof SecretInjection)[keyof typeof SecretInjection];
|
|
138
|
+
export declare const SecretInjectionNumber: {
|
|
139
|
+
readonly Default: ProtoSecretInjection.DEFAULT;
|
|
140
|
+
readonly Environment: ProtoSecretInjection.ENVIRONMENT;
|
|
141
|
+
readonly EgressPlaceholder: ProtoSecretInjection.EGRESS_PLACEHOLDER;
|
|
142
|
+
};
|
|
143
|
+
export declare const PolicyMode: {
|
|
144
|
+
readonly Default: ProtoPolicyMode.DEFAULT;
|
|
145
|
+
readonly Disabled: ProtoPolicyMode.DISABLED;
|
|
146
|
+
readonly After: ProtoPolicyMode.AFTER;
|
|
147
|
+
};
|
|
148
|
+
export type PolicyMode = (typeof PolicyMode)[keyof typeof PolicyMode];
|
|
149
|
+
export declare const PolicyModeNumber: {
|
|
150
|
+
readonly Default: ProtoPolicyMode.DEFAULT;
|
|
151
|
+
readonly Disabled: ProtoPolicyMode.DISABLED;
|
|
152
|
+
readonly After: ProtoPolicyMode.AFTER;
|
|
153
|
+
};
|
|
154
|
+
export declare const WaitCondition: {
|
|
155
|
+
readonly Default: ProtoWaitCondition.DEFAULT;
|
|
156
|
+
readonly Submitted: ProtoWaitCondition.SUBMITTED;
|
|
157
|
+
readonly Scheduled: ProtoWaitCondition.SCHEDULED;
|
|
158
|
+
readonly Started: ProtoWaitCondition.STARTED;
|
|
159
|
+
readonly Ready: ProtoWaitCondition.READY;
|
|
160
|
+
};
|
|
161
|
+
export type WaitCondition = (typeof WaitCondition)[keyof typeof WaitCondition];
|
|
162
|
+
export declare const WaitConditionNumber: {
|
|
163
|
+
readonly Default: ProtoWaitCondition.DEFAULT;
|
|
164
|
+
readonly Submitted: ProtoWaitCondition.SUBMITTED;
|
|
165
|
+
readonly Scheduled: ProtoWaitCondition.SCHEDULED;
|
|
166
|
+
readonly Started: ProtoWaitCondition.STARTED;
|
|
167
|
+
readonly Ready: ProtoWaitCondition.READY;
|
|
168
|
+
};
|
|
169
|
+
export declare const SandboxState: {
|
|
170
|
+
readonly Unknown: ProtoSandboxState.UNKNOWN;
|
|
171
|
+
readonly Queued: ProtoSandboxState.QUEUED;
|
|
172
|
+
readonly Starting: ProtoSandboxState.STARTING;
|
|
173
|
+
readonly Running: ProtoSandboxState.RUNNING;
|
|
174
|
+
readonly Stopping: ProtoSandboxState.STOPPING;
|
|
175
|
+
readonly Stopped: ProtoSandboxState.STOPPED;
|
|
176
|
+
readonly Pausing: ProtoSandboxState.PAUSING;
|
|
177
|
+
readonly Paused: ProtoSandboxState.PAUSED;
|
|
178
|
+
readonly Archiving: ProtoSandboxState.ARCHIVING;
|
|
179
|
+
readonly Archived: ProtoSandboxState.ARCHIVED;
|
|
180
|
+
readonly Terminating: ProtoSandboxState.TERMINATING;
|
|
181
|
+
readonly Terminated: ProtoSandboxState.TERMINATED;
|
|
182
|
+
readonly Deleting: ProtoSandboxState.DELETING;
|
|
183
|
+
readonly Deleted: ProtoSandboxState.DELETED;
|
|
184
|
+
readonly Error: ProtoSandboxState.ERROR;
|
|
185
|
+
};
|
|
186
|
+
export type SandboxState = (typeof SandboxState)[keyof typeof SandboxState];
|
|
187
|
+
export declare const LifecycleCapability: {
|
|
188
|
+
readonly Unknown: ProtoLifecycleCapability.UNKNOWN;
|
|
189
|
+
readonly Refresh: ProtoLifecycleCapability.REFRESH;
|
|
190
|
+
readonly Start: ProtoLifecycleCapability.START;
|
|
191
|
+
readonly Stop: ProtoLifecycleCapability.STOP;
|
|
192
|
+
readonly Pause: ProtoLifecycleCapability.PAUSE;
|
|
193
|
+
readonly Terminate: ProtoLifecycleCapability.TERMINATE;
|
|
194
|
+
readonly Archive: ProtoLifecycleCapability.ARCHIVE;
|
|
195
|
+
readonly Delete: ProtoLifecycleCapability.DELETE;
|
|
196
|
+
};
|
|
197
|
+
export type LifecycleCapability = (typeof LifecycleCapability)[keyof typeof LifecycleCapability];
|
|
198
|
+
export declare const ValueOrigin: {
|
|
199
|
+
readonly Provider: ProtoValueOrigin.PROVIDER;
|
|
200
|
+
readonly Unknown: ProtoValueOrigin.UNKNOWN;
|
|
201
|
+
readonly Request: ProtoValueOrigin.REQUEST;
|
|
202
|
+
};
|
|
203
|
+
export type ValueOrigin = (typeof ValueOrigin)[keyof typeof ValueOrigin];
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// Portable sandbox data contracts come from standard protobuf generation.
|
|
2
|
+
// These aliases keep the SDK entrypoint concise while ensuring one representation.
|
|
3
|
+
import { EgressMode as ProtoEgressMode, IsolationKind as ProtoIsolationKind, LifecycleCapability as ProtoLifecycleCapability, PolicyMode as ProtoPolicyMode, PortTransport as ProtoPortTransport, SandboxState as ProtoSandboxState, SecretInjection as ProtoSecretInjection, SnapshotKind as ProtoSnapshotKind, ValueOrigin as ProtoValueOrigin, WaitCondition as ProtoWaitCondition, } from "@sandbox-kit/contracts/sandbox";
|
|
4
|
+
import { protoEnum } from "#internal/proto_enum.js";
|
|
5
|
+
// Ergonomic PascalCase names over protobuf enum values; not a second contract.
|
|
6
|
+
export const SnapshotKind = protoEnum(ProtoSnapshotKind);
|
|
7
|
+
export const SnapshotKindNumber = SnapshotKind;
|
|
8
|
+
export const IsolationKind = protoEnum(ProtoIsolationKind);
|
|
9
|
+
export const IsolationKindNumber = IsolationKind;
|
|
10
|
+
export const EgressMode = protoEnum(ProtoEgressMode);
|
|
11
|
+
export const EgressModeNumber = EgressMode;
|
|
12
|
+
export const PortTransport = protoEnum(ProtoPortTransport);
|
|
13
|
+
export const PortTransportNumber = PortTransport;
|
|
14
|
+
export const SecretInjection = protoEnum(ProtoSecretInjection);
|
|
15
|
+
export const SecretInjectionNumber = SecretInjection;
|
|
16
|
+
export const PolicyMode = protoEnum(ProtoPolicyMode);
|
|
17
|
+
export const PolicyModeNumber = PolicyMode;
|
|
18
|
+
export const WaitCondition = protoEnum(ProtoWaitCondition);
|
|
19
|
+
export const WaitConditionNumber = WaitCondition;
|
|
20
|
+
export const SandboxState = protoEnum(ProtoSandboxState);
|
|
21
|
+
export const LifecycleCapability = protoEnum(ProtoLifecycleCapability);
|
|
22
|
+
export const ValueOrigin = protoEnum(ProtoValueOrigin);
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type Duration } from "@bufbuild/protobuf/wkt";
|
|
2
|
+
/** True when a value looks like a protobuf Duration message or init. */
|
|
3
|
+
export declare function isDurationValue(value: unknown): value is Duration;
|
|
4
|
+
type DurationFieldName = "timeout" | "queueTimeout" | "maximumLifetime" | "after";
|
|
5
|
+
/**
|
|
6
|
+
* Recursively replace known protobuf Duration fields with millisecond numbers
|
|
7
|
+
* for public request construction. Field-name based so maps like `labels` are
|
|
8
|
+
* left alone. Public values are always milliseconds.
|
|
9
|
+
*/
|
|
10
|
+
export type DurationFieldsToMs<T> = T extends readonly (infer U)[] ? DurationFieldsToMs<U>[] : T extends object ? {
|
|
11
|
+
[K in keyof T]: K extends DurationFieldName ? undefined extends T[K] ? number | undefined : number : DurationFieldsToMs<T[K]>;
|
|
12
|
+
} : T;
|
|
13
|
+
/** Convert public ms numbers on known duration fields into protobuf Durations. */
|
|
14
|
+
export declare function materializeDurationFields<T>(value: T): T;
|
|
15
|
+
export {};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { durationFromMs } from "@bufbuild/protobuf/wkt";
|
|
2
|
+
/** True when a value looks like a protobuf Duration message or init. */
|
|
3
|
+
export function isDurationValue(value) {
|
|
4
|
+
return (typeof value === "object" &&
|
|
5
|
+
value !== null &&
|
|
6
|
+
("seconds" in value || "nanos" in value) &&
|
|
7
|
+
!Array.isArray(value));
|
|
8
|
+
}
|
|
9
|
+
const durationFieldNames = new Set([
|
|
10
|
+
"timeout",
|
|
11
|
+
"queueTimeout",
|
|
12
|
+
"maximumLifetime",
|
|
13
|
+
"after",
|
|
14
|
+
]);
|
|
15
|
+
/** Convert public ms numbers on known duration fields into protobuf Durations. */
|
|
16
|
+
export function materializeDurationFields(value) {
|
|
17
|
+
return materializeDurationFieldsAt(value, []);
|
|
18
|
+
}
|
|
19
|
+
function materializeDurationFieldsAt(value, path) {
|
|
20
|
+
if (value === null || value === undefined)
|
|
21
|
+
return value;
|
|
22
|
+
if (typeof value === "number") {
|
|
23
|
+
const leaf = path[path.length - 1];
|
|
24
|
+
if (leaf !== undefined && durationFieldNames.has(leaf)) {
|
|
25
|
+
return durationFromMs(value);
|
|
26
|
+
}
|
|
27
|
+
return value;
|
|
28
|
+
}
|
|
29
|
+
if (typeof value !== "object")
|
|
30
|
+
return value;
|
|
31
|
+
if (isDurationValue(value))
|
|
32
|
+
return value;
|
|
33
|
+
if (Array.isArray(value)) {
|
|
34
|
+
return value.map((item) => materializeDurationFieldsAt(item, path));
|
|
35
|
+
}
|
|
36
|
+
const out = {};
|
|
37
|
+
for (const [key, child] of Object.entries(value)) {
|
|
38
|
+
out[key] = materializeDurationFieldsAt(child, [...path, key]);
|
|
39
|
+
}
|
|
40
|
+
return out;
|
|
41
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
type Simplify<T> = {
|
|
2
|
+
[K in keyof T]: T[K];
|
|
3
|
+
} & {};
|
|
4
|
+
type PreserveOptional<Orig, New> = undefined extends Orig ? New | undefined : New;
|
|
5
|
+
/**
|
|
6
|
+
* Replace selected fields with R[K], keeping each field's optionality from T.
|
|
7
|
+
* Prefer this over call-site `Omit<T, K> & { K?: New }`. Keys in R that are
|
|
8
|
+
* absent from T are ignored; only overlapping keys are rewritten.
|
|
9
|
+
*/
|
|
10
|
+
export type RemapFields<T, R> = Simplify<{
|
|
11
|
+
[K in keyof T]: K extends keyof R ? PreserveOptional<T[K], R[K]> : T[K];
|
|
12
|
+
}>;
|
|
13
|
+
type AllowlistField = "outboundCidrs" | "outboundDomains" | "inboundCidrs";
|
|
14
|
+
/**
|
|
15
|
+
* Recursively unwrap StringAllowlist-shaped fields to plain `string[]`.
|
|
16
|
+
* Present empty arrays still mean deny-all after materialize.
|
|
17
|
+
*/
|
|
18
|
+
export type FlattenAllowlistFields<T> = T extends readonly (infer U)[] ? FlattenAllowlistFields<U>[] : T extends object ? {
|
|
19
|
+
[K in keyof T]: K extends AllowlistField ? PreserveOptional<T[K], string[]> : FlattenAllowlistFields<T[K]>;
|
|
20
|
+
} : T;
|
|
21
|
+
type EmptyMarkerField = "providerDefault";
|
|
22
|
+
/**
|
|
23
|
+
* Recursively turn empty wire marker messages into `true` presence flags
|
|
24
|
+
* (e.g. `source.providerDefault?: true`).
|
|
25
|
+
*/
|
|
26
|
+
export type EmptyMarkersAsTrue<T> = T extends readonly (infer U)[] ? EmptyMarkersAsTrue<U>[] : T extends object ? {
|
|
27
|
+
[K in keyof T]: K extends EmptyMarkerField ? PreserveOptional<T[K], true> : EmptyMarkersAsTrue<T[K]>;
|
|
28
|
+
} : T;
|
|
29
|
+
type StringMapField = "environment" | "labels";
|
|
30
|
+
/**
|
|
31
|
+
* Recursively replace noisy proto string maps with `Record<string, string>`.
|
|
32
|
+
*/
|
|
33
|
+
export type PlainStringMapFields<T> = T extends readonly (infer U)[] ? PlainStringMapFields<U>[] : T extends object ? {
|
|
34
|
+
[K in keyof T]: K extends StringMapField ? PreserveOptional<T[K], Record<string, string>> : PlainStringMapFields<T[K]>;
|
|
35
|
+
} : T;
|
|
36
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { RemapFields } from "./input_remap.js";
|
|
2
|
+
import type { StripProto } from "./strip_proto.js";
|
|
3
|
+
type Simplify<T> = {
|
|
4
|
+
[K in keyof T]: T[K];
|
|
5
|
+
} & {};
|
|
6
|
+
type ProtoOneof = {
|
|
7
|
+
case: string | undefined;
|
|
8
|
+
value?: unknown;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Derive nested exclusive input fields from a protobuf-es `{ case, value }` oneof.
|
|
12
|
+
* Variant payloads are StripProto'd (no `$typeName` / `$unknown`).
|
|
13
|
+
*/
|
|
14
|
+
export type FlattenOneof<T extends ProtoOneof> = Simplify<{
|
|
15
|
+
[K in Exclude<T["case"], undefined>]?: StripProto<Exclude<Extract<T, {
|
|
16
|
+
case: K;
|
|
17
|
+
}>["value"], undefined>>;
|
|
18
|
+
}>;
|
|
19
|
+
/**
|
|
20
|
+
* Strip protobuf-es internals, then replace listed fields with flattened oneof
|
|
21
|
+
* bags. Use when a wire field is a carrier message whose oneof should surface
|
|
22
|
+
* as exclusive keys on the public input (e.g. `source.kind` → `source.image`).
|
|
23
|
+
*
|
|
24
|
+
* `Oneofs` maps each remapped field to the oneof union to flatten.
|
|
25
|
+
* Further public remaps (allowlists, ms durations, plain maps) compose outside.
|
|
26
|
+
*/
|
|
27
|
+
export type StripAndFlatten<T, Oneofs extends {
|
|
28
|
+
[K in keyof Oneofs]: K extends keyof T ? ProtoOneof : never;
|
|
29
|
+
}> = RemapFields<StripProto<T>, {
|
|
30
|
+
[K in keyof Oneofs & string]: FlattenOneof<Oneofs[K]>;
|
|
31
|
+
}>;
|
|
32
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
type Simplify<T> = {
|
|
2
|
+
[K in keyof T]: T[K];
|
|
3
|
+
} & {};
|
|
4
|
+
/** `ALLOW_ALL` → `AllowAll`, `HTTP2_TLS` → `Http2Tls`. */
|
|
5
|
+
type SnakeToPascal<S extends string> = S extends `${infer Head}_${infer Tail}` ? `${Capitalize<Lowercase<Head>>}${SnakeToPascal<Tail>}` : Capitalize<Lowercase<S>>;
|
|
6
|
+
/** Forward protobuf-es enum member names (skip reverse numeric keys). */
|
|
7
|
+
type EnumMemberKeys<E> = {
|
|
8
|
+
[K in keyof E]: K extends string ? E[K] extends number ? K extends `${number}` ? never : K : never : never;
|
|
9
|
+
}[keyof E];
|
|
10
|
+
/**
|
|
11
|
+
* Public const object for a protobuf-es enum: PascalCase keys, same numeric
|
|
12
|
+
* values. Does not invent a second contract — only renames member keys.
|
|
13
|
+
*/
|
|
14
|
+
export type EnumConst<E> = Simplify<{
|
|
15
|
+
readonly [K in EnumMemberKeys<E> as SnakeToPascal<K & string>]: E[K];
|
|
16
|
+
}>;
|
|
17
|
+
/**
|
|
18
|
+
* Build an ergonomic enum const from a protobuf-es numeric enum object.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* export const EgressMode = protoEnum(ProtoEgressMode);
|
|
22
|
+
* // { Default: 0, AllowAll: 1, BlockAll: 2, Restricted: 3 }
|
|
23
|
+
*/
|
|
24
|
+
export declare function protoEnum<E extends Record<string, string | number>>(proto: E): EnumConst<E>;
|
|
25
|
+
export {};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
function snakeToPascal(name) {
|
|
2
|
+
return name
|
|
3
|
+
.toLowerCase()
|
|
4
|
+
.split("_")
|
|
5
|
+
.map((part) => part.charAt(0).toUpperCase() + part.slice(1))
|
|
6
|
+
.join("");
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Build an ergonomic enum const from a protobuf-es numeric enum object.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* export const EgressMode = protoEnum(ProtoEgressMode);
|
|
13
|
+
* // { Default: 0, AllowAll: 1, BlockAll: 2, Restricted: 3 }
|
|
14
|
+
*/
|
|
15
|
+
export function protoEnum(proto) {
|
|
16
|
+
const out = {};
|
|
17
|
+
for (const [key, value] of Object.entries(proto)) {
|
|
18
|
+
if (typeof value !== "number")
|
|
19
|
+
continue;
|
|
20
|
+
if (/^\d+$/.test(key))
|
|
21
|
+
continue;
|
|
22
|
+
out[snakeToPascal(key)] = value;
|
|
23
|
+
}
|
|
24
|
+
return out;
|
|
25
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { Duration, Timestamp } from "@bufbuild/protobuf/wkt";
|
|
2
|
+
type ProtoKey = "$typeName" | "$unknown";
|
|
3
|
+
/**
|
|
4
|
+
* True for proto3 map fields (`{ [key: string]: V }`), including non-string
|
|
5
|
+
* values such as `map<string, ValueOrigin>`. Not true for plain messages.
|
|
6
|
+
*/
|
|
7
|
+
type IsProtoMap<T> = T extends object ? string extends keyof T ? T extends readonly unknown[] ? false : true : false : false;
|
|
8
|
+
/**
|
|
9
|
+
* Required proto3 maps/repeated/enums become optional for construction.
|
|
10
|
+
* protobuf-es enums are numeric, so required `number` fields soften too.
|
|
11
|
+
* Map *entry* keys (index signatures) are not softened — that would yield
|
|
12
|
+
* `Record<string, V | undefined>`.
|
|
13
|
+
*/
|
|
14
|
+
type SoftenField<V, K> = string extends K ? false : V extends readonly unknown[] ? true : IsProtoMap<V> extends true ? true : V extends number ? true : false;
|
|
15
|
+
type OptionalKeys<T> = Exclude<{
|
|
16
|
+
[K in keyof T]-?: undefined extends T[K] ? K : never;
|
|
17
|
+
}[keyof T], ProtoKey>;
|
|
18
|
+
type RequiredKeys<T> = Exclude<keyof T, OptionalKeys<T> | ProtoKey>;
|
|
19
|
+
type SoftenedKeys<T> = {
|
|
20
|
+
[K in RequiredKeys<T>]: SoftenField<T[K], K> extends true ? K : never;
|
|
21
|
+
}[RequiredKeys<T>];
|
|
22
|
+
type KeptRequiredKeys<T> = Exclude<RequiredKeys<T>, SoftenedKeys<T>>;
|
|
23
|
+
type Simplify<T> = {
|
|
24
|
+
[K in keyof T]: T[K];
|
|
25
|
+
} & {};
|
|
26
|
+
type StripProtoObject<T> = Simplify<{
|
|
27
|
+
[K in OptionalKeys<T> & keyof T]?: StripProto<Exclude<T[K], undefined>>;
|
|
28
|
+
} & {
|
|
29
|
+
[K in SoftenedKeys<T>]?: StripProto<T[K]>;
|
|
30
|
+
} & {
|
|
31
|
+
[K in KeptRequiredKeys<T>]: StripProto<T[K]>;
|
|
32
|
+
}>;
|
|
33
|
+
/**
|
|
34
|
+
* Recursively drop protobuf-es message internals for public SDK types:
|
|
35
|
+
*
|
|
36
|
+
* - removes `$typeName` / `$unknown` at every level (including nested messages)
|
|
37
|
+
* - keeps normal field optionality
|
|
38
|
+
* - softens required proto3 maps/repeated/enums to optional
|
|
39
|
+
* - keeps wire `Duration` opaque for provider helpers
|
|
40
|
+
* - maps `Timestamp` to `Date`
|
|
41
|
+
*
|
|
42
|
+
* Nested messages are stripped in place, so aliases do not need `Omit` + remap
|
|
43
|
+
* just to clean child protobuf fields.
|
|
44
|
+
*/
|
|
45
|
+
export type StripProto<T> = T extends Duration ? Duration : T extends Timestamp ? Date : T extends string | number | boolean | bigint | null | undefined | symbol | Date | Uint8Array | ((...args: never[]) => unknown) ? T : T extends readonly (infer U)[] ? StripProto<U>[] : T extends object ? StripProtoObject<T> : T;
|
|
46
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { MetadataObject } from "#contracts/sandbox_data_contracts.js";
|
|
2
|
+
import type { MetadataPlain } from "#metadata/metadata_plain.js";
|
|
3
|
+
export type { MetadataPlain } from "#metadata/metadata_plain.js";
|
|
4
|
+
/** Converts a declarative map into the protobuf metadata object. */
|
|
5
|
+
export declare function metadataObjectFromMap(source: Record<string, MetadataPlain> | undefined): MetadataObject | undefined;
|
|
6
|
+
/** Converts a protobuf metadata object into a declarative map. */
|
|
7
|
+
export declare function metadataObjectAsMap(source: MetadataObject | undefined): Record<string, MetadataPlain> | undefined;
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
// Handwritten helpers for protobuf metadata objects (mirrors Go sandbox metadata helpers).
|
|
2
|
+
import { create } from "@bufbuild/protobuf";
|
|
3
|
+
import { MetadataListSchema, MetadataObjectSchema, MetadataValueSchema, } from "@sandbox-kit/contracts/sandbox";
|
|
4
|
+
/** Converts a declarative map into the protobuf metadata object. */
|
|
5
|
+
export function metadataObjectFromMap(source) {
|
|
6
|
+
if (source === undefined)
|
|
7
|
+
return undefined;
|
|
8
|
+
const values = {};
|
|
9
|
+
for (const [key, value] of Object.entries(source)) {
|
|
10
|
+
values[key] = metadataValueFromPlain(value);
|
|
11
|
+
}
|
|
12
|
+
return create(MetadataObjectSchema, { values });
|
|
13
|
+
}
|
|
14
|
+
/** Converts a protobuf metadata object into a declarative map. */
|
|
15
|
+
export function metadataObjectAsMap(source) {
|
|
16
|
+
if (source === undefined)
|
|
17
|
+
return undefined;
|
|
18
|
+
const out = {};
|
|
19
|
+
for (const [key, value] of Object.entries(source.values ?? {})) {
|
|
20
|
+
out[key] = metadataValueAsPlain(value);
|
|
21
|
+
}
|
|
22
|
+
return out;
|
|
23
|
+
}
|
|
24
|
+
function metadataValueFromPlain(value) {
|
|
25
|
+
// create() returns a protobuf Message; public aliases are StripProto shapes.
|
|
26
|
+
if (value === null)
|
|
27
|
+
return create(MetadataValueSchema, {});
|
|
28
|
+
if (typeof value === "boolean")
|
|
29
|
+
return create(MetadataValueSchema, {
|
|
30
|
+
value: { case: "boolean", value },
|
|
31
|
+
});
|
|
32
|
+
if (typeof value === "string")
|
|
33
|
+
return create(MetadataValueSchema, {
|
|
34
|
+
value: { case: "text", value },
|
|
35
|
+
});
|
|
36
|
+
if (typeof value === "bigint") {
|
|
37
|
+
if (value < 0n)
|
|
38
|
+
return create(MetadataValueSchema, {
|
|
39
|
+
value: { case: "signedInteger", value },
|
|
40
|
+
});
|
|
41
|
+
return create(MetadataValueSchema, {
|
|
42
|
+
value: { case: "unsignedInteger", value },
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
if (typeof value === "number") {
|
|
46
|
+
if (!Number.isFinite(value)) {
|
|
47
|
+
throw new Error("sandbox-kit: metadata numbers must be finite");
|
|
48
|
+
}
|
|
49
|
+
if (Number.isInteger(value)) {
|
|
50
|
+
const asBigInt = BigInt(value);
|
|
51
|
+
if (value < 0)
|
|
52
|
+
return create(MetadataValueSchema, {
|
|
53
|
+
value: { case: "signedInteger", value: asBigInt },
|
|
54
|
+
});
|
|
55
|
+
return create(MetadataValueSchema, {
|
|
56
|
+
value: { case: "unsignedInteger", value: asBigInt },
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
return create(MetadataValueSchema, {
|
|
60
|
+
value: { case: "number", value },
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
if (value instanceof Uint8Array)
|
|
64
|
+
return create(MetadataValueSchema, {
|
|
65
|
+
value: { case: "binary", value },
|
|
66
|
+
});
|
|
67
|
+
if (Array.isArray(value)) {
|
|
68
|
+
return create(MetadataValueSchema, {
|
|
69
|
+
value: {
|
|
70
|
+
case: "list",
|
|
71
|
+
value: create(MetadataListSchema, {
|
|
72
|
+
values: value.map(metadataValueFromPlain),
|
|
73
|
+
}),
|
|
74
|
+
},
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
return create(MetadataValueSchema, {
|
|
78
|
+
value: {
|
|
79
|
+
case: "object",
|
|
80
|
+
value: metadataObjectFromMap(value),
|
|
81
|
+
},
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
function metadataValueAsPlain(value) {
|
|
85
|
+
switch (value.value?.case) {
|
|
86
|
+
case undefined:
|
|
87
|
+
return null;
|
|
88
|
+
case "boolean":
|
|
89
|
+
case "text":
|
|
90
|
+
case "number":
|
|
91
|
+
case "binary":
|
|
92
|
+
return value.value.value;
|
|
93
|
+
case "signedInteger":
|
|
94
|
+
case "unsignedInteger":
|
|
95
|
+
return value.value.value;
|
|
96
|
+
case "list":
|
|
97
|
+
return (value.value.value?.values ?? []).map(metadataValueAsPlain);
|
|
98
|
+
case "object":
|
|
99
|
+
return metadataObjectAsMap(value.value.value) ?? {};
|
|
100
|
+
default:
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plain JSON-like values accepted for public metadata / providerOptions maps.
|
|
3
|
+
* Nested objects use an interface so IDEs do not expand the recursive union.
|
|
4
|
+
*/
|
|
5
|
+
export type MetadataPlain = null | boolean | string | number | bigint | Uint8Array | MetadataPlain[] | MetadataPlainObject;
|
|
6
|
+
/** Nested object branch of {@link MetadataPlain}. */
|
|
7
|
+
export interface MetadataPlainObject {
|
|
8
|
+
[key: string]: MetadataPlain;
|
|
9
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|