@k8ts/metadata 0.4.15 → 0.5.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.
Files changed (51) hide show
  1. package/dist/index.d.ts +2 -2
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js.map +1 -1
  4. package/dist/input/dict-input.d.ts +2 -1
  5. package/dist/input/dict-input.d.ts.map +1 -1
  6. package/dist/input/parse-dict.d.ts +1 -3
  7. package/dist/input/parse-dict.d.ts.map +1 -1
  8. package/dist/input/parse-dict.js +7 -11
  9. package/dist/input/parse-dict.js.map +1 -1
  10. package/dist/key/parse-key.d.ts.map +1 -1
  11. package/dist/key/parse-key.js +3 -2
  12. package/dist/key/parse-key.js.map +1 -1
  13. package/dist/key/repr.d.ts +0 -2
  14. package/dist/key/repr.d.ts.map +1 -1
  15. package/dist/key/repr.js +0 -4
  16. package/dist/key/repr.js.map +1 -1
  17. package/dist/key/types.d.ts +2 -7
  18. package/dist/key/types.d.ts.map +1 -1
  19. package/dist/key/types.js.map +1 -1
  20. package/dist/meta.d.ts +25 -65
  21. package/dist/meta.d.ts.map +1 -1
  22. package/dist/meta.js +106 -119
  23. package/dist/meta.js.map +1 -1
  24. package/dist/order-meta-keyed-object.d.ts +2 -0
  25. package/dist/order-meta-keyed-object.d.ts.map +1 -0
  26. package/dist/order-meta-keyed-object.js +21 -0
  27. package/dist/order-meta-keyed-object.js.map +1 -0
  28. package/dist/util.d.ts +23 -0
  29. package/dist/util.d.ts.map +1 -0
  30. package/dist/util.js +113 -0
  31. package/dist/util.js.map +1 -0
  32. package/package.json +16 -14
  33. package/src/index.ts +2 -2
  34. package/src/input/dict-input.ts +6 -1
  35. package/src/input/parse-dict.ts +9 -13
  36. package/src/key/parse-key.ts +5 -3
  37. package/src/key/repr.ts +1 -5
  38. package/src/key/types.ts +2 -9
  39. package/src/meta.ts +116 -145
  40. package/src/order-meta-keyed-object.ts +20 -0
  41. package/src/util.ts +115 -0
  42. package/dist/key/convert.d.ts +0 -6
  43. package/dist/key/convert.d.ts.map +0 -1
  44. package/dist/key/convert.js +0 -7
  45. package/dist/key/convert.js.map +0 -1
  46. package/dist/mutable-meta.d.ts +0 -2
  47. package/dist/mutable-meta.d.ts.map +0 -1
  48. package/dist/mutable-meta.js +0 -3
  49. package/dist/mutable-meta.js.map +0 -1
  50. package/src/key/convert.ts +0 -6
  51. package/src/mutable-meta.ts +0 -0
@@ -1,5 +1,6 @@
1
1
  import { ValueKey } from "../key"
2
2
  import type { Key } from "../key/types"
3
+ import type { MetaLike } from "../meta"
3
4
 
4
5
  export namespace MetaInputParts {
5
6
  type Of<T extends string, V> = {
@@ -11,4 +12,8 @@ export namespace MetaInputParts {
11
12
  export type Input = Full & Heading
12
13
  }
13
14
 
14
- export type InputMeta = MetaInputParts.Input | undefined | Iterable<readonly [ValueKey, string]>
15
+ export type InputMeta =
16
+ | MetaLike
17
+ | MetaInputParts.Input
18
+ | undefined
19
+ | Iterable<readonly [ValueKey, string]>
@@ -1,24 +1,20 @@
1
- import { Map } from "immutable"
2
1
  import { isNullish } from "what-are-you"
3
2
  import { parseInnerKey, parseOuterKey } from "../key/parse-key"
4
- import { SectionKey, ValueKey } from "../key/repr"
3
+ import { SectionKey } from "../key/repr"
5
4
  import { Meta } from "../meta"
6
5
  import type { InputMeta } from "./dict-input"
7
6
 
8
- export function parseMetaInput(input: InputMeta): Map<ValueKey, string> {
7
+ export function parseMetaInput(input: InputMeta): Map<string, string> {
9
8
  if (input == null) {
10
- return Map()
9
+ return new Map()
11
10
  }
12
- if (Map.isMap(input)) {
13
- return input as Map<ValueKey, string>
11
+ if (input instanceof Map) {
12
+ return new Map(input) as Map<string, string>
14
13
  }
15
14
  if (input instanceof Meta.Meta) {
16
- return input["_dict"]
15
+ return new Map(input["_dict"] as Map<string, string>)
17
16
  }
18
- if (input instanceof Meta.MutableMeta) {
19
- return input["_meta"]["_dict"]
20
- }
21
- let map = Map<ValueKey, string>()
17
+ let map = new Map<string, string>()
22
18
  for (const [key, value] of Object.entries(input)) {
23
19
  const outer = parseOuterKey(key)
24
20
  if (isNullish(value)) {
@@ -37,13 +33,13 @@ export function parseMetaInput(input: InputMeta): Map<ValueKey, string> {
37
33
  if (typeof vv !== "string") {
38
34
  throw new Error(`Expected string value for inner key ${kk}`)
39
35
  }
40
- map = map.set(inner.section(outer), vv as string)
36
+ map.set(inner.section(outer).str, vv as string)
41
37
  }
42
38
  } else {
43
39
  if (typeof value !== "string") {
44
40
  throw new Error(`Expected string value for key ${key}`)
45
41
  }
46
- map = map.set(outer, value as string)
42
+ map.set(outer.str, value as string)
47
43
  }
48
44
  }
49
45
  return map
@@ -1,4 +1,4 @@
1
- import { anyCharOf, anyStringOf, digit, lower, string, upper } from "parjs"
1
+ import { anyCharOf, anyStringOf, digit, letter, lower, string } from "parjs"
2
2
  import { many1, map, maybe, or, qthen, stringify, then, thenq } from "parjs/combinators"
3
3
 
4
4
  import { MetadataError } from "../error"
@@ -6,9 +6,11 @@ import { SectionKey, ValueKey } from "./repr"
6
6
 
7
7
  const cPrefix = anyCharOf("%^#")
8
8
  const cSection = string("/")
9
+ export const normalChar = letter().pipe(or(digit())).expects("alphanumeric")
10
+ const cDot = anyCharOf(".")
11
+
12
+ const cExtra = anyCharOf(`-_`).pipe(or(cDot)).expects("'-', '_', or '.'")
9
13
 
10
- const cExtra = anyCharOf("-_.").expects("'-', '_', or '.'")
11
- export const normalChar = upper().pipe(or(lower(), digit())).expects("alphanumeric")
12
14
  const cNameChar = lower().pipe(or(digit())).pipe(or("-"))
13
15
  const cInterior = normalChar.pipe(or(cExtra)).expects("alphanumeric, '-', '_', or '.'")
14
16
 
package/src/key/repr.ts CHANGED
@@ -1,9 +1,7 @@
1
- import { hash } from "immutable"
2
1
  import { MetadataError } from "../error"
3
2
  import { normalChar } from "./parse-key"
4
3
  interface ImmObject {
5
4
  equals(other: ImmObject): boolean
6
- hashCode(): number
7
5
  }
8
6
 
9
7
  abstract class KeyType implements ImmObject {
@@ -11,9 +9,7 @@ abstract class KeyType implements ImmObject {
11
9
  equals(other: ImmObject): boolean {
12
10
  return this.constructor === other.constructor && this.toString() === other.toString()
13
11
  }
14
- hashCode(): number {
15
- return hash(this.toString())
16
- }
12
+
17
13
  toString() {
18
14
  return this.str
19
15
  }
package/src/key/types.ts CHANGED
@@ -8,19 +8,12 @@ export namespace Char {
8
8
 
9
9
  export type Section = "/"
10
10
  export const Section = "/"
11
-
12
- export type Lower =
13
- `${"a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" | "j" | "k" | "l" | "m" | "n" | "o" | "p" | "q" | "r" | "s" | "t" | "u" | "v" | "w" | "x" | "y" | "z"}`
14
- export type Upper = Uppercase<Lower>
15
- export type Digit = `${"0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"}`
16
- export type Extra = "-" | "_" | "."
17
- export type Normal = `${Lower | Digit}`
18
11
  }
19
12
 
20
13
  export namespace Key {
21
- export type Section = `${Char.Normal}${string}${Char.Section}`
14
+ export type Section = `${string}${Char.Section}`
22
15
  export type Special = "name" | "namespace"
23
- export type Value = (`${Char.Prefix.Custom}${string}` & `${string}${Char.Normal}`) | Special
16
+ export type Value = (`${Char.Prefix.Custom}${string}` & `${string}${string}`) | Special
24
17
 
25
18
  export type Key = Section | Value
26
19
  }
package/src/meta.ts CHANGED
@@ -1,12 +1,18 @@
1
- import { Map, Set } from "immutable"
1
+ 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
5
  import { pNameValue } from "./key/parse-key"
6
6
  import { checkMetaString, ValueKey, type SectionKey } from "./key/repr"
7
- import { Key as Key_ } from "./key/types"
7
+ import { Key } from "./key/types"
8
+ import { orderMetaKeyedObject } from "./order-meta-keyed-object"
9
+ import { equalsMap, toJS } from "./util"
8
10
  export type Meta = Meta.Meta
9
11
  export type MutableMeta = Meta.MutableMeta
12
+ const MetaMarker = Symbol("k8ts.org/metadata")
13
+ export interface MetaLike {
14
+ readonly [MetaMarker]: true
15
+ }
10
16
  export namespace Meta {
11
17
  export function _checkNameValue(what: string, v: string) {
12
18
  if (!pNameValue.parse(v).isOk) {
@@ -14,73 +20,81 @@ export namespace Meta {
14
20
  }
15
21
  checkMetaString(what, v, 63)
16
22
  }
17
- export function _checkValue(key: ValueKey, v: string) {
18
- if (key.metaType === "label") {
19
- checkMetaString(`value of ${key.str}`, v, 63)
20
- } else if (key.metaType === "core") {
21
- _checkNameValue(`value of ${key.str}`, v)
23
+ export function _checkValue(key: string, v: string) {
24
+ const parsed = parseKey(key)
25
+ if (!(parsed instanceof ValueKey)) {
26
+ throw new MetadataError(`Expected value key, got section key for ${key}`)
27
+ }
28
+ if (parsed.metaType === "label") {
29
+ checkMetaString(`value of ${key}`, v, 63)
30
+ } else if (parsed.metaType === "core") {
31
+ _checkNameValue(`value of ${key}`, v)
22
32
  }
23
33
  }
24
34
  export type Input = InputMeta
25
- export import Key = Key_
26
- export class Meta implements Iterable<[ValueKey, string]> {
27
- constructor(private readonly _dict: Map<ValueKey, string>) {
35
+ export class Meta implements Iterable<[ValueKey, string]>, MetaLike {
36
+ readonly [MetaMarker] = true
37
+ constructor(private readonly _dict: Map<string, string>) {
28
38
  for (const [key, value] of _dict.entries()) {
29
39
  _checkValue(key, value)
30
40
  }
31
41
  }
32
42
 
33
- [Symbol.iterator]() {
34
- return this._dict.entries()[Symbol.iterator]()
43
+ *[Symbol.iterator]() {
44
+ for (const entry of this._dict.entries()) {
45
+ yield [parseKey(entry[0]) as ValueKey, entry[1]] as [ValueKey, string]
46
+ }
35
47
  }
36
- protected _create(raw: Map<ValueKey, string>) {
48
+ protected _create(raw: Map<string, string>) {
37
49
  return new Meta(raw)
38
50
  }
39
- private _createWith(f: (raw: Map<ValueKey, string>) => Map<ValueKey, string>) {
40
- return this._create(f(this._dict))
51
+ clone() {
52
+ return this._create(new Map(this._dict))
41
53
  }
42
- add(key: Key.Value, value: string): Meta
54
+ add(key: Key.Value, value?: string): Meta
43
55
  add(key: Key.Section, value: MetaInputParts.Nested): Meta
44
56
  add(input: InputMeta): Meta
45
57
  add(a: any, b?: any) {
46
- return this._createWith(raw => {
47
- const parsed = _pairToMap([a, b])
48
- const newMap = raw.mergeWith((prev, cur, key) => {
49
- throw new MetadataError(`Duplicate entry for ${key}, was ${prev} now ${cur}`, {
50
- key: key.str
58
+ const parsed = _pairToMap([a, b])
59
+ for (const [k, v] of parsed) {
60
+ if (this._dict.has(k)) {
61
+ const prev = this._dict.get(k)
62
+ throw new MetadataError(`Duplicate entry for ${k}, was ${prev} now ${v}`, {
63
+ key: (k as any).str
51
64
  })
52
- }, parsed)
53
- return newMap
54
- })
65
+ }
66
+ this._dict.set(k, v)
67
+ }
68
+ return this
55
69
  }
56
70
 
57
71
  equals(other: Meta.Input) {
58
- return this._dict.equals(make(other)._dict)
72
+ return equalsMap(this._dict, make(other)._dict)
59
73
  }
60
74
 
61
75
  section(key: string) {
62
- return this._createWith(raw => {
63
- return raw.mapKeys(k => k.section(key))
64
- })
76
+ const newS = seq(this).map(([k, v]) => [k.section(key), v] as const)
77
+ return parseMetaInput(newS)
65
78
  }
66
79
 
67
- overwrite(key: Key.Value, value: string): Meta
80
+ overwrite(key: Key.Value, value: string | undefined): Meta
68
81
  overwrite(key: Key.Section, value: MetaInputParts.Nested): Meta
69
82
  overwrite(input?: InputMeta): Meta
70
83
  overwrite(a?: any, b?: any) {
71
84
  if (a === undefined) {
72
85
  return this
73
86
  }
74
- return this._createWith(raw => {
75
- const fromPair = _pairToMap([a, b])
76
- return raw.merge(fromPair)
77
- })
87
+ const fromPair = _pairToMap([a, b])
88
+ for (const [k, v] of fromPair.entries()) {
89
+ this._dict.set(k, v)
90
+ }
91
+ return this
78
92
  }
79
93
 
80
94
  has<X extends Key.Value>(key: X) {
81
95
  const parsed = parseKey(key)
82
96
  if (parsed instanceof ValueKey) {
83
- return this._dict.has(parsed)
97
+ return this._dict.has(key)
84
98
  } else {
85
99
  return this._matchSectionKeys(parsed).size > 0
86
100
  }
@@ -88,7 +102,7 @@ export namespace Meta {
88
102
 
89
103
  get(key: Key.Value) {
90
104
  const parsed = parseKey(key)
91
- const v = this._dict.get(parsed as ValueKey)
105
+ const v = this._dict.get(key)
92
106
  if (v === undefined) {
93
107
  throw new MetadataError(`Key ${key} not found!`, { key })
94
108
  }
@@ -100,34 +114,44 @@ export namespace Meta {
100
114
  if (!(parsed instanceof ValueKey)) {
101
115
  throw new MetadataError("Unexpected section key!", { key })
102
116
  }
103
- return this._dict.get(parsed) ?? fallback
117
+ return this._dict.get(key) ?? fallback
104
118
  }
105
119
 
106
120
  private _matchSectionKeys(key: SectionKey) {
107
- return this._dict.filter((_, k) => k.parent?.equals(key))
121
+ return seq(this)
122
+ .filter(([k, v]) => k.parent?.equals(key) ?? false)
123
+ .toMap(x => [x[0].str, x[1]] as const)
124
+ .pull()
108
125
  }
109
126
 
110
127
  pick(...keySpecs: Key.Key[]) {
111
- return this._createWith(raw => {
112
- const parsed = keySpecs.map(parseKey)
113
- let keySet = Set()
114
- for (const key of parsed) {
115
- if (key instanceof ValueKey) {
116
- keySet = keySet.add(key)
117
- } else {
118
- const sectionKeys = this._matchSectionKeys(key)
119
- keySet = keySet.union(sectionKeys.keySeq())
128
+ const parsed = keySpecs.map(parseKey)
129
+ const keyStrSet = new Set<string>()
130
+ for (const key of parsed) {
131
+ if (key instanceof ValueKey) {
132
+ keyStrSet.add(key.str)
133
+ } else {
134
+ const sectionKeys = this._matchSectionKeys(key)
135
+ for (const k of sectionKeys.keys()) {
136
+ keyStrSet.add(k)
120
137
  }
121
138
  }
122
- return raw.filter((_, k) => keySet.has(k))
123
- })
139
+ }
140
+ const out = new Map<string, string>()
141
+ for (const [k, v] of this._dict.entries()) {
142
+ if (keyStrSet.has(k)) out.set(k, v)
143
+ }
144
+ return this._create(out)
124
145
  }
125
146
 
126
147
  private _prefixed(prefix: string) {
127
- return this._dict
128
- .filter((_, k) => k._prefix === prefix)
129
- .mapKeys(k => k.suffix)
130
- .toObject()
148
+ const out: { [k: string]: string } = {}
149
+ for (const [k, v] of this) {
150
+ if (k._prefix === prefix) {
151
+ out[k.suffix] = v
152
+ }
153
+ }
154
+ return orderMetaKeyedObject(out)
131
155
  }
132
156
 
133
157
  get labels() {
@@ -143,7 +167,14 @@ export namespace Meta {
143
167
  }
144
168
 
145
169
  get values() {
146
- return this._dict.toJS()
170
+ return toJS(this._dict)
171
+ }
172
+
173
+ get keys(): ValueKey[] {
174
+ return seq(this)
175
+ .map(([k, v]) => k)
176
+ .toArray()
177
+ .pull()
147
178
  }
148
179
 
149
180
  get core() {
@@ -155,14 +186,25 @@ export namespace Meta {
155
186
  remove(ns: Key.Section, key: string): this
156
187
  remove(ns: Key.Section): this
157
188
  remove(a: any, b?: any) {
158
- return this._createWith(raw => {
159
- const parsed = parseKey(a)
160
- if (parsed instanceof ValueKey) {
161
- return raw.delete(parsed)
162
- } else {
163
- return raw.filter((_, k) => !k.parent?.equals(parsed))
189
+ const parsed = parseKey(a)
190
+ if (parsed instanceof ValueKey) {
191
+ this._dict.delete(parsed.str)
192
+ return this
193
+ }
194
+ if (b !== undefined) {
195
+ // remove specific key from section
196
+ for (const k of this.keys) {
197
+ if (k.parent?.equals(parsed) && k.suffix === b) {
198
+ this._dict.delete(k.str)
199
+ }
164
200
  }
165
- })
201
+ return this
202
+ }
203
+ // remove entire section
204
+ for (const k of this.keys) {
205
+ if (k.parent?.equals(parsed)) this._dict.delete(k.str)
206
+ }
207
+ return this
166
208
  }
167
209
 
168
210
  expand() {
@@ -175,10 +217,6 @@ export namespace Meta {
175
217
  annotations
176
218
  }
177
219
  }
178
-
179
- toMutable() {
180
- return new MutableMeta(this)
181
- }
182
220
  }
183
221
 
184
222
  export function make(key: Key.Value, value: string): Meta
@@ -187,11 +225,9 @@ export namespace Meta {
187
225
  export function make(a?: any, b?: any) {
188
226
  return new Meta(_pairToMap([a, b]))
189
227
  }
190
- function _pairToObject(pair: [string, string | object] | [object]) {
191
- const [key, value] = pair
192
- if (key instanceof Meta) {
193
- return Map(key)
194
- }
228
+ function _pairToObject(pair: [string | ValueKey, string | object] | [object]) {
229
+ let [key, value] = pair
230
+ key = key instanceof ValueKey ? key.str : key
195
231
  if (typeof key === "string") {
196
232
  return {
197
233
  [key]: value as string
@@ -199,11 +235,8 @@ export namespace Meta {
199
235
  }
200
236
  return key
201
237
  }
202
- function _pairToMap(pair: [string, string | object] | [object]) {
203
- return parseMetaInput(_pairToObject(pair)).filter((v, k) => v != null)
204
- }
205
- export function makeMutable(input: InputMeta = {}) {
206
- return make(input).toMutable()
238
+ function _pairToMap(pair: [string | ValueKey, string | object] | [object]) {
239
+ return parseMetaInput(_pairToObject(pair))
207
240
  }
208
241
 
209
242
  export function splat(...input: InputMeta[]) {
@@ -214,77 +247,15 @@ export namespace Meta {
214
247
  return value instanceof Meta
215
248
  }
216
249
 
217
- export class MutableMeta {
218
- constructor(private _meta: Meta) {}
219
-
220
- add(key: Key.Value, value: string): this
221
- add(key: Key.Section, value: MetaInputParts.Nested): this
222
- add(input: InputMeta): this
223
- add(a: any, b?: any) {
224
- this._meta = this._meta.add(a, b)
225
- return this
226
- }
227
-
228
- remove(key: Key.Value): this
229
- remove(ns: Key.Section, key: string): this
230
- remove(ns: Key.Section): this
231
- remove(a: any, b?: any) {
232
- this._meta = this._meta.remove(a, b)
233
- return this
234
- }
235
-
236
- overwrite(key: Key.Value, value: string): this
237
- overwrite(key: Key.Section, value: MetaInputParts.Nested): this
238
- overwrite(input?: InputMeta): this
239
- overwrite(a?: any, b?: any) {
240
- this._meta = this._meta.overwrite(a, b)
241
- return this
242
- }
243
- equals(other: Meta.Input) {
244
- return this._meta.equals(other)
245
- }
246
- get(key: Key.Value) {
247
- return this._meta.get(key)
248
- }
249
-
250
- tryGet(key: Key.Value, fallback?: string) {
251
- return this._meta.tryGet(key, fallback)
252
- }
253
-
254
- has(key: Key.Value) {
255
- return this._meta.has(key)
256
- }
257
-
258
- pick(...keySpecs: Key.Key[]) {
259
- const newMeta = this._meta.pick(...keySpecs)
260
- return new MutableMeta(newMeta)
261
- }
262
-
263
- toMutable() {
264
- return new MutableMeta(this._meta)
265
- }
266
-
267
- section(key: string) {
268
- return new MutableMeta(this._meta.section(key))
269
- }
270
- get labels() {
271
- return this._meta.labels
272
- }
273
-
274
- get annotations() {
275
- return this._meta.annotations
276
- }
277
-
278
- get comments() {
279
- return this._meta.comments
280
- }
281
-
282
- get core() {
283
- return this._meta.core
284
- }
285
-
286
- toImmutable() {
287
- return this._meta
250
+ export class MutableMeta extends Meta {
251
+ // MutableMeta is now just a direct extension of Meta so callers
252
+ // that expect MutableMeta keep working. The class body is empty
253
+ // because all mutation behavior lives on `Meta` itself.
254
+ constructor(...args: any[]) {
255
+ // Construct as a Meta instance. `Meta` constructor signature
256
+ // expects a Map<ValueKey, string> which callers provide when
257
+ // creating mutable instances.
258
+ super(args[0])
288
259
  }
289
260
  }
290
261
  }
@@ -0,0 +1,20 @@
1
+ import { seq } from "doddle"
2
+
3
+ function comparisonKey(key: string) {
4
+ const bySlash = key.split("/")
5
+ if (bySlash.length === 1) {
6
+ return key
7
+ }
8
+ if (bySlash.length > 2) {
9
+ throw new Error(`Invalid composed key ${key}, too many '/' characters.`)
10
+ }
11
+ const [dns, name] = bySlash
12
+ const dnsParts = dns.split(".").reverse()
13
+ return [...dnsParts, name].join("\uffff")
14
+ }
15
+
16
+ export function orderMetaKeyedObject(input: Record<string, string>): Record<string, any> {
17
+ const entries = seq(Object.entries(input)).orderBy(([key]) => comparisonKey(key))
18
+
19
+ return Object.fromEntries(entries)
20
+ }
package/src/util.ts ADDED
@@ -0,0 +1,115 @@
1
+ type Pair<X> = [X, X]
2
+ export function mergeWith<K1, K2, V1, V2, V3>(
3
+ map1: Map<K1, V1>,
4
+ map2: Map<K2, V2>,
5
+ merger: (val1: V1, val2: V2, key: K1 | K2) => V3
6
+ ): Map<K1 | K2, V1 | V2 | V3> {
7
+ const result = new Map<K1 | K2, V1 | V2 | V3>(map1)
8
+ const allKeys = new Set<K1 | K2>([...map1.keys(), ...map2.keys()])
9
+ for (const k of allKeys) {
10
+ const val1 = map1.get(k as K1)
11
+ const val2 = map2.get(k as K2)
12
+ if (val1 !== undefined && val2 !== undefined) {
13
+ result.set(k, merger(val1, val2, k))
14
+ } else if (val2 !== undefined) {
15
+ result.set(k, val2)
16
+ }
17
+ }
18
+ return result
19
+ }
20
+
21
+ export function merge<K1, K2, V1, V2>(map1: Map<K1, V1>, map2: Map<K2, V2>): Map<K1 | K2, V1 | V2> {
22
+ return mergeWith(map1, map2, (_old, _new) => _new)
23
+ }
24
+
25
+ export function filterMap<K, V>(map: Map<K, V>, pred: (v: V, k: K) => boolean): Map<K, V> {
26
+ const out = new Map<K, V>()
27
+ for (const [k, v] of map.entries()) {
28
+ if (pred(v, k)) out.set(k, v)
29
+ }
30
+ return out
31
+ }
32
+
33
+ export function mapKeys<K, V, NK>(map: Map<K, V>, fn: (k: K) => NK): Map<NK, V> {
34
+ const out = new Map<NK, V>()
35
+ for (const [k, v] of map.entries()) {
36
+ out.set(fn(k), v)
37
+ }
38
+ return out
39
+ }
40
+
41
+ export function mapValues<K, V, NV>(map: Map<K, V>, fn: (v: V, k: K) => NV): Map<K, NV> {
42
+ const out = new Map<K, NV>()
43
+ for (const [k, v] of map.entries()) {
44
+ out.set(k, fn(v, k))
45
+ }
46
+ return out
47
+ }
48
+
49
+ export function toObject<K, V>(map: Map<K, V>): { [k: string]: V } {
50
+ const out: { [k: string]: V } = {}
51
+ for (const [k, v] of map.entries()) {
52
+ const key = (k as any)?.str ?? String(k)
53
+ out[key] = v
54
+ }
55
+ return out
56
+ }
57
+
58
+ export function toJS<K, V>(map: Map<K, V>): { [k: string]: V } {
59
+ return toObject(map)
60
+ }
61
+
62
+ export function equalsMap<K, V>(a: Map<K, V>, b: Map<K, V>): boolean {
63
+ if (a.size !== b.size) return false
64
+ for (const [ka, va] of a.entries()) {
65
+ let found = false
66
+ for (const [kb, vb] of b.entries()) {
67
+ const sa = (ka as any)?.str ?? ka
68
+ const sb = (kb as any)?.str ?? kb
69
+ if (sa === sb) {
70
+ found = true
71
+ if (va !== vb) return false
72
+ break
73
+ }
74
+ }
75
+ if (!found) return false
76
+ }
77
+ return true
78
+ }
79
+
80
+ export function mapFromObject<V>(obj: { [k: string]: V }): Map<string, V> {
81
+ const map = new Map<string, V>()
82
+ for (const k of Object.keys(obj)) {
83
+ map.set(k, obj[k])
84
+ }
85
+ return map
86
+ }
87
+
88
+ export function mapToObject<V>(map: Map<string, V>): { [k: string]: V } {
89
+ const obj: { [k: string]: V } = {}
90
+ for (const [k, v] of map.entries()) {
91
+ obj[k] = v
92
+ }
93
+ return obj
94
+ }
95
+
96
+ export type SourcedPropertyDescriptor = PropertyDescriptor & {
97
+ source: object
98
+ }
99
+ export function getDeepPropertyDescriptor(
100
+ obj: any,
101
+ propertyKey: string | symbol
102
+ ): SourcedPropertyDescriptor | undefined {
103
+ let current = obj
104
+ while (current) {
105
+ const descriptor = Object.getOwnPropertyDescriptor(current, propertyKey)
106
+ if (descriptor) {
107
+ return {
108
+ ...descriptor,
109
+ source: current
110
+ }
111
+ }
112
+ current = Object.getPrototypeOf(current)
113
+ }
114
+ return undefined
115
+ }
@@ -1,6 +0,0 @@
1
- import type { Map } from "immutable";
2
- import type { ValueKey } from "./repr";
3
- export declare function toObjectForm(map: Map<ValueKey, string>): {
4
- [key: string]: string;
5
- };
6
- //# sourceMappingURL=convert.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"convert.d.ts","sourceRoot":"","sources":["../../src/key/convert.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,WAAW,CAAA;AACpC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAA;AAEtC,wBAAgB,YAAY,CAAC,GAAG,EAAE,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC;;EAEtD"}
@@ -1,7 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.toObjectForm = toObjectForm;
4
- function toObjectForm(map) {
5
- return map.mapKeys(x => x.str).toObject();
6
- }
7
- //# sourceMappingURL=convert.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"convert.js","sourceRoot":"","sources":["../../src/key/convert.ts"],"names":[],"mappings":";;AAGA,oCAEC;AAFD,SAAgB,YAAY,CAAC,GAA0B;IACnD,OAAO,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAA;AAC7C,CAAC"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=mutable-meta.d.ts.map