@norskvideo/ctl-product-template-schema 0.1.53 → 0.1.55
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/index.d.ts +34 -0
- package/index.js +45 -0
- package/pack.js +3 -0
- package/package.json +1 -1
package/index.d.ts
CHANGED
|
@@ -4,6 +4,11 @@ export declare const ProductTemplateTargetSchema: z.ZodEnum<{
|
|
|
4
4
|
}>;
|
|
5
5
|
export type ProductTemplateTarget = z.infer<typeof ProductTemplateTargetSchema>;
|
|
6
6
|
export declare const RESERVED_INSTANCE_ROUTE_SEGMENTS: readonly ["studio", "media", "visualiser", "uvis", "status", "metrics"];
|
|
7
|
+
/** How a template's runtimes appear on fleet dashboards (RFC 0006 §4.1). */
|
|
8
|
+
export declare const ProductTemplateDashboardSchema: z.ZodObject<{
|
|
9
|
+
kind: z.ZodString;
|
|
10
|
+
previews: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
11
|
+
}, z.core.$strip>;
|
|
7
12
|
export declare const PRODUCT_TEMPLATE_ADVANCED_NETWORK_MODES: readonly ["docker", "hybrid"];
|
|
8
13
|
export declare const ProductTemplateAdvancedSchema: z.ZodObject<{
|
|
9
14
|
networkMode: z.ZodOptional<z.ZodObject<{
|
|
@@ -36,6 +41,9 @@ export declare const ProductTemplateAdvancedSchema: z.ZodObject<{
|
|
|
36
41
|
openFileLimit: z.ZodOptional<z.ZodObject<{
|
|
37
42
|
default: z.ZodOptional<z.ZodNumber>;
|
|
38
43
|
}, z.core.$strip>>;
|
|
44
|
+
memoryLimit: z.ZodOptional<z.ZodObject<{
|
|
45
|
+
default: z.ZodOptional<z.ZodString>;
|
|
46
|
+
}, z.core.$strip>>;
|
|
39
47
|
}, z.core.$strip>;
|
|
40
48
|
export declare const ProductTemplateAllocatedPortSchema: z.ZodObject<{
|
|
41
49
|
param: z.ZodString;
|
|
@@ -197,6 +205,14 @@ export declare const ProductTemplateManifestSchema: z.ZodObject<{
|
|
|
197
205
|
websocket: z.ZodOptional<z.ZodBoolean>;
|
|
198
206
|
auth: z.ZodOptional<z.ZodBoolean>;
|
|
199
207
|
}, z.core.$strip>>>;
|
|
208
|
+
operations: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
209
|
+
path: z.ZodString;
|
|
210
|
+
openapi: z.ZodString;
|
|
211
|
+
}, z.core.$strip>>>;
|
|
212
|
+
}, z.core.$strip>>;
|
|
213
|
+
dashboard: z.ZodOptional<z.ZodObject<{
|
|
214
|
+
kind: z.ZodString;
|
|
215
|
+
previews: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
200
216
|
}, z.core.$strip>>;
|
|
201
217
|
allowWorkflowUploads: z.ZodOptional<z.ZodBoolean>;
|
|
202
218
|
isStudio: z.ZodOptional<z.ZodBoolean>;
|
|
@@ -240,6 +256,9 @@ export declare const ProductTemplateManifestSchema: z.ZodObject<{
|
|
|
240
256
|
openFileLimit: z.ZodOptional<z.ZodObject<{
|
|
241
257
|
default: z.ZodOptional<z.ZodNumber>;
|
|
242
258
|
}, z.core.$strip>>;
|
|
259
|
+
memoryLimit: z.ZodOptional<z.ZodObject<{
|
|
260
|
+
default: z.ZodOptional<z.ZodString>;
|
|
261
|
+
}, z.core.$strip>>;
|
|
243
262
|
}, z.core.$strip>>;
|
|
244
263
|
requirements: z.ZodOptional<z.ZodObject<{
|
|
245
264
|
capacity: z.ZodOptional<z.ZodObject<{
|
|
@@ -458,6 +477,14 @@ export declare const ProductTemplateMaterialsSchema: z.ZodObject<{
|
|
|
458
477
|
websocket: z.ZodOptional<z.ZodBoolean>;
|
|
459
478
|
auth: z.ZodOptional<z.ZodBoolean>;
|
|
460
479
|
}, z.core.$strip>>>;
|
|
480
|
+
operations: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
481
|
+
path: z.ZodString;
|
|
482
|
+
openapi: z.ZodString;
|
|
483
|
+
}, z.core.$strip>>>;
|
|
484
|
+
}, z.core.$strip>>;
|
|
485
|
+
dashboard: z.ZodOptional<z.ZodObject<{
|
|
486
|
+
kind: z.ZodString;
|
|
487
|
+
previews: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
461
488
|
}, z.core.$strip>>;
|
|
462
489
|
allowWorkflowUploads: z.ZodOptional<z.ZodBoolean>;
|
|
463
490
|
isStudio: z.ZodOptional<z.ZodBoolean>;
|
|
@@ -501,6 +528,9 @@ export declare const ProductTemplateMaterialsSchema: z.ZodObject<{
|
|
|
501
528
|
openFileLimit: z.ZodOptional<z.ZodObject<{
|
|
502
529
|
default: z.ZodOptional<z.ZodNumber>;
|
|
503
530
|
}, z.core.$strip>>;
|
|
531
|
+
memoryLimit: z.ZodOptional<z.ZodObject<{
|
|
532
|
+
default: z.ZodOptional<z.ZodString>;
|
|
533
|
+
}, z.core.$strip>>;
|
|
504
534
|
}, z.core.$strip>>;
|
|
505
535
|
requirements: z.ZodOptional<z.ZodObject<{
|
|
506
536
|
capacity: z.ZodOptional<z.ZodObject<{
|
|
@@ -665,6 +695,10 @@ export declare const ProductTemplateMaterialsSchema: z.ZodObject<{
|
|
|
665
695
|
path: z.ZodString;
|
|
666
696
|
content: z.ZodUnion<readonly [z.ZodString, z.ZodCustom<Uint8Array<ArrayBuffer>, Uint8Array<ArrayBuffer>>]>;
|
|
667
697
|
}, z.core.$strip>>>;
|
|
698
|
+
openapi: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
699
|
+
path: z.ZodString;
|
|
700
|
+
content: z.ZodUnion<readonly [z.ZodString, z.ZodCustom<Uint8Array<ArrayBuffer>, Uint8Array<ArrayBuffer>>]>;
|
|
701
|
+
}, z.core.$strip>>>;
|
|
668
702
|
workdirSeed: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
669
703
|
path: z.ZodString;
|
|
670
704
|
content: z.ZodUnion<readonly [z.ZodString, z.ZodCustom<Uint8Array<ArrayBuffer>, Uint8Array<ArrayBuffer>>]>;
|
package/index.js
CHANGED
|
@@ -87,6 +87,36 @@ const ProductTemplateRouteSchema = z.object({
|
|
|
87
87
|
description: "Whether the route sits behind the runner's oauth2 auth_request. Omit for the default `true`. Set false only for a surface that must be reachable unauthenticated, as the media route is.",
|
|
88
88
|
}),
|
|
89
89
|
});
|
|
90
|
+
// The operations a template serves, each described by an OpenAPI document it
|
|
91
|
+
// carries under openapi/ (RFC 0006 §4.1, norsk-ctl task 123). Keyed by the
|
|
92
|
+
// instance path the document describes, so it covers the runtime-screen
|
|
93
|
+
// catch-all as well as declared routes. An operation is reachable from a
|
|
94
|
+
// dashboard only when marked `x-norsk-dashboard: true`, and needs the
|
|
95
|
+
// platform rung its `x-norsk-role` names on the runtime.
|
|
96
|
+
const SAFE_SEGMENTS = (value) => !value.split("/").some((s) => s === ".." || s === ".");
|
|
97
|
+
const ProductTemplateOperationsSchema = z.object({
|
|
98
|
+
path: z
|
|
99
|
+
.string()
|
|
100
|
+
.regex(/^\/[A-Za-z0-9._~-]+(\/[A-Za-z0-9._~-]+)*$/, "an absolute path under the instance, no trailing slash")
|
|
101
|
+
.refine(SAFE_SEGMENTS, { message: "no . or .. segments" })
|
|
102
|
+
.meta({
|
|
103
|
+
description: "The path under /instance/<id>/ the document's paths are relative to, e.g. /live/api/probe-api.",
|
|
104
|
+
}),
|
|
105
|
+
openapi: z
|
|
106
|
+
.string()
|
|
107
|
+
.regex(/^openapi\/[A-Za-z0-9._-]+(\/[A-Za-z0-9._-]+)*\.(ya?ml|json)$/, "a YAML or JSON file under openapi/")
|
|
108
|
+
.refine(SAFE_SEGMENTS, { message: "no . or .. segments" })
|
|
109
|
+
.meta({ description: "The OpenAPI 3 document in the template tar, e.g. openapi/probe-api.yaml." }),
|
|
110
|
+
});
|
|
111
|
+
/** How a template's runtimes appear on fleet dashboards (RFC 0006 §4.1). */
|
|
112
|
+
export const ProductTemplateDashboardSchema = z.object({
|
|
113
|
+
kind: z.string().min(1).meta({
|
|
114
|
+
description: "The discovery kind a runtime of this template announces itself as, e.g. norsk-probe.monitor.",
|
|
115
|
+
}),
|
|
116
|
+
previews: z.array(z.string().min(1)).optional().meta({
|
|
117
|
+
description: "The roles of the MoQ previews it offers, e.g. main.",
|
|
118
|
+
}),
|
|
119
|
+
});
|
|
90
120
|
const ProductTemplateProxySchema = z.object({
|
|
91
121
|
expose: z.array(z.string()).default([]).meta({
|
|
92
122
|
description: "Paths (or globs) the runner's nginx routes through to this instance. Anything not in the list returns 404 from the proxy. Glob-shaped strings (`/static/*`) are accepted as hints — current implementation treats the whole set as a signal to mount a catch-all on the instance root; per-path filtering can come later.",
|
|
@@ -94,6 +124,9 @@ const ProductTemplateProxySchema = z.object({
|
|
|
94
124
|
routes: z.array(ProductTemplateRouteSchema).optional().meta({
|
|
95
125
|
description: "Extra named services to route under the instance root, beside the runtime-screen catch-all. Additive and optional: a template that omits it routes exactly as before, so an older runner ignoring the field still launches the product.",
|
|
96
126
|
}),
|
|
127
|
+
operations: z.array(ProductTemplateOperationsSchema).optional().meta({
|
|
128
|
+
description: "The operations this template's runtimes serve, each set described by an OpenAPI document in the tar; the ones marked x-norsk-dashboard are what fleet dashboards may call, each decided per user by the platform. Additive: a runner that predates it ignores it.",
|
|
129
|
+
}),
|
|
97
130
|
});
|
|
98
131
|
// product-template-schema cannot import @norsk-ctl/shared (dependency direction), so
|
|
99
132
|
// this is a literal copy of the runner's network-mode enum — and the runner
|
|
@@ -146,6 +179,12 @@ export const ProductTemplateAdvancedSchema = z
|
|
|
146
179
|
// and not others) — so this is how a product that needs a HIGHER one says
|
|
147
180
|
// so, not how it gets a ceiling at all. Instance-wide, not per-service.
|
|
148
181
|
openFileLimit: z.object({ default: z.number().int().min(1024).max(1048576).optional() }).optional(),
|
|
182
|
+
// Memory ceiling for each of the instance's containers (docker `mem_limit`
|
|
183
|
+
// syntax, e.g. "24g"; swap is capped at the same value). The runner states
|
|
184
|
+
// one for every instance (16g) — an engine with none once drove a shared
|
|
185
|
+
// host into a global OOM kill — so this is how a product that needs MORE
|
|
186
|
+
// says so. "unlimited" opts the product out of a ceiling altogether.
|
|
187
|
+
memoryLimit: z.object({ default: z.string().optional() }).optional(),
|
|
149
188
|
})
|
|
150
189
|
.meta({ id: "ProductTemplateAdvanced", outputId: "ProductTemplateAdvanced" });
|
|
151
190
|
// A host-port binding whose value rides a product-template parameter, opted in per
|
|
@@ -362,6 +401,9 @@ export const ProductTemplateManifestSchema = z
|
|
|
362
401
|
description: "Per-instance Debug menu toggles. Each of `studio`/`visualiser` defaults to shown; set false to hide a redundant link (e.g. Studio hides its own 'Open Studio').",
|
|
363
402
|
}),
|
|
364
403
|
proxy: ProductTemplateProxySchema.optional(),
|
|
404
|
+
dashboard: ProductTemplateDashboardSchema.optional().meta({
|
|
405
|
+
description: "How this template's runtimes appear on fleet dashboards: the kind they announce, and their previews. Absent = not on dashboards.",
|
|
406
|
+
}),
|
|
365
407
|
allowWorkflowUploads: z.boolean().optional().meta({
|
|
366
408
|
description: "Whether the operator may upload workflow documents for this product. They land in the working directory's studio-save-files/, where Studio lists them for the operator to open — so this is for Norsk Studio itself (the editor), not for appliances built on it: an appliance (probe, playout) generates its one workflow from its config screen and has nothing to select. Absent = false. Assets are governed separately by `supportsCustomAssets`.",
|
|
367
409
|
}),
|
|
@@ -519,6 +561,9 @@ export const ProductTemplateMaterialsSchema = z
|
|
|
519
561
|
.array(ProductTemplateFileSchema)
|
|
520
562
|
.default([])
|
|
521
563
|
.meta({ description: "Free-form product files — packed under assets/ in the tar" }),
|
|
564
|
+
openapi: z.array(ProductTemplateFileSchema).optional().meta({
|
|
565
|
+
description: "The OpenAPI documents proxy.operations names, packed under openapi/ in the tar. Optional so materials built before it still typecheck.",
|
|
566
|
+
}),
|
|
522
567
|
workdirSeed: z.array(ProductTemplateFileSchema).default([]).meta({
|
|
523
568
|
description: "Files copied recursively into the launch workdir at launch time. Packed under workdir-seed/ in the tar. Existing files in the launch workdir win on conflict (the seed only fills gaps), so re-launches and operator-edits-in-place are non-destructive. Lets a product template ship a 'starter pack' of demo workflows / dashboards / components that the runtime sees in /data on first launch.",
|
|
524
569
|
}),
|
package/pack.js
CHANGED
|
@@ -33,6 +33,9 @@ export function productTemplateTarEntries(materials) {
|
|
|
33
33
|
for (const a of materials.assets) {
|
|
34
34
|
entries.push({ name: `assets/${a.path}`, content: a.content });
|
|
35
35
|
}
|
|
36
|
+
for (const o of materials.openapi ?? []) {
|
|
37
|
+
entries.push({ name: `openapi/${o.path}`, content: o.content });
|
|
38
|
+
}
|
|
36
39
|
for (const s of materials.workdirSeed) {
|
|
37
40
|
entries.push({ name: `workdir-seed/${s.path}`, content: s.content });
|
|
38
41
|
}
|