@mxweb/classable 1.0.0 → 1.1.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.
package/CHANGELOG.md CHANGED
@@ -5,6 +5,30 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [1.1.0] - 2026-01-17
9
+
10
+ ### Added
11
+
12
+ - **Type Utilities**
13
+ - `Readonlyable<T>` - Utility type that accepts both mutable and readonly versions, useful for `Object.freeze()` or `as const`
14
+ - `InstanceByStatic<T, Method, Args, Runtime>` - Type for classes using static factory methods instead of direct constructor instantiation
15
+ - `ClassableSelector<T, Args, Runtime>` - Selector function type for choosing a classable from a list with custom logic
16
+
17
+ - **classable API**
18
+ - `classable.from(def, runtime?)` - Create an instance via a static factory method definition
19
+ - `classable.select(selector)` - Higher-order function to create a selector that picks a classable based on custom criteria
20
+ - `classable.placeholderInstance` - Pre-configured placeholder using InstanceByStatic pattern
21
+
22
+ - **Placeholder**
23
+ - Added `Placeholder.getInstance()` static method for factory pattern support
24
+
25
+ ### Changed
26
+
27
+ - Updated `Args` type parameter across all APIs to use `Readonlyable<any[]>` for flexible readonly/mutable array support
28
+ - `ClassableByResolver.target` now uses `[...Args]` spread to convert readonly arrays to mutable
29
+ - `Classable` type now properly handles readonly arrays
30
+ - `StaticExtended` type updated to support `Readonlyable<any[]>`
31
+
8
32
  ## [1.0.0] - 2026-01-17
9
33
 
10
34
  ### Added
@@ -41,4 +65,5 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
41
65
  - Comprehensive README with examples
42
66
  - MIT License
43
67
 
68
+ [1.1.0]: https://github.com/mxwebio/mxweb-classable/releases/tag/v1.1.0
44
69
  [1.0.0]: https://github.com/mxwebio/mxweb-classable/releases/tag/v1.0.0
package/README.md CHANGED
@@ -85,12 +85,30 @@ interface ClassableByResolver<InstanceType, Args, Runtime> {
85
85
  }
86
86
  ```
87
87
 
88
+ ### Readonlyable
89
+
90
+ All `Args` type parameters accept both mutable and readonly arrays, so you can use `Object.freeze()` or `as const` without type errors:
91
+
92
+ ```typescript
93
+ // Both work seamlessly
94
+ const mutableResolver = {
95
+ target: User,
96
+ resolve: () => ['John', 30] // mutable array
97
+ };
98
+
99
+ const frozenResolver = Object.freeze({
100
+ target: User,
101
+ resolve: () => ['John', 30] as const // readonly array
102
+ });
103
+ ```
104
+
88
105
  ## API Reference
89
106
 
90
107
  ### Type Utilities
91
108
 
92
109
  | Type | Description |
93
110
  |------|-------------|
111
+ | `Readonlyable<T>` | Accepts both mutable and readonly versions of a type |
94
112
  | `UnitClass<T>` | Class constructor with no arguments |
95
113
  | `ClassType<T, Args>` | Class constructor with specific arguments |
96
114
  | `AbstractClassType<T, Args>` | Abstract class constructor |
@@ -99,6 +117,8 @@ interface ClassableByResolver<InstanceType, Args, Runtime> {
99
117
  | `AnyConstructor` | Any class or abstract class |
100
118
  | `Classable<T, Args, Runtime>` | Class or resolver configuration |
101
119
  | `ClassableByResolver<T, Args, Runtime>` | Resolver configuration |
120
+ | `InstanceByStatic<T, Method, Args, Runtime>` | Static factory method pattern |
121
+ | `ClassableSelector<T, Args, Runtime>` | Selector function for choosing classables |
102
122
 
103
123
  ### `classable` API
104
124
 
@@ -211,14 +231,57 @@ classable.getDescriptor(resolver);
211
231
  // { type: "resolver", target: "User" }
212
232
  ```
213
233
 
234
+ #### `classable.from(def, runtime?)`
235
+
236
+ Creates an instance from a static factory method definition.
237
+
238
+ ```typescript
239
+ class Cache {
240
+ private constructor(private ttl: number) {}
241
+
242
+ static create(ttl: number): Cache {
243
+ return new Cache(ttl);
244
+ }
245
+ }
246
+
247
+ const cacheInstance = classable.from({
248
+ target: Cache,
249
+ selector: () => ({ method: "create", args: [3600] })
250
+ });
251
+
252
+ // With runtime context
253
+ const dynamicCache = classable.from({
254
+ target: Cache,
255
+ selector: (ctx) => ({ method: "create", args: [ctx.cacheTTL] })
256
+ }, appContext);
257
+ ```
258
+
259
+ #### `classable.select(selector)`
260
+
261
+ Creates a selector function that chooses a classable from a list based on custom logic.
262
+
263
+ ```typescript
264
+ // Simple selector
265
+ const pickFirst = classable.select((...classes) => {
266
+ return [classes[0], []];
267
+ });
268
+ const [selected, args] = pickFirst(ServiceA, ServiceB);
269
+
270
+ // With runtime context
271
+ const pickByEnv = classable.select<Logger, [], Env>((env, ...loggers) => {
272
+ return env.isDev ? [loggers[0], []] : [loggers[1], []];
273
+ });
274
+ const [logger, loggerArgs] = pickByEnv(devEnv, DevLogger, ProdLogger);
275
+ ```
276
+
214
277
  ### Placeholder
215
278
 
216
- A utility class for marking unresolved bindings:
279
+ Utility classes for marking unresolved bindings:
217
280
 
218
281
  ```typescript
219
282
  import { classable } from '@mxweb/classable';
220
283
 
221
- // Use as default value
284
+ // Use placeholder resolver as default value
222
285
  class Container {
223
286
  private bindings = new Map();
224
287
 
@@ -226,10 +289,51 @@ class Container {
226
289
  this.bindings.set(key, cls);
227
290
  }
228
291
  }
292
+
293
+ // Use placeholderInstance for static factory pattern
294
+ const instance = classable.from(classable.placeholderInstance);
295
+ // Returns new Placeholder via getInstance()
229
296
  ```
230
297
 
231
298
  ## Advanced Usage
232
299
 
300
+ ### Static Factory Method Pattern
301
+
302
+ Use `InstanceByStatic` for classes that use static factory methods instead of direct instantiation:
303
+
304
+ ```typescript
305
+ import { classable, InstanceByStatic } from '@mxweb/classable';
306
+
307
+ class Database {
308
+ private constructor(private connectionString: string) {}
309
+
310
+ static connect(connectionString: string): Database {
311
+ return new Database(connectionString);
312
+ }
313
+
314
+ static createInMemory(): Database {
315
+ return new Database(':memory:');
316
+ }
317
+ }
318
+
319
+ // Define static factory configuration
320
+ const dbDef: InstanceByStatic<Database, 'connect', [string]> = {
321
+ target: Database,
322
+ selector: () => ({ method: 'connect', args: ['postgres://localhost'] })
323
+ };
324
+
325
+ // Create instance via factory method
326
+ const db = classable.from(dbDef);
327
+
328
+ // With runtime context for dynamic selection
329
+ const dynamicDb = classable.from({
330
+ target: Database,
331
+ selector: (ctx) => ctx.isTest
332
+ ? { method: 'createInMemory', args: [] }
333
+ : { method: 'connect', args: [ctx.dbUrl] }
334
+ }, appContext);
335
+ ```
336
+
233
337
  ### Dependency Injection Pattern
234
338
 
235
339
  ```typescript
@@ -332,6 +436,12 @@ const asyncResolver = {
332
436
  const asyncUser = classable.create(asyncResolver, context); // Promise<User>
333
437
  ```
334
438
 
439
+ ## Documentation
440
+
441
+ For detailed documentation, guides, and API reference, visit:
442
+
443
+ [https://edge.mxweb.io/classable](https://edge.mxweb.io/classable)
444
+
335
445
  ## License
336
446
 
337
447
  MIT
package/dist/index.d.ts CHANGED
@@ -1,3 +1,21 @@
1
+ /**
2
+ * Utility type that accepts both mutable and readonly versions of a type.
3
+ *
4
+ * This is useful for accepting values from `Object.freeze()` or `as const`
5
+ * without forcing users to always use readonly modifiers.
6
+ *
7
+ * @template T - The base type to make flexible.
8
+ *
9
+ * @example
10
+ * ```typescript
11
+ * // Accepts both mutable and readonly arrays
12
+ * function process(items: Readonlyable<string[]>) { ... }
13
+ *
14
+ * process(["a", "b"]); // mutable array - OK
15
+ * process(["a", "b"] as const); // readonly array - OK
16
+ * ```
17
+ */
18
+ export type Readonlyable<T> = T extends Readonly<infer U> ? U | Readonly<U> : T | Readonly<T>;
1
19
  /**
2
20
  * Represents a class constructor that takes no arguments.
3
21
  * @template InstanceType - The type of instance created by this constructor.
@@ -79,9 +97,9 @@ export type AnyConstructor = ClassType<any, any[]> | AbstractClassType<any, any[
79
97
  * };
80
98
  * ```
81
99
  */
82
- export interface ClassableByResolver<InstanceType, Args extends any[] = [], Runtime = never> {
100
+ export interface ClassableByResolver<InstanceType, Args extends Readonlyable<any[]> = [], Runtime = never> {
83
101
  /** The target class constructor to instantiate. */
84
- target: ClassType<InstanceType, Args>;
102
+ target: ClassType<InstanceType, [...Args]>;
85
103
  /**
86
104
  * Function that resolves constructor arguments.
87
105
  * Can return arguments synchronously or as a Promise.
@@ -107,7 +125,7 @@ export interface ClassableByResolver<InstanceType, Args extends any[] = [], Runt
107
125
  * register({ target: User, resolve: () => ["John", 30] });
108
126
  * ```
109
127
  */
110
- export type Classable<InstanceType, Args extends any[] = [], Runtime = never> = ClassType<InstanceType, Args> | ClassableByResolver<InstanceType, Args, Runtime>;
128
+ export type Classable<InstanceType, Args extends Readonlyable<any[]> = [], Runtime = never> = ClassType<InstanceType, [...Args]> | ClassableByResolver<InstanceType, Args, Runtime>;
111
129
  /**
112
130
  * A placeholder class used as a marker for unresolved or pending class registrations.
113
131
  * Useful in dependency injection containers or lazy initialization patterns.
@@ -124,6 +142,7 @@ export type Classable<InstanceType, Args extends any[] = [], Runtime = never> =
124
142
  * ```
125
143
  */
126
144
  export declare class Placeholder {
145
+ static getInstance(): Placeholder;
127
146
  }
128
147
  /**
129
148
  * Pre-configured placeholder resolver that creates an empty Placeholder instance.
@@ -147,7 +166,91 @@ export type ThisExtended<Extend> = Placeholder & Extend;
147
166
  * @template InstanceType - The instance type of the class.
148
167
  * @template Args - Constructor argument types.
149
168
  */
150
- export type StaticExtended<Extend, InstanceType = any, Args extends any[] = []> = ClassType<InstanceType, Args> & Extend;
169
+ export type StaticExtended<Extend, InstanceType = any, Args extends Readonlyable<any[]> = []> = ClassType<InstanceType, [...Args]> & Extend;
170
+ /**
171
+ * Represents a class whose instances are created via a static factory method.
172
+ *
173
+ * This type is used for classes that expose a static method (e.g., `factory`, `create`)
174
+ * for instantiation instead of using `new` directly.
175
+ *
176
+ * @template InstanceType - The type of instance created by the static method.
177
+ * @template Method - The name of the static method to call (defaults to "factory").
178
+ * @template Args - Tuple type of arguments passed to the static method.
179
+ * @template Runtime - Optional runtime context type passed to the selector.
180
+ *
181
+ * @remarks
182
+ * - The constructor MAY exist and MAY take arguments.
183
+ * - Constructor arguments are considered an implementation detail
184
+ * and are intentionally typed as `any[]`.
185
+ * - Consumers MUST NOT rely on `new`.
186
+ *
187
+ * @example
188
+ * ```typescript
189
+ * class UserService {
190
+ * private constructor(private db: Database) {}
191
+ *
192
+ * static factory(db: Database): UserService {
193
+ * return new UserService(db);
194
+ * }
195
+ * }
196
+ *
197
+ * const def: InstanceByStatic<UserService, "factory", [Database]> = {
198
+ * target: UserService,
199
+ * selector: () => ({ method: "factory", args: [new Database()] })
200
+ * };
201
+ * ```
202
+ */
203
+ export type InstanceByStatic<InstanceType, Method extends string = "factory", Args extends Readonlyable<any[]> = [], Runtime = never> = {
204
+ target: StaticExtended<{
205
+ [K in Method]: (...args: Args) => InstanceType;
206
+ }, InstanceType, any[]>;
207
+ selector: (...args: Runtime extends never ? [] : [runtime: Runtime]) => {
208
+ method: Method;
209
+ args: Args;
210
+ };
211
+ };
212
+ /**
213
+ * Pre-configured placeholder instance using static factory method pattern.
214
+ * Use this as a default value for InstanceByStatic bindings.
215
+ *
216
+ * @example
217
+ * ```typescript
218
+ * const instance = classable.from(classable.placeholderInstance);
219
+ * // Returns new Placeholder instance via getInstance()
220
+ * ```
221
+ */
222
+ export declare const placeholderInstance: Readonly<{
223
+ target: typeof Placeholder;
224
+ selector: () => {
225
+ method: string;
226
+ args: [];
227
+ };
228
+ }>;
229
+ /**
230
+ * A selector function that chooses and returns a classable with its arguments.
231
+ *
232
+ * This type represents a function that takes a list of classables (and optionally a runtime context)
233
+ * and returns the selected classable along with its constructor arguments.
234
+ *
235
+ * @template InstanceType - The type of instance to be created.
236
+ * @template Args - Tuple type of constructor arguments.
237
+ * @template Runtime - Optional runtime context type for dependency resolution.
238
+ *
239
+ * @returns A tuple of [Classable, Args] or a Promise resolving to the same.
240
+ *
241
+ * @example
242
+ * ```typescript
243
+ * const selectByEnv: ClassableSelector<Logger, [], AppContext> = (runtime, ...classes) => {
244
+ * const LoggerClass = runtime.isDev ? DevLogger : ProdLogger;
245
+ * return [LoggerClass, []];
246
+ * };
247
+ *
248
+ * const selectFirst: ClassableSelector<Service, [string]> = (...classes) => {
249
+ * return [classes[0] as Classable<Service, [string]>, ["default"]];
250
+ * };
251
+ * ```
252
+ */
253
+ export type ClassableSelector<InstanceType, Args extends Readonlyable<any[]> = [], Runtime = never> = (...args: Runtime extends never ? Array<Classable<any, any[]>> : [runtime: Runtime, ...Array<Classable<any, any[], Runtime>>]) => [Classable<InstanceType, Args>, Args] | Promise<[Classable<InstanceType, Args>, Args]>;
151
254
  /**
152
255
  * Interface defining all available methods on the `classable` API object.
153
256
  * This provides type-safe access to class manipulation utilities.
@@ -156,19 +259,21 @@ export interface ClassableAPI {
156
259
  /** Reference to the Placeholder class constructor. */
157
260
  Placeholder: ClassType<Placeholder>;
158
261
  /** Pre-configured placeholder resolver instance. */
159
- placeholder: ClassableByResolver<Placeholder>;
262
+ placeholder: ClassableByResolver<Placeholder, readonly []>;
263
+ /** Pre-configured placeholder instance using InstanceByStatic pattern. */
264
+ placeholderInstance: InstanceByStatic<Placeholder, "getInstance", []>;
160
265
  /** Checks if a value is a class constructor. */
161
266
  is: (fn: unknown) => fn is AnyClass<any>;
162
267
  /** Checks if a value is an abstract class constructor. */
163
268
  isAbstract: (fn: unknown) => fn is AnyAbstractClass<any>;
164
269
  /** Checks if a value is a ClassableByResolver object. */
165
- isResolver: <InstanceType, Args extends any[] = [], Runtime = never>(obj: unknown) => obj is ClassableByResolver<InstanceType, Args, Runtime>;
270
+ isResolver: <InstanceType, Args extends Readonlyable<any[]> = [], Runtime = never>(obj: unknown) => obj is ClassableByResolver<InstanceType, Args, Runtime>;
166
271
  /** Converts a class constructor to a resolver configuration. */
167
- toResolver<T, A extends any[] = [], R = never>(cls: ClassType<T, A>, runtime?: R): ClassableByResolver<T, [], R>;
272
+ toResolver<T, A extends Readonlyable<any[]> = [], R = never>(cls: ClassType<T, [...A]>, runtime?: R): ClassableByResolver<T, [], R>;
168
273
  /** Extracts the target class from a Classable (class or resolver). */
169
274
  getTarget: <Target>(cls: Classable<Target, any[], any>) => Target;
170
275
  /** Creates a new resolver with a custom resolve function. */
171
- withResolve: <InstanceType, Args extends any[] = [], Runtime = never>(base: Classable<InstanceType, Args, Runtime>, resolve: ClassableByResolver<InstanceType, Args, Runtime>["resolve"]) => ClassableByResolver<InstanceType, Args, Runtime>;
276
+ withResolve: <InstanceType, Args extends Readonlyable<any[]> = [], Runtime = never>(base: Classable<InstanceType, Args, Runtime>, resolve: ClassableByResolver<InstanceType, Args, Runtime>["resolve"]) => ClassableByResolver<InstanceType, Args, Runtime>;
172
277
  /** Wraps a class with a transformation function. */
173
278
  wrap<T>(cls: ClassType<T>, wrapper: (target: ClassType<T>) => ClassType<T>): ClassType<T>;
174
279
  /** Wraps a resolver's target with a transformation function. */
@@ -181,13 +286,64 @@ export interface ClassableAPI {
181
286
  /** Creates an instance from a plain class. */
182
287
  create<InstanceType>(cls: ClassType<InstanceType>): InstanceType;
183
288
  /** Creates an instance from a resolver with sync resolve function. */
184
- create<InstanceType, Args extends any[], Runtime>(cls: ClassableByResolver<InstanceType, Args, Runtime> & {
289
+ create<InstanceType, Args extends Readonlyable<any[]>, Runtime>(cls: ClassableByResolver<InstanceType, Args, Runtime> & {
185
290
  resolve: (runtime: Runtime) => Args;
186
291
  }, runtime: Runtime): InstanceType;
187
292
  /** Creates an instance from a resolver with async resolve function. */
188
- create<InstanceType, Args extends any[], Runtime>(cls: ClassableByResolver<InstanceType, Args, Runtime> & {
293
+ create<InstanceType, Args extends Readonlyable<any[]>, Runtime>(cls: ClassableByResolver<InstanceType, Args, Runtime> & {
189
294
  resolve: (runtime: Runtime) => Promise<Args>;
190
295
  }, runtime: Runtime): Promise<InstanceType>;
296
+ /**
297
+ * Creates an instance from a static factory method definition.
298
+ *
299
+ * This method invokes the static method specified in the `InstanceByStatic` definition
300
+ * to create an instance, allowing for factory pattern implementations.
301
+ *
302
+ * @template InstanceType - The type of instance created.
303
+ * @template Method - The static method name to invoke.
304
+ * @template Args - Arguments passed to the static method.
305
+ * @template Runtime - Optional runtime context type.
306
+ * @param def - The static factory definition containing target class and selector.
307
+ * @param runtime - Optional runtime context passed to the selector.
308
+ * @returns The created instance.
309
+ *
310
+ * @example
311
+ * ```typescript
312
+ * class Cache {
313
+ * static create(ttl: number): Cache { return new Cache(ttl); }
314
+ * }
315
+ *
316
+ * const instance = classable.from({
317
+ * target: Cache,
318
+ * selector: () => ({ method: "create", args: [3600] })
319
+ * });
320
+ * ```
321
+ */
322
+ from: <InstanceType, Method extends string = "factory", Args extends Readonlyable<any[]> = [], Runtime = never>(def: InstanceByStatic<InstanceType, Method, Args, Runtime>, runtime?: Runtime) => InstanceType;
323
+ /**
324
+ * Creates a selector function that chooses a classable from a list based on custom logic.
325
+ *
326
+ * This higher-order function takes a selection strategy and returns a function
327
+ * that can be called with classables to select and instantiate the appropriate one.
328
+ *
329
+ * @template InstanceType - The type of instance to be created.
330
+ * @template Args - Constructor arguments for the selected classable.
331
+ * @template Runtime - Optional runtime context type.
332
+ * @param select - The selector function that implements the selection logic.
333
+ * @returns A function that accepts classables and returns the selection result.
334
+ *
335
+ * @example
336
+ * ```typescript
337
+ * const pickFirst = classable.select((cls1, cls2) => [cls1, []]);
338
+ * const [selected, args] = pickFirst(ServiceA, ServiceB);
339
+ *
340
+ * // With runtime context
341
+ * const pickByEnv = classable.select<Logger, [], Env>((env, ...loggers) => {
342
+ * return env.isDev ? [loggers[0], []] : [loggers[1], []];
343
+ * });
344
+ * ```
345
+ */
346
+ select: <InstanceType, Args extends Readonlyable<any[]> = [], Runtime = never>(select: ClassableSelector<InstanceType, Args, Runtime>) => (...args: Runtime extends never ? [...classes: Array<Classable<any, any[], Runtime>>] : [runtime: Runtime, ...classes: Array<Classable<any, any[], Runtime>>]) => ReturnType<ClassableSelector<InstanceType, Args, Runtime>>;
191
347
  }
192
348
  /**
193
349
  * The main classable API object providing utilities for working with classes and resolvers.
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- function e(e,t){return"object"==typeof e&&null!==e&&Object.prototype.hasOwnProperty.call(e,t)}class t{}const r=Object.freeze({target:t,resolve:()=>[]}),o=Object.freeze({Placeholder:t,placeholder:r,is:e=>"function"==typeof e&&/^class\s/.test(Function.prototype.toString.call(e)),isAbstract:e=>"function"==typeof e&&/^abstract\s+class\s/.test(Function.prototype.toString.call(e)),isResolver:t=>e(t,"target")&&o.is(t.target)&&e(t,"resolve")&&"function"==typeof t.resolve,toResolver:e=>o.isResolver(e)?e:{target:e,resolve:()=>[]},create:(e,t)=>{if(o.isResolver(e)){const r=e.resolve(...void 0===t?[]:[t]);return r instanceof Promise?r.then(t=>new e.target(...t)):new e.target(...r)}return new e(...[])},getTarget:e=>o.isResolver(e)?e.target:e,withResolve:(e,t)=>({target:(o.isResolver(e)?e:o.toResolver(e)).target,resolve:t}),wrap:(e,t)=>o.isResolver(e)?{target:t(e.target),resolve:e.resolve}:t(e),getDescriptor:e=>o.isResolver(e)?{type:"resolver",target:e.target.name}:{type:"class",target:e.name}});export{t as Placeholder,o as classable,r as placeholder};
1
+ function e(e,t){return"object"==typeof e&&null!==e&&Object.prototype.hasOwnProperty.call(e,t)}class t{static getInstance(){return new t}}const r=Object.freeze({target:t,resolve:()=>[]}),s=Object.freeze({target:t,selector:()=>({method:"getInstance",args:[]})}),o=Object.freeze({Placeholder:t,placeholder:r,placeholderInstance:s,is:e=>"function"==typeof e&&/^class\s/.test(Function.prototype.toString.call(e)),isAbstract:e=>"function"==typeof e&&/^abstract\s+class\s/.test(Function.prototype.toString.call(e)),isResolver:t=>e(t,"target")&&o.is(t.target)&&e(t,"resolve")&&"function"==typeof t.resolve,toResolver:e=>o.isResolver(e)?e:{target:e,resolve:()=>[]},create:(e,t)=>{if(o.isResolver(e)){const r=e.resolve(...void 0===t?[]:[t]);return r instanceof Promise?r.then(t=>new e.target(...t)):new e.target(...r)}return new e(...[])},getTarget:e=>o.isResolver(e)?e.target:e,withResolve:(e,t)=>({target:(o.isResolver(e)?e:o.toResolver(e)).target,resolve:t}),wrap:(e,t)=>o.isResolver(e)?{target:t(e.target),resolve:e.resolve}:t(e),getDescriptor:e=>o.isResolver(e)?{type:"resolver",target:e.target.name}:{type:"class",target:e.name},from:(e,t)=>{const{target:r,selector:s}=e,{method:o,args:a}=s(...void 0===t?[]:[t]);return r[o](...a)},select:e=>(...t)=>e(...t)});export{t as Placeholder,o as classable,r as placeholder,s as placeholderInstance};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mxweb/classable",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "A class-first abstraction for defining logic as resolvable units without runtime assumptions.",
5
5
  "license": "MIT",
6
6
  "keywords": [
@@ -11,7 +11,9 @@
11
11
  "resolver",
12
12
  "meta-programming",
13
13
  "framework-agnostic",
14
- "esm-only"
14
+ "esm-only",
15
+ "static-factory",
16
+ "dependency-injection"
15
17
  ],
16
18
  "type": "module",
17
19
  "module": "dist/index.js",
@@ -38,7 +40,8 @@
38
40
  "lint": "eslint \"src/**/*.{ts,tsx}\"",
39
41
  "lint:fix": "eslint \"src/**/*.{ts,tsx}\" --fix",
40
42
  "format": "prettier --write \"src/**/*.{ts,tsx,json,md}\"",
41
- "format:check": "prettier --check \"src/**/*.{ts,tsx,json,md}\""
43
+ "format:check": "prettier --check \"src/**/*.{ts,tsx,json,md}\"",
44
+ "prepublishOnly": "yarn build"
42
45
  },
43
46
  "devDependencies": {
44
47
  "@babel/core": "^7.28.6",