@distilled.cloud/core 1.0.0-rc.3 → 1.0.0-rc.4

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@distilled.cloud/core",
3
- "version": "1.0.0-rc.3",
3
+ "version": "1.0.0-rc.4",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/alchemy-run/distilled",
@@ -31,12 +31,12 @@
31
31
  "build": "tsc -b"
32
32
  },
33
33
  "devDependencies": {
34
- "@effect/platform-bun": ">=4.0.0-beta.102 || >=4.0.0",
34
+ "@effect/platform-bun": ">=4.0.0-beta.104 || >=4.0.0",
35
35
  "@types/bun": "latest",
36
36
  "@types/node": "latest",
37
- "effect": ">=4.0.0-beta.102 || >=4.0.0"
37
+ "effect": ">=4.0.0-beta.104 || >=4.0.0"
38
38
  },
39
39
  "peerDependencies": {
40
- "effect": ">=4.0.0-beta.102 || >=4.0.0"
40
+ "effect": ">=4.0.0-beta.104 || >=4.0.0"
41
41
  }
42
42
  }
package/src/category.ts CHANGED
@@ -9,7 +9,7 @@
9
9
  * ```ts
10
10
  * import * as Category from "@distilled.cloud/core/category";
11
11
  *
12
- * export class Unauthorized extends Schema.TaggedErrorClass<Unauthorized>()(
12
+ * export class Unauthorized extends Schema.TaggedError<Unauthorized>()(
13
13
  * "Unauthorized",
14
14
  * { message: Schema.String },
15
15
  * ).pipe(Category.withAuthError) {}
@@ -92,7 +92,7 @@ export interface RetryableInfo {
92
92
  *
93
93
  * @example
94
94
  * ```ts
95
- * export class MyError extends Schema.TaggedErrorClass<MyError>()(
95
+ * export class MyError extends Schema.TaggedError<MyError>()(
96
96
  * "MyError",
97
97
  * { message: Schema.String },
98
98
  * ).pipe(Category.withCategory(Category.AuthError)) {}
@@ -123,13 +123,13 @@ export const withCategory =
123
123
  * @example
124
124
  * ```ts
125
125
  * // Standard retryable error
126
- * export class TransientError extends Schema.TaggedErrorClass<TransientError>()(
126
+ * export class TransientError extends Schema.TaggedError<TransientError>()(
127
127
  * "TransientError",
128
128
  * { message: Schema.String },
129
129
  * ).pipe(Category.withRetryable()) {}
130
130
  *
131
131
  * // Throttling error (uses longer backoff)
132
- * export class RateLimitError extends Schema.TaggedErrorClass<RateLimitError>()(
132
+ * export class RateLimitError extends Schema.TaggedError<RateLimitError>()(
133
133
  * "RateLimitError",
134
134
  * { message: Schema.String },
135
135
  * ).pipe(Category.withRetryable({ throttling: true })) {}
@@ -9,7 +9,7 @@
9
9
  * .annotate({ identifier: "X" })
10
10
  * as any as S.Schema<X>; // no inference needed
11
11
  *
12
- * plus closed-alias string-union enums, `S.TaggedErrorClass` error classes, and
12
+ * plus closed-alias string-union enums, `S.TaggedError` error classes, and
13
13
  * `API.make(() => ({ … }))` operation consts. The helpers here own those
14
14
  * shared skeletons; providers own the content strings (member pipes, trait
15
15
  * calls, config fields). Emitted output is normalized by oxfmt afterwards,
@@ -120,7 +120,7 @@ export interface ErrorClassOptions {
120
120
  }
121
121
 
122
122
  /**
123
- * `export class X extends /*@__PURE__*​/ S.TaggedErrorClass<X>()("X", { … }) {}`
123
+ * `export class X extends /*@__PURE__*​/ S.TaggedError<X>()("X", { … }) {}`
124
124
  *
125
125
  * The PURE markers are what make an unused error class droppable. A class
126
126
  * whose heritage clause is an unannotated call can never be tree-shaken —
@@ -130,12 +130,12 @@ export interface ErrorClassOptions {
130
130
  *
131
131
  * `wrap` needs its own marker as well as the inner one: a pure call's
132
132
  * ARGUMENTS are still evaluated, so annotating only
133
- * `T.applyErrorMatchers(S.TaggedErrorClass…(…), […])` leaves the inner call
133
+ * `T.applyErrorMatchers(S.TaggedError…(…), […])` leaves the inner call
134
134
  * holding the class alive. Verified against esbuild in both directions.
135
135
  */
136
136
  export const errorClass = (o: ErrorClassOptions): string => {
137
137
  const annotations = o.annotations ? `,\n${o.annotations}` : "";
138
- const cls = `${PURE}S.TaggedErrorClass<${o.name}>()(${q(o.tag ?? o.name)}, {\n${o.fields.join("\n")}\n}${annotations})${o.pipes ?? ""}`;
138
+ const cls = `${PURE}S.TaggedError<${o.name}>()(${q(o.tag ?? o.name)}, {\n${o.fields.join("\n")}\n}${annotations})${o.pipes ?? ""}`;
139
139
  const body = o.wrap ? `${PURE}${o.wrap(cls)}` : cls;
140
140
  return `export class ${o.name} extends ${body} {}\n`;
141
141
  };
@@ -1030,14 +1030,26 @@ export const generateService = (
1030
1030
  // No items path: `.items()` is a page passthrough at runtime, so an
1031
1031
  // item IS a whole response.
1032
1032
  if (!itemsPath) return tsRef(outputId);
1033
- let def = shapes[outputId];
1033
+ let id: string = outputId;
1034
+ // Whether the path crossed a list on the way down (`"edges.node"` on a
1035
+ // Relay connection). When it did, the path itself is what fans out, so
1036
+ // the value it lands on IS one item — it needn't be a list again.
1037
+ let fannedOut = false;
1034
1038
  for (const segment of itemsPath.split(".")) {
1039
+ let def: any = shapes[id];
1040
+ if (def?.type === "list") {
1041
+ id = def.member.target as string;
1042
+ def = shapes[id];
1043
+ fannedOut = true;
1044
+ }
1035
1045
  if (def?.type !== "structure") return undefined;
1036
1046
  const info = memberInfos(def).find((m) => m.tsName === segment);
1037
1047
  if (!info) return undefined;
1038
- def = shapes[info.target];
1048
+ id = info.target;
1039
1049
  }
1040
- return def?.type === "list" ? tsRef(def.member.target) : undefined;
1050
+ const last: any = shapes[id];
1051
+ if (last?.type === "list") return tsRef(last.member.target);
1052
+ return fannedOut ? tsRef(id) : undefined;
1041
1053
  };
1042
1054
 
1043
1055
  const emitOperation =