@k8ts/instruments 0.2.1 → 0.4.1

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 (161) hide show
  1. package/dist/_embedder/base.js +3 -2
  2. package/dist/_embedder/index.js +0 -1
  3. package/dist/_string/index.js +0 -1
  4. package/dist/_string/markers.d.ts +2 -2
  5. package/dist/_string/markers.d.ts.map +1 -1
  6. package/dist/_string/markers.js +26 -11
  7. package/dist/_string/post-processor.js +1 -4
  8. package/dist/_string/pretty-objects.js +51 -50
  9. package/dist/_string/pretty-print.js +0 -1
  10. package/dist/_string/super-script.js +0 -1
  11. package/dist/api-kind/index.js +3 -1
  12. package/dist/cmd/cli-command.js +3 -1
  13. package/dist/cmd/cli-term.js +5 -1
  14. package/dist/cmd/index.js +0 -1
  15. package/dist/cmd/types.js +0 -1
  16. package/dist/data-sources/index.d.ts +37 -0
  17. package/dist/data-sources/index.d.ts.map +1 -0
  18. package/dist/data-sources/index.js +104 -0
  19. package/dist/displayers/displayers.js +2 -5
  20. package/dist/displayers/index.js +0 -1
  21. package/dist/env/env.js +1 -1
  22. package/dist/env/index.js +0 -1
  23. package/dist/env/types.js +0 -1
  24. package/dist/env/validate-name.js +0 -1
  25. package/dist/error.js +0 -1
  26. package/dist/forward-exports/delayed-exports.js +12 -18
  27. package/dist/forward-exports/index.js +0 -1
  28. package/dist/graph/base-node.d.ts +6 -4
  29. package/dist/graph/base-node.d.ts.map +1 -1
  30. package/dist/graph/base-node.js +60 -51
  31. package/dist/graph/base-origin-entity.js +15 -30
  32. package/dist/graph/dependencies.d.ts +2 -2
  33. package/dist/graph/dependencies.d.ts.map +1 -1
  34. package/dist/graph/dependencies.js +16 -19
  35. package/dist/graph/index.js +0 -1
  36. package/dist/graph/origin-node.d.ts +1 -1
  37. package/dist/graph/origin-node.d.ts.map +1 -1
  38. package/dist/graph/origin-node.js +33 -34
  39. package/dist/graph/relations.d.ts +2 -2
  40. package/dist/graph/relations.d.ts.map +1 -1
  41. package/dist/graph/relations.js +1 -4
  42. package/dist/graph/resource-node.d.ts +1 -1
  43. package/dist/graph/resource-node.d.ts.map +1 -1
  44. package/dist/graph/resource-node.js +16 -18
  45. package/dist/image/family.d.ts +10 -6
  46. package/dist/image/family.d.ts.map +1 -1
  47. package/dist/image/family.js +160 -44
  48. package/dist/image/index.js +0 -1
  49. package/dist/index.d.ts +1 -0
  50. package/dist/index.d.ts.map +1 -1
  51. package/dist/index.js +1 -1
  52. package/dist/kind-map/index.js +2 -1
  53. package/dist/manifest/index.js +0 -1
  54. package/dist/manifest/manifest-builder.d.ts +7 -11
  55. package/dist/manifest/manifest-builder.d.ts.map +1 -1
  56. package/dist/manifest/manifest-builder.js +3 -6
  57. package/dist/ports/error.js +1 -2
  58. package/dist/ports/index.js +0 -1
  59. package/dist/ports/map.js +1 -1
  60. package/dist/ports/set.d.ts +2 -2
  61. package/dist/ports/set.d.ts.map +1 -1
  62. package/dist/ports/set.js +16 -2
  63. package/dist/ports/tools/entry.js +0 -1
  64. package/dist/ports/tools/parse.js +0 -1
  65. package/dist/ports/types.d.ts +2 -2
  66. package/dist/ports/types.d.ts.map +1 -1
  67. package/dist/ports/types.js +0 -1
  68. package/dist/producer/index.js +0 -1
  69. package/dist/producer/producer.js +0 -1
  70. package/dist/ref-key/index.js +0 -1
  71. package/dist/ref-key/ref-key.js +2 -1
  72. package/dist/reference/forward-ref.js +13 -27
  73. package/dist/reference/index.js +0 -1
  74. package/dist/reference/refable.js +0 -1
  75. package/dist/resources/index.js +0 -1
  76. package/dist/resources/objects.js +4 -1
  77. package/dist/resources/parser.js +0 -1
  78. package/dist/resources/types.js +0 -1
  79. package/dist/src.tsbuildinfo +1 -1
  80. package/dist/tracing/git.js +1 -1
  81. package/dist/tracing/index.js +0 -1
  82. package/dist/tracing/trace.js +1 -1
  83. package/dist/tracing/traced.js +0 -1
  84. package/dist/units/index.js +0 -1
  85. package/dist/units/unit-parser.js +16 -11
  86. package/dist/units/units.js +0 -1
  87. package/package.json +3 -3
  88. package/src/_embedder/base.ts +1 -1
  89. package/src/_string/markers.ts +28 -9
  90. package/src/data-sources/index.ts +126 -0
  91. package/src/graph/base-node.ts +20 -10
  92. package/src/graph/dependencies.ts +2 -2
  93. package/src/graph/origin-node.ts +5 -5
  94. package/src/graph/relations.ts +2 -2
  95. package/src/graph/resource-node.ts +3 -3
  96. package/src/image/family.ts +45 -29
  97. package/src/index.ts +1 -0
  98. package/src/manifest/manifest-builder.ts +6 -5
  99. package/src/ports/set.ts +17 -3
  100. package/src/ports/types.ts +5 -3
  101. package/src/tsconfig.json +5 -0
  102. package/dist/_embedder/base.js.map +0 -1
  103. package/dist/_embedder/index.js.map +0 -1
  104. package/dist/_string/index.js.map +0 -1
  105. package/dist/_string/markers.js.map +0 -1
  106. package/dist/_string/post-processor.js.map +0 -1
  107. package/dist/_string/pretty-objects.js.map +0 -1
  108. package/dist/_string/pretty-print.js.map +0 -1
  109. package/dist/_string/super-script.js.map +0 -1
  110. package/dist/api-kind/index.js.map +0 -1
  111. package/dist/cmd/cli-command.js.map +0 -1
  112. package/dist/cmd/cli-term.js.map +0 -1
  113. package/dist/cmd/index.js.map +0 -1
  114. package/dist/cmd/types.js.map +0 -1
  115. package/dist/displayers/displayers.js.map +0 -1
  116. package/dist/displayers/index.js.map +0 -1
  117. package/dist/env/env.js.map +0 -1
  118. package/dist/env/index.js.map +0 -1
  119. package/dist/env/types.js.map +0 -1
  120. package/dist/env/validate-name.js.map +0 -1
  121. package/dist/error.js.map +0 -1
  122. package/dist/forward-exports/delayed-exports.js.map +0 -1
  123. package/dist/forward-exports/index.js.map +0 -1
  124. package/dist/graph/base-node.js.map +0 -1
  125. package/dist/graph/base-origin-entity.js.map +0 -1
  126. package/dist/graph/dependencies.js.map +0 -1
  127. package/dist/graph/index.js.map +0 -1
  128. package/dist/graph/origin-node.js.map +0 -1
  129. package/dist/graph/relations.js.map +0 -1
  130. package/dist/graph/resource-node.js.map +0 -1
  131. package/dist/image/family.js.map +0 -1
  132. package/dist/image/index.js.map +0 -1
  133. package/dist/index.js.map +0 -1
  134. package/dist/kind-map/index.js.map +0 -1
  135. package/dist/manifest/index.js.map +0 -1
  136. package/dist/manifest/manifest-builder.js.map +0 -1
  137. package/dist/ports/error.js.map +0 -1
  138. package/dist/ports/index.js.map +0 -1
  139. package/dist/ports/map.js.map +0 -1
  140. package/dist/ports/set.js.map +0 -1
  141. package/dist/ports/tools/entry.js.map +0 -1
  142. package/dist/ports/tools/parse.js.map +0 -1
  143. package/dist/ports/types.js.map +0 -1
  144. package/dist/producer/index.js.map +0 -1
  145. package/dist/producer/producer.js.map +0 -1
  146. package/dist/ref-key/index.js.map +0 -1
  147. package/dist/ref-key/ref-key.js.map +0 -1
  148. package/dist/reference/forward-ref.js.map +0 -1
  149. package/dist/reference/index.js.map +0 -1
  150. package/dist/reference/refable.js.map +0 -1
  151. package/dist/resources/index.js.map +0 -1
  152. package/dist/resources/objects.js.map +0 -1
  153. package/dist/resources/parser.js.map +0 -1
  154. package/dist/resources/types.js.map +0 -1
  155. package/dist/tracing/git.js.map +0 -1
  156. package/dist/tracing/index.js.map +0 -1
  157. package/dist/tracing/trace.js.map +0 -1
  158. package/dist/tracing/traced.js.map +0 -1
  159. package/dist/units/index.js.map +0 -1
  160. package/dist/units/unit-parser.js.map +0 -1
  161. package/dist/units/units.js.map +0 -1
@@ -7,6 +7,7 @@ exports.GitTrace = void 0;
7
7
  const dayjs_1 = __importDefault(require("dayjs"));
8
8
  const simple_git_1 = __importDefault(require("simple-git"));
9
9
  class GitTrace {
10
+ props;
10
11
  constructor(props) {
11
12
  this.props = props;
12
13
  }
@@ -42,4 +43,3 @@ class GitTrace {
42
43
  }
43
44
  }
44
45
  exports.GitTrace = GitTrace;
45
- //# sourceMappingURL=git.js.map
@@ -17,4 +17,3 @@ Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./git"), exports);
18
18
  __exportStar(require("./trace"), exports);
19
19
  __exportStar(require("./traced"), exports);
20
- //# sourceMappingURL=index.js.map
@@ -4,6 +4,7 @@ exports.Trace = void 0;
4
4
  const lodash_1 = require("lodash");
5
5
  const path_1 = require("path");
6
6
  class Trace {
7
+ trace;
7
8
  constructor(trace) {
8
9
  const findGoodFrame = (e) => {
9
10
  return !e.native && e.file && !e.file.includes("node:");
@@ -24,4 +25,3 @@ class Trace {
24
25
  }
25
26
  }
26
27
  exports.Trace = Trace;
27
- //# sourceMappingURL=trace.js.map
@@ -3,4 +3,3 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.TraceEmbedder = void 0;
4
4
  const _embedder_1 = require("../_embedder");
5
5
  exports.TraceEmbedder = new _embedder_1.Embedder("TRACED");
6
- //# sourceMappingURL=traced.js.map
@@ -19,4 +19,3 @@ var unit_parser_1 = require("./unit-parser");
19
19
  Object.defineProperty(exports, "UnitParser", { enumerable: true, get: function () { return unit_parser_1.UnitParser; } });
20
20
  Object.defineProperty(exports, "UnitValue", { enumerable: true, get: function () { return unit_parser_1.UnitValue; } });
21
21
  __exportStar(require("./units"), exports);
22
- //# sourceMappingURL=index.js.map
@@ -10,6 +10,9 @@ const pValueUnit = (0, parjs_1.int)().pipe((0, combinators_1.then)(pUnit), (0, c
10
10
  return { value, unit };
11
11
  }));
12
12
  class UnitValue {
13
+ unit;
14
+ value;
15
+ type;
13
16
  constructor(unit, value, type) {
14
17
  this.unit = unit;
15
18
  this.value = value;
@@ -24,19 +27,12 @@ class UnitValue {
24
27
  }
25
28
  exports.UnitValue = UnitValue;
26
29
  class UnitParser {
30
+ unitType;
31
+ _units;
32
+ parser;
27
33
  constructor(unitType, _units) {
28
34
  this.unitType = unitType;
29
35
  this._units = _units;
30
- this.parse = (input) => {
31
- const pUnitValue = this.parser;
32
- const result = pUnitValue.parse(input);
33
- if (result.kind !== "OK") {
34
- throw new error_1.InstrumentsError(`Failed to parse ${this.unitType}`, {
35
- more: result.trace.toString()
36
- });
37
- }
38
- return result.value;
39
- };
40
36
  this.parser = pValueUnit.pipe((0, combinators_1.map)(({ value, unit }) => {
41
37
  const gotType = this._units.has(unit);
42
38
  if (!gotType) {
@@ -45,9 +41,18 @@ class UnitParser {
45
41
  return new UnitValue(unit, value, this.unitType);
46
42
  }));
47
43
  }
44
+ parse = (input) => {
45
+ const pUnitValue = this.parser;
46
+ const result = pUnitValue.parse(input);
47
+ if (result.kind !== "OK") {
48
+ throw new error_1.InstrumentsError(`Failed to parse ${this.unitType}`, {
49
+ more: result.trace.toString()
50
+ });
51
+ }
52
+ return result.value;
53
+ };
48
54
  static make(unitType, units) {
49
55
  return new UnitParser(unitType, units);
50
56
  }
51
57
  }
52
58
  exports.UnitParser = UnitParser;
53
- //# sourceMappingURL=unit-parser.js.map
@@ -33,4 +33,3 @@ var Unit;
33
33
  Unit.Data = unit_parser_1.UnitParser.make("data", (0, immutable_1.Set)(["M", "G", "T", "K", "Mi", "Gi", "Ki"]));
34
34
  Unit.Time = unit_parser_1.UnitParser.make("time", (0, immutable_1.Set)(["m", "h", "d", "s", "ms"]));
35
35
  })(Unit || (exports.Unit = Unit = {}));
36
- //# sourceMappingURL=units.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@k8ts/instruments",
3
- "version": "0.2.1",
3
+ "version": "0.4.1",
4
4
  "description": "A collection of utilities and core components for k8ts.",
5
5
  "keywords": [
6
6
  "kubernetes",
@@ -54,7 +54,6 @@
54
54
  "test:coverage": "jest --coverage"
55
55
  },
56
56
  "dependencies": {
57
- "@k8ts/metadata": "^0.2.1",
58
57
  "chalk": "4.1.2",
59
58
  "dayjs": "^1.11.13",
60
59
  "doddle": "^5.0.0-beta.16",
@@ -65,6 +64,7 @@
65
64
  "stacktracey": "^2.1.8"
66
65
  },
67
66
  "devDependencies": {
67
+ "@k8ts/metadata": "^0.4.1",
68
68
  "@swc/core": "^1.11.11",
69
69
  "@swc/jest": "^0.2.37",
70
70
  "@types/jest": "^29.5.12",
@@ -80,7 +80,7 @@
80
80
  "yamprint": "^0.8.4"
81
81
  },
82
82
  "peerDependencies": {
83
- "@k8ts/metadata": "^0.1.0"
83
+ "@k8ts/metadata": "^0.4.1"
84
84
  },
85
85
  "packageManager": "yarn@4.1.1",
86
86
  "engines": {
@@ -34,7 +34,7 @@ export class Embedder<Target extends object, Value> {
34
34
  const input = this.tryGet(target)
35
35
  if (!input) {
36
36
  throw new Error(
37
- `Target of type ${target.constructor.name} doesn't have any embedded data for ${this.name}!`
37
+ `Target of type ${target} doesn't have any embedded data for ${this.name}!`
38
38
  )
39
39
  }
40
40
  return input
@@ -30,18 +30,37 @@ const interchangeable = {
30
30
  mac_char: "⌘ "
31
31
  }
32
32
 
33
- const colors = [chalk.red, chalk.green, chalk.yellow, chalk.blue, chalk.magenta, chalk.cyan]
33
+ const colors = [
34
+ chalk.redBright,
35
+ chalk.yellowBright,
36
+ chalk.blue,
37
+ chalk.magenta,
38
+ chalk.cyan,
39
+ chalk.blueBright
40
+ ]
34
41
 
35
42
  const numbered = Object.values(interchangeable)
36
43
 
37
- export function getMarkerForIndex(index: number, alias: string) {
38
- const clamedIndex = index % numbered.length
44
+ // We want to have symbols be as distinct as possible
45
+ // that means we use each symbol with a different color
46
+
47
+ // Instead of using all symbols of a single color, then all symbols of another color
48
+ // We mix it up, so we only get repeat colors after all symbols have been used
49
+
50
+ // we can get combinations of color + symbol like this:
51
+ // symbol = i % symbols.length
52
+ // color = (Math.floor(i / colors.length) + i)
53
+
54
+ export function getMarkerForIndex(index: number) {
55
+ const clampedIndex = index % numbered.length
39
56
  const multiplier = Math.floor(index / numbered.length)
40
- const char = numbered[clamedIndex]
41
- const color = colors[multiplier % colors.length]
42
- const marker = [char, alias].join(" ")
43
- const colored = color(marker)
44
- return colored
57
+ const char = numbered[clampedIndex]
58
+ const color = colors[(multiplier + clampedIndex) % colors.length]
59
+ const colored = color(char)
60
+ return `${colored} `
45
61
  }
46
62
 
47
- export const external = "∃"
63
+ export function getMarkerForExternal() {
64
+ const external = "∃"
65
+ return chalk.yellowBright(external)
66
+ }
@@ -0,0 +1,126 @@
1
+ import { doddle, DoddleAsync } from "doddle"
2
+ import { readFile } from "fs/promises"
3
+ import { Map } from "immutable"
4
+ import { dirname, join, resolve } from "path"
5
+ import StackTracey from "stacktracey"
6
+ import { InstrumentsError } from "../error"
7
+ export type LocalFileMode = "text" | "binary"
8
+
9
+ export interface LocalFileSourceProps<Mode extends LocalFileMode = "text"> {
10
+ pointOfCall: StackTracey
11
+ path: string
12
+ cwd?: string
13
+ mode?: Mode
14
+ }
15
+ export class LocalFileSource<Mode extends LocalFileMode = "text"> {
16
+ constructor(private readonly _props: LocalFileSourceProps<Mode>) {}
17
+
18
+ get cwd() {
19
+ if (this._props.cwd) {
20
+ return this._props.cwd
21
+ }
22
+ const where = this._props.pointOfCall.at(0)
23
+ return dirname(where.file)
24
+ }
25
+
26
+ get path() {
27
+ const where = this._props.pointOfCall.at(0)
28
+ const joined = join(dirname(where.file), this._props.path)
29
+ return resolve(joined)
30
+ }
31
+
32
+ contents = doddle(async () => {
33
+ const mode = this._props.mode ?? "text"
34
+ if (mode === "binary") {
35
+ const data = await readFile(this.path, null)
36
+ return data
37
+ }
38
+ return readFile(this.path, "utf-8")
39
+ }) as DoddleAsync<Mode extends "text" ? string : Uint8Array>
40
+ }
41
+
42
+ export function localFile<Mode extends LocalFileMode = "text">(
43
+ path: string,
44
+ props?: Pick<LocalFileSourceProps<Mode>, "cwd" | "mode">
45
+ ): LocalFileSource<Mode>
46
+ export function localFile(args: TemplateStringsArray, ...params: any[]): LocalFileSource<"text">
47
+ export function localFile(args: any, ...params: any[]) {
48
+ if (typeof args === "string") {
49
+ const options = params[0] ?? {}
50
+ return new LocalFileSource({
51
+ pointOfCall: new StackTracey().slice(1),
52
+ path: args,
53
+ ...(options ?? {})
54
+ })
55
+ }
56
+ const path = String.raw(args, ...params)
57
+ return new LocalFileSource({
58
+ pointOfCall: new StackTracey().slice(1),
59
+ path
60
+ })
61
+ }
62
+
63
+ export interface TypedArrayLike {
64
+ buffer: ArrayBuffer
65
+ byteLength: number
66
+ }
67
+ export type DataSource_Text = LocalFileSource<"text"> | string
68
+ export type DataSource_Binary = LocalFileSource<"binary"> | TypedArrayLike | ArrayBuffer
69
+ export type DataSourceRecord_Text = Record<string, DataSource_Text>
70
+ export type DataSourceRecord_Binary = Record<string, DataSource_Binary>
71
+ export type DataSourceRecord = DataSourceRecord_Text | DataSourceRecord_Binary
72
+ export function isTypedArray(data: DataSource_Binary): data is TypedArrayLike {
73
+ return (
74
+ typeof data === "object" &&
75
+ "buffer" in data &&
76
+ "byteSize" in data &&
77
+ typeof data.byteSize === "number"
78
+ )
79
+ }
80
+ export function isArrayBuffer(data: DataSource_Binary): data is ArrayBuffer {
81
+ return data instanceof ArrayBuffer
82
+ }
83
+ export interface DataSourceResolvedRecord {
84
+ data: Record<string, string>
85
+ binaryData: Record<string, Uint8Array>
86
+ }
87
+ type MaybePromise<T> = T | Promise<T>
88
+ async function promiseAllMap<K, V>(m: Map<K, MaybePromise<V>>) {
89
+ const promises = m.toArray().map(async x => [x[0], await x[1]] as [K, V])
90
+ const res = await Promise.all(promises)
91
+ return Map(res)
92
+ }
93
+ export async function resolveText(record: DataSourceRecord_Text) {
94
+ const mp = Map(record).map(async (v, k) => {
95
+ let resolved = v
96
+ if (v instanceof LocalFileSource) {
97
+ resolved = await v.contents.pull()
98
+ }
99
+ if (typeof resolved !== "string") {
100
+ throw new InstrumentsError(
101
+ `Got an invalid data value ${v} for key ${k}. Must be a string.`
102
+ )
103
+ }
104
+ return resolved
105
+ })
106
+ return promiseAllMap(mp)
107
+ }
108
+ export async function resolveBinary(record: DataSourceRecord_Binary) {
109
+ const mp = Map(record).map(async (v, k) => {
110
+ let resolved = v
111
+ if (v instanceof LocalFileSource) {
112
+ resolved = await v.contents.pull()
113
+ }
114
+ if (isTypedArray(resolved)) {
115
+ return new Uint8Array(resolved.buffer)
116
+ } else if (isArrayBuffer(resolved)) {
117
+ return new Uint8Array(resolved)
118
+ } else {
119
+ throw new InstrumentsError(
120
+ `Got an invalid data value ${v} for key ${k}. Must be binary data.`
121
+ )
122
+ }
123
+ })
124
+
125
+ return promiseAllMap(mp)
126
+ }
@@ -3,7 +3,7 @@ import { hash, Set } from "immutable"
3
3
  import { Kind } from "../api-kind"
4
4
  import { RefKey } from "../ref-key"
5
5
  import { ForwardRef } from "../reference"
6
- import { NeedsEdge } from "./dependencies"
6
+ import { Relation } from "./dependencies"
7
7
 
8
8
  export interface BaseEntity<Node extends BaseNode<Node>> {
9
9
  readonly node: Node
@@ -17,13 +17,14 @@ export abstract class BaseNode<
17
17
  Node extends BaseNode<Node, Entity>,
18
18
  Entity extends BaseEntity<Node> = BaseEntity<Node>
19
19
  > {
20
+ private _eqProxy = {}
20
21
  abstract readonly key: RefKey
21
22
  get kind() {
22
23
  return this.key.kind
23
24
  }
24
25
 
25
26
  abstract readonly kids: Seq<Node>
26
- abstract readonly needs: Seq<NeedsEdge<Node>>
27
+ abstract readonly relations: Seq<Relation<Node>>
27
28
  abstract readonly parent: Node | null
28
29
  protected get _asNode() {
29
30
  return this as any as Node
@@ -41,11 +42,11 @@ export abstract class BaseNode<
41
42
  return this.key.name
42
43
  }
43
44
  get isRoot() {
44
- return this.parent === null
45
+ return this.parent === null && this._entity.kind.name !== "PodTemplate"
45
46
  }
46
47
 
47
48
  hashCode() {
48
- return hash(this)
49
+ return hash(this._eqProxy)
49
50
  }
50
51
  equals(other: any) {
51
52
  if (ForwardRef.is(other)) {
@@ -97,25 +98,34 @@ export abstract class BaseNode<
97
98
  return this.equals(other) || Set(this.ancestors).has(other._asNode)
98
99
  }
99
100
 
100
- isNeeding(other: Node): boolean {
101
- return this.needsGraph.some(x => x.needed.equals(other)).pull()
101
+ hasRelationTo(other: Node): boolean {
102
+ return this.recursiveRelations.some(x => x.needed.equals(other)).pull()
102
103
  }
103
104
 
104
- readonly needsGraph = seq(() => {
105
+ readonly recursiveRelationsSubtree = seq((): Seq<Relation<Node>> => {
106
+ const self = this
107
+ return seq(function* () {
108
+ for (const child of [self, ...self.descendants] as Node[]) {
109
+ yield* child.recursiveRelations
110
+ }
111
+ }) as any
112
+ })
113
+
114
+ readonly recursiveRelations = seq(() => {
105
115
  let resources = Set<Node>()
106
- const recurseIntoDependency = function* (root: NeedsEdge<Node>): Iterable<NeedsEdge<Node>> {
116
+ const recurseIntoDependency = function* (root: Relation<Node>): Iterable<Relation<Node>> {
107
117
  yield root
108
118
  if (resources.has(root.needed)) {
109
119
  return
110
120
  }
111
121
  resources = resources.add(root.needed)
112
122
 
113
- const ownDeps = root.needed.needs
123
+ const ownDeps = root.needed.relations
114
124
  for (const needsEdge of ownDeps) {
115
125
  yield* recurseIntoDependency(needsEdge)
116
126
  }
117
127
  }
118
- return seq(recurseIntoDependency.bind(null, new NeedsEdge<Node>("self", this._asNode)))
128
+ return seq(recurseIntoDependency.bind(null, new Relation<Node>("self", this._asNode)))
119
129
  .after(() => {
120
130
  resources = Set()
121
131
  })
@@ -9,7 +9,7 @@ export namespace Dependencies {
9
9
  }
10
10
  export function dependencies(record: Dependencies.Input) {
11
11
  return Object.entries(record).map(([key, value]) => {
12
- return new NeedsEdge(key, value.node)
12
+ return new Relation(key, value.node)
13
13
  })
14
14
  }
15
15
  @displayers({
@@ -19,7 +19,7 @@ export function dependencies(record: Dependencies.Input) {
19
19
  return [`${chalk.gray.italic.white(`${dep.why}`)}`, "➜ ", chalk.italic(`${neededFmt}`)]
20
20
  }
21
21
  })
22
- export class NeedsEdge<Node extends BaseNode<Node>> {
22
+ export class Relation<Node extends BaseNode<Node>> {
23
23
  constructor(
24
24
  readonly why: string,
25
25
  readonly needed: Node
@@ -2,7 +2,7 @@ import { Meta } from "@k8ts/metadata"
2
2
  import chalk from "chalk"
3
3
  import { doddle, seq, Seq } from "doddle"
4
4
  import StackTracey from "stacktracey"
5
- import { getMarkerForIndex, toSuperScript } from "../_string"
5
+ import { getMarkerForExternal, getMarkerForIndex } from "../_string"
6
6
  import { displayers } from "../displayers"
7
7
  import { KindMap } from "../kind-map"
8
8
  import { RefKey } from "../ref-key"
@@ -14,16 +14,16 @@ import { ResourceNode } from "./resource-node"
14
14
  simple: s => `[${s.shortFqn}]`,
15
15
  prefix: s => {
16
16
  if (s.name === "EXTERNAL") {
17
- return "🌐"
17
+ return getMarkerForExternal()
18
18
  }
19
- return getMarkerForIndex(s.index, s._entity.alias ?? toSuperScript(s.index))
19
+ return getMarkerForIndex(s.index)
20
20
  },
21
21
  pretty(origin, format) {
22
22
  const kindName = chalk.greenBright.bold(origin.kind.name)
23
23
  const resourceName = chalk.cyan(origin.name)
24
24
  const pref = this.prefix!()
25
25
 
26
- return `${kindName}:${resourceName} (${pref})`
26
+ return chalk.underline(`${pref}${kindName}:${resourceName}`)
27
27
  }
28
28
  })
29
29
  export class Origin extends BaseNode<Origin, OriginEntity> implements Iterable<ResourceNode> {
@@ -54,7 +54,7 @@ export class Origin extends BaseNode<Origin, OriginEntity> implements Iterable<R
54
54
  private _kindMap: KindMap
55
55
  private _attached = [] as ResourceNode[]
56
56
 
57
- get needs() {
57
+ get relations() {
58
58
  return seq.empty()
59
59
  }
60
60
  [Symbol.iterator]() {
@@ -1,10 +1,10 @@
1
1
  import { Embedder } from "../_embedder/base"
2
- import { Dependencies, dependencies, NeedsEdge } from "./dependencies"
2
+ import { Dependencies, dependencies, Relation } from "./dependencies"
3
3
  import { ResourceEntity, ResourceNode } from "./resource-node"
4
4
 
5
5
  export namespace Relations {
6
6
  export interface Out {
7
- needs: () => Iterable<NeedsEdge<ResourceNode>>
7
+ needs: () => Iterable<Relation<ResourceNode>>
8
8
  parent: () => ResourceNode | null
9
9
  kids: () => ResourceNode[]
10
10
  }
@@ -19,18 +19,18 @@ import { Relations } from "./relations"
19
19
  }
20
20
  const resourceName = chalk.blueBright(resource.name)
21
21
  const mainPart = `${kindName}/${resourceName}`
22
- let originPart = ` (${displayers.get(resource.origin).prefix!()})`
22
+ let originPart = `${displayers.get(resource.origin).prefix!()}`
23
23
  let text = ""
24
24
 
25
25
  text += mainPart
26
26
  if (format !== "local") {
27
- text += originPart
27
+ text = `${originPart}${text}`
28
28
  }
29
29
  return text
30
30
  }
31
31
  })
32
32
  export class ResourceNode extends BaseNode<ResourceNode, ResourceEntity> {
33
- get needs() {
33
+ get relations() {
34
34
  return seq(this._relations.needs)
35
35
  }
36
36
 
@@ -1,67 +1,83 @@
1
+ import { displayers } from "../displayers"
2
+
1
3
  export type JoinIfNotEmpty<A extends string, J extends string, B extends string> = A extends ""
2
4
  ? B
3
5
  : B extends ""
4
6
  ? A
5
7
  : `${A}${J}${B}`
8
+ @displayers({
9
+ simple: s => s._url
10
+ })
6
11
  export class ImageHost<Text extends string = string> {
7
12
  private readonly _url: Text
8
13
  constructor(source: Text) {
9
14
  this._url = source
10
- this.toString = () => this[Symbol.toStringTag]
15
+ }
16
+
17
+ author<Author extends string>(name: Author) {
18
+ return new ImageAuthor<JoinIfNotEmpty<Text, "/", Author>>(this.toString(), name)
11
19
  }
12
20
 
13
21
  image<Image extends string>(name: Image) {
14
- return new BaseImage<JoinIfNotEmpty<Text, "/", Image>>(this, name)
22
+ return new BaseImage<JoinIfNotEmpty<Text, "/", Image>>(this.toString(), name)
15
23
  }
16
24
 
17
25
  get [Symbol.toStringTag]() {
18
26
  return this._url
19
27
  }
20
28
  }
29
+ @displayers({
30
+ simple: s => s._url
31
+ })
32
+ export class ImageAuthor<Text extends string = string> {
33
+ private readonly _url: Text
34
+ constructor(base: string, name: string) {
35
+ this._url = base === "" ? (name as Text) : ([base, name].join("/") as Text)
36
+ }
21
37
 
38
+ image<Image extends string>(name: Image) {
39
+ return new BaseImage<JoinIfNotEmpty<Text, "/", Image>>(this.toString(), name)
40
+ }
41
+ }
42
+ @displayers({
43
+ simple: s => {
44
+ if (!s._base) {
45
+ return s._name
46
+ }
47
+ return [s._base, s._name].join("/")
48
+ }
49
+ })
22
50
  export class BaseImage<Text extends string = string> {
23
51
  constructor(
24
- private readonly _source: ImageHost,
52
+ private readonly _base: string,
25
53
  private readonly _name: string
26
- ) {
27
- this.toString = () => this[Symbol.toStringTag]
28
- }
54
+ ) {}
29
55
 
30
56
  tag<Tag extends string>(tag: Tag) {
31
57
  return new TaggedImage<JoinIfNotEmpty<Text, ":", Tag>>(this, tag)
32
58
  }
33
-
34
- get [Symbol.toStringTag]() {
35
- if (this._source[Symbol.toStringTag] === "") {
36
- return this._name
59
+ }
60
+ @displayers({
61
+ simple: s => {
62
+ const fam = s._family.toString()
63
+ if (s._tag === "") {
64
+ return fam
37
65
  }
38
- return [this._source, this._name].join("/")
66
+ return [fam, s._tag].join(":")
39
67
  }
40
- }
41
-
68
+ })
42
69
  export class TaggedImage<Text extends string = string> {
43
70
  constructor(
44
71
  private readonly _family: BaseImage<string>,
45
72
  private readonly _tag: string
46
- ) {
47
- this.toString = () => this.text
48
- }
49
-
50
- get text() {
51
- const fam = this._family[Symbol.toStringTag]
52
- if (this._tag === "") {
53
- return fam
54
- }
55
- return [fam, this._tag].join(":")
56
- }
57
-
58
- get [Symbol.toStringTag]() {
59
- return this.text
60
- }
73
+ ) {}
61
74
  }
62
75
 
63
76
  export namespace Image {
64
- export function name<Name extends string>(name: Name) {
77
+ export function author<Author extends string>(name: Author) {
78
+ return new ImageHost("").author(name)
79
+ }
80
+ export function name<Name extends `${string}/${string}`>(name: Name) {
65
81
  return new ImageHost("").image(name)
66
82
  }
67
83
 
package/src/index.ts CHANGED
@@ -2,6 +2,7 @@ export * from "./_embedder"
2
2
  export * from "./_string"
3
3
  export * from "./api-kind"
4
4
  export * from "./cmd"
5
+ export * from "./data-sources"
5
6
  export * from "./displayers"
6
7
  export * from "./env"
7
8
  export * from "./forward-exports"
@@ -8,12 +8,13 @@ import {
8
8
  import { Embedder } from "../_embedder/base"
9
9
  import { MetadataEntity } from "../graph/resource-node"
10
10
 
11
+ type MaybePromise<T> = T | Promise<T>
11
12
  export namespace ManifestBuilder {
12
13
  export interface Out {
13
- body: () => PreManifest
14
- metadata: () => ManifestMetadata
14
+ body: () => MaybePromise<PreManifest>
15
+ metadata: () => Partial<ManifestMetadata>
15
16
  ident: () => ManifestIdentFields
16
- manifest: () => BaseManifest
17
+ manifest: () => MaybePromise<BaseManifest>
17
18
  }
18
19
 
19
20
  export type In<Target extends MetadataEntity = MetadataEntity> = Partial<{
@@ -52,11 +53,11 @@ class BuilderDecorator {
52
53
  }
53
54
  }
54
55
 
55
- manifest(trait: ManifestBuilder.Out, self: MetadataEntity) {
56
+ async manifest(trait: ManifestBuilder.Out, self: MetadataEntity) {
56
57
  const mani = {
57
58
  ...trait.ident(),
58
59
  metadata: trait.metadata(),
59
- ...trait.body()
60
+ ...(await trait.body())
60
61
  }
61
62
  ManifestSourceEmbedder.set(mani, self)
62
63
  return mani