@akashnetwork/chain-sdk 1.0.0-alpha.37 → 1.0.0-alpha.38
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/dist/cjs/sdk/client/sdkMetadata.cjs +1 -1
- package/dist/cjs/sdk/client/sdkMetadata.cjs.map +2 -2
- package/dist/cjs/sdl/manifest/generateManifest.cjs +8 -1
- package/dist/cjs/sdl/manifest/generateManifest.cjs.map +2 -2
- package/dist/cjs/sdl/validateSDL/validateSDL.cjs +39 -15
- package/dist/cjs/sdl/validateSDL/validateSDL.cjs.map +2 -2
- package/dist/esm/{chunk-R42YS74B.js → chunk-JY5F3I26.js} +49 -18
- package/dist/esm/chunk-JY5F3I26.js.map +7 -0
- package/dist/esm/index.js +1 -1
- package/dist/esm/index.web.js +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/dist/esm/chunk-R42YS74B.js.map +0 -7
|
@@ -22,7 +22,7 @@ __export(sdkMetadata_exports, {
|
|
|
22
22
|
withMetadata: () => withMetadata
|
|
23
23
|
});
|
|
24
24
|
module.exports = __toCommonJS(sdkMetadata_exports);
|
|
25
|
-
const SDK_METHOD_METADATA = /* @__PURE__ */ new
|
|
25
|
+
const SDK_METHOD_METADATA = /* @__PURE__ */ new WeakMap();
|
|
26
26
|
function withMetadata(fn, metadata) {
|
|
27
27
|
SDK_METHOD_METADATA.set(fn, metadata);
|
|
28
28
|
return fn;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/sdk/client/sdkMetadata.ts"],
|
|
4
|
-
"sourcesContent": ["import type { ServiceLoader } from \"./createServiceLoader.ts\";\nimport type { ServiceDesc } from \"./types.ts\";\n\nconst SDK_METHOD_METADATA = new
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,MAAM,sBAAsB,oBAAI,
|
|
4
|
+
"sourcesContent": ["import type { ServiceLoader } from \"./createServiceLoader.ts\";\nimport type { ServiceDesc } from \"./types.ts\";\n\nconst SDK_METHOD_METADATA = new WeakMap<SDKMethod, SDKMethodMetadata>();\nexport function withMetadata<T extends SDKMethod>(fn: T, metadata: SDKMethodMetadata): T {\n SDK_METHOD_METADATA.set(fn, metadata);\n return fn;\n}\n\nexport function getMetadata(fn: SDKMethod): SDKMethodMetadata | undefined {\n return SDK_METHOD_METADATA.get(fn);\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type SDKMethod = (input: any, options?: any) => Promise<any>;\n\ninterface SDKMethodMetadata {\n /**\n * The path to the method in the service loader.\n * 1st number is the index of the service and the 2nd is the local name of the method.\n */\n path: [number, string];\n\n serviceLoader: ServiceLoader<ReadonlyArray<() => Promise<ServiceDesc>>>;\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,MAAM,sBAAsB,oBAAI,QAAsC;AAC/D,SAAS,aAAkC,IAAO,UAAgC;AACvF,sBAAoB,IAAI,IAAI,QAAQ;AACpC,SAAO;AACT;AAEO,SAAS,YAAY,IAA8C;AACxE,SAAO,oBAAoB,IAAI,EAAE;AACnC;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -81,10 +81,17 @@ function generateManifest(sdl) {
|
|
|
81
81
|
})
|
|
82
82
|
})
|
|
83
83
|
}),
|
|
84
|
-
boundComputes: {}
|
|
84
|
+
boundComputes: {},
|
|
85
|
+
teeType: void 0
|
|
85
86
|
};
|
|
86
87
|
groupsMap.set(placementName, group);
|
|
87
88
|
}
|
|
89
|
+
const teeType = service.params?.tee;
|
|
90
|
+
if (teeType && !group.teeType) {
|
|
91
|
+
group.teeType = teeType;
|
|
92
|
+
group.dgroup.requirements.attributes.push({ key: "tee/type", value: teeType });
|
|
93
|
+
group.dgroup.requirements.attributes.sort((a, b) => a.key.localeCompare(b.key));
|
|
94
|
+
}
|
|
88
95
|
const profileKey = `${placementName}:${svcdepl.profile}`;
|
|
89
96
|
const location = group.boundComputes[svcdepl.profile];
|
|
90
97
|
if (location === void 0) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/sdl/manifest/generateManifest.ts"],
|
|
4
|
-
"sourcesContent": ["import { PlacementRequirements, SignedBy } from \"../../generated/protos/akash/base/attributes/v1/attribute.ts\";\nimport { CPU } from \"../../generated/protos/akash/base/resources/v1beta4/cpu.ts\";\nimport { GPU } from \"../../generated/protos/akash/base/resources/v1beta4/gpu.ts\";\nimport { Memory } from \"../../generated/protos/akash/base/resources/v1beta4/memory.ts\";\nimport { Resources } from \"../../generated/protos/akash/base/resources/v1beta4/resources.ts\";\nimport { Storage } from \"../../generated/protos/akash/base/resources/v1beta4/storage.ts\";\nimport { DeploymentReclamation } from \"../../generated/protos/akash/deployment/v1/deployment.ts\";\nimport { GroupSpec } from \"../../generated/protos/akash/deployment/v1beta4/groupspec.ts\";\nimport { ResourceUnit } from \"../../generated/protos/akash/deployment/v1beta4/resourceunit.ts\";\nimport { Group } from \"../../generated/protos/akash/manifest/v2beta3/group.ts\";\nimport { ImageCredentials, Service, ServiceParams, StorageParams, TEEParams } from \"../../generated/protos/akash/manifest/v2beta3/service.ts\";\nimport { ServiceExpose } from \"../../generated/protos/akash/manifest/v2beta3/serviceexpose.ts\";\nimport type { ValidationError } from \"../../utils/jsonSchemaValidation.ts\";\nimport { castArray } from \"../utils.ts\";\nimport type { SDLInput } from \"../validateSDL/validateSDL.ts\";\nimport { validateSDL } from \"../validateSDL/validateSDL.ts\";\nimport {\n buildHttpOptions,\n buildResourceAttributes,\n buildServiceEndpoints,\n buildStorageAttributes,\n computeEndpointSequenceNumbers,\n encodeResourceValue,\n parseCpuUnits,\n parseGpuUnits,\n parseMemoryBytes,\n parseServiceProto,\n parseStorageBytes,\n type SDLCompute,\n type SDLService,\n transformGpuAttributes,\n} from \"./manifestUtils.ts\";\nimport { minWindowToDuration } from \"./reclamationDuration.ts\";\n\nexport interface GenerateManifestOkResult {\n groups: Group[];\n groupSpecs: GroupSpec[];\n reclamation?: DeploymentReclamation;\n}\n\nexport type Manifest = GenerateManifestOkResult[\"groups\"];\nexport type GenerateManifestResult =\n | { ok?: false; value: ValidationError[] }\n | { ok: true; value: GenerateManifestOkResult };\nexport function generateManifest(sdl: SDLInput): GenerateManifestResult {\n const errors = validateSDL(sdl);\n if (errors) return { ok: false, value: errors };\n\n const endpointSequenceNumbers = computeEndpointSequenceNumbers(sdl.services);\n const groupsMap = new Map<string, {\n dgroup: GroupSpec;\n boundComputes: Record<string, number>;\n }>();\n const resourceIds = new Map<string, number>();\n\n const deploymentsByPlacement = new Map<string, [string, { profile: string; count: number }][]>();\n for (const [svcName, placements] of Object.entries(sdl.deployment)) {\n for (const [placementName, deployment] of Object.entries(placements)) {\n let list = deploymentsByPlacement.get(placementName);\n if (!list) {\n list = [];\n deploymentsByPlacement.set(placementName, list);\n }\n list.push([svcName, deployment]);\n }\n }\n for (const list of deploymentsByPlacement.values()) {\n list.sort(([a], [b]) => a.localeCompare(b));\n }\n\n const services = Object.entries(sdl.services).sort(([a], [b]) => a.localeCompare(b));\n\n for (const [svcName, service] of services) {\n for (const [placementName, svcdepl] of Object.entries(sdl.deployment[svcName])) {\n const compute = sdl.profiles.compute[svcdepl.profile];\n const infra = sdl.profiles.placement[placementName];\n const pricing = infra.pricing[svcdepl.profile];\n const price = {\n denom: pricing.denom,\n amount: pricing.amount?.toString(),\n };\n\n let group = groupsMap.get(placementName);\n\n if (!group) {\n group = {\n dgroup: GroupSpec.fromPartial({\n name: placementName,\n resources: [],\n requirements: PlacementRequirements.fromPartial({\n attributes: buildResourceAttributes(infra.attributes),\n signedBy: SignedBy.fromPartial({\n allOf: infra.signedBy?.allOf,\n anyOf: infra.signedBy?.anyOf,\n }),\n }),\n }),\n boundComputes: {},\n };\n\n groupsMap.set(placementName, group);\n }\n\n const profileKey = `${placementName}:${svcdepl.profile}`;\n const location = group.boundComputes[svcdepl.profile];\n\n if (location === undefined) {\n const resId = group.dgroup.resources.length > 0\n ? group.dgroup.resources.length + 1\n : 1;\n\n resourceIds.set(profileKey, resId);\n\n const resources = buildResources(resId, compute, service, endpointSequenceNumbers);\n\n group.dgroup.resources.push(\n ResourceUnit.fromPartial({\n resource: resources,\n count: svcdepl.count,\n price,\n }),\n );\n\n group.boundComputes[svcdepl.profile] = group.dgroup.resources.length - 1;\n } else {\n if (!resourceIds.has(profileKey)) {\n resourceIds.set(profileKey, group.dgroup.resources[location].resource!.id);\n }\n\n group.dgroup.resources[location].count += svcdepl.count;\n group.dgroup.resources[location].resource!.endpoints.push(\n ...buildServiceEndpoints(service, endpointSequenceNumbers),\n );\n }\n }\n }\n\n for (const group of groupsMap.values()) {\n for (const resourceUnit of group.dgroup.resources) {\n resourceUnit.resource!.endpoints.sort(\n (a, b) => a.kind - b.kind || a.sequenceNumber - b.sequenceNumber,\n );\n }\n }\n\n const sortedGroupNames = [...groupsMap.keys()].sort();\n let groups: Group[] | undefined;\n let groupSpecs: GroupSpec[] | undefined;\n let reclamation: DeploymentReclamation | undefined;\n\n const manifest = {\n // reclamation is a `MsgCreateDeployment` field, not a manifest group, and is\n // not needed in every call \u2014 so it's lazy like `groups`/`groupSpecs`.\n // `validateSDL` (run above) already guaranteed `min_window` is valid, so\n // `minWindowToDuration` never throws here.\n get reclamation() {\n if (sdl.reclamation && !reclamation) {\n reclamation = DeploymentReclamation.fromPartial({\n minWindow: minWindowToDuration(sdl.reclamation.min_window),\n });\n }\n return reclamation;\n },\n get groups() {\n groups ??= sortedGroupNames.map((placementName) => {\n const deployments = deploymentsByPlacement.get(placementName)!;\n\n return Group.fromPartial({\n name: placementName,\n services: deployments.map(([svcName]) => {\n const service = sdl.services[svcName];\n const deployment = sdl.deployment[svcName][placementName];\n const compute = sdl.profiles.compute[deployment.profile];\n const resourceId = resourceIds.get(`${placementName}:${deployment.profile}`) || 1;\n\n return buildManifestService(\n resourceId,\n svcName,\n service,\n compute,\n deployment.count,\n endpointSequenceNumbers,\n );\n }),\n });\n });\n return groups;\n },\n get groupSpecs() {\n groupSpecs ??= sortedGroupNames.map((name) => groupsMap.get(name)!.dgroup);\n return groupSpecs;\n },\n };\n\n return { ok: true, value: manifest };\n}\n\nfunction buildResources(\n id: number,\n compute: SDLCompute,\n service: SDLService,\n endpointSequenceNumbers: Record<string, number>,\n): Resources {\n const res = compute.resources;\n const cpuAttributes = buildResourceAttributes(res.cpu.attributes);\n const gpuAttributes = res.gpu?.attributes ? transformGpuAttributes(res.gpu.attributes) : [];\n\n return Resources.fromPartial({\n id,\n cpu: CPU.fromPartial({\n units: { val: encodeResourceValue(parseCpuUnits(res.cpu)) },\n attributes: cpuAttributes,\n }),\n memory: Memory.fromPartial({\n quantity: { val: encodeResourceValue(parseMemoryBytes(res.memory)) },\n }),\n storage: castArray(res.storage).map((s) =>\n Storage.fromPartial({\n name: s.name || \"default\",\n quantity: { val: encodeResourceValue(parseStorageBytes(s.size)) },\n attributes: buildStorageAttributes(s.attributes),\n }),\n ),\n gpu: GPU.fromPartial({\n units: { val: encodeResourceValue(parseGpuUnits(res.gpu)) },\n attributes: gpuAttributes,\n }),\n endpoints: buildServiceEndpoints(service, endpointSequenceNumbers),\n });\n}\n\nfunction buildManifestService(\n resourceId: number,\n name: string,\n service: SDLService,\n compute: SDLCompute,\n count: number,\n endpointSequenceNumbers: Record<string, number>,\n): Service {\n const credentials = service.credentials\n ? ImageCredentials.fromPartial({\n host: service.credentials.host,\n email: service.credentials.email || \"\",\n username: service.credentials.username,\n password: service.credentials.password,\n })\n : undefined;\n\n const params = buildParams(service);\n\n return Service.fromPartial({\n name,\n image: service.image,\n command: service.command || [],\n args: service.args || [],\n env: service.env || [],\n resources: buildResources(resourceId, compute, service, endpointSequenceNumbers),\n count,\n expose: buildManifestExpose(service, endpointSequenceNumbers),\n params,\n credentials,\n });\n}\n\nfunction buildParams(service: SDLService): ServiceParams | undefined {\n if (!service.params) return undefined;\n\n const storage = service.params.storage || {};\n const storageNames = service.params.storage ? Object.keys(storage).sort() : [];\n const result = ServiceParams.fromPartial({\n storage: storageNames.map((name) => {\n const config = storage[name];\n return StorageParams.fromPartial({\n name,\n mount: config.mount || \"\",\n readOnly: config.readOnly || false,\n });\n }),\n });\n\n // Permissions are not in the protobuf type but need to be preserved\n if (service.params.permissions) {\n (result as unknown as Record<string, unknown>).permissions = service.params.permissions;\n }\n\n // Project TEE onto the manifest, mirroring Go's groupBuilder\n // (params.TEE = {Type, Attestation: true}). `attestation` is hard-coded true\n // (not an input knob); the provider injects the attestation sidecar.\n if (service.params.tee) {\n result.tee = TEEParams.fromPartial({ type: service.params.tee, attestation: true });\n }\n\n return result;\n}\n\nfunction buildManifestExpose(\n service: SDLService,\n endpointSequenceNumbers: Record<string, number>,\n): ServiceExpose[] {\n return (service.expose ?? [])\n .flatMap((expose) =>\n (expose.to ?? []).map((to) =>\n ServiceExpose.fromPartial({\n port: expose.port,\n externalPort: expose.as,\n proto: parseServiceProto(expose.proto),\n service: to.service || \"\",\n global: to.global || false,\n hosts: expose.accept || [],\n httpOptions: buildHttpOptions(expose.http_options),\n ip: to.ip || \"\",\n endpointSequenceNumber: endpointSequenceNumbers[to.ip!],\n }),\n ),\n )\n .sort((a, b) => {\n if (a.service !== b.service) return a.service.localeCompare(b.service);\n if (a.port !== b.port) return a.port - b.port;\n if (a.proto !== b.proto) return a.proto.localeCompare(b.proto);\n if (a.global !== b.global) return a.global ? -1 : 1;\n return 0;\n });\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,uBAAgD;AAChD,iBAAoB;AACpB,iBAAoB;AACpB,oBAAuB;AACvB,uBAA0B;AAC1B,qBAAwB;AACxB,wBAAsC;AACtC,uBAA0B;AAC1B,0BAA6B;AAC7B,mBAAsB;AACtB,qBAAmF;AACnF,2BAA8B;AAE9B,mBAA0B;AAE1B,yBAA4B;AAC5B,2BAeO;AACP,iCAAoC;AAY7B,SAAS,iBAAiB,KAAuC;AACtE,QAAM,aAAS,gCAAY,GAAG;AAC9B,MAAI,OAAQ,QAAO,EAAE,IAAI,OAAO,OAAO,OAAO;AAE9C,QAAM,8BAA0B,qDAA+B,IAAI,QAAQ;AAC3E,QAAM,YAAY,oBAAI,
|
|
4
|
+
"sourcesContent": ["import { PlacementRequirements, SignedBy } from \"../../generated/protos/akash/base/attributes/v1/attribute.ts\";\nimport { CPU } from \"../../generated/protos/akash/base/resources/v1beta4/cpu.ts\";\nimport { GPU } from \"../../generated/protos/akash/base/resources/v1beta4/gpu.ts\";\nimport { Memory } from \"../../generated/protos/akash/base/resources/v1beta4/memory.ts\";\nimport { Resources } from \"../../generated/protos/akash/base/resources/v1beta4/resources.ts\";\nimport { Storage } from \"../../generated/protos/akash/base/resources/v1beta4/storage.ts\";\nimport { DeploymentReclamation } from \"../../generated/protos/akash/deployment/v1/deployment.ts\";\nimport { GroupSpec } from \"../../generated/protos/akash/deployment/v1beta4/groupspec.ts\";\nimport { ResourceUnit } from \"../../generated/protos/akash/deployment/v1beta4/resourceunit.ts\";\nimport { Group } from \"../../generated/protos/akash/manifest/v2beta3/group.ts\";\nimport { ImageCredentials, Service, ServiceParams, StorageParams, TEEParams } from \"../../generated/protos/akash/manifest/v2beta3/service.ts\";\nimport { ServiceExpose } from \"../../generated/protos/akash/manifest/v2beta3/serviceexpose.ts\";\nimport type { ValidationError } from \"../../utils/jsonSchemaValidation.ts\";\nimport { castArray } from \"../utils.ts\";\nimport type { SDLInput } from \"../validateSDL/validateSDL.ts\";\nimport { validateSDL } from \"../validateSDL/validateSDL.ts\";\nimport {\n buildHttpOptions,\n buildResourceAttributes,\n buildServiceEndpoints,\n buildStorageAttributes,\n computeEndpointSequenceNumbers,\n encodeResourceValue,\n parseCpuUnits,\n parseGpuUnits,\n parseMemoryBytes,\n parseServiceProto,\n parseStorageBytes,\n type SDLCompute,\n type SDLService,\n transformGpuAttributes,\n} from \"./manifestUtils.ts\";\nimport { minWindowToDuration } from \"./reclamationDuration.ts\";\n\nexport interface GenerateManifestOkResult {\n groups: Group[];\n groupSpecs: GroupSpec[];\n reclamation?: DeploymentReclamation;\n}\n\nexport type Manifest = GenerateManifestOkResult[\"groups\"];\nexport type GenerateManifestResult =\n | { ok?: false; value: ValidationError[] }\n | { ok: true; value: GenerateManifestOkResult };\nexport function generateManifest(sdl: SDLInput): GenerateManifestResult {\n const errors = validateSDL(sdl);\n if (errors) return { ok: false, value: errors };\n\n const endpointSequenceNumbers = computeEndpointSequenceNumbers(sdl.services);\n const groupsMap = new Map<string, {\n dgroup: GroupSpec;\n boundComputes: Record<string, number>;\n teeType?: string;\n }>();\n const resourceIds = new Map<string, number>();\n\n const deploymentsByPlacement = new Map<string, [string, { profile: string; count: number }][]>();\n for (const [svcName, placements] of Object.entries(sdl.deployment)) {\n for (const [placementName, deployment] of Object.entries(placements)) {\n let list = deploymentsByPlacement.get(placementName);\n if (!list) {\n list = [];\n deploymentsByPlacement.set(placementName, list);\n }\n list.push([svcName, deployment]);\n }\n }\n for (const list of deploymentsByPlacement.values()) {\n list.sort(([a], [b]) => a.localeCompare(b));\n }\n\n const services = Object.entries(sdl.services).sort(([a], [b]) => a.localeCompare(b));\n\n for (const [svcName, service] of services) {\n for (const [placementName, svcdepl] of Object.entries(sdl.deployment[svcName])) {\n const compute = sdl.profiles.compute[svcdepl.profile];\n const infra = sdl.profiles.placement[placementName];\n const pricing = infra.pricing[svcdepl.profile];\n const price = {\n denom: pricing.denom,\n amount: pricing.amount?.toString(),\n };\n\n let group = groupsMap.get(placementName);\n\n if (!group) {\n group = {\n dgroup: GroupSpec.fromPartial({\n name: placementName,\n resources: [],\n requirements: PlacementRequirements.fromPartial({\n attributes: buildResourceAttributes(infra.attributes),\n signedBy: SignedBy.fromPartial({\n allOf: infra.signedBy?.allOf,\n anyOf: infra.signedBy?.anyOf,\n }),\n }),\n }),\n boundComputes: {},\n teeType: undefined,\n };\n\n groupsMap.set(placementName, group);\n }\n\n const teeType = service.params?.tee;\n if (teeType && !group.teeType) {\n group.teeType = teeType;\n group.dgroup.requirements!.attributes.push({ key: \"tee/type\", value: teeType });\n group.dgroup.requirements!.attributes.sort((a, b) => a.key.localeCompare(b.key));\n }\n\n const profileKey = `${placementName}:${svcdepl.profile}`;\n const location = group.boundComputes[svcdepl.profile];\n\n if (location === undefined) {\n const resId = group.dgroup.resources.length > 0\n ? group.dgroup.resources.length + 1\n : 1;\n\n resourceIds.set(profileKey, resId);\n\n const resources = buildResources(resId, compute, service, endpointSequenceNumbers);\n\n group.dgroup.resources.push(\n ResourceUnit.fromPartial({\n resource: resources,\n count: svcdepl.count,\n price,\n }),\n );\n\n group.boundComputes[svcdepl.profile] = group.dgroup.resources.length - 1;\n } else {\n if (!resourceIds.has(profileKey)) {\n resourceIds.set(profileKey, group.dgroup.resources[location].resource!.id);\n }\n\n group.dgroup.resources[location].count += svcdepl.count;\n group.dgroup.resources[location].resource!.endpoints.push(\n ...buildServiceEndpoints(service, endpointSequenceNumbers),\n );\n }\n }\n }\n\n for (const group of groupsMap.values()) {\n for (const resourceUnit of group.dgroup.resources) {\n resourceUnit.resource!.endpoints.sort(\n (a, b) => a.kind - b.kind || a.sequenceNumber - b.sequenceNumber,\n );\n }\n }\n\n const sortedGroupNames = [...groupsMap.keys()].sort();\n let groups: Group[] | undefined;\n let groupSpecs: GroupSpec[] | undefined;\n let reclamation: DeploymentReclamation | undefined;\n\n const manifest = {\n // reclamation is a `MsgCreateDeployment` field, not a manifest group, and is\n // not needed in every call \u2014 so it's lazy like `groups`/`groupSpecs`.\n // `validateSDL` (run above) already guaranteed `min_window` is valid, so\n // `minWindowToDuration` never throws here.\n get reclamation() {\n if (sdl.reclamation && !reclamation) {\n reclamation = DeploymentReclamation.fromPartial({\n minWindow: minWindowToDuration(sdl.reclamation.min_window),\n });\n }\n return reclamation;\n },\n get groups() {\n groups ??= sortedGroupNames.map((placementName) => {\n const deployments = deploymentsByPlacement.get(placementName)!;\n\n return Group.fromPartial({\n name: placementName,\n services: deployments.map(([svcName]) => {\n const service = sdl.services[svcName];\n const deployment = sdl.deployment[svcName][placementName];\n const compute = sdl.profiles.compute[deployment.profile];\n const resourceId = resourceIds.get(`${placementName}:${deployment.profile}`) || 1;\n\n return buildManifestService(\n resourceId,\n svcName,\n service,\n compute,\n deployment.count,\n endpointSequenceNumbers,\n );\n }),\n });\n });\n return groups;\n },\n get groupSpecs() {\n groupSpecs ??= sortedGroupNames.map((name) => groupsMap.get(name)!.dgroup);\n return groupSpecs;\n },\n };\n\n return { ok: true, value: manifest };\n}\n\nfunction buildResources(\n id: number,\n compute: SDLCompute,\n service: SDLService,\n endpointSequenceNumbers: Record<string, number>,\n): Resources {\n const res = compute.resources;\n const cpuAttributes = buildResourceAttributes(res.cpu.attributes);\n const gpuAttributes = res.gpu?.attributes ? transformGpuAttributes(res.gpu.attributes) : [];\n\n return Resources.fromPartial({\n id,\n cpu: CPU.fromPartial({\n units: { val: encodeResourceValue(parseCpuUnits(res.cpu)) },\n attributes: cpuAttributes,\n }),\n memory: Memory.fromPartial({\n quantity: { val: encodeResourceValue(parseMemoryBytes(res.memory)) },\n }),\n storage: castArray(res.storage).map((s) =>\n Storage.fromPartial({\n name: s.name || \"default\",\n quantity: { val: encodeResourceValue(parseStorageBytes(s.size)) },\n attributes: buildStorageAttributes(s.attributes),\n }),\n ),\n gpu: GPU.fromPartial({\n units: { val: encodeResourceValue(parseGpuUnits(res.gpu)) },\n attributes: gpuAttributes,\n }),\n endpoints: buildServiceEndpoints(service, endpointSequenceNumbers),\n });\n}\n\nfunction buildManifestService(\n resourceId: number,\n name: string,\n service: SDLService,\n compute: SDLCompute,\n count: number,\n endpointSequenceNumbers: Record<string, number>,\n): Service {\n const credentials = service.credentials\n ? ImageCredentials.fromPartial({\n host: service.credentials.host,\n email: service.credentials.email || \"\",\n username: service.credentials.username,\n password: service.credentials.password,\n })\n : undefined;\n\n const params = buildParams(service);\n\n return Service.fromPartial({\n name,\n image: service.image,\n command: service.command || [],\n args: service.args || [],\n env: service.env || [],\n resources: buildResources(resourceId, compute, service, endpointSequenceNumbers),\n count,\n expose: buildManifestExpose(service, endpointSequenceNumbers),\n params,\n credentials,\n });\n}\n\nfunction buildParams(service: SDLService): ServiceParams | undefined {\n if (!service.params) return undefined;\n\n const storage = service.params.storage || {};\n const storageNames = service.params.storage ? Object.keys(storage).sort() : [];\n const result = ServiceParams.fromPartial({\n storage: storageNames.map((name) => {\n const config = storage[name];\n return StorageParams.fromPartial({\n name,\n mount: config.mount || \"\",\n readOnly: config.readOnly || false,\n });\n }),\n });\n\n // Permissions are not in the protobuf type but need to be preserved\n if (service.params.permissions) {\n (result as unknown as Record<string, unknown>).permissions = service.params.permissions;\n }\n\n // Project TEE onto the manifest, mirroring Go's groupBuilder\n // (params.TEE = {Type, Attestation: true}). `attestation` is hard-coded true\n // (not an input knob); the provider injects the attestation sidecar.\n if (service.params.tee) {\n result.tee = TEEParams.fromPartial({ type: service.params.tee, attestation: true });\n }\n\n return result;\n}\n\nfunction buildManifestExpose(\n service: SDLService,\n endpointSequenceNumbers: Record<string, number>,\n): ServiceExpose[] {\n return (service.expose ?? [])\n .flatMap((expose) =>\n (expose.to ?? []).map((to) =>\n ServiceExpose.fromPartial({\n port: expose.port,\n externalPort: expose.as,\n proto: parseServiceProto(expose.proto),\n service: to.service || \"\",\n global: to.global || false,\n hosts: expose.accept || [],\n httpOptions: buildHttpOptions(expose.http_options),\n ip: to.ip || \"\",\n endpointSequenceNumber: endpointSequenceNumbers[to.ip!],\n }),\n ),\n )\n .sort((a, b) => {\n if (a.service !== b.service) return a.service.localeCompare(b.service);\n if (a.port !== b.port) return a.port - b.port;\n if (a.proto !== b.proto) return a.proto.localeCompare(b.proto);\n if (a.global !== b.global) return a.global ? -1 : 1;\n return 0;\n });\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -33,7 +33,7 @@ module.exports = __toCommonJS(validateSDL_exports);
|
|
|
33
33
|
var import_jsonSchemaValidation = require("../../utils/jsonSchemaValidation.cjs");
|
|
34
34
|
var import_utils = require("../utils.cjs");
|
|
35
35
|
var import_validateSDLInput = require("./validateSDLInput.cjs");
|
|
36
|
-
var _endpointsUsed, _portsUsed, _sdl, _errors, _SDLValidator_instances, validateDeploymentWithRelations_fn, validateDeploymentRelations_fn, validateServiceStorages_fn, validateStorages_fn, validateGPU_fn, validateTEE_fn, validateLeaseIP_fn, validateEndpoints_fn;
|
|
36
|
+
var _endpointsUsed, _portsUsed, _teeTypeByPlacement, _sdl, _errors, _SDLValidator_instances, validateDeploymentWithRelations_fn, validateDeploymentRelations_fn, validateServiceStorages_fn, validateStorages_fn, validateGPU_fn, validateTEE_fn, validateLeaseIP_fn, validateEndpoints_fn;
|
|
37
37
|
const ERROR_MESSAGES = {
|
|
38
38
|
"#/definitions/storageRamClassMustNotBePersistent"(error) {
|
|
39
39
|
return `"ram" storage${(0, import_jsonSchemaValidation.getErrorLocation)((0, import_jsonSchemaValidation.dirname)(error.instancePath))} cannot be persistent`;
|
|
@@ -62,6 +62,7 @@ class SDLValidator {
|
|
|
62
62
|
__privateAdd(this, _SDLValidator_instances);
|
|
63
63
|
__privateAdd(this, _endpointsUsed, /* @__PURE__ */ new Set());
|
|
64
64
|
__privateAdd(this, _portsUsed, /* @__PURE__ */ new Map());
|
|
65
|
+
__privateAdd(this, _teeTypeByPlacement, /* @__PURE__ */ new Map());
|
|
65
66
|
__privateAdd(this, _sdl);
|
|
66
67
|
__privateAdd(this, _errors, []);
|
|
67
68
|
__privateSet(this, _sdl, sdl);
|
|
@@ -79,6 +80,7 @@ class SDLValidator {
|
|
|
79
80
|
}
|
|
80
81
|
_endpointsUsed = new WeakMap();
|
|
81
82
|
_portsUsed = new WeakMap();
|
|
83
|
+
_teeTypeByPlacement = new WeakMap();
|
|
82
84
|
_sdl = new WeakMap();
|
|
83
85
|
_errors = new WeakMap();
|
|
84
86
|
_SDLValidator_instances = new WeakSet();
|
|
@@ -268,25 +270,47 @@ validateGPU_fn = function(serviceName, deploymentName) {
|
|
|
268
270
|
});
|
|
269
271
|
}
|
|
270
272
|
};
|
|
271
|
-
// Mirrors Go `
|
|
272
|
-
//
|
|
273
|
-
//
|
|
274
|
-
//
|
|
273
|
+
// Mirrors Go's TEE rules from `buildGroups` (go/sdl/groupBuilder_v2.go:58-83,
|
|
274
|
+
// groupBuilder_v2_1.go:59-84). Two checks, both on `deploymentName` (the
|
|
275
|
+
// placement-group name):
|
|
276
|
+
// 1. `validateTEEWithGPU` — the `cpu-gpu` type requires GPU resources on the
|
|
277
|
+
// resolved compute profile (`cpu`/absent need none).
|
|
278
|
+
// 2. `errTEETypeMismatch` — a placementg diff group may carry only one tee type,
|
|
279
|
+
// since `generateManifest` projects it as a single `tee/type` requirement
|
|
280
|
+
// attribute. Detecting the conflict here (the validation layer) means
|
|
281
|
+
// standalone `validateSDL` callers catch it, and `generateManifest` can
|
|
282
|
+
// project unconditionally.
|
|
283
|
+
// Unsupported tee values are rejected structurally by the input schema (`tee`
|
|
284
|
+
// enum in validateSDLInput.ts) before this runs.
|
|
275
285
|
validateTEE_fn = function(serviceName, deploymentName) {
|
|
276
286
|
const tee = __privateGet(this, _sdl).services?.[serviceName]?.params?.tee;
|
|
277
|
-
if (tee
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
287
|
+
if (!tee) return;
|
|
288
|
+
if (tee === "cpu-gpu") {
|
|
289
|
+
const profile = __privateGet(this, _sdl).deployment[serviceName]?.[deploymentName]?.profile;
|
|
290
|
+
const gpu = __privateGet(this, _sdl).profiles?.compute?.[profile]?.resources.gpu;
|
|
291
|
+
const hasGpu = gpu?.units !== void 0 && gpu.units !== 0;
|
|
292
|
+
if (!hasGpu) {
|
|
293
|
+
__privateGet(this, _errors).push({
|
|
294
|
+
message: `Service "${serviceName}" tee type requires gpu resources.`,
|
|
295
|
+
instancePath: `/services/${serviceName}/params/tee`,
|
|
296
|
+
schemaPath: "#/properties/services/additionalProperties/properties/params/properties/tee",
|
|
297
|
+
keyword: "required",
|
|
298
|
+
params: {
|
|
299
|
+
missingProperty: "gpu"
|
|
300
|
+
}
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
const existing = __privateGet(this, _teeTypeByPlacement).get(deploymentName);
|
|
305
|
+
if (existing === void 0) {
|
|
306
|
+
__privateGet(this, _teeTypeByPlacement).set(deploymentName, tee);
|
|
307
|
+
} else if (existing !== tee) {
|
|
282
308
|
__privateGet(this, _errors).push({
|
|
283
|
-
message: `
|
|
309
|
+
message: `conflicting tee types in placement group "${deploymentName}": "${existing}" and "${tee}"`,
|
|
284
310
|
instancePath: `/services/${serviceName}/params/tee`,
|
|
285
311
|
schemaPath: "#/properties/services/additionalProperties/properties/params/properties/tee",
|
|
286
|
-
keyword: "
|
|
287
|
-
params: {
|
|
288
|
-
missingProperty: "gpu"
|
|
289
|
-
}
|
|
312
|
+
keyword: "tee",
|
|
313
|
+
params: {}
|
|
290
314
|
});
|
|
291
315
|
}
|
|
292
316
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/sdl/validateSDL/validateSDL.ts"],
|
|
4
|
-
"sourcesContent": ["import type { ErrorMessages, ValidationError, ValidationFunction } from \"../../utils/jsonSchemaValidation.ts\";\nimport { dirname, getErrorLocation, humanizeErrors } from \"../../utils/jsonSchemaValidation.ts\";\nimport { castArray, stringToBoolean } from \"../utils.ts\";\nimport { schema as validationSDLSchema, type SDLInput, validate as validateSDLInput } from \"./validateSDLInput.ts\";\n\nexport { validationSDLSchema };\nexport type { SDLInput };\n\nconst ERROR_MESSAGES: ErrorMessages = {\n \"#/definitions/storageRamClassMustNotBePersistent\"(error) {\n return `\"ram\" storage${getErrorLocation(dirname(error.instancePath))} cannot be persistent`;\n },\n \"#/definitions/exposeToWithIpEnforcesGlobal\"() {\n return `If an IP is declared, the directive must be declared as global.`;\n },\n // Mirrors the shared schema's `min_window` pattern (`^[1-9][0-9]*(s|m|h)$`).\n // Go stays the lenient layer (`go/sdl/reclamation.go` accepts any `> 0`\n // `time.ParseDuration`), so this is a sanctioned schema-only-stricter rule.\n \"#/properties/reclamation/properties/min_window/pattern\"() {\n return `Reclamation min_window must be a whole number followed by s, m, or h (e.g. \"24h\", \"30m\").`;\n },\n};\n\nexport function validateSDL(sdl: SDLInput): undefined | ValidationError[] {\n validateSDLInput(sdl);\n const schemaErrors = humanizeErrors((validateSDLInput as ValidationFunction).errors, validationSDLSchema, ERROR_MESSAGES);\n if (schemaErrors.length) return schemaErrors;\n\n const validator = new SDLValidator(sdl);\n const errors = validator.validate();\n\n const allErrors = schemaErrors.concat(errors);\n return allErrors.length ? allErrors : undefined;\n}\n\nclass SDLValidator {\n readonly #endpointsUsed = new Set<string>();\n readonly #portsUsed = new Map<string, string>();\n readonly #sdl: SDLInput;\n readonly #errors: ValidationError[] = [];\n\n constructor(sdl: SDLInput) {\n this.#sdl = sdl;\n }\n\n validate() {\n if (this.#sdl.services) {\n Object.keys(this.#sdl.services).forEach((serviceName) => {\n this.#validateDeploymentWithRelations(serviceName);\n this.#validateLeaseIP(serviceName);\n });\n }\n\n this.#validateEndpoints();\n return this.#errors;\n }\n\n #validateDeploymentWithRelations(serviceName: string) {\n const deployment = this.#sdl.deployment[serviceName];\n if (!deployment) {\n this.#errors.push({\n message: `Service \"${serviceName}\" is not defined at \"/deployment\" section.`,\n instancePath: `/deployment`,\n schemaPath: \"#/properties/deployment\",\n keyword: \"required\",\n params: {\n missingProperty: serviceName,\n },\n });\n return;\n }\n\n Object.keys(this.#sdl.deployment[serviceName]).forEach((deploymentName) => {\n this.#validateDeploymentRelations(serviceName, deploymentName);\n this.#validateServiceStorages(serviceName, deploymentName);\n this.#validateStorages(serviceName, deploymentName);\n this.#validateGPU(serviceName, deploymentName);\n this.#validateTEE(serviceName, deploymentName);\n });\n }\n\n #validateDeploymentRelations(serviceName: string, deploymentName: string) {\n const serviceDeployment = this.#sdl.deployment?.[serviceName]?.[deploymentName];\n const compute = this.#sdl.profiles?.compute?.[serviceDeployment?.profile];\n const infra = this.#sdl.profiles?.placement?.[deploymentName];\n\n if (!infra) {\n this.#errors.push({\n message: `The placement \"${deploymentName}\" is not defined in the \"placement\" section.`,\n instancePath: `/profiles/placement`,\n schemaPath: \"#/properties/profiles/properties/placement\",\n keyword: \"required\",\n params: {\n missingProperty: deploymentName,\n },\n });\n }\n\n if (infra && !infra.pricing?.[serviceDeployment?.profile]) {\n this.#errors.push({\n message: `The pricing for the \"${serviceDeployment?.profile}\" profile is not defined in the \"${deploymentName}\" placement.`,\n instancePath: `/profiles/placement/${deploymentName}/pricing`,\n schemaPath: \"#/properties/profiles/properties/placement/additionalProperties/properties/pricing\",\n keyword: \"required\",\n params: {\n missingProperty: serviceDeployment?.profile,\n },\n });\n }\n\n if (!compute) {\n this.#errors.push({\n message: `The compute requirements for the \"${serviceDeployment?.profile}\" profile are not defined in the \"compute\" section.`,\n instancePath: `/profiles/compute`,\n schemaPath: \"#/properties/profiles/properties/compute\",\n keyword: \"required\",\n params: {\n missingProperty: serviceDeployment?.profile,\n },\n });\n }\n }\n\n #validateServiceStorages(serviceName: string, deploymentName: string) {\n const service = this.#sdl.services?.[serviceName];\n const mounts: Record<string, string> = {};\n const serviceDeployment = this.#sdl.deployment[serviceName][deploymentName];\n const compute = this.#sdl.profiles?.compute?.[serviceDeployment.profile];\n const storages = castArray(compute?.resources.storage);\n\n if (!service?.params?.storage) {\n return;\n }\n\n Object.entries(service.params.storage).forEach(([storageName, storage]) => {\n if (!storage) {\n this.#errors.push({\n message: `Storage \"${storageName}\" is not configured.`,\n instancePath: `/services/${serviceName}/params/storage/${storageName}`,\n schemaPath: \"#/properties/services/additionalProperties/properties/params/properties/storage/additionalProperties\",\n keyword: \"required\",\n params: {\n missingProperty: storageName,\n },\n });\n return;\n }\n const storageNameExists = storages.some(({ name }) => name === storageName);\n if (!storageNameExists) {\n this.#errors.push({\n message: `Service \"${serviceName}\" references non-existing compute volume \"${storageName}\".`,\n instancePath: `/profiles/compute/${serviceDeployment.profile}/resources/storage`,\n schemaPath: \"#/properties/profiles/properties/compute/additionalProperties/properties/resources/properties/storage\",\n keyword: \"required\",\n params: {\n missingProperty: storageName,\n },\n });\n return;\n }\n\n const mount = String(storage.mount);\n const volumeName = mounts[mount];\n\n if (volumeName && !storage.mount) {\n this.#errors.push({\n message: \"Multiple root ephemeral storages are not allowed.\",\n instancePath: `/services/${serviceName}/params/storage/${storageName}`,\n schemaPath: \"#/properties/services/additionalProperties/properties/params/properties/storage\",\n keyword: \"uniqueItems\",\n params: {\n duplicate: volumeName,\n },\n });\n }\n if (volumeName && storage.mount) {\n this.#errors.push({\n message: `Mount \"${mount}\" already in use by volume \"${volumeName}\".`,\n instancePath: `/services/${serviceName}/params/storage/${storageName}/mount`,\n schemaPath: \"#/properties/services/additionalProperties/properties/params/properties/storage/additionalProperties/properties/mount\",\n keyword: \"uniqueItems\",\n params: {\n duplicate: mount,\n },\n });\n }\n\n mounts[mount] = storageName;\n });\n }\n\n #validateStorages(serviceName: string, deploymentName: string) {\n const service = this.#sdl.services?.[serviceName];\n const serviceDeployment = this.#sdl.deployment[serviceName][deploymentName];\n const compute = this.#sdl.profiles?.compute?.[serviceDeployment.profile];\n const storages = castArray(compute?.resources.storage);\n\n storages.forEach((storage) => {\n const persistent = stringToBoolean(storage.attributes?.persistent as string | boolean || false);\n\n if (persistent && !service?.params?.storage?.[storage.name || \"\"]?.mount) {\n this.#errors.push({\n message: `Persistent storage \"${storage.name || \"default\"}\" requires a mount path in /services/${serviceName}/params/storage/${storage.name || \"default\"}/mount.`,\n instancePath: `/services/${serviceName}/params/storage/${storage.name || \"default\"}`,\n schemaPath: \"#/properties/services/additionalProperties/properties/params/properties/storage/additionalProperties/properties/mount\",\n keyword: \"required\",\n params: {\n missingProperty: \"mount\",\n },\n });\n }\n });\n }\n\n #validateGPU(serviceName: string, deploymentName: string) {\n const deployment = this.#sdl.deployment[serviceName];\n const compute = this.#sdl.profiles?.compute?.[deployment[deploymentName]?.profile];\n const gpu = compute?.resources.gpu;\n if (!gpu) return;\n\n const hasUnits = gpu.units !== undefined && gpu.units !== 0;\n const hasAttributes = typeof gpu.attributes !== \"undefined\";\n const hasVendor = hasAttributes && typeof gpu.attributes?.vendor !== \"undefined\";\n\n const profile = deployment[deploymentName]?.profile;\n const gpuPath = `/profiles/compute/${profile}/resources/gpu`;\n\n if (!hasUnits && hasAttributes) {\n this.#errors.push({\n message: \"GPU must not have attributes if units is 0.\",\n instancePath: `${gpuPath}/attributes`,\n schemaPath: \"#/properties/profiles/properties/compute/additionalProperties/properties/resources/properties/gpu/properties/attributes\",\n keyword: \"additionalProperties\",\n params: {\n additionalProperty: \"attributes\",\n },\n });\n }\n if (hasUnits && !hasAttributes) {\n this.#errors.push({\n message: \"GPU must have attributes if units is not 0.\",\n instancePath: gpuPath,\n schemaPath: \"#/properties/profiles/properties/compute/additionalProperties/properties/resources/properties/gpu\",\n keyword: \"required\",\n params: {\n missingProperty: \"attributes\",\n },\n });\n }\n if (hasUnits && !hasVendor) {\n this.#errors.push({\n message: \"GPU must specify a vendor if units is not 0.\",\n instancePath: `${gpuPath}/attributes`,\n schemaPath: \"#/properties/profiles/properties/compute/additionalProperties/properties/resources/properties/gpu/properties/attributes/properties/vendor\",\n keyword: \"required\",\n params: {\n missingProperty: \"vendor\",\n },\n });\n }\n }\n\n // Mirrors Go `validateTEEWithGPU` (go/sdl/tee.go): the `cpu-gpu` TEE type\n // requires GPU resources on the resolved compute profile. `cpu` (and absent)\n // need no GPU. Unsupported tee values are rejected structurally by the input\n // schema (`tee` enum in validateSDLInput.ts) before this runs.\n #validateTEE(serviceName: string, deploymentName: string) {\n const tee = this.#sdl.services?.[serviceName]?.params?.tee;\n if (tee !== \"cpu-gpu\") return;\n\n const profile = this.#sdl.deployment[serviceName]?.[deploymentName]?.profile;\n const gpu = this.#sdl.profiles?.compute?.[profile]?.resources.gpu;\n const hasGpu = gpu?.units !== undefined && gpu.units !== 0;\n\n if (!hasGpu) {\n this.#errors.push({\n message: `Service \"${serviceName}\" tee type requires gpu resources.`,\n instancePath: `/services/${serviceName}/params/tee`,\n schemaPath: \"#/properties/services/additionalProperties/properties/params/properties/tee\",\n keyword: \"required\",\n params: {\n missingProperty: \"gpu\",\n },\n });\n }\n }\n\n #validateLeaseIP(serviceName: string) {\n this.#sdl.services?.[serviceName]?.expose?.forEach((expose, exposeIndex) => {\n const proto = expose.proto?.toUpperCase() || \"TCP\";\n\n expose.to?.forEach((to, toIndex) => {\n if (to.ip?.length) {\n const toPath = `/services/${serviceName}/expose/${exposeIndex}/to/${toIndex}`;\n\n if (!to.global) {\n this.#errors.push({\n message: `If an IP is declared, the directive must be declared as global.`,\n instancePath: `${toPath}/global`,\n schemaPath: \"#/definitions/exposeToWithIpEnforcesGlobal/then/properties/global/const\",\n keyword: \"const\",\n params: {\n allowedValue: true,\n },\n });\n }\n if (!this.#sdl.endpoints?.[to.ip]) {\n this.#errors.push({\n message: `Unknown endpoint \"${to.ip}\" for service \"${serviceName}\". Add it to the \"endpoints\" section.`,\n instancePath: `/endpoints/${to.ip}`,\n schemaPath: \"#/properties/endpoints\",\n keyword: \"required\",\n params: {\n missingProperty: to.ip,\n },\n });\n }\n\n this.#endpointsUsed.add(to.ip);\n\n const externalPort = expose.as ?? expose.port;\n const portKey = `${to.ip}-${externalPort}-${proto}`;\n const otherServiceName = this.#portsUsed.get(portKey);\n\n if (this.#portsUsed.has(portKey)) {\n this.#errors.push({\n message: `IP endpoint \"${to.ip}\" port ${externalPort} protocol ${proto} already in use by service \"${otherServiceName}\".`,\n instancePath: `${toPath}/ip`,\n schemaPath: \"#/properties/services/additionalProperties/properties/expose/items/properties/to/items\",\n keyword: \"uniqueItems\",\n params: {\n duplicate: portKey,\n },\n });\n }\n this.#portsUsed.set(portKey, serviceName);\n }\n });\n });\n }\n\n #validateEndpoints() {\n if (!this.#sdl.endpoints) return;\n\n Object.keys(this.#sdl.endpoints).forEach((endpoint) => {\n if (!this.#endpointsUsed.has(endpoint)) {\n this.#errors.push({\n message: `Endpoint \"${endpoint}\" declared but never used.`,\n instancePath: `/endpoints/${endpoint}`,\n schemaPath: \"#/properties/endpoints\",\n keyword: \"additionalProperties\",\n params: {\n additionalProperty: endpoint,\n },\n });\n }\n });\n }\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA,qDAAAA;AAAA;AAAA;AACA,kCAA0D;AAC1D,mBAA2C;AAC3C,8BAA2F;AAH3F;AAQA,MAAM,iBAAgC;AAAA,EACpC,mDAAmD,OAAO;AACxD,WAAO,oBAAgB,kDAAiB,qCAAQ,MAAM,YAAY,CAAC,CAAC;AAAA,EACtE;AAAA,EACA,+CAA+C;AAC7C,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAIA,2DAA2D;AACzD,WAAO;AAAA,EACT;AACF;AAEO,SAAS,YAAY,KAA8C;AACxE,8BAAAC,UAAiB,GAAG;AACpB,QAAM,mBAAe,4CAAgB,wBAAAA,SAAwC,QAAQ,wBAAAC,QAAqB,cAAc;AACxH,MAAI,aAAa,OAAQ,QAAO;AAEhC,QAAM,YAAY,IAAI,aAAa,GAAG;AACtC,QAAM,SAAS,UAAU,SAAS;AAElC,QAAM,YAAY,aAAa,OAAO,MAAM;AAC5C,SAAO,UAAU,SAAS,YAAY;AACxC;AAEA,MAAM,aAAa;AAAA,
|
|
4
|
+
"sourcesContent": ["import type { ErrorMessages, ValidationError, ValidationFunction } from \"../../utils/jsonSchemaValidation.ts\";\nimport { dirname, getErrorLocation, humanizeErrors } from \"../../utils/jsonSchemaValidation.ts\";\nimport { castArray, stringToBoolean } from \"../utils.ts\";\nimport { schema as validationSDLSchema, type SDLInput, validate as validateSDLInput } from \"./validateSDLInput.ts\";\n\nexport { validationSDLSchema };\nexport type { SDLInput };\n\nconst ERROR_MESSAGES: ErrorMessages = {\n \"#/definitions/storageRamClassMustNotBePersistent\"(error) {\n return `\"ram\" storage${getErrorLocation(dirname(error.instancePath))} cannot be persistent`;\n },\n \"#/definitions/exposeToWithIpEnforcesGlobal\"() {\n return `If an IP is declared, the directive must be declared as global.`;\n },\n // Mirrors the shared schema's `min_window` pattern (`^[1-9][0-9]*(s|m|h)$`).\n // Go stays the lenient layer (`go/sdl/reclamation.go` accepts any `> 0`\n // `time.ParseDuration`), so this is a sanctioned schema-only-stricter rule.\n \"#/properties/reclamation/properties/min_window/pattern\"() {\n return `Reclamation min_window must be a whole number followed by s, m, or h (e.g. \"24h\", \"30m\").`;\n },\n};\n\nexport function validateSDL(sdl: SDLInput): undefined | ValidationError[] {\n validateSDLInput(sdl);\n const schemaErrors = humanizeErrors((validateSDLInput as ValidationFunction).errors, validationSDLSchema, ERROR_MESSAGES);\n if (schemaErrors.length) return schemaErrors;\n\n const validator = new SDLValidator(sdl);\n const errors = validator.validate();\n\n const allErrors = schemaErrors.concat(errors);\n return allErrors.length ? allErrors : undefined;\n}\n\nclass SDLValidator {\n readonly #endpointsUsed = new Set<string>();\n readonly #portsUsed = new Map<string, string>();\n readonly #teeTypeByPlacement = new Map<string, string>();\n readonly #sdl: SDLInput;\n readonly #errors: ValidationError[] = [];\n\n constructor(sdl: SDLInput) {\n this.#sdl = sdl;\n }\n\n validate() {\n if (this.#sdl.services) {\n Object.keys(this.#sdl.services).forEach((serviceName) => {\n this.#validateDeploymentWithRelations(serviceName);\n this.#validateLeaseIP(serviceName);\n });\n }\n\n this.#validateEndpoints();\n return this.#errors;\n }\n\n #validateDeploymentWithRelations(serviceName: string) {\n const deployment = this.#sdl.deployment[serviceName];\n if (!deployment) {\n this.#errors.push({\n message: `Service \"${serviceName}\" is not defined at \"/deployment\" section.`,\n instancePath: `/deployment`,\n schemaPath: \"#/properties/deployment\",\n keyword: \"required\",\n params: {\n missingProperty: serviceName,\n },\n });\n return;\n }\n\n Object.keys(this.#sdl.deployment[serviceName]).forEach((deploymentName) => {\n this.#validateDeploymentRelations(serviceName, deploymentName);\n this.#validateServiceStorages(serviceName, deploymentName);\n this.#validateStorages(serviceName, deploymentName);\n this.#validateGPU(serviceName, deploymentName);\n this.#validateTEE(serviceName, deploymentName);\n });\n }\n\n #validateDeploymentRelations(serviceName: string, deploymentName: string) {\n const serviceDeployment = this.#sdl.deployment?.[serviceName]?.[deploymentName];\n const compute = this.#sdl.profiles?.compute?.[serviceDeployment?.profile];\n const infra = this.#sdl.profiles?.placement?.[deploymentName];\n\n if (!infra) {\n this.#errors.push({\n message: `The placement \"${deploymentName}\" is not defined in the \"placement\" section.`,\n instancePath: `/profiles/placement`,\n schemaPath: \"#/properties/profiles/properties/placement\",\n keyword: \"required\",\n params: {\n missingProperty: deploymentName,\n },\n });\n }\n\n if (infra && !infra.pricing?.[serviceDeployment?.profile]) {\n this.#errors.push({\n message: `The pricing for the \"${serviceDeployment?.profile}\" profile is not defined in the \"${deploymentName}\" placement.`,\n instancePath: `/profiles/placement/${deploymentName}/pricing`,\n schemaPath: \"#/properties/profiles/properties/placement/additionalProperties/properties/pricing\",\n keyword: \"required\",\n params: {\n missingProperty: serviceDeployment?.profile,\n },\n });\n }\n\n if (!compute) {\n this.#errors.push({\n message: `The compute requirements for the \"${serviceDeployment?.profile}\" profile are not defined in the \"compute\" section.`,\n instancePath: `/profiles/compute`,\n schemaPath: \"#/properties/profiles/properties/compute\",\n keyword: \"required\",\n params: {\n missingProperty: serviceDeployment?.profile,\n },\n });\n }\n }\n\n #validateServiceStorages(serviceName: string, deploymentName: string) {\n const service = this.#sdl.services?.[serviceName];\n const mounts: Record<string, string> = {};\n const serviceDeployment = this.#sdl.deployment[serviceName][deploymentName];\n const compute = this.#sdl.profiles?.compute?.[serviceDeployment.profile];\n const storages = castArray(compute?.resources.storage);\n\n if (!service?.params?.storage) {\n return;\n }\n\n Object.entries(service.params.storage).forEach(([storageName, storage]) => {\n if (!storage) {\n this.#errors.push({\n message: `Storage \"${storageName}\" is not configured.`,\n instancePath: `/services/${serviceName}/params/storage/${storageName}`,\n schemaPath: \"#/properties/services/additionalProperties/properties/params/properties/storage/additionalProperties\",\n keyword: \"required\",\n params: {\n missingProperty: storageName,\n },\n });\n return;\n }\n const storageNameExists = storages.some(({ name }) => name === storageName);\n if (!storageNameExists) {\n this.#errors.push({\n message: `Service \"${serviceName}\" references non-existing compute volume \"${storageName}\".`,\n instancePath: `/profiles/compute/${serviceDeployment.profile}/resources/storage`,\n schemaPath: \"#/properties/profiles/properties/compute/additionalProperties/properties/resources/properties/storage\",\n keyword: \"required\",\n params: {\n missingProperty: storageName,\n },\n });\n return;\n }\n\n const mount = String(storage.mount);\n const volumeName = mounts[mount];\n\n if (volumeName && !storage.mount) {\n this.#errors.push({\n message: \"Multiple root ephemeral storages are not allowed.\",\n instancePath: `/services/${serviceName}/params/storage/${storageName}`,\n schemaPath: \"#/properties/services/additionalProperties/properties/params/properties/storage\",\n keyword: \"uniqueItems\",\n params: {\n duplicate: volumeName,\n },\n });\n }\n if (volumeName && storage.mount) {\n this.#errors.push({\n message: `Mount \"${mount}\" already in use by volume \"${volumeName}\".`,\n instancePath: `/services/${serviceName}/params/storage/${storageName}/mount`,\n schemaPath: \"#/properties/services/additionalProperties/properties/params/properties/storage/additionalProperties/properties/mount\",\n keyword: \"uniqueItems\",\n params: {\n duplicate: mount,\n },\n });\n }\n\n mounts[mount] = storageName;\n });\n }\n\n #validateStorages(serviceName: string, deploymentName: string) {\n const service = this.#sdl.services?.[serviceName];\n const serviceDeployment = this.#sdl.deployment[serviceName][deploymentName];\n const compute = this.#sdl.profiles?.compute?.[serviceDeployment.profile];\n const storages = castArray(compute?.resources.storage);\n\n storages.forEach((storage) => {\n const persistent = stringToBoolean(storage.attributes?.persistent as string | boolean || false);\n\n if (persistent && !service?.params?.storage?.[storage.name || \"\"]?.mount) {\n this.#errors.push({\n message: `Persistent storage \"${storage.name || \"default\"}\" requires a mount path in /services/${serviceName}/params/storage/${storage.name || \"default\"}/mount.`,\n instancePath: `/services/${serviceName}/params/storage/${storage.name || \"default\"}`,\n schemaPath: \"#/properties/services/additionalProperties/properties/params/properties/storage/additionalProperties/properties/mount\",\n keyword: \"required\",\n params: {\n missingProperty: \"mount\",\n },\n });\n }\n });\n }\n\n #validateGPU(serviceName: string, deploymentName: string) {\n const deployment = this.#sdl.deployment[serviceName];\n const compute = this.#sdl.profiles?.compute?.[deployment[deploymentName]?.profile];\n const gpu = compute?.resources.gpu;\n if (!gpu) return;\n\n const hasUnits = gpu.units !== undefined && gpu.units !== 0;\n const hasAttributes = typeof gpu.attributes !== \"undefined\";\n const hasVendor = hasAttributes && typeof gpu.attributes?.vendor !== \"undefined\";\n\n const profile = deployment[deploymentName]?.profile;\n const gpuPath = `/profiles/compute/${profile}/resources/gpu`;\n\n if (!hasUnits && hasAttributes) {\n this.#errors.push({\n message: \"GPU must not have attributes if units is 0.\",\n instancePath: `${gpuPath}/attributes`,\n schemaPath: \"#/properties/profiles/properties/compute/additionalProperties/properties/resources/properties/gpu/properties/attributes\",\n keyword: \"additionalProperties\",\n params: {\n additionalProperty: \"attributes\",\n },\n });\n }\n if (hasUnits && !hasAttributes) {\n this.#errors.push({\n message: \"GPU must have attributes if units is not 0.\",\n instancePath: gpuPath,\n schemaPath: \"#/properties/profiles/properties/compute/additionalProperties/properties/resources/properties/gpu\",\n keyword: \"required\",\n params: {\n missingProperty: \"attributes\",\n },\n });\n }\n if (hasUnits && !hasVendor) {\n this.#errors.push({\n message: \"GPU must specify a vendor if units is not 0.\",\n instancePath: `${gpuPath}/attributes`,\n schemaPath: \"#/properties/profiles/properties/compute/additionalProperties/properties/resources/properties/gpu/properties/attributes/properties/vendor\",\n keyword: \"required\",\n params: {\n missingProperty: \"vendor\",\n },\n });\n }\n }\n\n // Mirrors Go's TEE rules from `buildGroups` (go/sdl/groupBuilder_v2.go:58-83,\n // groupBuilder_v2_1.go:59-84). Two checks, both on `deploymentName` (the\n // placement-group name):\n // 1. `validateTEEWithGPU` \u2014 the `cpu-gpu` type requires GPU resources on the\n // resolved compute profile (`cpu`/absent need none).\n // 2. `errTEETypeMismatch` \u2014 a placementg diff group may carry only one tee type,\n // since `generateManifest` projects it as a single `tee/type` requirement\n // attribute. Detecting the conflict here (the validation layer) means\n // standalone `validateSDL` callers catch it, and `generateManifest` can\n // project unconditionally.\n // Unsupported tee values are rejected structurally by the input schema (`tee`\n // enum in validateSDLInput.ts) before this runs.\n #validateTEE(serviceName: string, deploymentName: string) {\n const tee = this.#sdl.services?.[serviceName]?.params?.tee;\n if (!tee) return;\n\n if (tee === \"cpu-gpu\") {\n const profile = this.#sdl.deployment[serviceName]?.[deploymentName]?.profile;\n const gpu = this.#sdl.profiles?.compute?.[profile]?.resources.gpu;\n const hasGpu = gpu?.units !== undefined && gpu.units !== 0;\n\n if (!hasGpu) {\n this.#errors.push({\n message: `Service \"${serviceName}\" tee type requires gpu resources.`,\n instancePath: `/services/${serviceName}/params/tee`,\n schemaPath: \"#/properties/services/additionalProperties/properties/params/properties/tee\",\n keyword: \"required\",\n params: {\n missingProperty: \"gpu\",\n },\n });\n }\n }\n\n const existing = this.#teeTypeByPlacement.get(deploymentName);\n if (existing === undefined) {\n this.#teeTypeByPlacement.set(deploymentName, tee);\n } else if (existing !== tee) {\n this.#errors.push({\n message: `conflicting tee types in placement group \"${deploymentName}\": \"${existing}\" and \"${tee}\"`,\n instancePath: `/services/${serviceName}/params/tee`,\n schemaPath: \"#/properties/services/additionalProperties/properties/params/properties/tee\",\n keyword: \"tee\",\n params: {},\n });\n }\n }\n\n #validateLeaseIP(serviceName: string) {\n this.#sdl.services?.[serviceName]?.expose?.forEach((expose, exposeIndex) => {\n const proto = expose.proto?.toUpperCase() || \"TCP\";\n\n expose.to?.forEach((to, toIndex) => {\n if (to.ip?.length) {\n const toPath = `/services/${serviceName}/expose/${exposeIndex}/to/${toIndex}`;\n\n if (!to.global) {\n this.#errors.push({\n message: `If an IP is declared, the directive must be declared as global.`,\n instancePath: `${toPath}/global`,\n schemaPath: \"#/definitions/exposeToWithIpEnforcesGlobal/then/properties/global/const\",\n keyword: \"const\",\n params: {\n allowedValue: true,\n },\n });\n }\n if (!this.#sdl.endpoints?.[to.ip]) {\n this.#errors.push({\n message: `Unknown endpoint \"${to.ip}\" for service \"${serviceName}\". Add it to the \"endpoints\" section.`,\n instancePath: `/endpoints/${to.ip}`,\n schemaPath: \"#/properties/endpoints\",\n keyword: \"required\",\n params: {\n missingProperty: to.ip,\n },\n });\n }\n\n this.#endpointsUsed.add(to.ip);\n\n const externalPort = expose.as ?? expose.port;\n const portKey = `${to.ip}-${externalPort}-${proto}`;\n const otherServiceName = this.#portsUsed.get(portKey);\n\n if (this.#portsUsed.has(portKey)) {\n this.#errors.push({\n message: `IP endpoint \"${to.ip}\" port ${externalPort} protocol ${proto} already in use by service \"${otherServiceName}\".`,\n instancePath: `${toPath}/ip`,\n schemaPath: \"#/properties/services/additionalProperties/properties/expose/items/properties/to/items\",\n keyword: \"uniqueItems\",\n params: {\n duplicate: portKey,\n },\n });\n }\n this.#portsUsed.set(portKey, serviceName);\n }\n });\n });\n }\n\n #validateEndpoints() {\n if (!this.#sdl.endpoints) return;\n\n Object.keys(this.#sdl.endpoints).forEach((endpoint) => {\n if (!this.#endpointsUsed.has(endpoint)) {\n this.#errors.push({\n message: `Endpoint \"${endpoint}\" declared but never used.`,\n instancePath: `/endpoints/${endpoint}`,\n schemaPath: \"#/properties/endpoints\",\n keyword: \"additionalProperties\",\n params: {\n additionalProperty: endpoint,\n },\n });\n }\n });\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["validationSDLSchema", "validateSDLInput", "validationSDLSchema"]
|
|
7
7
|
}
|
|
@@ -3658,12 +3658,13 @@ function validateSDL(sdl) {
|
|
|
3658
3658
|
const allErrors = schemaErrors.concat(errors);
|
|
3659
3659
|
return allErrors.length ? allErrors : void 0;
|
|
3660
3660
|
}
|
|
3661
|
-
var _endpointsUsed, _portsUsed, _sdl, _errors, _SDLValidator_instances, validateDeploymentWithRelations_fn, validateDeploymentRelations_fn, validateServiceStorages_fn, validateStorages_fn, validateGPU_fn, validateTEE_fn, validateLeaseIP_fn, validateEndpoints_fn;
|
|
3661
|
+
var _endpointsUsed, _portsUsed, _teeTypeByPlacement, _sdl, _errors, _SDLValidator_instances, validateDeploymentWithRelations_fn, validateDeploymentRelations_fn, validateServiceStorages_fn, validateStorages_fn, validateGPU_fn, validateTEE_fn, validateLeaseIP_fn, validateEndpoints_fn;
|
|
3662
3662
|
var SDLValidator = class {
|
|
3663
3663
|
constructor(sdl) {
|
|
3664
3664
|
__privateAdd(this, _SDLValidator_instances);
|
|
3665
3665
|
__privateAdd(this, _endpointsUsed, /* @__PURE__ */ new Set());
|
|
3666
3666
|
__privateAdd(this, _portsUsed, /* @__PURE__ */ new Map());
|
|
3667
|
+
__privateAdd(this, _teeTypeByPlacement, /* @__PURE__ */ new Map());
|
|
3667
3668
|
__privateAdd(this, _sdl);
|
|
3668
3669
|
__privateAdd(this, _errors, []);
|
|
3669
3670
|
__privateSet(this, _sdl, sdl);
|
|
@@ -3681,6 +3682,7 @@ var SDLValidator = class {
|
|
|
3681
3682
|
};
|
|
3682
3683
|
_endpointsUsed = new WeakMap();
|
|
3683
3684
|
_portsUsed = new WeakMap();
|
|
3685
|
+
_teeTypeByPlacement = new WeakMap();
|
|
3684
3686
|
_sdl = new WeakMap();
|
|
3685
3687
|
_errors = new WeakMap();
|
|
3686
3688
|
_SDLValidator_instances = new WeakSet();
|
|
@@ -3870,25 +3872,47 @@ validateGPU_fn = function(serviceName, deploymentName) {
|
|
|
3870
3872
|
});
|
|
3871
3873
|
}
|
|
3872
3874
|
};
|
|
3873
|
-
// Mirrors Go `
|
|
3874
|
-
//
|
|
3875
|
-
//
|
|
3876
|
-
//
|
|
3875
|
+
// Mirrors Go's TEE rules from `buildGroups` (go/sdl/groupBuilder_v2.go:58-83,
|
|
3876
|
+
// groupBuilder_v2_1.go:59-84). Two checks, both on `deploymentName` (the
|
|
3877
|
+
// placement-group name):
|
|
3878
|
+
// 1. `validateTEEWithGPU` — the `cpu-gpu` type requires GPU resources on the
|
|
3879
|
+
// resolved compute profile (`cpu`/absent need none).
|
|
3880
|
+
// 2. `errTEETypeMismatch` — a placementg diff group may carry only one tee type,
|
|
3881
|
+
// since `generateManifest` projects it as a single `tee/type` requirement
|
|
3882
|
+
// attribute. Detecting the conflict here (the validation layer) means
|
|
3883
|
+
// standalone `validateSDL` callers catch it, and `generateManifest` can
|
|
3884
|
+
// project unconditionally.
|
|
3885
|
+
// Unsupported tee values are rejected structurally by the input schema (`tee`
|
|
3886
|
+
// enum in validateSDLInput.ts) before this runs.
|
|
3877
3887
|
validateTEE_fn = function(serviceName, deploymentName) {
|
|
3878
3888
|
const tee = __privateGet(this, _sdl).services?.[serviceName]?.params?.tee;
|
|
3879
|
-
if (tee
|
|
3880
|
-
|
|
3881
|
-
|
|
3882
|
-
|
|
3883
|
-
|
|
3889
|
+
if (!tee) return;
|
|
3890
|
+
if (tee === "cpu-gpu") {
|
|
3891
|
+
const profile = __privateGet(this, _sdl).deployment[serviceName]?.[deploymentName]?.profile;
|
|
3892
|
+
const gpu = __privateGet(this, _sdl).profiles?.compute?.[profile]?.resources.gpu;
|
|
3893
|
+
const hasGpu = gpu?.units !== void 0 && gpu.units !== 0;
|
|
3894
|
+
if (!hasGpu) {
|
|
3895
|
+
__privateGet(this, _errors).push({
|
|
3896
|
+
message: `Service "${serviceName}" tee type requires gpu resources.`,
|
|
3897
|
+
instancePath: `/services/${serviceName}/params/tee`,
|
|
3898
|
+
schemaPath: "#/properties/services/additionalProperties/properties/params/properties/tee",
|
|
3899
|
+
keyword: "required",
|
|
3900
|
+
params: {
|
|
3901
|
+
missingProperty: "gpu"
|
|
3902
|
+
}
|
|
3903
|
+
});
|
|
3904
|
+
}
|
|
3905
|
+
}
|
|
3906
|
+
const existing = __privateGet(this, _teeTypeByPlacement).get(deploymentName);
|
|
3907
|
+
if (existing === void 0) {
|
|
3908
|
+
__privateGet(this, _teeTypeByPlacement).set(deploymentName, tee);
|
|
3909
|
+
} else if (existing !== tee) {
|
|
3884
3910
|
__privateGet(this, _errors).push({
|
|
3885
|
-
message: `
|
|
3911
|
+
message: `conflicting tee types in placement group "${deploymentName}": "${existing}" and "${tee}"`,
|
|
3886
3912
|
instancePath: `/services/${serviceName}/params/tee`,
|
|
3887
3913
|
schemaPath: "#/properties/services/additionalProperties/properties/params/properties/tee",
|
|
3888
|
-
keyword: "
|
|
3889
|
-
params: {
|
|
3890
|
-
missingProperty: "gpu"
|
|
3891
|
-
}
|
|
3914
|
+
keyword: "tee",
|
|
3915
|
+
params: {}
|
|
3892
3916
|
});
|
|
3893
3917
|
}
|
|
3894
3918
|
};
|
|
@@ -4156,10 +4180,17 @@ function generateManifest(sdl) {
|
|
|
4156
4180
|
})
|
|
4157
4181
|
})
|
|
4158
4182
|
}),
|
|
4159
|
-
boundComputes: {}
|
|
4183
|
+
boundComputes: {},
|
|
4184
|
+
teeType: void 0
|
|
4160
4185
|
};
|
|
4161
4186
|
groupsMap.set(placementName, group);
|
|
4162
4187
|
}
|
|
4188
|
+
const teeType = service.params?.tee;
|
|
4189
|
+
if (teeType && !group.teeType) {
|
|
4190
|
+
group.teeType = teeType;
|
|
4191
|
+
group.dgroup.requirements.attributes.push({ key: "tee/type", value: teeType });
|
|
4192
|
+
group.dgroup.requirements.attributes.sort((a, b) => a.key.localeCompare(b.key));
|
|
4193
|
+
}
|
|
4163
4194
|
const profileKey = `${placementName}:${svcdepl.profile}`;
|
|
4164
4195
|
const location = group.boundComputes[svcdepl.profile];
|
|
4165
4196
|
if (location === void 0) {
|
|
@@ -6175,7 +6206,7 @@ var JwtTokenManager = class {
|
|
|
6175
6206
|
};
|
|
6176
6207
|
|
|
6177
6208
|
// src/sdk/client/sdkMetadata.ts
|
|
6178
|
-
var SDK_METHOD_METADATA = /* @__PURE__ */ new
|
|
6209
|
+
var SDK_METHOD_METADATA = /* @__PURE__ */ new WeakMap();
|
|
6179
6210
|
function withMetadata(fn, metadata) {
|
|
6180
6211
|
SDK_METHOD_METADATA.set(fn, metadata);
|
|
6181
6212
|
return fn;
|
|
@@ -9170,4 +9201,4 @@ export {
|
|
|
9170
9201
|
isRetryEnabled,
|
|
9171
9202
|
createTxTransport
|
|
9172
9203
|
};
|
|
9173
|
-
//# sourceMappingURL=chunk-
|
|
9204
|
+
//# sourceMappingURL=chunk-JY5F3I26.js.map
|