@effected/toml 0.2.0 → 0.3.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 (3) hide show
  1. package/Toml.js +113 -31
  2. package/index.d.ts +87 -9
  3. package/package.json +1 -1
package/Toml.js CHANGED
@@ -4,7 +4,7 @@ import { parseExpressions } from "./internal/parser.js";
4
4
  import { buildValue } from "./internal/semantic.js";
5
5
  import { stringifyValue } from "./internal/stringifyValue.js";
6
6
  import { TomlDiagnostic } from "./TomlDiagnostic.js";
7
- import { Effect, Option, Schema, SchemaIssue, SchemaTransformation } from "effect";
7
+ import { Effect, Option, Result, Schema, SchemaIssue, SchemaTransformation } from "effect";
8
8
 
9
9
  //#region src/Toml.ts
10
10
  /**
@@ -54,34 +54,38 @@ var TomlStringifyError = class extends Schema.TaggedErrorClass()("TomlStringifyE
54
54
  * Run the parser and semantic pass, materializing the engine's raw carriers
55
55
  * into the typed error: `RawTomlError` becomes a positioned diagnostic and a
56
56
  * `GuardExceeded` depth trip becomes a `NestingDepthExceeded` diagnostic
57
- * (never an unhandled defect). Anything else is a genuine defect and rethrows.
57
+ * (never an unhandled defect). Anything else is a genuine defect and rethrows
58
+ * — synchronously to a `Result` caller, and as a `Die` through the `Effect`
59
+ * forms, which evaluate this inside the effect.
58
60
  */
59
- const parseOrFail = (text) => Effect.try({
60
- try: () => buildValue(parseExpressions(text)),
61
- catch: (defect) => {
62
- if (isRawTomlError(defect)) return new TomlParseError({ diagnostics: [TomlDiagnostic.fromRaw(text, defect.diagnostic)] });
63
- if (isGuardExceeded(defect)) return new TomlParseError({ diagnostics: [TomlDiagnostic.fromRaw(text, {
61
+ const parseToResult = (text) => {
62
+ try {
63
+ return Result.succeed(buildValue(parseExpressions(text)));
64
+ } catch (defect) {
65
+ if (isRawTomlError(defect)) return Result.fail(new TomlParseError({ diagnostics: [TomlDiagnostic.fromRaw(text, defect.diagnostic)] }));
66
+ if (isGuardExceeded(defect)) return Result.fail(new TomlParseError({ diagnostics: [TomlDiagnostic.fromRaw(text, {
64
67
  code: "NestingDepthExceeded",
65
68
  message: defect.message,
66
69
  offset: defect.offset,
67
70
  length: 0
68
- })] });
71
+ })] }));
69
72
  throw defect;
70
73
  }
71
- });
72
- const stringifyOrFail = (value, options) => Effect.try({
73
- try: () => stringifyValue(value, options?.newline ?? "\n"),
74
- catch: (defect) => {
75
- if (isRawTomlError(defect)) return new TomlStringifyError({ diagnostic: TomlDiagnostic.fromRaw("", defect.diagnostic) });
76
- if (isGuardExceeded(defect)) return new TomlStringifyError({ diagnostic: TomlDiagnostic.fromRaw("", {
74
+ };
75
+ const stringifyToResult = (value, options) => {
76
+ try {
77
+ return Result.succeed(stringifyValue(value, options?.newline ?? "\n"));
78
+ } catch (defect) {
79
+ if (isRawTomlError(defect)) return Result.fail(new TomlStringifyError({ diagnostic: TomlDiagnostic.fromRaw("", defect.diagnostic) }));
80
+ if (isGuardExceeded(defect)) return Result.fail(new TomlStringifyError({ diagnostic: TomlDiagnostic.fromRaw("", {
77
81
  code: "NestingDepthExceeded",
78
82
  message: defect.message,
79
83
  offset: 0,
80
84
  length: 0
81
- }) });
85
+ }) }));
82
86
  throw defect;
83
87
  }
84
- });
88
+ };
85
89
  /**
86
90
  * Static entry points for TOML parsing, stringification and the schema
87
91
  * factories. Not instantiable.
@@ -110,32 +114,110 @@ const stringifyOrFail = (value, options) => Effect.try({
110
114
  var Toml = class Toml {
111
115
  constructor() {}
112
116
  /**
113
- * Parse a TOML 1.1.0 document into a plain JavaScript value: tables and
114
- * inline tables become plain objects (`__proto__` lands as an own data
115
- * property), arrays become plain arrays, integers become `number` (or
116
- * `bigint` past 2^53) and date-times become the four `TomlDateTime`
117
- * classes. Fails with {@link TomlParseError} at the first violation;
118
- * returns `unknown`, never `any`.
117
+ * Parse a TOML 1.1.0 document into a plain JavaScript value, synchronously,
118
+ * returning a `Result` instead of an `Effect`: tables and inline tables
119
+ * become plain objects (`__proto__` lands as an own data property), arrays
120
+ * become plain arrays, integers become `number` (or `bigint` past 2^53) and
121
+ * date-times become the four `TomlDateTime` classes. Fails with
122
+ * {@link TomlParseError} at the first violation; returns `unknown`, never
123
+ * `any`.
119
124
  *
120
125
  * A nesting-depth bomb (arrays or inline tables past the engine cap) also
121
126
  * fails through {@link TomlParseError} with a `NestingDepthExceeded`
122
127
  * diagnostic, never as an unhandled defect.
128
+ *
129
+ * @remarks
130
+ * {@link Toml.parse} is defined in terms of this function; the two never
131
+ * diverge. Reach for the `Effect` variant inside Effect code — it carries
132
+ * the `Toml.parse` tracing span — and for this one at synchronous
133
+ * boundaries such as a lint-staged handler.
134
+ *
135
+ * @example
136
+ * ```ts
137
+ * import { Toml } from "@effected/toml";
138
+ * import { Result } from "effect";
139
+ *
140
+ * const ok = Toml.parseResult('name = "Alice"');
141
+ * if (Result.isSuccess(ok)) {
142
+ * console.log(ok.success); // => { name: "Alice" }
143
+ * }
144
+ *
145
+ * const bad = Toml.parseResult("name = ");
146
+ * if (Result.isFailure(bad)) {
147
+ * console.log(bad.failure._tag); // => "TomlParseError"
148
+ * }
149
+ * ```
150
+ *
151
+ * @param text - The TOML source to parse.
152
+ * @returns A `Result` succeeding with the decoded value (`unknown`, never
153
+ * `any`), or failing with {@link TomlParseError}.
154
+ */
155
+ static parseResult(text) {
156
+ return parseToResult(text);
157
+ }
158
+ /**
159
+ * Parse a TOML 1.1.0 document into a plain JavaScript value. Defined in
160
+ * terms of {@link Toml.parseResult} — synchronous callers can use that
161
+ * variant directly.
162
+ *
163
+ * @param text - The TOML source to parse.
164
+ * @returns An `Effect` that succeeds with the decoded value, or fails with
165
+ * {@link TomlParseError}.
123
166
  */
124
- static parse = Effect.fn("Toml.parse")(function* (text) {
125
- return yield* parseOrFail(text);
126
- });
167
+ static parse = Effect.fn("Toml.parse")((text) => Effect.fromResult(Toml.parseResult(text)));
127
168
  /**
128
- * Stringify a plain JavaScript value as a canonical TOML document: within
129
- * a table, non-table pairs first, then sub-tables as `[dotted.header]`
169
+ * Stringify a plain JavaScript value as a canonical TOML document,
170
+ * synchronously, returning a `Result` instead of an `Effect`: within a
171
+ * table, non-table pairs first, then sub-tables as `[dotted.header]`
130
172
  * sections depth-first, then arrays of tables as `[[dotted.header]]`
131
173
  * sections, a blank line before every header except at document start.
132
174
  * Fails with {@link TomlStringifyError} on unsupported values (TOML has no
133
175
  * null), out-of-int64-range `bigint`s, circular references and
134
176
  * depth-guard trips — all on the typed channel.
177
+ *
178
+ * @remarks
179
+ * {@link Toml.stringify} is defined in terms of this function; the two
180
+ * never diverge. Reach for the `Effect` variant inside Effect code — it
181
+ * carries the `Toml.stringify` tracing span — and for this one at
182
+ * synchronous boundaries.
183
+ *
184
+ * @example
185
+ * ```ts
186
+ * import { Toml } from "@effected/toml";
187
+ * import { Result } from "effect";
188
+ *
189
+ * const ok = Toml.stringifyResult({ name: "Alice" });
190
+ * if (Result.isSuccess(ok)) {
191
+ * console.log(ok.success); // => 'name = "Alice"\n'
192
+ * }
193
+ *
194
+ * const bad = Toml.stringifyResult({ nope: null });
195
+ * if (Result.isFailure(bad)) {
196
+ * console.log(bad.failure._tag); // => "TomlStringifyError"
197
+ * }
198
+ * ```
199
+ *
200
+ * @param value - The plain JavaScript value to stringify.
201
+ * @param options - Optional {@link TomlStringifyOptions}; `newline`
202
+ * defaults to `"\n"`.
203
+ * @returns A `Result` succeeding with the TOML text, or failing with
204
+ * {@link TomlStringifyError}.
205
+ */
206
+ static stringifyResult(value, options) {
207
+ return stringifyToResult(value, options);
208
+ }
209
+ /**
210
+ * Stringify a plain JavaScript value as a canonical TOML document. Defined
211
+ * in terms of {@link Toml.stringifyResult} — synchronous callers can use
212
+ * that variant directly.
213
+ *
214
+ * @param value - The plain JavaScript value to stringify.
215
+ * @param options - Optional {@link TomlStringifyOptions}; `newline`
216
+ * defaults to `"\n"`.
217
+ * @returns An `Effect` that succeeds with the TOML text, or fails with
218
+ * {@link TomlStringifyError}.
135
219
  */
136
- static stringify = Effect.fn("Toml.stringify")(function* (value, options) {
137
- return yield* stringifyOrFail(value, options);
138
- });
220
+ static stringify = Effect.fn("Toml.stringify")((value, options) => Effect.fromResult(Toml.stringifyResult(value, options)));
139
221
  /**
140
222
  * A `Schema<unknown, string>` decoding a TOML document and encoding values
141
223
  * back to canonical TOML text.
@@ -147,7 +229,7 @@ var Toml = class Toml {
147
229
  static fromString() {
148
230
  return Schema.String.pipe(Schema.decodeTo(Schema.Unknown, SchemaTransformation.transformOrFail({
149
231
  decode: (input) => Toml.parse(input).pipe(Effect.mapError((error) => new SchemaIssue.InvalidValue(Option.some(input), { message: error.message }))),
150
- encode: (value) => stringifyOrFail(value).pipe(Effect.mapError((error) => new SchemaIssue.InvalidValue(Option.some(value), { message: error.message })))
232
+ encode: (value) => Effect.fromResult(Toml.stringifyResult(value)).pipe(Effect.mapError((error) => new SchemaIssue.InvalidValue(Option.some(value), { message: error.message })))
151
233
  })));
152
234
  }
153
235
  /**
package/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Data, Effect, Schema, Stream } from "effect";
1
+ import { Data, Effect, Result, Schema, Stream } from "effect";
2
2
  //#region src/TomlDiagnostic.d.ts
3
3
  /**
4
4
  * Error codes emitted by the lexer stage.
@@ -186,26 +186,104 @@ interface TomlBoundCodec<T, RD = never, RE = never> {
186
186
  declare class Toml {
187
187
  private constructor();
188
188
  /**
189
- * Parse a TOML 1.1.0 document into a plain JavaScript value: tables and
190
- * inline tables become plain objects (`__proto__` lands as an own data
191
- * property), arrays become plain arrays, integers become `number` (or
192
- * `bigint` past 2^53) and date-times become the four `TomlDateTime`
193
- * classes. Fails with {@link TomlParseError} at the first violation;
194
- * returns `unknown`, never `any`.
189
+ * Parse a TOML 1.1.0 document into a plain JavaScript value, synchronously,
190
+ * returning a `Result` instead of an `Effect`: tables and inline tables
191
+ * become plain objects (`__proto__` lands as an own data property), arrays
192
+ * become plain arrays, integers become `number` (or `bigint` past 2^53) and
193
+ * date-times become the four `TomlDateTime` classes. Fails with
194
+ * {@link TomlParseError} at the first violation; returns `unknown`, never
195
+ * `any`.
195
196
  *
196
197
  * A nesting-depth bomb (arrays or inline tables past the engine cap) also
197
198
  * fails through {@link TomlParseError} with a `NestingDepthExceeded`
198
199
  * diagnostic, never as an unhandled defect.
200
+ *
201
+ * @remarks
202
+ * {@link Toml.parse} is defined in terms of this function; the two never
203
+ * diverge. Reach for the `Effect` variant inside Effect code — it carries
204
+ * the `Toml.parse` tracing span — and for this one at synchronous
205
+ * boundaries such as a lint-staged handler.
206
+ *
207
+ * @example
208
+ * ```ts
209
+ * import { Toml } from "@effected/toml";
210
+ * import { Result } from "effect";
211
+ *
212
+ * const ok = Toml.parseResult('name = "Alice"');
213
+ * if (Result.isSuccess(ok)) {
214
+ * console.log(ok.success); // => { name: "Alice" }
215
+ * }
216
+ *
217
+ * const bad = Toml.parseResult("name = ");
218
+ * if (Result.isFailure(bad)) {
219
+ * console.log(bad.failure._tag); // => "TomlParseError"
220
+ * }
221
+ * ```
222
+ *
223
+ * @param text - The TOML source to parse.
224
+ * @returns A `Result` succeeding with the decoded value (`unknown`, never
225
+ * `any`), or failing with {@link TomlParseError}.
226
+ */
227
+ static parseResult(text: string): Result.Result<unknown, TomlParseError>;
228
+ /**
229
+ * Parse a TOML 1.1.0 document into a plain JavaScript value. Defined in
230
+ * terms of {@link Toml.parseResult} — synchronous callers can use that
231
+ * variant directly.
232
+ *
233
+ * @param text - The TOML source to parse.
234
+ * @returns An `Effect` that succeeds with the decoded value, or fails with
235
+ * {@link TomlParseError}.
199
236
  */
200
237
  static readonly parse: (text: string) => Effect.Effect<unknown, TomlParseError, never>;
201
238
  /**
202
- * Stringify a plain JavaScript value as a canonical TOML document: within
203
- * a table, non-table pairs first, then sub-tables as `[dotted.header]`
239
+ * Stringify a plain JavaScript value as a canonical TOML document,
240
+ * synchronously, returning a `Result` instead of an `Effect`: within a
241
+ * table, non-table pairs first, then sub-tables as `[dotted.header]`
204
242
  * sections depth-first, then arrays of tables as `[[dotted.header]]`
205
243
  * sections, a blank line before every header except at document start.
206
244
  * Fails with {@link TomlStringifyError} on unsupported values (TOML has no
207
245
  * null), out-of-int64-range `bigint`s, circular references and
208
246
  * depth-guard trips — all on the typed channel.
247
+ *
248
+ * @remarks
249
+ * {@link Toml.stringify} is defined in terms of this function; the two
250
+ * never diverge. Reach for the `Effect` variant inside Effect code — it
251
+ * carries the `Toml.stringify` tracing span — and for this one at
252
+ * synchronous boundaries.
253
+ *
254
+ * @example
255
+ * ```ts
256
+ * import { Toml } from "@effected/toml";
257
+ * import { Result } from "effect";
258
+ *
259
+ * const ok = Toml.stringifyResult({ name: "Alice" });
260
+ * if (Result.isSuccess(ok)) {
261
+ * console.log(ok.success); // => 'name = "Alice"\n'
262
+ * }
263
+ *
264
+ * const bad = Toml.stringifyResult({ nope: null });
265
+ * if (Result.isFailure(bad)) {
266
+ * console.log(bad.failure._tag); // => "TomlStringifyError"
267
+ * }
268
+ * ```
269
+ *
270
+ * @param value - The plain JavaScript value to stringify.
271
+ * @param options - Optional {@link TomlStringifyOptions}; `newline`
272
+ * defaults to `"\n"`.
273
+ * @returns A `Result` succeeding with the TOML text, or failing with
274
+ * {@link TomlStringifyError}.
275
+ */
276
+ static stringifyResult(value: unknown, options?: TomlStringifyOptions): Result.Result<string, TomlStringifyError>;
277
+ /**
278
+ * Stringify a plain JavaScript value as a canonical TOML document. Defined
279
+ * in terms of {@link Toml.stringifyResult} — synchronous callers can use
280
+ * that variant directly.
281
+ *
282
+ * @param value - The plain JavaScript value to stringify.
283
+ * @param options - Optional {@link TomlStringifyOptions}; `newline`
284
+ * defaults to `"\n"`.
285
+ * @returns An `Effect` that succeeds with the TOML text, or fails with
286
+ * {@link TomlStringifyError}.
209
287
  */
210
288
  static readonly stringify: (value: unknown, options?: TomlStringifyOptions | undefined) => Effect.Effect<string, TomlStringifyError, never>;
211
289
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@effected/toml",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "private": false,
5
5
  "description": "TOML 1.1.0 parsing, editing and formatting as Effect schemas: typed diagnostics, a lossless CST and first-class date-time values.",
6
6
  "keywords": [