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