@thinair/factory 0.1.170 → 0.1.177

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/cli/evaluate.ts CHANGED
@@ -26,12 +26,8 @@ export const EvaluateInput = Schema.Struct({
26
26
  });
27
27
  export type EvaluateInput = typeof EvaluateInput.Type;
28
28
 
29
- const EvaluateNotice = Schema.Struct({ node: Schema.NullOr(NodeId), at: Schema.NullOr(SourceAt), message: Schema.String });
30
-
31
29
  export const EvaluateOutput = Schema.Struct({
32
30
  program: Schema.NullOr(Program),
33
- /** Notes that hold nothing: a retired constructor the code still calls runs as its replacement. */
34
- notices: Schema.Array(EvaluateNotice),
35
31
  problems: Schema.Array(Schema.Struct({
36
32
  /** `evaluate`: the code threw while it loaded. `value`: the encoder's checks. */
37
33
  step: Schema.Literals(["evaluate", "value"]),
@@ -77,13 +73,12 @@ const evaluate = Effect.fn("factory.evaluate")(function* (inputPath: string) {
77
73
  hash: (text) => createHash("sha256").update(text).digest("hex"),
78
74
  files: input.files,
79
75
  });
80
- return { program: encoded.program, notices: encoded.notices, problems: encoded.problems.map((problem) => ({ step: "value" as const, ...problem })) };
76
+ return { program: encoded.program, problems: encoded.problems.map((problem) => ({ step: "value" as const, ...problem })) };
81
77
  },
82
78
  catch: (error) => error,
83
79
  })),
84
80
  Effect.catch((error) => Effect.succeed<EvaluateOutput>({
85
81
  program: null,
86
- notices: [],
87
82
  problems: [{ step: "evaluate", node: null, at: throwAt(error, input.tree), message: `The factory's code threw while it loaded: ${error instanceof Error ? error.message : String(error)}` }],
88
83
  })),
89
84
  );
package/cli/load.ts CHANGED
@@ -6,7 +6,7 @@ import { createRequire } from "node:module";
6
6
  import path from "node:path";
7
7
  import { fileURLToPath } from "node:url";
8
8
  import { Context, Effect, Layer, Result, Schema } from "effect";
9
- import { holds, LOAD_VERSION, LoadJson, LoadPost, type Finding, type Load } from "../domain/load";
9
+ import { LOAD_VERSION, LoadJson, LoadPost, type Finding, type Load } from "../domain/load";
10
10
  import { appShapeProblems, AUTHORING_MODULES, folderKey, IGNORED_FOLDERS, isLoadedPath, memberFiles } from "../domain/system-elements/app-shape";
11
11
  import { FrameworkVersion, holesOf, type Node, type Program } from "../domain/system-elements/program";
12
12
  import { EvaluateOutputJson, type EvaluateInput } from "./evaluate";
@@ -272,7 +272,6 @@ const evaluate = Effect.fn("factory.load.evaluate")(function* (input: Omit<Evalu
272
272
  program: output.program,
273
273
  findings: [
274
274
  ...output.problems.map((problem) => finding(problem.step, problem.message, { node: problem.node, file: problem.at?.file ?? null, line: problem.at?.line ?? null })),
275
- ...output.notices.map((notice) => ({ ...finding("value", notice.message, { node: notice.node, file: notice.at?.file ?? null, line: notice.at?.line ?? null }), notice: true as const })),
276
275
  ],
277
276
  };
278
277
  });
@@ -357,7 +356,7 @@ export const loadFactory = Effect.fn("factory.load")(function* (input: Readonly<
357
356
 
358
357
  const load: Load = yield* timed(steps, "encode", Effect.sync((): Load => {
359
358
  const all = findings.map(pinned(program));
360
- return { version: LOAD_VERSION, framework, key: snapshot.key, state: all.some(holds) ? "held" : "ready", program, holes: program === null ? [] : holesOf(program), findings: all, cached: false, steps };
359
+ return { version: LOAD_VERSION, framework, key: snapshot.key, state: all.length > 0 ? "held" : "ready", program, holes: program === null ? [] : holesOf(program), findings: all, cached: false, steps };
361
360
  }));
362
361
  const encoded = yield* Schema.encodeEffect(LoadJson)(load).pipe(Effect.mapError((error) => new FactoryLoadFailed({ message: `The load does not encode: ${error.message}` })));
363
362
  yield* Effect.tryPromise({ try: () => mkdir(path.dirname(cacheFile), { recursive: true }).then(() => writeFile(cacheFile, JSON.stringify(encoded))), catch: failed("Could not write the load cache.") });
package/domain/load.ts CHANGED
@@ -22,12 +22,7 @@ export const Finding = Schema.Struct({
22
22
  file: Schema.NullOr(Schema.String),
23
23
  line: Schema.NullOr(Schema.Int),
24
24
  message: Schema.String,
25
- /** A note that holds nothing: the code still runs as written (a retired constructor runs as its replacement). */
26
- notice: Schema.optionalKey(Schema.Literal(true)),
27
25
  });
28
-
29
- /** Whether a finding holds the load: every finding but a notice does. */
30
- export const holds = (finding: Readonly<{ notice?: true | undefined }>) => finding.notice !== true;
31
26
  export type Finding = typeof Finding.Type;
32
27
 
33
28
  /** `ready` runs (live) or draws (preview). `held` keeps the last good revision: its findings say why. */
@@ -158,8 +158,6 @@ export interface Encoder {
158
158
  readonly ref: <T extends NodeTag>(to: T, value: Slot<T>) => Ref<T>;
159
159
  /** A problem with this node's settings, pinned to it. */
160
160
  readonly problem: (message: string) => void;
161
- /** A note on this node that holds nothing, pinned to it: its code still runs as written. */
162
- readonly notice: (message: string) => void;
163
161
  }
164
162
 
165
163
  /** The rows a floor reads, by the node each belongs to. The records name their nodes by id. */
@@ -1,5 +1,5 @@
1
1
  import { Schema } from "effect";
2
- import { AUTHORED, authoredHead, head, type Authored, type Encoder, type LiveRows } from "./node";
2
+ import { AUTHORED, authoredHead, head, type Authored, type LiveRows } from "./node";
3
3
 
4
4
  /*
5
5
  * A pool names a provider and an optional narrowing, nothing else.
@@ -13,19 +13,11 @@ import { AUTHORED, authoredHead, head, type Authored, type Encoder, type LiveRow
13
13
  */
14
14
 
15
15
  export const PROVIDERS = ["fleet", "github-actions"] as const;
16
- /**
17
- * Providers a program stored before one `fleet` took their place may still name (`pool:macs`, `pool:thinair-cloud`,
18
- * `pool:namespace`): read so a running factory's program stays readable until its next live load, never authored.
19
- * Placement reads `macs` and `thinair-cloud` as `fleet`; `namespace` never had a filling.
20
- */
21
- export const RETIRED_PROVIDERS = ["macs", "thinair-cloud", "namespace"] as const;
22
- export const Provider = Schema.Literals([...PROVIDERS, ...RETIRED_PROVIDERS]);
16
+ export const Provider = Schema.Literals(PROVIDERS);
23
17
  export type Provider = typeof Provider.Type;
24
- export type AuthoredProvider = (typeof PROVIDERS)[number];
25
- export type RetiredProvider = (typeof RETIRED_PROVIDERS)[number];
26
18
 
27
- /** Whether a pool names the owner's fleet: `fleet`, or a retired name that meant part of it. */
28
- export const isFleet = (provider: Provider) => provider === "fleet" || provider === "macs" || provider === "thinair-cloud";
19
+ /** Whether a pool names the owner's fleet. */
20
+ export const isFleet = (provider: Provider) => provider === "fleet";
29
21
 
30
22
  export const Os = Schema.Literals(["mac", "linux", "windows"]);
31
23
  export type Os = typeof Os.Type;
@@ -39,37 +31,21 @@ export type Narrowing = typeof Narrowing.Type;
39
31
  export const Node = Schema.TaggedStruct("Pool", { ...head, provider: Provider, ...Narrowing.fields });
40
32
  export type Node = typeof Node.Type;
41
33
 
42
- export interface AuthoredPool<P extends AuthoredProvider = AuthoredProvider> extends Authored<"Pool", string> {
34
+ export interface AuthoredPool<P extends Provider = Provider> extends Authored<"Pool", string> {
43
35
  readonly provider: P;
44
36
  readonly os: ReadonlyArray<Os>;
45
37
  readonly arch: ReadonlyArray<Arch>;
46
- /** The retired constructor that made it, when one did: it runs as the fleet, and the load says so. */
47
- readonly retired?: RetiredProvider;
48
38
  }
49
39
 
50
40
  type Narrow = Readonly<{ os?: ReadonlyArray<Os>; arch?: ReadonlyArray<Arch> }>;
51
41
 
52
- const made = <const P extends AuthoredProvider>(provider: P, narrow: Narrow | undefined): AuthoredPool<P> => ({
42
+ const made = <const P extends Provider>(provider: P, narrow: Narrow | undefined): AuthoredPool<P> => ({
53
43
  [AUTHORED]: authoredHead("Pool", provider, false),
54
44
  provider,
55
45
  os: narrow?.os ?? [],
56
46
  arch: narrow?.arch ?? [],
57
47
  });
58
48
 
59
- /**
60
- * A retired constructor, kept so code written before one fleet still loads and its passes still run: it makes the
61
- * fleet with the same narrowing, under its own name (`pool:macs`), so its node and every Ref to it stay as they were.
62
- */
63
- const retired = (name: RetiredProvider) => (narrow?: Narrow): AuthoredPool<"fleet"> => ({
64
- [AUTHORED]: authoredHead("Pool", name, false),
65
- provider: "fleet",
66
- os: narrow?.os ?? [],
67
- arch: narrow?.arch ?? [],
68
- retired: name,
69
- });
70
-
71
- const RETIRED_CALL: Readonly<Record<RetiredProvider, string>> = { macs: "pool.macs()", "thinair-cloud": "pool.thinairCloud()", namespace: "pool.namespace()" };
72
-
73
49
  /** The pools a factory can name. Each is named after its provider: `pool:fleet`. */
74
50
  export const pool = {
75
51
  /**
@@ -81,19 +57,9 @@ export const pool = {
81
57
  fleet: (narrow?: Narrow) => made("fleet", narrow),
82
58
  /** GitHub Actions runners, dispatched with the Agents App. */
83
59
  githubActions: (narrow?: Narrow) => made("github-actions", narrow),
84
- /** @deprecated The fleet: use `pool.fleet()`. It makes the fleet with this narrowing, and the load says so. */
85
- macs: retired("macs"),
86
- /** @deprecated The fleet, which Thinair Cloud joins once the owner names the factory's Cloud Organization: use `pool.fleet()`. */
87
- thinairCloud: retired("thinair-cloud"),
88
- /** @deprecated Never had a filling: use `pool.fleet()`. It makes the fleet with this narrowing, and the load says so. */
89
- namespace: retired("namespace"),
90
60
  };
91
61
 
92
- export const make = (authored: AuthoredPool, encoder: Encoder) => {
93
- if (authored.retired !== undefined)
94
- encoder.notice(`${RETIRED_CALL[authored.retired]} is pool.fleet() now: it runs as the fleet with the same narrowing. Rename it to pool.fleet().`);
95
- return { provider: authored.provider, os: [...authored.os], arch: [...authored.arch] };
96
- };
62
+ export const make = (authored: AuthoredPool) => ({ provider: authored.provider, os: [...authored.os], arch: [...authored.arch] });
97
63
 
98
64
  /** The machines placement can use now, from their own facts. */
99
65
  export const live = (node: Node, rows: LiveRows) => {
@@ -67,7 +67,7 @@ export type EncodeOptions = Readonly<{
67
67
  files: Readonly<Record<string, FileFacts>>;
68
68
  }>;
69
69
 
70
- export type Encoded = Readonly<{ program: Program | null; problems: ReadonlyArray<EncodeProblem>; notices: ReadonlyArray<EncodeProblem> }>;
70
+ export type Encoded = Readonly<{ program: Program | null; problems: ReadonlyArray<EncodeProblem> }>;
71
71
 
72
72
  /** JSON with keys sorted at every level: two values are the same when this is. */
73
73
  const canonicalJson = (value: unknown): string => JSON.stringify(value, (_key, item: unknown) =>
@@ -80,7 +80,6 @@ type Draft = Readonly<{ node: Readonly<Record<string, unknown>> & { readonly at:
80
80
  /** Encode a factory's root, as `factory.ts` exports it, into its Program. */
81
81
  export const encodeFactory = (root: unknown, options: EncodeOptions): Encoded => {
82
82
  const problems: EncodeProblem[] = [];
83
- const notices: EncodeProblem[] = [];
84
83
  const drafts = new Map<NodeId, Draft>();
85
84
  const encodedValues = new Map<object, NodeId>();
86
85
  const visiting = new Set<object>();
@@ -118,7 +117,6 @@ export const encodeFactory = (root: unknown, options: EncodeOptions): Encoded =>
118
117
  const encoder: Encoder = {
119
118
  ref: (tag, slot) => encode(tag, slot, { node: id, at }),
120
119
  problem: (message) => problems.push({ node: id, at, message }),
121
- notice: (message) => notices.push({ node: id, at, message }),
122
120
  };
123
121
  const settings = (definitions[made.tag] as Definition<Tag>).make(value as never, encoder);
124
122
  visiting.delete(value);
@@ -134,10 +132,10 @@ export const encodeFactory = (root: unknown, options: EncodeOptions): Encoded =>
134
132
 
135
133
  if (!isAuthored(root) || headOf(root).tag !== "Factory") {
136
134
  problems.push({ node: null, at: { file: "factory.ts", line: 1 }, message: "factory.ts's default export is the factory: export default defineFactory({ ... })." });
137
- return { program: null, problems, notices };
135
+ return { program: null, problems };
138
136
  }
139
137
  encode("Factory", root, null);
140
- if (broken) return { program: null, problems, notices };
138
+ if (broken) return { program: null, problems };
141
139
 
142
140
  // A node's digest covers its content and, when it holds code, the import closure of its file,
143
141
  // stopping at files that make other nodes: those nodes have digests of their own.
@@ -167,9 +165,9 @@ export const encodeFactory = (root: unknown, options: EncodeOptions): Encoded =>
167
165
  const decoded = Schema.decodeUnknownResult(Program)({ version: LANGUAGE_VERSION, framework: options.framework, root: ROOT_ID, nodes });
168
166
  if (Result.isFailure(decoded)) {
169
167
  problems.push({ node: null, at: null, message: `The program does not decode: ${decoded.failure.message}` });
170
- return { program: null, problems, notices };
168
+ return { program: null, problems };
171
169
  }
172
170
  for (const problem of graphProblems(decoded.success))
173
171
  problems.push({ node: problem.node, at: (decoded.success.nodes[problem.node] as Node | undefined)?.at ?? null, message: problem.message });
174
- return { program: decoded.success, problems, notices };
172
+ return { program: decoded.success, problems };
175
173
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thinair/factory",
3
- "version": "0.1.170",
3
+ "version": "0.1.177",
4
4
  "description": "The Thinair factory SDK: the language a factory's code is written in, and the loader that checks it.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",