@k8ts/instruments 0.9.3 → 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.
Files changed (169) hide show
  1. package/dist/core/graph/entity.d.ts +24 -5
  2. package/dist/core/graph/entity.d.ts.map +1 -1
  3. package/dist/core/graph/entity.js +11 -5
  4. package/dist/core/graph/entity.js.map +1 -1
  5. package/dist/core/graph/node.d.ts +31 -8
  6. package/dist/core/graph/node.d.ts.map +1 -1
  7. package/dist/core/graph/node.js +53 -26
  8. package/dist/core/graph/node.js.map +1 -1
  9. package/dist/core/graph/origin/entity.d.ts +9 -4
  10. package/dist/core/graph/origin/entity.d.ts.map +1 -1
  11. package/dist/core/graph/origin/entity.js +22 -2
  12. package/dist/core/graph/origin/entity.js.map +1 -1
  13. package/dist/core/graph/origin/events.d.ts +6 -6
  14. package/dist/core/graph/origin/events.d.ts.map +1 -1
  15. package/dist/core/graph/origin/exporter.d.ts +5 -4
  16. package/dist/core/graph/origin/exporter.d.ts.map +1 -1
  17. package/dist/core/graph/origin/exporter.js +9 -5
  18. package/dist/core/graph/origin/exporter.js.map +1 -1
  19. package/dist/core/graph/origin/external.d.ts +6 -2
  20. package/dist/core/graph/origin/external.d.ts.map +1 -1
  21. package/dist/core/graph/origin/external.js +4 -0
  22. package/dist/core/graph/origin/external.js.map +1 -1
  23. package/dist/core/graph/origin/kind-map/index.d.ts +7 -7
  24. package/dist/core/graph/origin/kind-map/index.d.ts.map +1 -1
  25. package/dist/core/graph/origin/kind-map/index.js +2 -2
  26. package/dist/core/graph/origin/kind-map/index.js.map +1 -1
  27. package/dist/core/graph/origin/node.d.ts +5 -5
  28. package/dist/core/graph/origin/node.d.ts.map +1 -1
  29. package/dist/core/graph/origin/origin-events.d.ts +6 -6
  30. package/dist/core/graph/origin/origin-events.d.ts.map +1 -1
  31. package/dist/core/graph/origin/tracker.d.ts +1 -1
  32. package/dist/core/graph/origin/tracker.d.ts.map +1 -1
  33. package/dist/core/graph/origin/tracker.js +2 -1
  34. package/dist/core/graph/origin/tracker.js.map +1 -1
  35. package/dist/core/graph/relation.d.ts +2 -2
  36. package/dist/core/graph/relation.d.ts.map +1 -1
  37. package/dist/core/graph/relation.js +1 -0
  38. package/dist/core/graph/relation.js.map +1 -1
  39. package/dist/core/graph/resource/api-kind/index.d.ts +51 -57
  40. package/dist/core/graph/resource/api-kind/index.d.ts.map +1 -1
  41. package/dist/core/graph/resource/api-kind/index.js +191 -205
  42. package/dist/core/graph/resource/api-kind/index.js.map +1 -1
  43. package/dist/core/graph/resource/child.d.ts +7 -6
  44. package/dist/core/graph/resource/child.d.ts.map +1 -1
  45. package/dist/core/graph/resource/child.js +3 -3
  46. package/dist/core/graph/resource/child.js.map +1 -1
  47. package/dist/core/graph/resource/entity.d.ts +8 -10
  48. package/dist/core/graph/resource/entity.d.ts.map +1 -1
  49. package/dist/core/graph/resource/entity.js +21 -11
  50. package/dist/core/graph/resource/entity.js.map +1 -1
  51. package/dist/core/graph/resource/external/base.d.ts +4 -9
  52. package/dist/core/graph/resource/external/base.d.ts.map +1 -1
  53. package/dist/core/graph/resource/external/base.js +5 -12
  54. package/dist/core/graph/resource/external/base.js.map +1 -1
  55. package/dist/core/graph/resource/external/features.d.ts +1 -10
  56. package/dist/core/graph/resource/external/features.d.ts.map +1 -1
  57. package/dist/core/graph/resource/external/props.d.ts +2 -2
  58. package/dist/core/graph/resource/external/props.d.ts.map +1 -1
  59. package/dist/core/graph/resource/node.d.ts +9 -9
  60. package/dist/core/graph/resource/node.d.ts.map +1 -1
  61. package/dist/core/graph/resource/node.js +6 -6
  62. package/dist/core/graph/resource/node.js.map +1 -1
  63. package/dist/core/graph/resource/ref-key/ref-key.d.ts +70 -7
  64. package/dist/core/graph/resource/ref-key/ref-key.d.ts.map +1 -1
  65. package/dist/core/graph/resource/ref-key/ref-key.js +47 -2
  66. package/dist/core/graph/resource/ref-key/ref-key.js.map +1 -1
  67. package/dist/core/graph/resource/reference/fw-ref-exports.d.ts +40 -9
  68. package/dist/core/graph/resource/reference/fw-ref-exports.d.ts.map +1 -1
  69. package/dist/core/graph/resource/reference/fw-ref-exports.js +47 -13
  70. package/dist/core/graph/resource/reference/fw-ref-exports.js.map +1 -1
  71. package/dist/core/graph/resource/reference/fw-ref.d.ts +41 -12
  72. package/dist/core/graph/resource/reference/fw-ref.d.ts.map +1 -1
  73. package/dist/core/graph/resource/reference/fw-ref.js +42 -10
  74. package/dist/core/graph/resource/reference/fw-ref.js.map +1 -1
  75. package/dist/core/graph/resource/reference/index.d.ts +2 -2
  76. package/dist/core/graph/resource/reference/index.d.ts.map +1 -1
  77. package/dist/core/graph/resource/reference/index.js +3 -3
  78. package/dist/core/graph/resource/reference/index.js.map +1 -1
  79. package/dist/core/graph/resource/reference/refable.d.ts +11 -12
  80. package/dist/core/graph/resource/reference/refable.d.ts.map +1 -1
  81. package/dist/core/graph/resource/top.d.ts +6 -5
  82. package/dist/core/graph/resource/top.d.ts.map +1 -1
  83. package/dist/core/graph/resource/top.js +6 -3
  84. package/dist/core/graph/resource/top.js.map +1 -1
  85. package/dist/core/manifest/index.d.ts +2 -2
  86. package/dist/core/manifest/index.d.ts.map +1 -1
  87. package/dist/core/manifest/index.js.map +1 -1
  88. package/dist/expressions/data-sources/base.d.ts +23 -0
  89. package/dist/expressions/data-sources/base.d.ts.map +1 -1
  90. package/dist/expressions/data-sources/base.js +22 -0
  91. package/dist/expressions/data-sources/base.js.map +1 -1
  92. package/dist/expressions/data-sources/env-var.d.ts +24 -1
  93. package/dist/expressions/data-sources/env-var.d.ts.map +1 -1
  94. package/dist/expressions/data-sources/env-var.js +22 -2
  95. package/dist/expressions/data-sources/env-var.js.map +1 -1
  96. package/dist/expressions/data-sources/interface.d.ts +30 -0
  97. package/dist/expressions/data-sources/interface.d.ts.map +1 -1
  98. package/dist/expressions/data-sources/local-file.d.ts +41 -3
  99. package/dist/expressions/data-sources/local-file.d.ts.map +1 -1
  100. package/dist/expressions/data-sources/local-file.js +37 -2
  101. package/dist/expressions/data-sources/local-file.js.map +1 -1
  102. package/dist/expressions/network/ports/index.d.ts +6 -6
  103. package/dist/expressions/network/ports/index.d.ts.map +1 -1
  104. package/dist/expressions/network/ports/index.js +4 -4
  105. package/dist/expressions/network/ports/index.js.map +1 -1
  106. package/dist/expressions/network/ports/map.d.ts +50 -8
  107. package/dist/expressions/network/ports/map.d.ts.map +1 -1
  108. package/dist/expressions/network/ports/map.js +34 -5
  109. package/dist/expressions/network/ports/map.js.map +1 -1
  110. package/dist/expressions/network/ports/set.d.ts +88 -13
  111. package/dist/expressions/network/ports/set.d.ts.map +1 -1
  112. package/dist/expressions/network/ports/set.js +49 -7
  113. package/dist/expressions/network/ports/set.js.map +1 -1
  114. package/dist/expressions/network/ports/tools/entry.d.ts +5 -4
  115. package/dist/expressions/network/ports/tools/entry.d.ts.map +1 -1
  116. package/dist/expressions/network/ports/tools/entry.js +1 -1
  117. package/dist/expressions/network/ports/tools/entry.js.map +1 -1
  118. package/dist/expressions/network/ports/tools/parse.d.ts +2 -2
  119. package/dist/expressions/network/ports/tools/parse.d.ts.map +1 -1
  120. package/dist/expressions/network/ports/tools/parse.js.map +1 -1
  121. package/dist/expressions/network/ports/types.d.ts +13 -22
  122. package/dist/expressions/network/ports/types.d.ts.map +1 -1
  123. package/dist/expressions/quantities/reqlem/objects.d.ts +2 -2
  124. package/dist/expressions/quantities/reqlem/objects.d.ts.map +1 -1
  125. package/dist/expressions/quantities/reqlem/objects.js +4 -4
  126. package/dist/expressions/quantities/reqlem/objects.js.map +1 -1
  127. package/dist/expressions/quantities/units/unit-parser.d.ts.map +1 -1
  128. package/dist/expressions/quantities/units/unit-parser.js +0 -1
  129. package/dist/expressions/quantities/units/unit-parser.js.map +1 -1
  130. package/package.json +5 -5
  131. package/src/core/graph/entities.md +1 -0
  132. package/src/core/graph/entity.ts +36 -9
  133. package/src/core/graph/node.ts +72 -41
  134. package/src/core/graph/origin/entity.ts +27 -7
  135. package/src/core/graph/origin/events.ts +6 -6
  136. package/src/core/graph/origin/exporter.ts +14 -12
  137. package/src/core/graph/origin/external.ts +6 -3
  138. package/src/core/graph/origin/kind-map/index.ts +13 -13
  139. package/src/core/graph/origin/node.ts +3 -3
  140. package/src/core/graph/origin/origin-events.ts +6 -6
  141. package/src/core/graph/origin/tracker.ts +2 -2
  142. package/src/core/graph/readme.md +161 -0
  143. package/src/core/graph/relation.ts +4 -2
  144. package/src/core/graph/resource/api-kind/index.ts +139 -160
  145. package/src/core/graph/resource/child.ts +7 -10
  146. package/src/core/graph/resource/entity.ts +25 -12
  147. package/src/core/graph/resource/external/base.ts +4 -12
  148. package/src/core/graph/resource/external/features.ts +0 -16
  149. package/src/core/graph/resource/external/props.ts +2 -2
  150. package/src/core/graph/resource/node.ts +8 -8
  151. package/src/core/graph/resource/ref-key/ref-key.ts +77 -11
  152. package/src/core/graph/resource/reference/fw-ref-exports.ts +69 -20
  153. package/src/core/graph/resource/reference/fw-ref.ts +75 -21
  154. package/src/core/graph/resource/reference/index.ts +2 -2
  155. package/src/core/graph/resource/reference/refable.ts +13 -18
  156. package/src/core/graph/resource/top.ts +8 -5
  157. package/src/core/manifest/index.ts +2 -2
  158. package/src/expressions/data-sources/base.ts +24 -0
  159. package/src/expressions/data-sources/env-var.ts +23 -1
  160. package/src/expressions/data-sources/interface.ts +32 -0
  161. package/src/expressions/data-sources/local-file.ts +59 -3
  162. package/src/expressions/network/ports/index.ts +7 -7
  163. package/src/expressions/network/ports/map.ts +58 -10
  164. package/src/expressions/network/ports/set.ts +100 -25
  165. package/src/expressions/network/ports/tools/entry.ts +9 -14
  166. package/src/expressions/network/ports/tools/parse.ts +3 -3
  167. package/src/expressions/network/ports/types.ts +12 -26
  168. package/src/expressions/quantities/reqlem/objects.ts +3 -3
  169. package/src/expressions/quantities/units/unit-parser.ts +0 -1
@@ -1,10 +1,23 @@
1
1
  import Path from "pathlib-js"
2
2
  import StackTracey from "stacktracey"
3
- import type { TypedArray } from "what-are-you"
4
3
  import { DataSource_Lazy } from "./base"
5
- export type DataSource_Allowed = string | Uint8Array | TypedArray
6
- export class DataSource_LocalFile_Path {
4
+
5
+ /** Union type of allowed data source value types. */
6
+ export type DataSource_Allowed = string | Uint8Array
7
+
8
+ /**
9
+ * Represents a local file path that can be read as text or binary data. Can be used instead of a
10
+ * primitive in some cases when building Kubernetes manifests.
11
+ */
12
+ class DataSource_LocalFile_Path {
7
13
  readonly path: Path
14
+
15
+ /**
16
+ * Creates a local file path data source.
17
+ *
18
+ * @param _cwd - The current working directory
19
+ * @param relPath - Relative path to the file
20
+ */
8
21
  constructor(
9
22
  private readonly _cwd: Path,
10
23
  relPath: string
@@ -12,8 +25,23 @@ export class DataSource_LocalFile_Path {
12
25
  this.path = this._cwd.join(relPath)
13
26
  }
14
27
 
28
+ /**
29
+ * Creates a lazy data source that reads the file as text.
30
+ *
31
+ * @param mode - Must be "text"
32
+ * @param encoding - Optional text encoding (default: "utf-8")
33
+ * @returns Lazy data source for text content
34
+ */
15
35
  as(mode: "text", encoding?: BufferEncoding): DataSource_Lazy<string>
36
+
37
+ /**
38
+ * Creates a lazy data source that reads the file as binary data.
39
+ *
40
+ * @param mode - Must be "binary"
41
+ * @returns Lazy data source for binary content
42
+ */
16
43
  as(mode: "binary"): DataSource_Lazy<Uint8Array>
44
+
17
45
  as(mode: "text" | "binary", encoding?: BufferEncoding): DataSource_Lazy {
18
46
  if (mode === "text") {
19
47
  return new DataSource_LocalFile_Text(this, encoding)
@@ -22,7 +50,15 @@ export class DataSource_LocalFile_Path {
22
50
  }
23
51
  }
24
52
  }
53
+
54
+ /** Data source for reading local files as text with specified encoding. */
25
55
  class DataSource_LocalFile_Text extends DataSource_Lazy<string> {
56
+ /**
57
+ * Creates a text file data source.
58
+ *
59
+ * @param _parent - Parent path object
60
+ * @param encoding - Text encoding (default: "utf-8")
61
+ */
26
62
  constructor(
27
63
  private readonly _parent: DataSource_LocalFile_Path,
28
64
  readonly encoding: BufferEncoding = "utf-8"
@@ -33,7 +69,13 @@ class DataSource_LocalFile_Text extends DataSource_Lazy<string> {
33
69
  }
34
70
  }
35
71
 
72
+ /** Data source for reading local files as binary (Uint8Array). */
36
73
  class DataSource_LocalFile_Binary extends DataSource_Lazy<Uint8Array> {
74
+ /**
75
+ * Creates a binary file data source.
76
+ *
77
+ * @param _parent - Parent path object
78
+ */
37
79
  constructor(private readonly _parent: DataSource_LocalFile_Path) {
38
80
  super(async () => {
39
81
  const x = await this._parent.path.readFile()
@@ -42,6 +84,20 @@ class DataSource_LocalFile_Binary extends DataSource_Lazy<Uint8Array> {
42
84
  }
43
85
  }
44
86
 
87
+ /**
88
+ * Creates a file path reference relative to the caller's file location. You must call `.as("text")`
89
+ * or `.as("binary")` on the returned object to get a data source.
90
+ *
91
+ * Can be used instead of a primitive in some cases when building Kubernetes manifests.
92
+ *
93
+ * @example
94
+ * // In /project/src/config.ts:
95
+ * const data = localRefFile("../data/config.json").as("text")
96
+ * const content = await data.get() // Reads /project/data/config.json
97
+ *
98
+ * @param path - Relative path to the file from the caller's directory
99
+ * @returns File path object that can be read as text or binary
100
+ */
45
101
  export function localRefFile(path: string) {
46
102
  const trace = new StackTracey().slice(1)
47
103
  const callerFile = trace.at(0).file
@@ -1,8 +1,8 @@
1
- import { PortSet } from "./set"
2
- import type { InputPortSetRecord } from "./types"
3
- export { PortMap } from "./map"
4
- export { PortSet } from "./set"
5
- export type { InputPortMapping, InputPortSetRecord, PortMapEntry, PortSetEntry } from "./types"
6
- export function ports<Names extends string>(input: InputPortSetRecord<Names>): PortSet<Names> {
7
- return PortSet.make(input)
1
+ import type { Port_Exports_Input } from "./set"
2
+ import { Port_Exports } from "./set"
3
+ export { Port_Map, type PortMapping_Input } from "./map"
4
+ export { Port_Exports, type Port_Exports_Input } from "./set"
5
+ export type { Port_Full, Port_Mapping_Entry } from "./types"
6
+ export function ports<Names extends string>(input: Port_Exports_Input<Names>): Port_Exports<Names> {
7
+ return Port_Exports.make(input)
8
8
  }
@@ -1,23 +1,47 @@
1
1
  import { filterMap, mapValues } from "@k8ts/metadata/util"
2
2
  import { PortError } from "./error"
3
- import type { PortMapEntry } from "./types"
4
- export class PortMap<Names extends string> {
5
- constructor(private readonly _map: Map<string, PortMapEntry>) {}
3
+ import type { Port_Mapping_Entry } from "./types"
6
4
 
7
- private _apply(f: (map: Map<string, PortMapEntry>) => Map<string, PortMapEntry>): PortMap<any> {
8
- return new PortMap(f(this._map))
5
+ /**
6
+ * Represents an immutable mapping of named ports to their frontend/backend configuration.
7
+ *
8
+ * Used to define how container ports are exposed through services, mapping backend container ports
9
+ * to frontend service ports.
10
+ *
11
+ * @template Names The union type of all port names in the map.
12
+ */
13
+ export class Port_Map<Names extends string> {
14
+ constructor(private readonly _map: Map<string, Port_Mapping_Entry>) {}
15
+
16
+ private _apply(
17
+ f: (map: Map<string, Port_Mapping_Entry>) => Map<string, Port_Mapping_Entry>
18
+ ): Port_Map<any> {
19
+ return new Port_Map(f(this._map))
9
20
  }
10
21
 
11
- pick<InNames extends Names>(...name: InNames[]): PortMap<InNames> {
22
+ /**
23
+ * Creates a new Port_Map containing only the specified port names.
24
+ *
25
+ * @param name The port names to include in the new map.
26
+ * @returns A new Port_Map with only the selected ports.
27
+ */
28
+ pick<InNames extends Names>(...name: InNames[]): Port_Map<InNames> {
12
29
  return this._apply(map => filterMap(map, (_, key) => name.includes(key as InNames)))
13
30
  }
14
31
 
32
+ /** The underlying map of port names to their mapping entries. */
15
33
  get values() {
16
34
  return this._map
17
35
  }
18
36
 
19
- map(mapping: Record<Names, number>): PortMap<Names> {
20
- return new PortMap(
37
+ /**
38
+ * Remaps the frontend ports to new values.
39
+ *
40
+ * @param mapping A record mapping port names to their new frontend port numbers.
41
+ * @returns A new Port_Map with updated frontend ports.
42
+ */
43
+ map(mapping: Record<Names, number>): Port_Map<Names> {
44
+ return new Port_Map(
21
45
  mapValues(this._map, entry => {
22
46
  return {
23
47
  ...entry,
@@ -27,14 +51,38 @@ export class PortMap<Names extends string> {
27
51
  )
28
52
  }
29
53
 
30
- get(name: Names): PortMapEntry {
54
+ /**
55
+ * Retrieves a port mapping entry by name.
56
+ *
57
+ * @param name The name of the port to retrieve.
58
+ * @returns The port mapping entry.
59
+ * @throws {PortError} If the port name is not found in the map.
60
+ */
61
+ get(name: Names): Port_Mapping_Entry {
31
62
  if (!this._map.has(name)) {
32
63
  throw new PortError(`Port ${name} not found`)
33
64
  }
34
- return this._map.get(name) as PortMapEntry
65
+ return this._map.get(name) as Port_Mapping_Entry
35
66
  }
36
67
 
68
+ /** Converts this Port_Map to a standard Map. */
37
69
  toMap() {
38
70
  return this._map
39
71
  }
40
72
  }
73
+
74
+ /**
75
+ * Input type for creating port mappings.
76
+ *
77
+ * Each port name maps to either:
78
+ *
79
+ * - A number specifying the frontend port
80
+ * - `true` to use the same port number as the backend
81
+ *
82
+ * @template Names The union type of port names.
83
+ */
84
+ export type PortMapping_Input<Names extends string = string> = [Names] extends [never]
85
+ ? never
86
+ : {
87
+ [K in Names]: number | true
88
+ }
@@ -2,39 +2,70 @@ import { Meta } from "@k8ts/metadata"
2
2
  import { filterMap, mapValues, merge } from "@k8ts/metadata/util"
3
3
  import { seq } from "doddle"
4
4
  import { PortError } from "./error"
5
- import { PortMap } from "./map"
5
+ import { Port_Map, PortMapping_Input } from "./map"
6
6
  import { parsePortInput, portRecordInput } from "./tools/entry"
7
7
  import type {
8
- InputPort,
9
- InputPortMapping,
10
- InputPortSetEntry,
11
- InputPortSetRecord,
12
- InputProtocol,
13
- PortSetEntry
8
+ Port_Basic_Input,
9
+ Port_Full,
10
+ Port_Full_Input,
11
+ Port_Input,
12
+ Port_Protocol_Input
14
13
  } from "./types"
15
14
 
16
- declare const __NAMES__: unique symbol
17
- export class PortSet<Names extends string = never> {
18
- constructor(private readonly _map: Map<Names, PortSetEntry> = new Map()) {
15
+ /**
16
+ * An immutable dictionary of named network ports exported by a container. Each port also has an
17
+ * attached configuration.
18
+ *
19
+ * @template Names All exported port names.
20
+ */
21
+ export class Port_Exports<Names extends string = never> {
22
+ constructor(private readonly _map: Map<Names, Port_Full> = new Map()) {
19
23
  for (const entry of _map.values()) {
20
24
  Meta._checkNameValue(`container port '${entry.name}' (${entry.port})`, entry.name)
21
25
  }
22
26
  }
23
27
 
24
- private _apply(f: (map: Map<string, PortSetEntry>) => Map<string, PortSetEntry>) {
25
- return new PortSet(f(this._map))
28
+ private _apply(f: (map: Map<string, Port_Full>) => Map<string, Port_Full>) {
29
+ return new Port_Exports(f(this._map))
26
30
  }
27
31
 
28
- union<InNames extends string>(other: PortSet<InNames>): PortSet<Names | InNames> {
29
- return new PortSet(merge(this._map, other._map))
32
+ /**
33
+ * Creates a new Port_Exports that is the union of this and another Port_Exports.
34
+ *
35
+ * @param other The other Port_Exports to merge with.
36
+ * @returns A new Port_Exports containing ports from both dictionaries. The 2nd dictionary's
37
+ * ports will overwrite any with the same name from the first.
38
+ */
39
+ union<InNames extends string>(other: Port_Exports<InNames>): Port_Exports<Names | InNames> {
40
+ return new Port_Exports(merge(this._map, other._map))
30
41
  }
42
+
43
+ /**
44
+ * Adds a port with explicit name, port number, and protocol.
45
+ *
46
+ * @param name The unique name for the port.
47
+ * @param port The port number.
48
+ * @param protocol The protocol (TCP or UDP).
49
+ */
31
50
  add<Name extends string>(
32
51
  name: Name,
33
- port: InputPort,
34
- protocol: InputProtocol
35
- ): PortSet<Names | Name>
36
- add<Name extends string>(name: Name, entry: InputPortSetEntry): PortSet<Names | Name>
37
- add<InNames extends string>(input?: InputPortSetRecord<InNames>): PortSet<Names | InNames>
52
+ port: Port_Basic_Input,
53
+ protocol: Port_Protocol_Input
54
+ ): Port_Exports<Names | Name>
55
+ /**
56
+ * Adds a port with a name and full port configuration.
57
+ *
58
+ * @param name The unique name for the port.
59
+ * @param entry The port configuration including number and protocol, and optional host
60
+ * settings.
61
+ */
62
+ add<Name extends string>(name: Name, entry: Port_Full_Input): Port_Exports<Names | Name>
63
+ /**
64
+ * Adds multiple ports from a record of port configurations.
65
+ *
66
+ * @param input A record mapping port names to their configurations.
67
+ */
68
+ add<InNames extends string>(input?: Port_Exports_Input<InNames>): Port_Exports<Names | InNames>
38
69
  add(a: any, b?: any, c?: any): any {
39
70
  if (!a) {
40
71
  return this
@@ -51,27 +82,50 @@ export class PortSet<Names extends string = never> {
51
82
  })
52
83
  }
53
84
 
54
- pick<InNames extends Names>(...name: InNames[]): PortSet<InNames> {
85
+ /**
86
+ * Creates a new Port_Exports containing only the specified port names.
87
+ *
88
+ * @param name The port names to include.
89
+ * @returns A new Port_Exports with only the selected ports.
90
+ */
91
+ pick<InNames extends Names>(...name: InNames[]): Port_Exports<InNames> {
55
92
  return this._apply(map => filterMap(map, (_, key) => name.includes(key as InNames))) as any
56
93
  }
57
94
 
95
+ /** An array of all port names in this set. */
58
96
  get names() {
59
97
  return seq(this._map.keys()).toArray().pull() as Names[]
60
98
  }
61
99
 
62
- get(name: Names): PortSetEntry {
100
+ /**
101
+ * Retrieves a port by name.
102
+ *
103
+ * @param name The name of the port to retrieve.
104
+ * @returns The full port configuration.
105
+ * @throws {PortError} If the port name is not found.
106
+ */
107
+ get(name: Names): Port_Full {
63
108
  if (!this._map.has(name)) {
64
109
  throw new PortError(`Port ${name} not found`)
65
110
  }
66
111
  return this._map.get(name)!
67
112
  }
68
113
 
114
+ /** The underlying map of port names to their full configurations. */
69
115
  get values() {
70
116
  return this._map
71
117
  }
72
118
 
73
- map(mapping: InputPortMapping<Names>): PortMap<Names> {
74
- return new PortMap(
119
+ /**
120
+ * Creates a Port_Map by mapping each port to a frontend port number.
121
+ *
122
+ * @param mapping A record where each port name maps to either a frontend port number or `true`
123
+ * to use the backend port.
124
+ * @returns A new Port_Map with the specified frontend mappings.
125
+ * @throws {PortError} If a port name is missing from the mapping or has an invalid value.
126
+ */
127
+ map(mapping: PortMapping_Input<Names>): Port_Map<Names> {
128
+ return new Port_Map(
75
129
  mapValues(this._map, entry => {
76
130
  if (!(entry.name in mapping)) {
77
131
  throw new PortError(`Port ${entry.name} not found in mapping`)
@@ -97,7 +151,28 @@ export class PortSet<Names extends string = never> {
97
151
  )
98
152
  }
99
153
 
100
- static make<Names extends string>(input?: InputPortSetRecord<Names>) {
101
- return new PortSet().add(input)
154
+ /**
155
+ * Creates a new Port_Exports from a record of port configurations.
156
+ *
157
+ * @param input A record mapping port names to their configurations.
158
+ * @returns A new Port_Exports containing the specified ports.
159
+ */
160
+ static make<Names extends string>(input?: Port_Exports_Input<Names>) {
161
+ return new Port_Exports().add(input)
102
162
  }
103
163
  }
164
+
165
+ /**
166
+ * Input type for creating Port_Exports.
167
+ *
168
+ * A record mapping port names to their configurations, which can be:
169
+ *
170
+ * - A port number (uses TCP by default)
171
+ * - A tuple of `[port, protocol]`
172
+ * - A full port configuration object
173
+ *
174
+ * @template Names The union type of port names.
175
+ */
176
+ export type Port_Exports_Input<Names extends string = string> = {
177
+ [K in Names]: Port_Input
178
+ }
@@ -1,26 +1,21 @@
1
1
  import { seq } from "doddle"
2
2
  import { Ip4 } from "../../ip"
3
- import { PortSet } from "../set"
4
- import type {
5
- InputPortSetEntry,
6
- InputPortSetRecord,
7
- InputPortSetSpec,
8
- PortSetEntry,
9
- Protocol
10
- } from "../types"
3
+ import type { Port_Exports_Input } from "../set"
4
+ import { Port_Exports } from "../set"
5
+ import type { Port_Full, Port_Full_Input, Port_Input, Port_Protocol } from "../types"
11
6
  import { parsePortSpec } from "./parse"
12
7
 
13
- function portSetEntry(name: string, value: InputPortSetEntry): PortSetEntry {
8
+ function portSetEntry(name: string, value: Port_Full_Input): Port_Full {
14
9
  return {
15
10
  name,
16
11
  port: value.port,
17
- protocol: value.protocol.toUpperCase() as Protocol,
12
+ protocol: value.protocol.toUpperCase() as Port_Protocol,
18
13
  hostIp: value.hostIp ? new Ip4(value.hostIp) : undefined,
19
14
  hostPort: value.hostPort
20
15
  }
21
16
  }
22
17
 
23
- export function parsePortInput(name: string, input: InputPortSetSpec): PortSetEntry {
18
+ export function parsePortInput(name: string, input: Port_Input): Port_Full {
24
19
  if (typeof input === "string") {
25
20
  return portSetEntry(name, parsePortSpec(name, input))
26
21
  }
@@ -34,9 +29,9 @@ export function parsePortInput(name: string, input: InputPortSetSpec): PortSetEn
34
29
  }
35
30
 
36
31
  export function portRecordInput(
37
- record: InputPortSetRecord<string> | PortSet<string>
38
- ): Map<string, PortSetEntry> {
39
- if (record instanceof PortSet) {
32
+ record: Port_Exports_Input<string> | Port_Exports<string>
33
+ ): Map<string, Port_Full> {
34
+ if (record instanceof Port_Exports) {
40
35
  return record.values
41
36
  }
42
37
  const inputMap = seq(Object.entries(record))
@@ -1,7 +1,7 @@
1
1
  import { anyStringOf, int, string } from "parjs"
2
2
  import { map, maybe, must, qthen, then } from "parjs/combinators"
3
3
  import { PortError } from "../error"
4
- import type { InputPortSetEntry, Protocol } from "../types"
4
+ import type { Port_Full_Input, Port_Protocol } from "../types"
5
5
 
6
6
  function validatePort(port: number) {
7
7
  if (port < 0 || port > 65535) {
@@ -13,7 +13,7 @@ function validatePort(port: number) {
13
13
  return true
14
14
  }
15
15
  const pProtocol = anyStringOf("tcp", "udp", "TCP", "UDP").pipe(
16
- map(s => s.toUpperCase() as Protocol)
16
+ map(s => s.toUpperCase() as Port_Protocol)
17
17
  )
18
18
 
19
19
  const pPort = int().pipe(must(validatePort))
@@ -25,7 +25,7 @@ const pPortSpec = pPort.pipe(
25
25
  return {
26
26
  port,
27
27
  protocol: protocol?.toUpperCase() ?? "TCP"
28
- } as InputPortSetEntry
28
+ } as Port_Full_Input
29
29
  })
30
30
  )
31
31
 
@@ -1,43 +1,29 @@
1
1
  import type { Ip4, Ip4_String } from "../ip"
2
2
 
3
- export interface PortSpecObj {
4
- port: Port
5
- protocol: Protocol
6
- }
7
-
8
- export type Port = number
9
- export type InputPort = Port | `${Port}`
10
- export type InputProtocol = Protocol | Lowercase<Protocol>
11
- export type Protocol = "TCP" | "UDP"
12
- export type InputPortProto = `${Port}/${InputProtocol}`
13
- export interface PortMapEntry {
3
+ type Port = number
4
+ export type Port_Basic_Input = Port | `${Port}`
5
+ export type Port_Protocol_Input = Port_Protocol | Lowercase<Port_Protocol>
6
+ export type Port_Protocol = "TCP" | "UDP"
7
+ export type Port_WithProto_Input = `${Port}/${Port_Protocol_Input}`
8
+ export interface Port_Mapping_Entry {
14
9
  name: string
15
- protocol: Protocol
10
+ protocol: Port_Protocol
16
11
  frontend: number
17
12
  }
18
13
 
19
- export interface PortSetEntry {
14
+ export interface Port_Full {
20
15
  name: string
21
16
  port: number
22
- protocol: Protocol
17
+ protocol: Port_Protocol
23
18
  hostIp?: Ip4
24
19
  hostPort?: number
25
20
  }
26
21
 
27
- export interface InputPortSetEntry {
22
+ export interface Port_Full_Input {
28
23
  port: Port
29
- protocol: InputProtocol
24
+ protocol: Port_Protocol_Input
30
25
  hostIp?: Ip4_String
31
26
  hostPort?: Port
32
27
  }
33
28
 
34
- export type InputPortSetSpec = InputPortSetEntry | InputPort | InputPortProto
35
-
36
- export type InputPortSetRecord<Names extends string = string> = {
37
- [K in Names]: InputPortSetSpec
38
- }
39
- export type InputPortMapping<Names extends string = string> = [Names] extends [never]
40
- ? never
41
- : {
42
- [K in Names]: number | true
43
- }
29
+ export type Port_Input = Port_Full_Input | Port_Basic_Input | Port_WithProto_Input
@@ -9,7 +9,7 @@ import { AnyUnitParser } from "../units/unit-parser"
9
9
  import { createResourceParser } from "./parser"
10
10
  import type { ReqLimit, Resources_ReqLimits_Trait, Resources_UnitMap_Trait } from "./types"
11
11
 
12
- export class Resources_Map<const RM extends Resources_UnitMap_Trait<RM>> {
12
+ export class Resources_UnitMap<const RM extends Resources_UnitMap_Trait<RM>> {
13
13
  constructor(private _map: Map<string, ReqLimit>) {}
14
14
 
15
15
  toObject() {
@@ -65,7 +65,7 @@ export class ResourcesSpec<const RM extends Resources_UnitMap_Trait<RM>> {
65
65
  }
66
66
  __INPUT__!: Resources_ReqLimits_Trait<RM>
67
67
 
68
- parse<const R extends Resources_ReqLimits_Trait<RM>>(input: R): Resources_Map<RM> {
68
+ parse<const R extends Resources_ReqLimits_Trait<RM>>(input: R): Resources_UnitMap<RM> {
69
69
  const allKeys = new Set([...Object.keys(input), ...this._unitParsers.keys()])
70
70
  const map = seq(allKeys)
71
71
  .toMap(key => {
@@ -96,7 +96,7 @@ export class ResourcesSpec<const RM extends Resources_UnitMap_Trait<RM>> {
96
96
  return [key, getVal()] as const
97
97
  })
98
98
  .pull()
99
- return new Resources_Map(map as Map<string, ReqLimit>)
99
+ return new Resources_UnitMap(map as Map<string, ReqLimit>)
100
100
  }
101
101
 
102
102
  static make<const RM extends Resources_UnitMap_Trait<RM>>(unitMap: {
@@ -10,7 +10,6 @@ const pValueUnit = int().pipe(
10
10
  return { value, unit }
11
11
  })
12
12
  )
13
- // TODO: Simplify unit parser to allow for arbitrary resources/units
14
13
  export class UnitValue<Unit extends string = string> {
15
14
  constructor(
16
15
  readonly unit: Unit,