@k8ts/metadata 0.7.3 → 0.10.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/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/dist/input/dict-input.d.ts +4 -4
- package/dist/input/dict-input.d.ts.map +1 -1
- package/dist/input/parse-dict.js +2 -2
- package/dist/input/parse-dict.js.map +1 -1
- package/dist/key/index.d.ts +1 -1
- package/dist/key/index.d.ts.map +1 -1
- package/dist/key/index.js +3 -3
- package/dist/key/index.js.map +1 -1
- package/dist/key/parse-key.d.ts +4 -4
- package/dist/key/parse-key.d.ts.map +1 -1
- package/dist/key/parse-key.js +5 -5
- package/dist/key/parse-key.js.map +1 -1
- package/dist/key/repr.d.ts +18 -12
- package/dist/key/repr.d.ts.map +1 -1
- package/dist/key/repr.js +42 -26
- package/dist/key/repr.js.map +1 -1
- package/dist/key/types.d.ts +8 -6
- package/dist/key/types.d.ts.map +1 -1
- package/dist/key/types.js +4 -1
- package/dist/key/types.js.map +1 -1
- package/dist/meta.d.ts +263 -29
- package/dist/meta.d.ts.map +1 -1
- package/dist/meta.js +164 -73
- package/dist/meta.js.map +1 -1
- package/package.json +3 -3
- package/src/index.ts +2 -1
- package/src/input/dict-input.ts +4 -4
- package/src/input/parse-dict.ts +3 -3
- package/src/key/index.ts +1 -1
- package/src/key/parse-key.ts +6 -6
- package/src/key/repr.ts +47 -22
- package/src/key/types.ts +8 -7
- package/src/meta.ts +305 -94
package/src/meta.ts
CHANGED
|
@@ -2,13 +2,12 @@ import { seq } from "doddle"
|
|
|
2
2
|
import { MetadataError } from "./error"
|
|
3
3
|
import type { InputMeta, MetaInputParts } from "./input/dict-input"
|
|
4
4
|
import { parseKey, parseMetaInput } from "./key"
|
|
5
|
-
import { pNameValue } from "./key/parse-key"
|
|
6
|
-
import { checkMetaString,
|
|
5
|
+
import { parseInnerKey, parseSectionKey, pNameValue } from "./key/parse-key"
|
|
6
|
+
import { checkMetaString, MetadataKey, type DomainPrefix } from "./key/repr"
|
|
7
7
|
import { Key } from "./key/types"
|
|
8
8
|
import { orderMetaKeyedObject } from "./order-meta-keyed-object"
|
|
9
9
|
import { equalsMap, toJS } from "./util"
|
|
10
10
|
export type Meta = Meta.Meta
|
|
11
|
-
export type MutableMeta = Meta.MutableMeta
|
|
12
11
|
const MetaMarker = Symbol("k8ts.org/metadata")
|
|
13
12
|
export interface MetaLike {
|
|
14
13
|
readonly [MetaMarker]: true
|
|
@@ -22,7 +21,7 @@ export namespace Meta {
|
|
|
22
21
|
}
|
|
23
22
|
export function _checkValue(key: string, v: string) {
|
|
24
23
|
const parsed = parseKey(key)
|
|
25
|
-
if (!(parsed instanceof
|
|
24
|
+
if (!(parsed instanceof MetadataKey)) {
|
|
26
25
|
throw new MetadataError(`Expected value key, got section key for ${key}`)
|
|
27
26
|
}
|
|
28
27
|
if (parsed.metaType === "label") {
|
|
@@ -32,37 +31,151 @@ export namespace Meta {
|
|
|
32
31
|
}
|
|
33
32
|
}
|
|
34
33
|
export type Input = InputMeta
|
|
35
|
-
|
|
34
|
+
/**
|
|
35
|
+
* Mutable storage for k8s metadata. K8s metadata includes labels, annotations, and core fields.
|
|
36
|
+
* These are addressed using `CharPrefix`.
|
|
37
|
+
*
|
|
38
|
+
* - **Labels**: `%key` → `metadata.labels.key`
|
|
39
|
+
* - **Annotations**: `^key` → `metadata.annotations.key`
|
|
40
|
+
* - **Comments**: `#key` → Build-time metadata, not manifested in k8s objects.
|
|
41
|
+
* - **Core metadata**: `key` → `metadata.key` (e.g., `name`, `namespace`, etc.)
|
|
42
|
+
*
|
|
43
|
+
* In addition, you can address different metadata keys under the same domain using a
|
|
44
|
+
* `DomainKey`, of the form `example.com/`. When using a `DomainKey`, you use a `CharPrefix` on
|
|
45
|
+
* the inner keys.
|
|
46
|
+
*
|
|
47
|
+
* This lets you add different kinds of metadata under the same domain with ease.
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* meta.add("%app", "my-app") // adds label 'app' with value 'my-app'
|
|
51
|
+
* meta.add("example.section/", {
|
|
52
|
+
* "%label1": "value1", // adds `%example.section/label1` with value 'value1'
|
|
53
|
+
* "^annotation1": "value2" // adds `^example.section/annotation1` with value 'value2'
|
|
54
|
+
* })
|
|
55
|
+
*/
|
|
56
|
+
export class Meta implements Iterable<[MetadataKey, string]>, MetaLike {
|
|
36
57
|
readonly [MetaMarker] = true
|
|
58
|
+
/**
|
|
59
|
+
* Constructs a new Meta instance from a map of key-value pairs. Validates all keys and
|
|
60
|
+
* values during construction.
|
|
61
|
+
*
|
|
62
|
+
* @param _dict Internal map storing metadata key-value pairs
|
|
63
|
+
* @throws {MetadataError} If any key or value is invalid
|
|
64
|
+
*/
|
|
37
65
|
constructor(private readonly _dict: Map<string, string>) {
|
|
38
66
|
for (const [key, value] of _dict.entries()) {
|
|
39
67
|
_checkValue(key, value)
|
|
40
68
|
}
|
|
41
69
|
}
|
|
42
70
|
|
|
71
|
+
/**
|
|
72
|
+
* Makes Meta instances iterable, yielding [ValueKey, string] pairs.
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* for (const [key, value] of meta) {
|
|
76
|
+
* console.log(key.str, value)
|
|
77
|
+
* }
|
|
78
|
+
*/
|
|
43
79
|
*[Symbol.iterator]() {
|
|
44
80
|
for (const entry of this._dict.entries()) {
|
|
45
|
-
yield [parseKey(entry[0]) as
|
|
81
|
+
yield [parseKey(entry[0]) as MetadataKey, entry[1]] as [MetadataKey, string]
|
|
46
82
|
}
|
|
47
83
|
}
|
|
48
84
|
protected _create(raw: Map<string, string>) {
|
|
49
85
|
return new Meta(raw)
|
|
50
86
|
}
|
|
87
|
+
/**
|
|
88
|
+
* Creates a deep clone of this object.
|
|
89
|
+
*
|
|
90
|
+
* @returns
|
|
91
|
+
*/
|
|
51
92
|
clone() {
|
|
52
93
|
return this._create(new Map(this._dict))
|
|
53
94
|
}
|
|
54
95
|
|
|
96
|
+
/**
|
|
97
|
+
* Deletes a single value key from the metadata.
|
|
98
|
+
*
|
|
99
|
+
* @example
|
|
100
|
+
* meta.delete("name") // deletes core metadata 'name'
|
|
101
|
+
* meta.delete("%app") // deletes label 'app'
|
|
102
|
+
*
|
|
103
|
+
* @param key The value key to delete
|
|
104
|
+
*/
|
|
55
105
|
delete(key: Key.Value): Meta
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Deletes specific keys under a domain prefix.
|
|
109
|
+
*
|
|
110
|
+
* @example
|
|
111
|
+
* meta.delete("example.com/", "key1", "key2") // deletes specific keys in section
|
|
112
|
+
*
|
|
113
|
+
* @param ns The section key namespace
|
|
114
|
+
* @param keys Specific value keys within the section to delete
|
|
115
|
+
*/
|
|
116
|
+
delete(ns: Key.Domain, ...keys: Key.Value[]): Meta
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Deletes all keys within a section namespace.
|
|
120
|
+
*
|
|
121
|
+
* @example
|
|
122
|
+
* meta.delete("example.com/") // deletes all keys in section
|
|
123
|
+
*
|
|
124
|
+
* @param ns The section key namespace to delete
|
|
125
|
+
*/
|
|
126
|
+
delete(ns: Key.Domain): Meta
|
|
127
|
+
delete(a: any, ...rest: any[]) {
|
|
128
|
+
if (a.endsWith("/")) {
|
|
129
|
+
const sectionKey = parseSectionKey(a)
|
|
130
|
+
const onlyKeys = rest.map(parseInnerKey)
|
|
131
|
+
if (onlyKeys.length > 0) {
|
|
132
|
+
var deleteOnly = (key: MetadataKey) => onlyKeys.some(ok => ok.equals(key))
|
|
133
|
+
} else {
|
|
134
|
+
var deleteOnly = (_key: MetadataKey) => _key.domain().equals(sectionKey)
|
|
135
|
+
}
|
|
136
|
+
for (const k of this._keys) {
|
|
137
|
+
if (deleteOnly(k)) {
|
|
138
|
+
this._dict.delete(k.str)
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
} else {
|
|
142
|
+
this._dict.delete(a)
|
|
143
|
+
}
|
|
61
144
|
return this
|
|
62
145
|
}
|
|
63
146
|
|
|
147
|
+
/**
|
|
148
|
+
* Adds a single key-value pair to the metadata. Throws if the key already exists.
|
|
149
|
+
*
|
|
150
|
+
* @example
|
|
151
|
+
* meta.add("%app", "my-app") // adds label
|
|
152
|
+
* meta.add("name", "my-resource") // adds core metadata
|
|
153
|
+
*
|
|
154
|
+
* @param key The value key to add
|
|
155
|
+
* @param value The value to associate with the key
|
|
156
|
+
*/
|
|
64
157
|
add(key: Key.Value, value?: string): Meta
|
|
65
|
-
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Adds a nested object of key-value pairs within a section namespace. Throws if any key
|
|
161
|
+
* already exists.
|
|
162
|
+
*
|
|
163
|
+
* @example
|
|
164
|
+
* meta.add("example.com/", { "%label": "value", "^annotation": "data" })
|
|
165
|
+
*
|
|
166
|
+
* @param key The section key namespace
|
|
167
|
+
* @param value Nested object containing key-value pairs
|
|
168
|
+
*/
|
|
169
|
+
add(key: Key.Domain, value: MetaInputParts.Nested): Meta
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Adds multiple key-value pairs from an input object. Throws if any key already exists.
|
|
173
|
+
*
|
|
174
|
+
* @example
|
|
175
|
+
* meta.add({ "%app": "my-app", name: "my-resource" })
|
|
176
|
+
*
|
|
177
|
+
* @param input Object or map containing key-value pairs to add
|
|
178
|
+
*/
|
|
66
179
|
add(input: InputMeta): Meta
|
|
67
180
|
add(a: any, b?: any) {
|
|
68
181
|
const parsed = _pairToMap([a, b])
|
|
@@ -78,17 +191,47 @@ export namespace Meta {
|
|
|
78
191
|
return this
|
|
79
192
|
}
|
|
80
193
|
|
|
194
|
+
/**
|
|
195
|
+
* Compares this Meta instance to another for equality. Two instances are equal if they
|
|
196
|
+
* contain the same key-value pairs.
|
|
197
|
+
*
|
|
198
|
+
* @param other The other Meta instance or input to compare against
|
|
199
|
+
* @returns Whether the two Meta instances are equal
|
|
200
|
+
*/
|
|
81
201
|
equals(other: Meta.Input) {
|
|
82
202
|
return equalsMap(this._dict, make(other)._dict)
|
|
83
203
|
}
|
|
84
204
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
205
|
+
/**
|
|
206
|
+
* Overwrites a single key-value pair, replacing any existing value.
|
|
207
|
+
*
|
|
208
|
+
* @example
|
|
209
|
+
* meta.overwrite("%app", "new-app") // replaces existing label value
|
|
210
|
+
*
|
|
211
|
+
* @param key The value key to overwrite
|
|
212
|
+
* @param value The new value (undefined removes the key)
|
|
213
|
+
*/
|
|
90
214
|
overwrite(key: Key.Value, value: string | undefined): Meta
|
|
91
|
-
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Overwrites key-value pairs within a section namespace.
|
|
218
|
+
*
|
|
219
|
+
* @example
|
|
220
|
+
* meta.overwrite("example.com/", { "%label": "new-value" })
|
|
221
|
+
*
|
|
222
|
+
* @param key The section key namespace
|
|
223
|
+
* @param value Nested object containing key-value pairs to overwrite
|
|
224
|
+
*/
|
|
225
|
+
overwrite(key: Key.Domain, value: MetaInputParts.Nested): Meta
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Overwrites multiple key-value pairs from an input object.
|
|
229
|
+
*
|
|
230
|
+
* @example
|
|
231
|
+
* meta.overwrite({ "%app": "new-app", name: "new-name" })
|
|
232
|
+
*
|
|
233
|
+
* @param input Object or map containing key-value pairs to overwrite
|
|
234
|
+
*/
|
|
92
235
|
overwrite(input?: InputMeta): Meta
|
|
93
236
|
overwrite(a?: any, b?: any) {
|
|
94
237
|
if (a === undefined) {
|
|
@@ -101,15 +244,38 @@ export namespace Meta {
|
|
|
101
244
|
return this
|
|
102
245
|
}
|
|
103
246
|
|
|
104
|
-
|
|
247
|
+
/**
|
|
248
|
+
* Checks if a key with a given domain prefix exists in the metadata.
|
|
249
|
+
*
|
|
250
|
+
* @example
|
|
251
|
+
* meta.has("example.com/") // Checks for any key with this domain
|
|
252
|
+
* meta.has("%app") // Checks for the label 'app'
|
|
253
|
+
*
|
|
254
|
+
* @param domainPrefix The domain prefix to check for
|
|
255
|
+
* @returns True if any keys exist under the specified domain prefix, false otherwise
|
|
256
|
+
*/
|
|
257
|
+
has(domainPrefix: Key.Domain): boolean
|
|
258
|
+
/** @param key */
|
|
259
|
+
has(key: Key.Value): boolean
|
|
260
|
+
has(key: any) {
|
|
105
261
|
const parsed = parseKey(key)
|
|
106
|
-
if (parsed instanceof
|
|
262
|
+
if (parsed instanceof MetadataKey) {
|
|
107
263
|
return this._dict.has(key)
|
|
108
264
|
} else {
|
|
109
|
-
return this.
|
|
265
|
+
return this._matchDomainPrefixes(parsed).size > 0
|
|
110
266
|
}
|
|
111
267
|
}
|
|
112
268
|
|
|
269
|
+
/**
|
|
270
|
+
* Retrieves the value for the specified key. Throws if the key doesn't exist.
|
|
271
|
+
*
|
|
272
|
+
* @example
|
|
273
|
+
* const appName = meta.get("%app")
|
|
274
|
+
*
|
|
275
|
+
* @param key The value key to retrieve
|
|
276
|
+
* @returns The value associated with the key
|
|
277
|
+
* @throws {MetadataError} If the key is not found
|
|
278
|
+
*/
|
|
113
279
|
get(key: Key.Value) {
|
|
114
280
|
const parsed = parseKey(key)
|
|
115
281
|
const v = this._dict.get(key)
|
|
@@ -119,29 +285,50 @@ export namespace Meta {
|
|
|
119
285
|
return v
|
|
120
286
|
}
|
|
121
287
|
|
|
288
|
+
/**
|
|
289
|
+
* Attempts to retrieve the value for the specified key, returning a fallback if not found.
|
|
290
|
+
*
|
|
291
|
+
* @example
|
|
292
|
+
* const appName = meta.tryGet("%app", "default-app")
|
|
293
|
+
*
|
|
294
|
+
* @param key The value key to retrieve
|
|
295
|
+
* @param fallback Optional fallback value if key doesn't exist
|
|
296
|
+
* @returns The value associated with the key, or the fallback value
|
|
297
|
+
* @throws {MetadataError} If a domain key is provided instead of a value key
|
|
298
|
+
*/
|
|
122
299
|
tryGet(key: Key.Value, fallback?: string) {
|
|
123
300
|
const parsed = parseKey(key)
|
|
124
|
-
if (!(parsed instanceof
|
|
125
|
-
throw new MetadataError("Unexpected
|
|
301
|
+
if (!(parsed instanceof MetadataKey)) {
|
|
302
|
+
throw new MetadataError("Unexpected domain key!", { key })
|
|
126
303
|
}
|
|
127
304
|
return this._dict.get(key) ?? fallback
|
|
128
305
|
}
|
|
129
306
|
|
|
130
|
-
private
|
|
307
|
+
private _matchDomainPrefixes(key: DomainPrefix) {
|
|
131
308
|
return seq(this)
|
|
132
309
|
.filter(([k, v]) => k.parent?.equals(key) ?? false)
|
|
133
310
|
.toMap(x => [x[0].str, x[1]] as const)
|
|
134
311
|
.pull()
|
|
135
312
|
}
|
|
136
313
|
|
|
137
|
-
|
|
314
|
+
/**
|
|
315
|
+
* Creates a new Meta instance containing only some of the keys. You can pass both entire
|
|
316
|
+
* keys and domain prefixes to include all keys under that domain.
|
|
317
|
+
*
|
|
318
|
+
* @example
|
|
319
|
+
* const subset = meta.pick("%app", "name", "example.com/")
|
|
320
|
+
*
|
|
321
|
+
* @param keySpecs Keys or domain prefixes to include in the result
|
|
322
|
+
* @returns A new Meta instance with only the picked keys
|
|
323
|
+
*/
|
|
324
|
+
pick(...keySpecs: (Key.Domain | Key.Value)[]) {
|
|
138
325
|
const parsed = keySpecs.map(parseKey)
|
|
139
326
|
const keyStrSet = new Set<string>()
|
|
140
327
|
for (const key of parsed) {
|
|
141
|
-
if (key instanceof
|
|
328
|
+
if (key instanceof MetadataKey) {
|
|
142
329
|
keyStrSet.add(key.str)
|
|
143
330
|
} else {
|
|
144
|
-
const sectionKeys = this.
|
|
331
|
+
const sectionKeys = this._matchDomainPrefixes(key)
|
|
145
332
|
for (const k of sectionKeys.keys()) {
|
|
146
333
|
keyStrSet.add(k)
|
|
147
334
|
}
|
|
@@ -157,87 +344,131 @@ export namespace Meta {
|
|
|
157
344
|
private _prefixed(prefix: string) {
|
|
158
345
|
const out: { [k: string]: string } = {}
|
|
159
346
|
for (const [k, v] of this) {
|
|
160
|
-
if (k.
|
|
347
|
+
if (k.prefix() === prefix) {
|
|
161
348
|
out[k.suffix] = v
|
|
162
349
|
}
|
|
163
350
|
}
|
|
164
351
|
return orderMetaKeyedObject(out)
|
|
165
352
|
}
|
|
166
353
|
|
|
354
|
+
/**
|
|
355
|
+
* Returns all labels as a plain object that can be embedded into a k8s manifest, with keys
|
|
356
|
+
* in canonical order.
|
|
357
|
+
*
|
|
358
|
+
* @example
|
|
359
|
+
* const labels = Meta.make({
|
|
360
|
+
* "%app": "my-app",
|
|
361
|
+
* "%tier": "backend"
|
|
362
|
+
* }).labels
|
|
363
|
+
* // { app: "my-app", tier: "backend" }
|
|
364
|
+
*/
|
|
167
365
|
get labels() {
|
|
168
366
|
return this._prefixed("%")
|
|
169
367
|
}
|
|
170
368
|
|
|
369
|
+
/**
|
|
370
|
+
* Returns all annotations as a plain object that can be embedded into a k8s manifest, with
|
|
371
|
+
* keys in canonical order.
|
|
372
|
+
*
|
|
373
|
+
* @example
|
|
374
|
+
* const annotations = Meta.make({
|
|
375
|
+
* "^note": "This is important",
|
|
376
|
+
* "^description": "Detailed info"
|
|
377
|
+
* }).annotations
|
|
378
|
+
* // { note: "This is important", description: "Detailed info" }
|
|
379
|
+
*/
|
|
171
380
|
get annotations() {
|
|
172
381
|
return this._prefixed("^")
|
|
173
382
|
}
|
|
174
383
|
|
|
384
|
+
/**
|
|
385
|
+
* Returns all comments (build-time metadata) as a plain object, with keys in canonical
|
|
386
|
+
* order.
|
|
387
|
+
*
|
|
388
|
+
* @example
|
|
389
|
+
* const comments = Meta.make({
|
|
390
|
+
* "#note": "Internal use only"
|
|
391
|
+
* }).comments
|
|
392
|
+
* // { note: "Internal use only" }
|
|
393
|
+
*/
|
|
175
394
|
get comments() {
|
|
176
395
|
return this._prefixed("#")
|
|
177
396
|
}
|
|
397
|
+
/**
|
|
398
|
+
* Returns all core metadata fields (`name` and `namespace`) as a plain object that can be
|
|
399
|
+
* embedded into a k8s manifest, with keys in canonical order.
|
|
400
|
+
*
|
|
401
|
+
* @example
|
|
402
|
+
* const core = meta.core // { name: "my-resource", namespace: "default" }
|
|
403
|
+
*/
|
|
404
|
+
get core() {
|
|
405
|
+
return this._prefixed("") as {
|
|
406
|
+
[key in Key.Special]?: string
|
|
407
|
+
}
|
|
408
|
+
}
|
|
178
409
|
|
|
410
|
+
/**
|
|
411
|
+
* Returns all metadata key-value pairs as a flat JavaScript object, with each key prefixed
|
|
412
|
+
* appropriately.
|
|
413
|
+
*
|
|
414
|
+
* @example
|
|
415
|
+
* const all = Meta.make({
|
|
416
|
+
* "%app": "my-app",
|
|
417
|
+
* "^note": "This is important",
|
|
418
|
+
* name: "my-resource"
|
|
419
|
+
* }).values
|
|
420
|
+
* // { "%app": "my-app", "^note": "This is important", "name": "my-resource" }
|
|
421
|
+
*/
|
|
179
422
|
get values() {
|
|
180
423
|
return toJS(this._dict)
|
|
181
424
|
}
|
|
182
425
|
|
|
183
|
-
get
|
|
426
|
+
private get _keys(): MetadataKey[] {
|
|
184
427
|
return seq(this)
|
|
185
428
|
.map(([k, v]) => k)
|
|
186
429
|
.toArray()
|
|
187
430
|
.pull()
|
|
188
431
|
}
|
|
189
|
-
|
|
190
|
-
get core() {
|
|
191
|
-
return this._prefixed("") as {
|
|
192
|
-
[key in Key.Special]?: string
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
remove(key: Key.Value): this
|
|
196
|
-
remove(ns: Key.Section, key: string): this
|
|
197
|
-
remove(ns: Key.Section): this
|
|
198
|
-
remove(a: any, b?: any) {
|
|
199
|
-
const parsed = parseKey(a)
|
|
200
|
-
if (parsed instanceof ValueKey) {
|
|
201
|
-
this._dict.delete(parsed.str)
|
|
202
|
-
return this
|
|
203
|
-
}
|
|
204
|
-
if (b !== undefined) {
|
|
205
|
-
// remove specific key from section
|
|
206
|
-
for (const k of this.keys) {
|
|
207
|
-
if (k.parent?.equals(parsed) && k.suffix === b) {
|
|
208
|
-
this._dict.delete(k.str)
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
return this
|
|
212
|
-
}
|
|
213
|
-
// remove entire section
|
|
214
|
-
for (const k of this.keys) {
|
|
215
|
-
if (k.parent?.equals(parsed)) this._dict.delete(k.str)
|
|
216
|
-
}
|
|
217
|
-
return this
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
expand() {
|
|
221
|
-
const labels = this.labels
|
|
222
|
-
const annotations = this.annotations
|
|
223
|
-
const core = this.core
|
|
224
|
-
return {
|
|
225
|
-
...core,
|
|
226
|
-
labels,
|
|
227
|
-
annotations
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
432
|
}
|
|
231
433
|
|
|
434
|
+
/**
|
|
435
|
+
* Creates a Meta instance with a single key-value pair.
|
|
436
|
+
*
|
|
437
|
+
* @example
|
|
438
|
+
* const meta = Meta.make("%app", "my-app")
|
|
439
|
+
*
|
|
440
|
+
* @param key The value key
|
|
441
|
+
* @param value The value to associate with the key
|
|
442
|
+
*/
|
|
232
443
|
export function make(key: Key.Value, value: string): Meta
|
|
233
|
-
|
|
444
|
+
|
|
445
|
+
/**
|
|
446
|
+
* Creates a Meta instance with key-value pairs within a section namespace.
|
|
447
|
+
*
|
|
448
|
+
* @example
|
|
449
|
+
* const meta = Meta.make("example.com/", { "%label": "value" })
|
|
450
|
+
*
|
|
451
|
+
* @param key The section key namespace
|
|
452
|
+
* @param value Nested object containing key-value pairs
|
|
453
|
+
*/
|
|
454
|
+
export function make(key: Key.Domain, value: MetaInputParts.Nested): Meta
|
|
455
|
+
|
|
456
|
+
/**
|
|
457
|
+
* Creates a Meta instance from an input object or returns an empty Meta if no input provided.
|
|
458
|
+
*
|
|
459
|
+
* @example
|
|
460
|
+
* const meta = Meta.make({ "%app": "my-app", name: "resource" })
|
|
461
|
+
* const empty = Meta.make()
|
|
462
|
+
*
|
|
463
|
+
* @param input Object or map containing key-value pairs
|
|
464
|
+
*/
|
|
234
465
|
export function make(input?: InputMeta): Meta
|
|
235
466
|
export function make(a?: any, b?: any) {
|
|
236
467
|
return new Meta(_pairToMap([a, b]))
|
|
237
468
|
}
|
|
238
|
-
function _pairToObject(pair: [string |
|
|
469
|
+
function _pairToObject(pair: [string | MetadataKey, string | object] | [object]) {
|
|
239
470
|
let [key, value] = pair
|
|
240
|
-
key = key instanceof
|
|
471
|
+
key = key instanceof MetadataKey ? key.str : key
|
|
241
472
|
if (typeof key === "string") {
|
|
242
473
|
return {
|
|
243
474
|
[key]: value as string
|
|
@@ -245,27 +476,7 @@ export namespace Meta {
|
|
|
245
476
|
}
|
|
246
477
|
return key
|
|
247
478
|
}
|
|
248
|
-
function _pairToMap(pair: [string |
|
|
479
|
+
function _pairToMap(pair: [string | MetadataKey, string | object] | [object]) {
|
|
249
480
|
return parseMetaInput(_pairToObject(pair))
|
|
250
481
|
}
|
|
251
|
-
|
|
252
|
-
export function splat(...input: InputMeta[]) {
|
|
253
|
-
return input.map(make).reduce((acc, meta) => acc.add(meta), make())
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
export function is(value: any): value is Meta {
|
|
257
|
-
return value instanceof Meta
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
export class MutableMeta extends Meta {
|
|
261
|
-
// MutableMeta is now just a direct extension of Meta so callers
|
|
262
|
-
// that expect MutableMeta keep working. The class body is empty
|
|
263
|
-
// because all mutation behavior lives on `Meta` itself.
|
|
264
|
-
constructor(...args: any[]) {
|
|
265
|
-
// Construct as a Meta instance. `Meta` constructor signature
|
|
266
|
-
// expects a Map<ValueKey, string> which callers provide when
|
|
267
|
-
// creating mutable instances.
|
|
268
|
-
super(args[0])
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
482
|
}
|