@jfdevelops/create-error 0.1.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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Joey F.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,294 @@
1
+ # @jfdevelops/create-error
2
+
3
+ Create strongly typed, configurable error families from any synchronous
4
+ [Standard Schema](https://standardschema.dev/schema) object.
5
+
6
+ ## Install
7
+
8
+ ```sh
9
+ pnpm add @jfdevelops/create-error
10
+ ```
11
+
12
+ Bring your own Standard Schema-compatible validation library, such as Zod,
13
+ Valibot, or ArkType. `create-error` does not bundle one.
14
+
15
+ ## Quick start
16
+
17
+ ```ts
18
+ import { createError } from '@jfdevelops/create-error';
19
+ import { z } from 'zod';
20
+
21
+ const createFormError = createError({
22
+ definition: z.object({
23
+ code: z.string(),
24
+ scope: z.string(),
25
+ }),
26
+ data: {
27
+ property: 'context',
28
+ resolve({ definition, input }) {
29
+ return { ...input, scope: definition.scope };
30
+ },
31
+ },
32
+ message({ definition, data, implementation }) {
33
+ return implementation({
34
+ context: data,
35
+ scope: definition.scope,
36
+ });
37
+ },
38
+ properties({ definition, data, implementation }) {
39
+ return {
40
+ code: definition.code,
41
+ scope: definition.scope,
42
+ context: data,
43
+ renderMessage(renderer = implementation) {
44
+ return renderer({
45
+ context: data,
46
+ scope: definition.scope,
47
+ });
48
+ },
49
+ };
50
+ },
51
+ toJSON(error) {
52
+ return {
53
+ name: error.name,
54
+ code: error.code,
55
+ scope: error.scope,
56
+ message: error.message,
57
+ context: error.context,
58
+ };
59
+ },
60
+ });
61
+
62
+ export const FormError = createFormError.Error;
63
+
64
+ export class InvalidFieldError extends createFormError({
65
+ code: 'invalidField',
66
+ scope: 'field',
67
+ })
68
+ .defineContext(
69
+ z.object({
70
+ field: z.string(),
71
+ scope: z.literal('field'),
72
+ }),
73
+ )
74
+ .implement(
75
+ ({ code, context }) => `${code}: ${context.field} is invalid`,
76
+ ) {}
77
+
78
+ const error = new InvalidFieldError({ field: 'email' });
79
+
80
+ error.code; // "invalidField"
81
+ error.scope; // "field"
82
+ error.context; // { field: string; scope: "field" }
83
+ error instanceof Error; // true
84
+ error instanceof FormError; // true
85
+ ```
86
+
87
+ No explicit generic arguments or `as const` assertions are needed. Definition
88
+ inputs are checked by the schema, and definition-derived fields use its parsed
89
+ output type so transformations remain type-safe.
90
+
91
+ For reusable or separately declared configurations, the package exports a
92
+ common `CreateErrorConfig` type:
93
+
94
+ ```ts
95
+ import { createError, type CreateErrorConfig } from '@jfdevelops/create-error';
96
+
97
+ const definition = z.object({ code: z.string() });
98
+
99
+ const config = {
100
+ definition,
101
+ data: {
102
+ property: 'context',
103
+ resolve: ({ input }) => input,
104
+ },
105
+ message: ({ data, implementation }) => implementation(data),
106
+ } satisfies CreateErrorConfig<typeof definition>;
107
+
108
+ const createDomainError = createError(config);
109
+ ```
110
+
111
+ ## How the factory works
112
+
113
+ The API has four stages:
114
+
115
+ 1. `createError(blueprint)` configures a family and returns a factory.
116
+ 2. `factory(definition)` validates and captures one definition.
117
+ 3. The returned builder optionally selects a context schema with
118
+ `defineContext(schema)`.
119
+ 4. `implement(callback)` captures the implementation and produces an
120
+ extendable concrete error class.
121
+
122
+ The definition builder exposes both `defineContext` and `implement`.
123
+ `defineContext` returns a narrower builder that exposes only `implement`, so a
124
+ context schema can be selected only once. Calling `implement` directly keeps
125
+ context schemas optional. Every implementation receives exactly one argument;
126
+ the blueprint decides its shape when it calls `implementation(argument)`. When
127
+ that argument is a constructed object, the concrete definition fields are added
128
+ automatically, so implementations can read values such as `code` without the
129
+ blueprint repeating them. Forwarding opaque data directly preserves its original
130
+ scalar, tuple, object, or class-instance shape.
131
+
132
+ The `definition` option must implement Standard Schema V1 and must produce an
133
+ object. Validation runs when `factory(definition)` is called. Because class
134
+ creation is synchronous, a schema whose `validate` method returns a promise is
135
+ rejected with a `TypeError`.
136
+
137
+ ## What `data` and `properties` do
138
+
139
+ `data` defines the constructor-input lifecycle. Its `resolve` callback receives
140
+ the concrete definition and the value passed to `new ErrorClass(input)`. The
141
+ callback can preserve that input, normalize it, or combine it with definition
142
+ values. After optional `defineContext` validation, the final value is stored on
143
+ the instance using `data.property`.
144
+
145
+ `properties` defines the rest of the instance API. It can expose definition
146
+ values such as a stable error code, derive fields from the resolved data, or add
147
+ methods and getters. It does not participate in input validation or
148
+ transformation.
149
+
150
+ For a small error family, the constructor input can pass straight through and
151
+ `properties` can be omitted entirely:
152
+
153
+ ```ts
154
+ const createLookupError = createError({
155
+ definition: z.object({ code: z.string() }),
156
+ data: {
157
+ property: 'resourceId',
158
+ resolve: ({ input }) => input,
159
+ },
160
+ message: ({ data, implementation }) => implementation(data),
161
+ });
162
+
163
+ class MissingUserError extends createLookupError({ code: 'missingUser' })
164
+ .defineContext(z.string())
165
+ .implement((resourceId) => `User ${resourceId} was not found`) {}
166
+
167
+ const error = new MissingUserError('user_123');
168
+ error.resourceId; // string
169
+ ```
170
+
171
+ Use both options when constructor input needs normalization and the error should
172
+ present a richer public API:
173
+
174
+ ```ts
175
+ const createValidationError = createError({
176
+ definition: z.object({
177
+ code: z.string(),
178
+ section: z.string(),
179
+ }),
180
+ data: {
181
+ property: 'context',
182
+ resolve: ({ definition, input }) => ({
183
+ ...input,
184
+ section: definition.section,
185
+ }),
186
+ },
187
+ message: ({ data, implementation }) => implementation(data),
188
+ properties: ({ definition, data }) => ({
189
+ code: definition.code,
190
+ section: definition.section,
191
+ describe: () => `${definition.code} in ${data.section}`,
192
+ }),
193
+ });
194
+
195
+ class InvalidEmailError extends createValidationError({
196
+ code: 'invalidEmail',
197
+ section: 'profile',
198
+ })
199
+ .defineContext(
200
+ z.object({
201
+ field: z.string(),
202
+ section: z.literal('profile'),
203
+ }),
204
+ )
205
+ .implement(({ field }) => `${field} is invalid`) {}
206
+
207
+ const error = new InvalidEmailError({ field: 'email' });
208
+ error.context; // { field: string; section: "profile" }
209
+ error.code; // "invalidEmail"
210
+ error.describe(); // "invalidEmail in profile"
211
+ ```
212
+
213
+ Use schema-native restrictions when definitions have a closed set of values:
214
+
215
+ ```ts
216
+ const createHttpError = createError({
217
+ definition: z.object({
218
+ code: z.enum(['notFound', 'unauthorized']),
219
+ scope: z.literal('request'),
220
+ }),
221
+ data: {
222
+ property: 'details',
223
+ resolve: ({ input }) => input,
224
+ },
225
+ message: ({ implementation, data }) => implementation(data),
226
+ });
227
+
228
+ const NotFoundError = createHttpError({
229
+ code: 'notFound',
230
+ scope: 'request',
231
+ })
232
+ .defineContext(z.object({ resource: z.string() }))
233
+ .implement((details) => `${details.resource} was not found`);
234
+ ```
235
+
236
+ ## Data and behavior
237
+
238
+ `data.resolve` can return any value: objects, scalars, tuples, unions, class
239
+ instances, `null`, and `undefined` are all supported. When `defineContext` is
240
+ used, its Standard Schema validates the resolved data, its input type determines
241
+ the concrete error constructor input, and its output type is passed to the
242
+ implementation and stored on the error. Without a context schema, the last
243
+ parameter of the consumer implementation determines those types.
244
+
245
+ For each new error instance, callbacks run in this order:
246
+
247
+ 1. `data.resolve`
248
+ 2. Context validation and transformation, when configured
249
+ 3. `message`
250
+ 4. `properties`, when configured
251
+
252
+ Exceptions thrown by a schema or callback are not wrapped. Native `Error`
253
+ behavior is preserved, including stack traces, subclass names, prototypes, and
254
+ the optional `cause` passed as the second constructor argument.
255
+
256
+ Every family exposes its shared base as `factory.Error`. Concrete classes and
257
+ named subclasses also inherit a lazy invariant helper:
258
+
259
+ ```ts
260
+ InvalidFieldError.invariant(
261
+ formIsValid,
262
+ () => ({ field: 'email' }),
263
+ { cause },
264
+ );
265
+ ```
266
+
267
+ The input function runs only when the condition is falsy.
268
+
269
+ When `toJSON` is configured, it is installed once on the family prototype and
270
+ used by `JSON.stringify`. Its callback can read native error fields, configured
271
+ properties, and the resolved data property; each concrete error's `toJSON()`
272
+ return type preserves parsed definition output and context-schema output. When
273
+ omitted, the family does not add a `toJSON` method.
274
+
275
+ ## Property safety
276
+
277
+ `properties` may add fields, methods, getters, symbols, and other own property
278
+ descriptors. It cannot replace `name`, `message`, `stack`, `cause`,
279
+ `constructor`, or `prototype`. The configured data property may only be
280
+ repeated with the exact resolved value. Collisions throw a `TypeError`.
281
+
282
+ The library always creates the family base class. Customize a family through
283
+ the blueprint instead of supplying a separate `BaseError`.
284
+
285
+ ## Releasing
286
+
287
+ This project uses Changesets for versioning and changelogs. Add a changeset
288
+ with `pnpm changeset` whenever a package change should be released. Maintainers
289
+ can consume pending changesets with `pnpm version-packages`, review the updated
290
+ version and changelog, then publish with `pnpm release`.
291
+
292
+ ## License
293
+
294
+ MIT
@@ -0,0 +1,135 @@
1
+
2
+ //#region src/create-error.ts
3
+ const protectedPropertyNames = new Set([
4
+ "name",
5
+ "message",
6
+ "stack",
7
+ "cause",
8
+ "constructor",
9
+ "prototype"
10
+ ]);
11
+ function isObjectLike(value) {
12
+ return value !== null && (typeof value === "object" || typeof value === "function");
13
+ }
14
+ function isPlainObject(value) {
15
+ if (!isObjectLike(value)) return false;
16
+ const prototype = Object.getPrototypeOf(value);
17
+ return prototype === Object.prototype || prototype === null;
18
+ }
19
+ function includeDefinition(argument, definition) {
20
+ if (!isPlainObject(argument)) return argument;
21
+ return {
22
+ ...definition,
23
+ ...argument
24
+ };
25
+ }
26
+ function validateStandardSchema(schema, subject) {
27
+ if (!isObjectLike(schema)) throw new TypeError(`${subject} must be a Standard Schema object`);
28
+ const standard = Reflect.get(schema, "~standard");
29
+ if (!isObjectLike(standard) || Reflect.get(standard, "version") !== 1 || typeof Reflect.get(standard, "vendor") !== "string" || typeof Reflect.get(standard, "validate") !== "function") throw new TypeError(`${subject} must implement Standard Schema V1`);
30
+ }
31
+ function validateBlueprint(config) {
32
+ validateStandardSchema(config.definition, "definition");
33
+ if (typeof config.data.property !== "string" || config.data.property.length === 0) throw new TypeError("data.property must be a non-empty string");
34
+ if (protectedPropertyNames.has(config.data.property)) throw new TypeError(`data.property cannot overwrite protected property "${config.data.property}"`);
35
+ }
36
+ function formatIssuePath(path) {
37
+ if (!path?.length) return "";
38
+ return `${path.map((segment) => typeof segment === "object" ? segment.key : segment).map(String).join(".")}: `;
39
+ }
40
+ function parseSchema(schema, input, subject) {
41
+ const result = schema["~standard"].validate(input);
42
+ if (result instanceof Promise) throw new TypeError(`${subject} schema validation must be synchronous`);
43
+ if (result.issues) {
44
+ const details = result.issues.map((issue) => `${formatIssuePath(issue.path)}${issue.message}`).join("; ");
45
+ throw new TypeError(`Invalid error ${subject}: ${details}`);
46
+ }
47
+ return result.value;
48
+ }
49
+ function parseDefinition(schema, definition) {
50
+ const parsedDefinition = parseSchema(schema, definition, "definition");
51
+ if (!isObjectLike(parsedDefinition)) throw new TypeError("definition schema must produce an object");
52
+ return parsedDefinition;
53
+ }
54
+ function assignProperties(error, properties, dataProperty, data) {
55
+ for (const key of Reflect.ownKeys(properties)) {
56
+ if (typeof key === "string" && protectedPropertyNames.has(key)) throw new TypeError(`Cannot overwrite protected error property "${key}"`);
57
+ const descriptor = Object.getOwnPropertyDescriptor(properties, key);
58
+ if (!descriptor) continue;
59
+ if (key === dataProperty && (!("value" in descriptor) || descriptor.value !== data)) throw new TypeError(`Cannot overwrite resolved data property "${dataProperty}"`);
60
+ Object.defineProperty(error, key, descriptor);
61
+ }
62
+ }
63
+ function createError(config) {
64
+ validateBlueprint(config);
65
+ class FamilyError extends Error {
66
+ static invariant(condition, input, options) {
67
+ if (condition) return;
68
+ const resolvedInput = typeof input === "function" ? input() : input;
69
+ throw new this(resolvedInput, options);
70
+ }
71
+ constructor(message, options) {
72
+ super(message, options);
73
+ const name = new.target.name;
74
+ if (name) this.name = name;
75
+ }
76
+ }
77
+ if (config.toJSON) Object.defineProperty(FamilyError.prototype, "toJSON", {
78
+ configurable: true,
79
+ value: function toJSON() {
80
+ return config.toJSON?.(this);
81
+ },
82
+ writable: true
83
+ });
84
+ function createDefinition(definition) {
85
+ const parsedDefinition = parseDefinition(config.definition, definition);
86
+ function createImplementation(implementation, contextSchema) {
87
+ return class extends FamilyError {
88
+ constructor(input, options) {
89
+ const resolvedData = config.data.resolve({
90
+ definition: parsedDefinition,
91
+ input
92
+ });
93
+ const data = contextSchema ? parseSchema(contextSchema, resolvedData, "context") : resolvedData;
94
+ const implementationWithDefinition = (argument) => implementation(argument === data ? argument : includeDefinition(argument, parsedDefinition));
95
+ const message = config.message({
96
+ data,
97
+ definition: parsedDefinition,
98
+ implementation: implementationWithDefinition
99
+ });
100
+ super(message, options);
101
+ Object.defineProperty(this, config.data.property, {
102
+ configurable: true,
103
+ enumerable: true,
104
+ value: data,
105
+ writable: true
106
+ });
107
+ const properties = config.properties?.({
108
+ data,
109
+ definition: parsedDefinition,
110
+ implementation: implementationWithDefinition
111
+ });
112
+ if (properties) assignProperties(this, properties, config.data.property, data);
113
+ }
114
+ };
115
+ }
116
+ function implement(implementation) {
117
+ return createImplementation(implementation);
118
+ }
119
+ function defineContext(contextSchema) {
120
+ validateStandardSchema(contextSchema, "context");
121
+ return { implement(implementation) {
122
+ return createImplementation(implementation, contextSchema);
123
+ } };
124
+ }
125
+ return {
126
+ defineContext,
127
+ implement
128
+ };
129
+ }
130
+ return Object.assign(createDefinition, { Error: FamilyError });
131
+ }
132
+
133
+ //#endregion
134
+ exports.createError = createError;
135
+ //# sourceMappingURL=create-error.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-error.cjs","names":["implementationWithDefinition: RuntimeImplementation"],"sources":["../src/create-error.ts"],"sourcesContent":["import type { StandardSchemaV1 } from '@standard-schema/spec';\r\n\r\nimport type {\r\n BlueprintContext,\r\n BlueprintErrorTemplate,\r\n CreateErrorConfig,\r\n ErrorFamilyFactory,\r\n} from './types.js';\r\n\r\ntype RuntimeImplementation = (argument: unknown) => string;\r\n\r\ntype ErrorConfigBody<\r\n Schema extends StandardSchemaV1,\r\n DataConfig extends CreateErrorConfig<Schema>['data'],\r\n MessageCallback extends CreateErrorConfig<Schema>['message'],\r\n> = {\r\n data: DataConfig;\r\n message: MessageCallback;\r\n};\r\n\r\ntype ErrorConfigWithProperties<\r\n Schema extends StandardSchemaV1,\r\n DataConfig extends CreateErrorConfig<Schema>['data'],\r\n MessageCallback extends CreateErrorConfig<Schema>['message'],\r\n Properties extends object,\r\n> = ErrorConfigBody<Schema, DataConfig, MessageCallback> & {\r\n properties(context: BlueprintContext<Schema>): Properties;\r\n};\r\n\r\ntype ErrorConfigWithoutProperties<\r\n Schema extends StandardSchemaV1,\r\n DataConfig extends CreateErrorConfig<Schema>['data'],\r\n MessageCallback extends CreateErrorConfig<Schema>['message'],\r\n> = ErrorConfigBody<Schema, DataConfig, MessageCallback> & {\r\n properties?: never;\r\n};\r\n\r\ntype ExactCreateErrorConfig<\r\n Schema extends StandardSchemaV1,\r\n Config extends object,\r\n> = {\r\n definition: Schema;\r\n} & Config &\r\n (StandardSchemaV1.InferOutput<Schema> extends object\r\n ? unknown\r\n : { definition: never });\r\n\r\ntype SerializedCreateErrorConfig<\r\n Schema extends StandardSchemaV1,\r\n Config extends object,\r\n Json,\r\n> = ExactCreateErrorConfig<\r\n Schema,\r\n Config & {\r\n toJSON(error: BlueprintErrorTemplate<NoInfer<Config>>): Json;\r\n }\r\n>;\r\n\r\nconst protectedPropertyNames = new Set([\r\n 'name',\r\n 'message',\r\n 'stack',\r\n 'cause',\r\n 'constructor',\r\n 'prototype',\r\n]);\r\n\r\nfunction isObjectLike(value: unknown): value is object {\r\n return (\r\n value !== null && (typeof value === 'object' || typeof value === 'function')\r\n );\r\n}\r\n\r\nfunction isPlainObject(value: unknown): value is Record<PropertyKey, unknown> {\r\n if (!isObjectLike(value)) {\r\n return false;\r\n }\r\n\r\n const prototype = Object.getPrototypeOf(value);\r\n\r\n return prototype === Object.prototype || prototype === null;\r\n}\r\n\r\nfunction includeDefinition(\r\n argument: unknown,\r\n definition: object,\r\n): unknown {\r\n if (!isPlainObject(argument)) {\r\n return argument;\r\n }\r\n\r\n return { ...definition, ...argument };\r\n}\r\n\r\nfunction validateStandardSchema(schema: unknown, subject: string) {\r\n if (!isObjectLike(schema)) {\r\n throw new TypeError(`${subject} must be a Standard Schema object`);\r\n }\r\n\r\n const standard = Reflect.get(schema, '~standard') as unknown;\r\n\r\n if (\r\n !isObjectLike(standard) ||\r\n Reflect.get(standard, 'version') !== 1 ||\r\n typeof Reflect.get(standard, 'vendor') !== 'string' ||\r\n typeof Reflect.get(standard, 'validate') !== 'function'\r\n ) {\r\n throw new TypeError(`${subject} must implement Standard Schema V1`);\r\n }\r\n}\r\n\r\nfunction validateBlueprint(config: CreateErrorConfig<StandardSchemaV1>) {\r\n validateStandardSchema(config.definition, 'definition');\r\n\r\n if (\r\n typeof config.data.property !== 'string' ||\r\n config.data.property.length === 0\r\n ) {\r\n throw new TypeError('data.property must be a non-empty string');\r\n }\r\n\r\n if (protectedPropertyNames.has(config.data.property)) {\r\n throw new TypeError(\r\n `data.property cannot overwrite protected property \"${config.data.property}\"`,\r\n );\r\n }\r\n}\r\n\r\nfunction formatIssuePath(path: StandardSchemaV1.Issue['path']) {\r\n if (!path?.length) {\r\n return '';\r\n }\r\n\r\n const keys = path.map((segment) =>\r\n typeof segment === 'object' ? segment.key : segment,\r\n );\r\n\r\n return `${keys.map(String).join('.')}: `;\r\n}\r\n\r\nfunction parseSchema<Schema extends StandardSchemaV1>(\r\n schema: Schema,\r\n input: StandardSchemaV1.InferInput<Schema>,\r\n subject: string,\r\n) {\r\n const result = schema['~standard'].validate(input);\r\n\r\n if (result instanceof Promise) {\r\n throw new TypeError(`${subject} schema validation must be synchronous`);\r\n }\r\n\r\n if (result.issues) {\r\n const details = result.issues\r\n .map((issue) => `${formatIssuePath(issue.path)}${issue.message}`)\r\n .join('; ');\r\n\r\n throw new TypeError(`Invalid error ${subject}: ${details}`);\r\n }\r\n\r\n return result.value;\r\n}\r\n\r\nfunction parseDefinition<Schema extends StandardSchemaV1>(\r\n schema: Schema,\r\n definition: StandardSchemaV1.InferInput<Schema>,\r\n) {\r\n const parsedDefinition = parseSchema(schema, definition, 'definition');\r\n\r\n if (!isObjectLike(parsedDefinition)) {\r\n throw new TypeError('definition schema must produce an object');\r\n }\r\n\r\n return parsedDefinition;\r\n}\r\n\r\nfunction assignProperties(\r\n error: Error & Record<string, unknown>,\r\n properties: object,\r\n dataProperty: string,\r\n data: unknown,\r\n) {\r\n for (const key of Reflect.ownKeys(properties)) {\r\n if (typeof key === 'string' && protectedPropertyNames.has(key)) {\r\n throw new TypeError(`Cannot overwrite protected error property \"${key}\"`);\r\n }\r\n\r\n const descriptor = Object.getOwnPropertyDescriptor(properties, key);\r\n\r\n if (!descriptor) {\r\n continue;\r\n }\r\n\r\n if (\r\n key === dataProperty &&\r\n (!('value' in descriptor) || descriptor.value !== data)\r\n ) {\r\n throw new TypeError(`Cannot overwrite resolved data property \"${dataProperty}\"`);\r\n }\r\n\r\n Object.defineProperty(error, key, descriptor);\r\n }\r\n}\r\n\r\n/**\r\n * Creates an error family with additional instance properties and typed JSON\r\n * serialization.\r\n *\r\n * @param config Defines the family, its public properties, and its serialized\r\n * representation.\r\n * @returns A callable factory with a shared `.Error` base class.\r\n *\r\n * @example\r\n * ```ts\r\n * const createApiError = createError({\r\n * definition: z.object({ code: z.string() }),\r\n * data: {\r\n * property: 'context',\r\n * resolve: ({ input }) => input,\r\n * },\r\n * message: ({ data, implementation }) => implementation(data),\r\n * properties: ({ definition }) => ({ code: definition.code }),\r\n * toJSON: (error) => ({\r\n * code: error.code,\r\n * context: error.context,\r\n * message: error.message,\r\n * }),\r\n * });\r\n * ```\r\n */\r\nexport function createError<\r\n const Schema extends StandardSchemaV1,\r\n const DataConfig extends CreateErrorConfig<Schema>['data'],\r\n const MessageCallback extends CreateErrorConfig<Schema>['message'],\r\n const Properties extends object,\r\n Json,\r\n>(\r\n config: SerializedCreateErrorConfig<\r\n Schema,\r\n ErrorConfigWithProperties<\r\n Schema,\r\n DataConfig,\r\n MessageCallback,\r\n Properties\r\n >,\r\n Json\r\n >,\r\n): ErrorFamilyFactory<Schema, typeof config>;\r\n\r\n/**\r\n * Creates an error family with typed JSON serialization and no additional\r\n * instance properties.\r\n *\r\n * @param config Defines the family and its serialized representation.\r\n * @returns A callable factory with a shared `.Error` base class.\r\n *\r\n * @example\r\n * ```ts\r\n * const createLogError = createError({\r\n * definition: z.object({ code: z.string() }),\r\n * data: {\r\n * property: 'details',\r\n * resolve: ({ input }) => input,\r\n * },\r\n * message: ({ data, implementation }) => implementation(data),\r\n * toJSON: (error) => ({\r\n * details: error.details,\r\n * message: error.message,\r\n * }),\r\n * });\r\n * ```\r\n */\r\nexport function createError<\r\n const Schema extends StandardSchemaV1,\r\n const DataConfig extends CreateErrorConfig<Schema>['data'],\r\n const MessageCallback extends CreateErrorConfig<Schema>['message'],\r\n Json,\r\n>(\r\n config: SerializedCreateErrorConfig<\r\n Schema,\r\n ErrorConfigWithoutProperties<Schema, DataConfig, MessageCallback>,\r\n Json\r\n >,\r\n): ErrorFamilyFactory<Schema, typeof config>;\r\n\r\n/**\r\n * Creates a configurable family of strongly typed error classes.\r\n *\r\n * Callback execution order is `data.resolve`, optional context validation,\r\n * `message`, then `properties`. Parsed definition output and constructor data\r\n * are inferred without explicit generic arguments or `as const`.\r\n *\r\n * @param config Defines the family's schema, data lifecycle, message, and\r\n * optional public properties.\r\n * @returns A callable factory with a shared `.Error` base class.\r\n *\r\n * @example\r\n * ```ts\r\n * const createRequestError = createError({\r\n * definition: z.object({ code: z.string() }),\r\n * data: {\r\n * property: 'context',\r\n * resolve: ({ input }) => input,\r\n * },\r\n * message: ({ data, implementation }) => implementation(data),\r\n * properties: ({ definition }) => ({ code: definition.code }),\r\n * });\r\n * ```\r\n */\r\nexport function createError<\r\n const Schema extends StandardSchemaV1,\r\n const Config extends Omit<CreateErrorConfig<Schema>, 'definition'>,\r\n>(\r\n config: ExactCreateErrorConfig<Schema, Config>,\r\n): ErrorFamilyFactory<Schema, typeof config>;\r\nexport function createError<\r\n const Schema extends StandardSchemaV1,\r\n const Config extends Omit<CreateErrorConfig<Schema>, 'definition'>,\r\n>(\r\n config: ExactCreateErrorConfig<Schema, Config>,\r\n): ErrorFamilyFactory<Schema, typeof config> {\r\n validateBlueprint(config as CreateErrorConfig<StandardSchemaV1>);\r\n\r\n class FamilyError extends Error {\r\n static invariant<Condition, Input>(\r\n this: new (input: Input, options?: ErrorOptions) => Error,\r\n condition: Condition,\r\n input: Input | (() => Input),\r\n options?: ErrorOptions,\r\n ): asserts condition {\r\n if (condition) {\r\n return;\r\n }\r\n\r\n const resolvedInput =\r\n typeof input === 'function' ? (input as () => Input)() : input;\r\n\r\n throw new this(resolvedInput, options);\r\n }\r\n\r\n constructor(message: string, options?: ErrorOptions) {\r\n super(message, options);\r\n const name = new.target.name;\r\n if (name) {\r\n this.name = name;\r\n }\r\n }\r\n }\r\n\r\n if (config.toJSON) {\r\n Object.defineProperty(FamilyError.prototype, 'toJSON', {\r\n configurable: true,\r\n value: function toJSON(this: Error & Record<string, unknown>) {\r\n return config.toJSON?.(this as never);\r\n },\r\n writable: true,\r\n });\r\n }\r\n\r\n function createDefinition<\r\n const Definition extends StandardSchemaV1.InferInput<Schema>,\r\n >(definition: Definition) {\r\n const parsedDefinition = parseDefinition(config.definition, definition);\r\n\r\n function createImplementation(\r\n implementation: RuntimeImplementation,\r\n contextSchema?: StandardSchemaV1,\r\n ) {\r\n return class extends FamilyError {\r\n constructor(input: unknown, options?: ErrorOptions) {\r\n const resolvedData = config.data.resolve({\r\n definition: parsedDefinition,\r\n input,\r\n } as never);\r\n const data = contextSchema\r\n ? parseSchema(contextSchema, resolvedData, 'context')\r\n : resolvedData;\r\n const implementationWithDefinition: RuntimeImplementation = (\r\n argument,\r\n ) =>\r\n implementation(\r\n argument === data\r\n ? argument\r\n : includeDefinition(argument, parsedDefinition),\r\n );\r\n const message = config.message({\r\n data,\r\n definition: parsedDefinition,\r\n implementation: implementationWithDefinition,\r\n } as never);\r\n\r\n super(message, options);\r\n\r\n Object.defineProperty(this, config.data.property, {\r\n configurable: true,\r\n enumerable: true,\r\n value: data,\r\n writable: true,\r\n });\r\n\r\n const properties = config.properties?.({\r\n data,\r\n definition: parsedDefinition,\r\n implementation: implementationWithDefinition,\r\n } as never);\r\n\r\n if (properties) {\r\n assignProperties(\r\n this as Error & Record<string, unknown>,\r\n properties,\r\n config.data.property,\r\n data,\r\n );\r\n }\r\n }\r\n };\r\n }\r\n\r\n function implement(implementation: RuntimeImplementation) {\r\n return createImplementation(implementation);\r\n }\r\n\r\n function defineContext<ContextSchema extends StandardSchemaV1>(\r\n contextSchema: ContextSchema,\r\n ) {\r\n validateStandardSchema(contextSchema, 'context');\r\n\r\n return {\r\n implement(implementation: RuntimeImplementation) {\r\n return createImplementation(implementation, contextSchema);\r\n },\r\n };\r\n }\r\n\r\n return {\r\n defineContext,\r\n implement,\r\n };\r\n }\r\n\r\n return Object.assign(createDefinition, {\r\n Error: FamilyError,\r\n }) as unknown as ErrorFamilyFactory<Schema, typeof config>;\r\n}\r\n"],"mappings":"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"}
@@ -0,0 +1,101 @@
1
+ import { BlueprintContext, BlueprintErrorTemplate, CreateErrorConfig, ErrorFamilyFactory } from "./types.cjs";
2
+ import { StandardSchemaV1 } from "@standard-schema/spec";
3
+
4
+ //#region src/create-error.d.ts
5
+ type ErrorConfigBody<Schema extends StandardSchemaV1, DataConfig extends CreateErrorConfig<Schema>['data'], MessageCallback extends CreateErrorConfig<Schema>['message']> = {
6
+ data: DataConfig;
7
+ message: MessageCallback;
8
+ };
9
+ type ErrorConfigWithProperties<Schema extends StandardSchemaV1, DataConfig extends CreateErrorConfig<Schema>['data'], MessageCallback extends CreateErrorConfig<Schema>['message'], Properties extends object> = ErrorConfigBody<Schema, DataConfig, MessageCallback> & {
10
+ properties(context: BlueprintContext<Schema>): Properties;
11
+ };
12
+ type ErrorConfigWithoutProperties<Schema extends StandardSchemaV1, DataConfig extends CreateErrorConfig<Schema>['data'], MessageCallback extends CreateErrorConfig<Schema>['message']> = ErrorConfigBody<Schema, DataConfig, MessageCallback> & {
13
+ properties?: never;
14
+ };
15
+ type ExactCreateErrorConfig<Schema extends StandardSchemaV1, Config extends object> = {
16
+ definition: Schema;
17
+ } & Config & (StandardSchemaV1.InferOutput<Schema> extends object ? unknown : {
18
+ definition: never;
19
+ });
20
+ type SerializedCreateErrorConfig<Schema extends StandardSchemaV1, Config extends object, Json> = ExactCreateErrorConfig<Schema, Config & {
21
+ toJSON(error: BlueprintErrorTemplate<NoInfer<Config>>): Json;
22
+ }>;
23
+ /**
24
+ * Creates an error family with additional instance properties and typed JSON
25
+ * serialization.
26
+ *
27
+ * @param config Defines the family, its public properties, and its serialized
28
+ * representation.
29
+ * @returns A callable factory with a shared `.Error` base class.
30
+ *
31
+ * @example
32
+ * ```ts
33
+ * const createApiError = createError({
34
+ * definition: z.object({ code: z.string() }),
35
+ * data: {
36
+ * property: 'context',
37
+ * resolve: ({ input }) => input,
38
+ * },
39
+ * message: ({ data, implementation }) => implementation(data),
40
+ * properties: ({ definition }) => ({ code: definition.code }),
41
+ * toJSON: (error) => ({
42
+ * code: error.code,
43
+ * context: error.context,
44
+ * message: error.message,
45
+ * }),
46
+ * });
47
+ * ```
48
+ */
49
+ declare function createError<const Schema extends StandardSchemaV1, const DataConfig extends CreateErrorConfig<Schema>['data'], const MessageCallback extends CreateErrorConfig<Schema>['message'], const Properties extends object, Json>(config: SerializedCreateErrorConfig<Schema, ErrorConfigWithProperties<Schema, DataConfig, MessageCallback, Properties>, Json>): ErrorFamilyFactory<Schema, typeof config>;
50
+ /**
51
+ * Creates an error family with typed JSON serialization and no additional
52
+ * instance properties.
53
+ *
54
+ * @param config Defines the family and its serialized representation.
55
+ * @returns A callable factory with a shared `.Error` base class.
56
+ *
57
+ * @example
58
+ * ```ts
59
+ * const createLogError = createError({
60
+ * definition: z.object({ code: z.string() }),
61
+ * data: {
62
+ * property: 'details',
63
+ * resolve: ({ input }) => input,
64
+ * },
65
+ * message: ({ data, implementation }) => implementation(data),
66
+ * toJSON: (error) => ({
67
+ * details: error.details,
68
+ * message: error.message,
69
+ * }),
70
+ * });
71
+ * ```
72
+ */
73
+ declare function createError<const Schema extends StandardSchemaV1, const DataConfig extends CreateErrorConfig<Schema>['data'], const MessageCallback extends CreateErrorConfig<Schema>['message'], Json>(config: SerializedCreateErrorConfig<Schema, ErrorConfigWithoutProperties<Schema, DataConfig, MessageCallback>, Json>): ErrorFamilyFactory<Schema, typeof config>;
74
+ /**
75
+ * Creates a configurable family of strongly typed error classes.
76
+ *
77
+ * Callback execution order is `data.resolve`, optional context validation,
78
+ * `message`, then `properties`. Parsed definition output and constructor data
79
+ * are inferred without explicit generic arguments or `as const`.
80
+ *
81
+ * @param config Defines the family's schema, data lifecycle, message, and
82
+ * optional public properties.
83
+ * @returns A callable factory with a shared `.Error` base class.
84
+ *
85
+ * @example
86
+ * ```ts
87
+ * const createRequestError = createError({
88
+ * definition: z.object({ code: z.string() }),
89
+ * data: {
90
+ * property: 'context',
91
+ * resolve: ({ input }) => input,
92
+ * },
93
+ * message: ({ data, implementation }) => implementation(data),
94
+ * properties: ({ definition }) => ({ code: definition.code }),
95
+ * });
96
+ * ```
97
+ */
98
+ declare function createError<const Schema extends StandardSchemaV1, const Config extends Omit<CreateErrorConfig<Schema>, 'definition'>>(config: ExactCreateErrorConfig<Schema, Config>): ErrorFamilyFactory<Schema, typeof config>;
99
+ //#endregion
100
+ export { createError };
101
+ //# sourceMappingURL=create-error.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-error.d.cts","names":[],"sources":["../src/create-error.ts"],"sourcesContent":[],"mappings":";;;;KAWK,+BACY,qCACI,kBAAkB,yCACb,kBAAkB;QAEpC;EALH,OAAA,EAMM,eANS;CACH;KAQZ,yBAPkC,CAAA,eAQtB,gBARsB,EAAA,mBASlB,iBATkB,CASA,MATA,CAAA,CAAA,MAAA,CAAA,EAAA,wBAUb,iBAVa,CAUK,MAVL,CAAA,CAAA,SAAA,CAAA,EAAA,mBAAA,MAAA,CAAA,GAYnC,eAZmC,CAYnB,MAZmB,EAYX,UAZW,EAYC,eAZD,CAAA,GAAA;EAAlB,UAAA,CAAA,OAAA,EAaC,gBAbD,CAakB,MAblB,CAAA,CAAA,EAa4B,UAb5B;CACuB;KAevC,4BAfqB,CAAA,eAgBT,gBAhBS,EAAA,mBAiBL,iBAjBK,CAiBa,MAjBb,CAAA,CAAA,MAAA,CAAA,EAAA,wBAkBA,iBAlBA,CAkBkB,MAlBlB,CAAA,CAAA,SAAA,CAAA,CAAA,GAmBtB,eAnBsB,CAmBN,MAnBM,EAmBE,UAnBF,EAmBc,eAnBd,CAAA,GAAA;EAElB,UAAA,CAAA,EAAA,KAAA;CACG;KAoBN,sBApBqB,CAAA,eAqBT,gBArBS,EAAA,eAAA,MAAA,CAAA,GAAA;EAGrB,UAAA,EAqBS,MArBT;CACY,GAqBb,MArBa,GAAA,CAsBd,gBAAA,CAAiB,WAtBH,CAsBe,MAtBf,CAAA,SAAA,MAAA,GAAA,OAAA,GAAA;EACsB,UAAA,EAAA,KAAA;CAAlB,CAAA;KAyBhB,2BAxBuC,CAAA,eAyB3B,gBAzB2B,EAAA,eAAA,MAAA,EAAA,IAAA,CAAA,GA4BxC,sBA5BwC,CA6B1C,MA7B0C,EA8B1C,MA9B0C,GAAA;EAAlB,MAAA,CAAA,KAAA,EA+BR,sBA/BQ,CA+Be,OA/Bf,CA+BuB,MA/BvB,CAAA,CAAA,CAAA,EA+BkC,IA/BlC;CAEN,CAAA;;;;;;;;AACuC;;;;;;;;;;;AAOxC;;;;;;;AAUY;AAKd,iBAqLD,WArLC,CAAA,qBAsLM,gBAtLN,EAAA,yBAuLU,iBAvLV,CAuL4B,MAvL5B,CAAA,CAAA,MAAA,CAAA,EAAA,8BAwLe,iBAxLf,CAwLiC,MAxLjC,CAAA,CAAA,SAAA,CAAA,EAAA,yBAAA,MAAA,EAAA,IAAA,CAAA,CAAA,MAAA,EA4LP,2BA5LO,CA6Lb,MA7La,EA8Lb,yBA9La,CA+LX,MA/LW,EAgMX,UAhMW,EAiMX,eAjMW,EAkMX,UAlMW,CAAA,EAoMb,IApMa,CAAA,CAAA,EAsMd,kBAtMc,CAsMK,MAtML,EAAA,OAsMoB,MAtMpB,CAAA;;;;;;;;;AAqLjB;;;;;;;;;;;;;;;AAiBqC,iBAyBrB,WAzBqB,CAAA,qBA0Bd,gBA1Bc,EAAA,yBA2BV,iBA3BU,CA2BQ,MA3BR,CAAA,CAAA,MAAA,CAAA,EAAA,8BA4BL,iBA5BK,CA4Ba,MA5Bb,CAAA,CAAA,SAAA,CAAA,EAAA,IAAA,CAAA,CAAA,MAAA,EA+B3B,2BA/B2B,CAgCjC,MAhCiC,EAiCjC,4BAjCiC,CAiCJ,MAjCI,EAiCI,UAjCJ,EAiCgB,eAjChB,CAAA,EAkCjC,IAlCiC,CAAA,CAAA,EAoClC,kBApCkC,CAoCf,MApCe,EAAA,OAoCA,MApCA,CAAA;;;AAyBrC;;;;;;;;;;;;;;;;;AAqCA;;;;;AAIiC,iBAJjB,WAIiB,CAAA,qBAHV,gBAGU,EAAA,qBAFV,IAEU,CAFL,iBAEK,CAFa,MAEb,CAAA,EAAA,YAAA,CAAA,CAAA,CAAA,MAAA,EAAvB,sBAAuB,CAAA,MAAA,EAAQ,MAAR,CAAA,CAAA,EAC9B,kBAD8B,CACX,MADW,EAAA,OACI,MADJ,CAAA"}