@gi-tcg/gts-runtime 0.6.8 → 0.7.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/dist/index.d.ts +42 -35
- package/dist/index.js +62 -34
- package/package.json +1 -1
- package/src/attribute_return.ts +13 -7
- package/src/index.ts +6 -2
- package/src/simple_view_model.ts +16 -12
- package/src/view_model.ts +185 -114
- package/src/symbols.ts +0 -3
package/dist/index.d.ts
CHANGED
|
@@ -15,8 +15,8 @@ declare namespace AttributeReturn {
|
|
|
15
15
|
"~meta": void;
|
|
16
16
|
};
|
|
17
17
|
};
|
|
18
|
-
type With<
|
|
19
|
-
namedDefinition: BlockDefinitionRewriteMeta<
|
|
18
|
+
type With<VMI extends IViewModelInstance, TMeta = VMI["~viewModel"]["~namedDefinition"]["~meta"]> = {
|
|
19
|
+
namedDefinition: BlockDefinitionRewriteMeta<VMI["~viewModel"]["~namedDefinition"], TMeta>;
|
|
20
20
|
};
|
|
21
21
|
type DoneRewriteMeta<NewMeta> = {
|
|
22
22
|
namedDefinition: {
|
|
@@ -24,17 +24,12 @@ declare namespace AttributeReturn {
|
|
|
24
24
|
};
|
|
25
25
|
rewriteMeta: NewMeta;
|
|
26
26
|
};
|
|
27
|
-
type WithRewriteMeta<NewMeta,
|
|
28
|
-
namedDefinition: BlockDefinitionRewriteMeta<
|
|
27
|
+
type WithRewriteMeta<NewMeta, VMI extends IViewModelInstance, TMeta = VMI["~viewModel"]["~namedDefinition"]["~meta"]> = {
|
|
28
|
+
namedDefinition: BlockDefinitionRewriteMeta<VMI["~viewModel"]["~namedDefinition"], TMeta>;
|
|
29
29
|
rewriteMeta: NewMeta;
|
|
30
30
|
};
|
|
31
31
|
}
|
|
32
32
|
//#endregion
|
|
33
|
-
//#region src/symbols.d.ts
|
|
34
|
-
type Meta = "~meta";
|
|
35
|
-
type Action = "~action";
|
|
36
|
-
type NamedDefinition = "~namedDefinition";
|
|
37
|
-
//#endregion
|
|
38
33
|
//#region src/view.d.ts
|
|
39
34
|
type AttributeName = string | symbol;
|
|
40
35
|
interface SingleAttributeNode {
|
|
@@ -66,39 +61,50 @@ declare function createBinding(rootVM: IViewModel<any, any, any>, node: SingleAt
|
|
|
66
61
|
interface AttributeBlockDefinition {
|
|
67
62
|
"~meta": any;
|
|
68
63
|
}
|
|
69
|
-
|
|
64
|
+
interface PartialAttributeBlockDefinition extends Partial<Record<string, AttributeDefinition>> {}
|
|
65
|
+
type BlockDefinitionRewriteMeta<BlockDef extends AttributeBlockDefinition, NewMeta> = Computed<Omit<BlockDef, "~meta"> & {
|
|
70
66
|
"~meta": NewMeta;
|
|
71
67
|
}, AttributeBlockDefinition>;
|
|
68
|
+
interface IViewModelInstance<T extends IViewModel<any, any, any> = IViewModel<any, any, any>> {
|
|
69
|
+
"~viewModel": T;
|
|
70
|
+
}
|
|
71
|
+
type DeferredIViewModel<T> = T extends IViewModel<any, any, any> ? T : never;
|
|
72
|
+
interface IReboundViewModel<BaseViewModel extends IViewModel<any, any, any>, NewCtorArgs extends any[]> extends DeferredIViewModel<IViewModel<BaseViewModel["~modelType"], BaseViewModel["~namedDefinition"], NewCtorArgs>> {}
|
|
73
|
+
interface INarrowedViewModel<BaseViewModel extends IViewModel<any, any, any>, NewMeta extends BaseViewModel["~namedDefinition"]["~meta"]> extends DeferredIViewModel<IViewModel<BaseViewModel["~modelType"], BlockDefinitionRewriteMeta<BaseViewModel["~namedDefinition"], NewMeta>, BaseViewModel["~ctorArgs"]>> {}
|
|
74
|
+
interface IExtendedViewModel<BaseViewModel extends IViewModel<any, any, any>, ChildModelT extends BaseViewModel["~modelType"], ChildBlockDef extends PartialAttributeBlockDefinition, ChildCtorArgs extends any[]> extends DeferredIViewModel<IViewModel<ChildModelT, Computed<Omit<BaseViewModel["~namedDefinition"], keyof ChildBlockDef> & ChildBlockDef & {
|
|
75
|
+
"~meta": BaseViewModel["~namedDefinition"]["~meta"];
|
|
76
|
+
}>, ChildCtorArgs>> {}
|
|
72
77
|
interface IViewModel<ModelT, BlockDef extends AttributeBlockDefinition, CtorArgs extends any[]> {
|
|
78
|
+
"~modelType": ModelT;
|
|
79
|
+
"~ctorArgs": CtorArgs;
|
|
80
|
+
"~namedDefinition": BlockDef;
|
|
81
|
+
new (): IViewModelInstance<this>;
|
|
82
|
+
"~viewModel": this;
|
|
73
83
|
parse(view: View<BlockDefinitionRewriteMeta<BlockDef, unknown>>, ...args: CtorArgs): ModelT;
|
|
74
84
|
/**
|
|
75
85
|
* Creates a new ViewModel with the same actions and binders, but with
|
|
76
|
-
*
|
|
77
|
-
* - a different initial Meta.
|
|
86
|
+
* a different constructor that accepts the specified arguments.
|
|
78
87
|
*
|
|
79
88
|
* This is useful for creating binding ViewModels directly that forwards
|
|
80
89
|
* the binding logic to inner ViewModels.
|
|
81
90
|
*/
|
|
82
|
-
bind<
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
"~namedDefinition":
|
|
91
|
+
bind<This extends IViewModel<any, any, any>>(this: This, ...args: CtorArgs): IReboundViewModel<This, []>;
|
|
92
|
+
/**
|
|
93
|
+
* Rewrite the initial meta.
|
|
94
|
+
* @param newMeta
|
|
95
|
+
*/
|
|
96
|
+
narrow<This extends IViewModel<any, any, any>, const NewMeta extends This["~namedDefinition"]["~meta"]>(this: This, newMeta: NewMeta): INarrowedViewModel<This, NewMeta>;
|
|
97
|
+
extend<This extends IViewModel<any, any, any>, ChildT extends ModelT, const ChildBlockDef extends PartialAttributeBlockDefinition, ChildCtorArgs extends any[] = []>(this: This, Ctor: new (...args: ChildCtorArgs) => ChildT, modelDefFn: (helper: AttributeDefHelper<ChildT>) => ChildBlockDef): IExtendedViewModel<This, ChildT, ChildBlockDef, ChildCtorArgs>;
|
|
88
98
|
}
|
|
89
99
|
type LazyAttributeActionOrBinder<ModelT> = (model: ModelT, positionals: () => unknown[], named: View<any>) => unknown;
|
|
90
100
|
declare function getCurrentContext(): "action" | "binder" | null;
|
|
91
|
-
declare class
|
|
101
|
+
declare class ViewModelRuntime {
|
|
92
102
|
#private;
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
bind<NewMeta = BlockDef[Meta]>(...args: CtorArgs): IViewModel<ModelT, BlockDefinitionRewriteMeta<BlockDef, NewMeta>, []>;
|
|
99
|
-
extend<ChildT extends ModelT, const ChildBlockDef extends Partial<Record<string | Action, AttributeDefinition>>, ChildCtorArgs extends any[] = []>(Ctor: new (...args: ChildCtorArgs) => ChildT, modelDefFn: (helper: AttributeDefHelper<ChildT>) => ChildBlockDef): IViewModel<ChildT, Computed<Omit<BlockDef, keyof ChildBlockDef> & ChildBlockDef & {
|
|
100
|
-
"~meta": BlockDef[Meta];
|
|
101
|
-
}>, ChildCtorArgs>;
|
|
103
|
+
constructor(Ctor: new (...args: any[]) => any);
|
|
104
|
+
setActionOrBinder(context: "action" | "binder", name: PropertyKey, action: LazyAttributeActionOrBinder<any>): void;
|
|
105
|
+
parse(view: View<any>, ...args: any[]): any;
|
|
106
|
+
bind(...args: any[]): ViewModelRuntime;
|
|
107
|
+
extend(ChildCtor: new (...args: any[]) => any, modelDefFn: (helper: AttributeDefHelper<any>) => any): ViewModelRuntime;
|
|
102
108
|
}
|
|
103
109
|
interface SimpleAttributeOptions {
|
|
104
110
|
required?: true;
|
|
@@ -111,7 +117,7 @@ type WithSimpleOptions<Base, Options extends SimpleAttributeOptions> = Base & (O
|
|
|
111
117
|
} : {});
|
|
112
118
|
declare class AttributeDefHelper<ModelT> {
|
|
113
119
|
#private;
|
|
114
|
-
constructor(
|
|
120
|
+
constructor(vmr: ViewModelRuntime);
|
|
115
121
|
"~assignActions"(defResult: Partial<Record<string, unknown>>): void;
|
|
116
122
|
attribute<T extends AttributeDefinition & {
|
|
117
123
|
as?: undefined;
|
|
@@ -136,9 +142,10 @@ declare class AttributeDefHelper<ModelT> {
|
|
|
136
142
|
}, Options>;
|
|
137
143
|
};
|
|
138
144
|
}
|
|
139
|
-
declare function defineViewModel<T, const BlockDef extends
|
|
145
|
+
declare function defineViewModel<T, const BlockDef extends PartialAttributeBlockDefinition, CtorArgs extends any[] = [], InitMeta = unknown>(Ctor: new (...args: CtorArgs) => T, modelDefFn: (helper: AttributeDefHelper<T>) => BlockDef, initMeta?: InitMeta): IViewModel<T, BlockDef & {
|
|
140
146
|
"~meta": InitMeta;
|
|
141
147
|
}, CtorArgs>;
|
|
148
|
+
declare function extendViewModel<BaseViewModel extends IViewModel<any, any, any>, ChildModelT extends BaseViewModel["~modelType"], const ChildBlockDef extends PartialAttributeBlockDefinition, ChildCtorArgs extends any[] = []>(baseViewModel: BaseViewModel, Ctor: new (...args: ChildCtorArgs) => ChildModelT, modelDefFn: (helper: AttributeDefHelper<ChildModelT>) => ChildBlockDef): IExtendedViewModel<BaseViewModel, ChildModelT, ChildBlockDef, ChildCtorArgs>;
|
|
142
149
|
interface AttributeDefinition {
|
|
143
150
|
(...args: any[]): AttributePositionalReturnBase;
|
|
144
151
|
as?(): any;
|
|
@@ -260,18 +267,18 @@ type IfAll<T extends (boolean | undefined)[], TrueT, FalseT> = T[number] extends
|
|
|
260
267
|
type SimpleViewModelAttribute<ValueT, Options extends SimpleViewModelOptions> = {
|
|
261
268
|
(value: ValueT): AttributeReturn.Done;
|
|
262
269
|
} & IfAll<[Options["recursive"], IsSingleton<ExtractObject<ValueT>>], {
|
|
263
|
-
(): AttributeReturn.With<
|
|
270
|
+
(): AttributeReturn.With<IViewModelInstance<ISimpleViewModel<ExtractObject<ValueT>, Options>>>;
|
|
264
271
|
}, IfAll<[Options["booleanSwitch"], true extends ValueT ? true : false], {
|
|
265
272
|
(): AttributeReturn.Done;
|
|
266
273
|
}, {}>>;
|
|
267
|
-
interface
|
|
274
|
+
interface ISimpleViewModel<T, Options extends SimpleViewModelOptions = {}> extends IViewModel<T, { [K in keyof T]-?: SimpleViewModelAttribute<T[K], Options> & {
|
|
268
275
|
uniqueKey(): K;
|
|
269
276
|
required(): {} extends Pick<T, K> ? false : true;
|
|
270
277
|
} } & {
|
|
271
|
-
"~meta":
|
|
278
|
+
"~meta": unknown;
|
|
272
279
|
}, []> {
|
|
273
280
|
Model: new () => T;
|
|
274
281
|
}
|
|
275
|
-
declare function defineSimpleViewModel<const T extends StandardJSONSchemaV1, const Options extends SimpleViewModelOptions = {}>(schema: T, options?: Options):
|
|
282
|
+
declare function defineSimpleViewModel<const T extends StandardJSONSchemaV1, const Options extends SimpleViewModelOptions = {}>(schema: T, options?: Options): ISimpleViewModel<StandardJSONSchemaV1.InferInput<T>, Options>;
|
|
276
283
|
//#endregion
|
|
277
|
-
export { type AttributeReturn as AR, type AttributeReturn, type
|
|
284
|
+
export { type AttributeReturn as AR, type AttributeReturn, type AttributeBlockDefinition, type AttributeDefinition, type IExtendedViewModel, type INarrowedViewModel, type IReboundViewModel, type ISimpleViewModel, type IViewModel, type IViewModelInstance, type NamedAttributesNode, type SimpleAttributeOptions, type SimpleViewModelOptions, type SingleAttributeNode, type View, createBinding, createDefine, defineSimpleViewModel, defineViewModel, extendViewModel, getCurrentContext };
|
package/dist/index.js
CHANGED
|
@@ -34,14 +34,14 @@ let currentContext = null;
|
|
|
34
34
|
function getCurrentContext() {
|
|
35
35
|
return currentContext;
|
|
36
36
|
}
|
|
37
|
-
var
|
|
37
|
+
var ViewModelRuntime = class ViewModelRuntime {
|
|
38
38
|
#registeredActions = /* @__PURE__ */ new Map();
|
|
39
39
|
#registeredBinders = /* @__PURE__ */ new Map();
|
|
40
40
|
#Ctor;
|
|
41
41
|
constructor(Ctor) {
|
|
42
42
|
this.#Ctor = Ctor;
|
|
43
43
|
}
|
|
44
|
-
|
|
44
|
+
setActionOrBinder(context, name, action) {
|
|
45
45
|
if (context === "action") this.#registeredActions.set(name, action);
|
|
46
46
|
else this.#registeredBinders.set(name, action);
|
|
47
47
|
}
|
|
@@ -64,36 +64,60 @@ var ViewModel = class ViewModel {
|
|
|
64
64
|
currentContext = null;
|
|
65
65
|
return model;
|
|
66
66
|
}
|
|
67
|
-
#clone() {
|
|
68
|
-
const
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
return
|
|
67
|
+
#clone(Ctor = this.#Ctor) {
|
|
68
|
+
const newVMR = new ViewModelRuntime(Ctor);
|
|
69
|
+
newVMR.#registeredActions = new Map(this.#registeredActions);
|
|
70
|
+
newVMR.#registeredBinders = new Map(this.#registeredBinders);
|
|
71
|
+
return newVMR;
|
|
72
72
|
}
|
|
73
73
|
bind(...args) {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
newModel.#Ctor = class extends this.#Ctor {
|
|
74
|
+
const ParentCtor = this.#Ctor;
|
|
75
|
+
class ReboundCtor extends ParentCtor {
|
|
77
76
|
constructor() {
|
|
78
77
|
super(...args);
|
|
79
78
|
}
|
|
80
|
-
}
|
|
81
|
-
return
|
|
79
|
+
}
|
|
80
|
+
return this.#clone(ReboundCtor);
|
|
82
81
|
}
|
|
83
|
-
extend(
|
|
84
|
-
const
|
|
85
|
-
|
|
86
|
-
for (const [name, binder] of this.#registeredBinders) newVM["~setActionOrBinder"]("binder", name, binder);
|
|
87
|
-
const helper = new AttributeDefHelper(newVM);
|
|
82
|
+
extend(ChildCtor, modelDefFn) {
|
|
83
|
+
const newVMR = this.#clone(ChildCtor);
|
|
84
|
+
const helper = new AttributeDefHelper(newVMR);
|
|
88
85
|
const defResult = modelDefFn(helper);
|
|
89
86
|
helper["~assignActions"](defResult);
|
|
90
|
-
return
|
|
87
|
+
return newVMR;
|
|
91
88
|
}
|
|
92
89
|
};
|
|
90
|
+
const runtimeViewModelSlot = Symbol("runtimeViewModel");
|
|
91
|
+
function isViewModel(value) {
|
|
92
|
+
return typeof value === "function" && runtimeViewModelSlot in value;
|
|
93
|
+
}
|
|
94
|
+
function createViewModel(vmr) {
|
|
95
|
+
class ViewModelDescriptor {
|
|
96
|
+
static [runtimeViewModelSlot] = vmr;
|
|
97
|
+
constructor() {
|
|
98
|
+
const name = new.target.name;
|
|
99
|
+
throw new Error(`ViewModel cannot be constructed. Use static method instead: \`${name}.parse\`, \`${name}.extend\` etc.`);
|
|
100
|
+
}
|
|
101
|
+
static parse(view, ...args) {
|
|
102
|
+
return vmr.parse(view, ...args);
|
|
103
|
+
}
|
|
104
|
+
static bind(...args) {
|
|
105
|
+
if (args.length === 0) return this;
|
|
106
|
+
return createViewModel(vmr.bind(...args));
|
|
107
|
+
}
|
|
108
|
+
static narrow(_newMeta) {
|
|
109
|
+
return this;
|
|
110
|
+
}
|
|
111
|
+
static extend(Ctor, modelDefFn) {
|
|
112
|
+
return createViewModel(vmr.extend(Ctor, modelDefFn));
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return ViewModelDescriptor;
|
|
116
|
+
}
|
|
93
117
|
var AttributeDefHelper = class AttributeDefHelper {
|
|
94
|
-
#
|
|
95
|
-
constructor(
|
|
96
|
-
this.#
|
|
118
|
+
#vmr;
|
|
119
|
+
constructor(vmr) {
|
|
120
|
+
this.#vmr = vmr;
|
|
97
121
|
}
|
|
98
122
|
static #lazyActionSlot = Symbol("actionSlot");
|
|
99
123
|
static #lazyBinderSlot = Symbol("binderSlot");
|
|
@@ -104,9 +128,9 @@ var AttributeDefHelper = class AttributeDefHelper {
|
|
|
104
128
|
continue;
|
|
105
129
|
}
|
|
106
130
|
const actionDescriptor = Object.getOwnPropertyDescriptor(value, AttributeDefHelper.#lazyActionSlot);
|
|
107
|
-
if (actionDescriptor) this.#
|
|
131
|
+
if (actionDescriptor) this.#vmr.setActionOrBinder("action", name, actionDescriptor.value);
|
|
108
132
|
const binderDescriptor = Object.getOwnPropertyDescriptor(value, AttributeDefHelper.#lazyBinderSlot);
|
|
109
|
-
if (binderDescriptor) this.#
|
|
133
|
+
if (binderDescriptor) this.#vmr.setActionOrBinder("binder", name, binderDescriptor.value);
|
|
110
134
|
}
|
|
111
135
|
}
|
|
112
136
|
attribute(action, binder) {
|
|
@@ -117,13 +141,13 @@ var AttributeDefHelper = class AttributeDefHelper {
|
|
|
117
141
|
enumerable: true
|
|
118
142
|
});
|
|
119
143
|
let lazyBinder;
|
|
120
|
-
if (
|
|
121
|
-
else if (binder) {
|
|
144
|
+
if (isViewModel(binder)) {
|
|
122
145
|
const vm = binder;
|
|
123
146
|
lazyBinder = (model, positionals, named) => {
|
|
124
147
|
return vm.parse(named);
|
|
125
148
|
};
|
|
126
|
-
} else lazyBinder = () =>
|
|
149
|
+
} else if (typeof binder === "function") lazyBinder = (model, positionals, named) => binder(model, positionals(), named);
|
|
150
|
+
else lazyBinder = () => {};
|
|
127
151
|
Object.defineProperty(returnValue, AttributeDefHelper.#lazyBinderSlot, {
|
|
128
152
|
value: lazyBinder,
|
|
129
153
|
enumerable: true
|
|
@@ -140,11 +164,14 @@ var AttributeDefHelper = class AttributeDefHelper {
|
|
|
140
164
|
}
|
|
141
165
|
};
|
|
142
166
|
function defineViewModel(Ctor, modelDefFn, initMeta) {
|
|
143
|
-
const
|
|
144
|
-
const helper = new AttributeDefHelper(
|
|
167
|
+
const vmr = new ViewModelRuntime(Ctor);
|
|
168
|
+
const helper = new AttributeDefHelper(vmr);
|
|
145
169
|
const defResult = modelDefFn(helper);
|
|
146
170
|
helper["~assignActions"](defResult);
|
|
147
|
-
return
|
|
171
|
+
return createViewModel(vmr);
|
|
172
|
+
}
|
|
173
|
+
function extendViewModel(baseViewModel, Ctor, modelDefFn) {
|
|
174
|
+
return baseViewModel.extend(Ctor, modelDefFn);
|
|
148
175
|
}
|
|
149
176
|
//#endregion
|
|
150
177
|
//#region src/simple_view_model.ts
|
|
@@ -166,8 +193,8 @@ function extractObjectSchema(propSchema) {
|
|
|
166
193
|
}
|
|
167
194
|
function createSimpleViewModelFromJsonSchema(jsonSchema, options) {
|
|
168
195
|
const Ctor = class SimpleViewModel {};
|
|
169
|
-
const
|
|
170
|
-
const helper = new AttributeDefHelper(
|
|
196
|
+
const vmr = new ViewModelRuntime(Ctor);
|
|
197
|
+
const helper = new AttributeDefHelper(vmr);
|
|
171
198
|
const defResult = {};
|
|
172
199
|
for (const key of Object.keys(jsonSchema.properties ?? {})) {
|
|
173
200
|
const propSchema = jsonSchema.properties[key];
|
|
@@ -175,13 +202,14 @@ function createSimpleViewModelFromJsonSchema(jsonSchema, options) {
|
|
|
175
202
|
defResult[key] = registerAttribute(helper, key, propSchema, options);
|
|
176
203
|
}
|
|
177
204
|
helper["~assignActions"](defResult);
|
|
178
|
-
|
|
205
|
+
const ViewModel = createViewModel(vmr);
|
|
206
|
+
Object.defineProperty(ViewModel, "Model", {
|
|
179
207
|
value: Ctor,
|
|
180
208
|
writable: false,
|
|
181
209
|
enumerable: true,
|
|
182
210
|
configurable: true
|
|
183
211
|
});
|
|
184
|
-
return
|
|
212
|
+
return ViewModel;
|
|
185
213
|
}
|
|
186
214
|
function registerAttribute(helper, key, propSchema, options) {
|
|
187
215
|
let objectSchema = null;
|
|
@@ -208,4 +236,4 @@ function defineSimpleViewModel(schema, options) {
|
|
|
208
236
|
return createSimpleViewModelFromJsonSchema(schema["~standard"].jsonSchema.input({ target: "draft-2020-12" }), resolvedOptions);
|
|
209
237
|
}
|
|
210
238
|
//#endregion
|
|
211
|
-
export { createBinding, createDefine, defineSimpleViewModel, defineViewModel, getCurrentContext };
|
|
239
|
+
export { createBinding, createDefine, defineSimpleViewModel, defineViewModel, extendViewModel, getCurrentContext };
|
package/package.json
CHANGED
package/src/attribute_return.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type {
|
|
2
2
|
AttributeBlockDefinition,
|
|
3
3
|
BlockDefinitionRewriteMeta,
|
|
4
|
-
|
|
4
|
+
IViewModelInstance,
|
|
5
5
|
} from "./view_model.ts";
|
|
6
6
|
|
|
7
7
|
export type Computed<T, Constraint = any> = T extends Constraint
|
|
@@ -28,10 +28,13 @@ export namespace AttributeReturn {
|
|
|
28
28
|
};
|
|
29
29
|
|
|
30
30
|
export type With<
|
|
31
|
-
|
|
32
|
-
TMeta =
|
|
31
|
+
VMI extends IViewModelInstance,
|
|
32
|
+
TMeta = VMI["~viewModel"]["~namedDefinition"]["~meta"],
|
|
33
33
|
> = {
|
|
34
|
-
namedDefinition: BlockDefinitionRewriteMeta<
|
|
34
|
+
namedDefinition: BlockDefinitionRewriteMeta<
|
|
35
|
+
VMI["~viewModel"]["~namedDefinition"],
|
|
36
|
+
TMeta
|
|
37
|
+
>;
|
|
35
38
|
};
|
|
36
39
|
|
|
37
40
|
export type DoneRewriteMeta<NewMeta> = {
|
|
@@ -41,10 +44,13 @@ export namespace AttributeReturn {
|
|
|
41
44
|
|
|
42
45
|
export type WithRewriteMeta<
|
|
43
46
|
NewMeta,
|
|
44
|
-
|
|
45
|
-
TMeta =
|
|
47
|
+
VMI extends IViewModelInstance,
|
|
48
|
+
TMeta = VMI["~viewModel"]["~namedDefinition"]["~meta"],
|
|
46
49
|
> = {
|
|
47
|
-
namedDefinition: BlockDefinitionRewriteMeta<
|
|
50
|
+
namedDefinition: BlockDefinitionRewriteMeta<
|
|
51
|
+
VMI["~viewModel"]["~namedDefinition"],
|
|
52
|
+
TMeta
|
|
53
|
+
>;
|
|
48
54
|
rewriteMeta: NewMeta;
|
|
49
55
|
};
|
|
50
56
|
}
|
package/src/index.ts
CHANGED
|
@@ -1,18 +1,22 @@
|
|
|
1
1
|
export {
|
|
2
2
|
defineViewModel,
|
|
3
|
+
extendViewModel,
|
|
3
4
|
getCurrentContext,
|
|
4
5
|
type AttributeDefinition,
|
|
5
6
|
type IViewModel,
|
|
7
|
+
type IViewModelInstance,
|
|
8
|
+
type IReboundViewModel,
|
|
9
|
+
type INarrowedViewModel,
|
|
10
|
+
type IExtendedViewModel,
|
|
6
11
|
type SimpleAttributeOptions,
|
|
7
12
|
type AttributeBlockDefinition,
|
|
8
13
|
} from "./view_model.ts";
|
|
9
14
|
export {
|
|
10
15
|
defineSimpleViewModel,
|
|
11
|
-
type
|
|
16
|
+
type ISimpleViewModel,
|
|
12
17
|
type SimpleViewModelOptions,
|
|
13
18
|
} from "./simple_view_model.ts";
|
|
14
19
|
export type { AttributeReturn, AR } from "./attribute_return.ts";
|
|
15
|
-
export type { Action, Meta, NamedDefinition } from "./symbols.ts";
|
|
16
20
|
|
|
17
21
|
export {
|
|
18
22
|
createBinding,
|
package/src/simple_view_model.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import type { StandardJSONSchemaV1 } from "@standard-schema/spec";
|
|
2
2
|
import {
|
|
3
3
|
AttributeDefHelper,
|
|
4
|
-
|
|
4
|
+
createViewModel,
|
|
5
5
|
type IViewModel,
|
|
6
|
-
type
|
|
6
|
+
type IViewModelInstance,
|
|
7
|
+
ViewModelRuntime,
|
|
7
8
|
} from "./view_model.ts";
|
|
8
9
|
import type { AttributeReturn } from "./attribute_return.ts";
|
|
9
10
|
import { Ajv2020 } from "ajv/dist/2020.js";
|
|
@@ -39,7 +40,9 @@ type SimpleViewModelAttribute<
|
|
|
39
40
|
} & IfAll<
|
|
40
41
|
[Options["recursive"], IsSingleton<ExtractObject<ValueT>>],
|
|
41
42
|
{
|
|
42
|
-
(): AttributeReturn.With<
|
|
43
|
+
(): AttributeReturn.With<
|
|
44
|
+
IViewModelInstance<ISimpleViewModel<ExtractObject<ValueT>, Options>>
|
|
45
|
+
>;
|
|
43
46
|
},
|
|
44
47
|
IfAll<
|
|
45
48
|
[Options["booleanSwitch"], true extends ValueT ? true : false],
|
|
@@ -48,7 +51,7 @@ type SimpleViewModelAttribute<
|
|
|
48
51
|
>
|
|
49
52
|
>;
|
|
50
53
|
|
|
51
|
-
export interface
|
|
54
|
+
export interface ISimpleViewModel<
|
|
52
55
|
T,
|
|
53
56
|
Options extends SimpleViewModelOptions = {},
|
|
54
57
|
> extends IViewModel<
|
|
@@ -59,7 +62,7 @@ export interface SimpleViewModel<
|
|
|
59
62
|
required(): {} extends Pick<T, K> ? false : true;
|
|
60
63
|
};
|
|
61
64
|
} & {
|
|
62
|
-
"~meta":
|
|
65
|
+
"~meta": unknown;
|
|
63
66
|
},
|
|
64
67
|
[]
|
|
65
68
|
> {
|
|
@@ -97,10 +100,10 @@ function extractObjectSchema(
|
|
|
97
100
|
function createSimpleViewModelFromJsonSchema(
|
|
98
101
|
jsonSchema: Record<string, unknown>,
|
|
99
102
|
options: SimpleViewModelOptions,
|
|
100
|
-
):
|
|
103
|
+
): ISimpleViewModel<any, any> {
|
|
101
104
|
const Ctor = class SimpleViewModel {};
|
|
102
|
-
const
|
|
103
|
-
const helper = new AttributeDefHelper(
|
|
105
|
+
const vmr = new ViewModelRuntime(Ctor);
|
|
106
|
+
const helper = new AttributeDefHelper(vmr);
|
|
104
107
|
const defResult: Record<string, any> = {};
|
|
105
108
|
for (const key of Object.keys(jsonSchema.properties ?? {})) {
|
|
106
109
|
const propSchema = (jsonSchema.properties as Record<string, unknown>)[key];
|
|
@@ -115,13 +118,14 @@ function createSimpleViewModelFromJsonSchema(
|
|
|
115
118
|
);
|
|
116
119
|
}
|
|
117
120
|
helper["~assignActions"](defResult);
|
|
118
|
-
|
|
121
|
+
const ViewModel = createViewModel(vmr);
|
|
122
|
+
Object.defineProperty(ViewModel, "Model", {
|
|
119
123
|
value: Ctor,
|
|
120
124
|
writable: false,
|
|
121
125
|
enumerable: true,
|
|
122
126
|
configurable: true,
|
|
123
127
|
});
|
|
124
|
-
return
|
|
128
|
+
return ViewModel as ISimpleViewModel<any, any>;
|
|
125
129
|
}
|
|
126
130
|
|
|
127
131
|
function registerAttribute(
|
|
@@ -162,7 +166,7 @@ export function defineSimpleViewModel<
|
|
|
162
166
|
>(
|
|
163
167
|
schema: T,
|
|
164
168
|
options?: Options,
|
|
165
|
-
):
|
|
169
|
+
): ISimpleViewModel<StandardJSONSchemaV1.InferInput<T>, Options> {
|
|
166
170
|
const resolvedOptions: SimpleViewModelOptions = {
|
|
167
171
|
booleanSwitch: false,
|
|
168
172
|
recursive: false,
|
|
@@ -174,5 +178,5 @@ export function defineSimpleViewModel<
|
|
|
174
178
|
return createSimpleViewModelFromJsonSchema(
|
|
175
179
|
jsonSchema,
|
|
176
180
|
resolvedOptions,
|
|
177
|
-
) as
|
|
181
|
+
) as ISimpleViewModel<StandardJSONSchemaV1.InferInput<T>, Options>;
|
|
178
182
|
}
|
package/src/view_model.ts
CHANGED
|
@@ -3,64 +3,115 @@ import type {
|
|
|
3
3
|
AttributeReturn,
|
|
4
4
|
Computed,
|
|
5
5
|
} from "./attribute_return.ts";
|
|
6
|
-
import type { Action, Meta } from "./symbols.ts";
|
|
7
6
|
import { View } from "./view.ts";
|
|
8
7
|
|
|
9
8
|
export interface AttributeBlockDefinition {
|
|
10
9
|
"~meta": any;
|
|
11
10
|
}
|
|
12
11
|
|
|
12
|
+
export interface PartialAttributeBlockDefinition extends Partial<
|
|
13
|
+
Record<string, AttributeDefinition>
|
|
14
|
+
> {}
|
|
15
|
+
|
|
13
16
|
export type BlockDefinitionRewriteMeta<
|
|
14
17
|
BlockDef extends AttributeBlockDefinition,
|
|
15
18
|
NewMeta,
|
|
16
19
|
> = Computed<
|
|
17
|
-
Omit<BlockDef,
|
|
20
|
+
Omit<BlockDef, "~meta"> & { "~meta": NewMeta },
|
|
18
21
|
AttributeBlockDefinition
|
|
19
22
|
>;
|
|
20
23
|
|
|
24
|
+
export interface IViewModelInstance<
|
|
25
|
+
T extends IViewModel<any, any, any> = IViewModel<any, any, any>,
|
|
26
|
+
> {
|
|
27
|
+
"~viewModel": T;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export type DeferredIViewModel<T> =
|
|
31
|
+
T extends IViewModel<any, any, any> ? T : never;
|
|
32
|
+
|
|
33
|
+
export interface IReboundViewModel<
|
|
34
|
+
BaseViewModel extends IViewModel<any, any, any>,
|
|
35
|
+
NewCtorArgs extends any[],
|
|
36
|
+
> extends DeferredIViewModel<
|
|
37
|
+
IViewModel<
|
|
38
|
+
BaseViewModel["~modelType"],
|
|
39
|
+
BaseViewModel["~namedDefinition"],
|
|
40
|
+
NewCtorArgs
|
|
41
|
+
>
|
|
42
|
+
> {}
|
|
43
|
+
export interface INarrowedViewModel<
|
|
44
|
+
BaseViewModel extends IViewModel<any, any, any>,
|
|
45
|
+
NewMeta extends BaseViewModel["~namedDefinition"]["~meta"],
|
|
46
|
+
> extends DeferredIViewModel<
|
|
47
|
+
IViewModel<
|
|
48
|
+
BaseViewModel["~modelType"],
|
|
49
|
+
BlockDefinitionRewriteMeta<BaseViewModel["~namedDefinition"], NewMeta>,
|
|
50
|
+
BaseViewModel["~ctorArgs"]
|
|
51
|
+
>
|
|
52
|
+
> {}
|
|
53
|
+
|
|
54
|
+
export interface IExtendedViewModel<
|
|
55
|
+
BaseViewModel extends IViewModel<any, any, any>,
|
|
56
|
+
ChildModelT extends BaseViewModel["~modelType"],
|
|
57
|
+
ChildBlockDef extends PartialAttributeBlockDefinition,
|
|
58
|
+
ChildCtorArgs extends any[],
|
|
59
|
+
> extends DeferredIViewModel<
|
|
60
|
+
IViewModel<
|
|
61
|
+
ChildModelT,
|
|
62
|
+
Computed<
|
|
63
|
+
Omit<BaseViewModel["~namedDefinition"], keyof ChildBlockDef> &
|
|
64
|
+
ChildBlockDef & { "~meta": BaseViewModel["~namedDefinition"]["~meta"] }
|
|
65
|
+
>,
|
|
66
|
+
ChildCtorArgs
|
|
67
|
+
>
|
|
68
|
+
> {}
|
|
69
|
+
|
|
21
70
|
export interface IViewModel<
|
|
22
71
|
ModelT,
|
|
23
72
|
BlockDef extends AttributeBlockDefinition,
|
|
24
73
|
CtorArgs extends any[],
|
|
25
74
|
> {
|
|
75
|
+
"~modelType": ModelT;
|
|
76
|
+
"~ctorArgs": CtorArgs;
|
|
77
|
+
"~namedDefinition": BlockDef;
|
|
78
|
+
new (): IViewModelInstance<this>;
|
|
79
|
+
"~viewModel": this;
|
|
26
80
|
parse(
|
|
27
81
|
view: View<BlockDefinitionRewriteMeta<BlockDef, unknown>>,
|
|
28
82
|
...args: CtorArgs
|
|
29
83
|
): ModelT;
|
|
30
84
|
/**
|
|
31
85
|
* Creates a new ViewModel with the same actions and binders, but with
|
|
32
|
-
*
|
|
33
|
-
* - a different initial Meta.
|
|
86
|
+
* a different constructor that accepts the specified arguments.
|
|
34
87
|
*
|
|
35
88
|
* This is useful for creating binding ViewModels directly that forwards
|
|
36
89
|
* the binding logic to inner ViewModels.
|
|
37
90
|
*/
|
|
38
|
-
bind<
|
|
39
|
-
|
|
40
|
-
BlockDefinitionRewriteMeta<BlockDef, NewMeta>,
|
|
41
|
-
CtorArgs
|
|
42
|
-
>;
|
|
43
|
-
bind<NewMeta = BlockDef[Meta]>(
|
|
91
|
+
bind<This extends IViewModel<any, any, any>>(
|
|
92
|
+
this: This,
|
|
44
93
|
...args: CtorArgs
|
|
45
|
-
):
|
|
94
|
+
): IReboundViewModel<This, []>;
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Rewrite the initial meta.
|
|
98
|
+
* @param newMeta
|
|
99
|
+
*/
|
|
100
|
+
narrow<This extends IViewModel<any, any, any>, const NewMeta extends This["~namedDefinition"]["~meta"]>(
|
|
101
|
+
this: This,
|
|
102
|
+
newMeta: NewMeta,
|
|
103
|
+
): INarrowedViewModel<This, NewMeta>;
|
|
104
|
+
|
|
46
105
|
extend<
|
|
106
|
+
This extends IViewModel<any, any, any>,
|
|
47
107
|
ChildT extends ModelT,
|
|
48
|
-
const ChildBlockDef extends
|
|
49
|
-
Record<string | Action, AttributeDefinition>
|
|
50
|
-
>,
|
|
108
|
+
const ChildBlockDef extends PartialAttributeBlockDefinition,
|
|
51
109
|
ChildCtorArgs extends any[] = [],
|
|
52
110
|
>(
|
|
111
|
+
this: This,
|
|
53
112
|
Ctor: new (...args: ChildCtorArgs) => ChildT,
|
|
54
113
|
modelDefFn: (helper: AttributeDefHelper<ChildT>) => ChildBlockDef,
|
|
55
|
-
):
|
|
56
|
-
ChildT,
|
|
57
|
-
Computed<
|
|
58
|
-
Omit<BlockDef, keyof ChildBlockDef> &
|
|
59
|
-
ChildBlockDef & { "~meta": BlockDef[Meta] }
|
|
60
|
-
>,
|
|
61
|
-
ChildCtorArgs
|
|
62
|
-
>;
|
|
63
|
-
"~namedDefinition": BlockDef;
|
|
114
|
+
): IExtendedViewModel<This, ChildT, ChildBlockDef, ChildCtorArgs>;
|
|
64
115
|
}
|
|
65
116
|
|
|
66
117
|
type LazyAttributeActionOrBinder<ModelT> = (
|
|
@@ -74,28 +125,19 @@ export function getCurrentContext(): "action" | "binder" | null {
|
|
|
74
125
|
return currentContext;
|
|
75
126
|
}
|
|
76
127
|
|
|
77
|
-
export class
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
> implements IViewModel<ModelT, BlockDef, CtorArgs> {
|
|
82
|
-
declare "~namedDefinition": BlockDef;
|
|
83
|
-
|
|
84
|
-
#registeredActions: Map<PropertyKey, LazyAttributeActionOrBinder<ModelT>> =
|
|
85
|
-
new Map();
|
|
86
|
-
#registeredBinders: Map<PropertyKey, LazyAttributeActionOrBinder<ModelT>> =
|
|
87
|
-
new Map();
|
|
128
|
+
export class ViewModelRuntime {
|
|
129
|
+
#registeredActions = new Map<PropertyKey, LazyAttributeActionOrBinder<any>>();
|
|
130
|
+
#registeredBinders = new Map<PropertyKey, LazyAttributeActionOrBinder<any>>();
|
|
131
|
+
#Ctor: new (...args: any[]) => any;
|
|
88
132
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
constructor(Ctor: new (...args: CtorArgs) => ModelT) {
|
|
133
|
+
constructor(Ctor: new (...args: any[]) => any) {
|
|
92
134
|
this.#Ctor = Ctor;
|
|
93
135
|
}
|
|
94
136
|
|
|
95
|
-
|
|
137
|
+
setActionOrBinder(
|
|
96
138
|
context: "action" | "binder",
|
|
97
139
|
name: PropertyKey,
|
|
98
|
-
action: LazyAttributeActionOrBinder<
|
|
140
|
+
action: LazyAttributeActionOrBinder<any>,
|
|
99
141
|
): void {
|
|
100
142
|
if (context === "action") {
|
|
101
143
|
this.#registeredActions.set(name, action);
|
|
@@ -104,10 +146,7 @@ export class ViewModel<
|
|
|
104
146
|
}
|
|
105
147
|
}
|
|
106
148
|
|
|
107
|
-
parse(
|
|
108
|
-
view: View<BlockDefinitionRewriteMeta<BlockDef, unknown>>,
|
|
109
|
-
...args: CtorArgs
|
|
110
|
-
): ModelT {
|
|
149
|
+
parse(view: View<any>, ...args: any[]): any {
|
|
111
150
|
currentContext = view._bindingCtx ? "binder" : "action";
|
|
112
151
|
const model = new this.#Ctor(...args);
|
|
113
152
|
for (const attrNode of view._node.attributes) {
|
|
@@ -133,65 +172,87 @@ export class ViewModel<
|
|
|
133
172
|
return model;
|
|
134
173
|
}
|
|
135
174
|
|
|
136
|
-
#clone() {
|
|
137
|
-
const
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
return
|
|
175
|
+
#clone(Ctor = this.#Ctor): ViewModelRuntime {
|
|
176
|
+
const newVMR = new ViewModelRuntime(Ctor);
|
|
177
|
+
newVMR.#registeredActions = new Map(this.#registeredActions);
|
|
178
|
+
newVMR.#registeredBinders = new Map(this.#registeredBinders);
|
|
179
|
+
return newVMR;
|
|
141
180
|
}
|
|
142
181
|
|
|
143
|
-
bind
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
CtorArgs
|
|
147
|
-
>;
|
|
148
|
-
bind<NewMeta = BlockDef[Meta]>(
|
|
149
|
-
...args: CtorArgs
|
|
150
|
-
): IViewModel<ModelT, BlockDefinitionRewriteMeta<BlockDef, NewMeta>, []>;
|
|
151
|
-
bind<NewMeta = BlockDef[Meta]>(
|
|
152
|
-
...args: any[]
|
|
153
|
-
): IViewModel<ModelT, BlockDefinitionRewriteMeta<BlockDef, NewMeta>, any> {
|
|
154
|
-
if (args.length === 0) {
|
|
155
|
-
return this as any;
|
|
156
|
-
}
|
|
157
|
-
const newModel = this.#clone() as ViewModel<any, any, any>;
|
|
158
|
-
newModel.#Ctor = class extends (this.#Ctor as new (...args: any[]) => any) {
|
|
182
|
+
bind(...args: any[]): ViewModelRuntime {
|
|
183
|
+
const ParentCtor = this.#Ctor;
|
|
184
|
+
class ReboundCtor extends ParentCtor {
|
|
159
185
|
constructor() {
|
|
160
186
|
super(...args);
|
|
161
187
|
}
|
|
162
|
-
}
|
|
163
|
-
return
|
|
188
|
+
}
|
|
189
|
+
return this.#clone(ReboundCtor);
|
|
164
190
|
}
|
|
165
191
|
|
|
166
|
-
extend
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
>(
|
|
173
|
-
Ctor: new (...args: ChildCtorArgs) => ChildT,
|
|
174
|
-
modelDefFn: (helper: AttributeDefHelper<ChildT>) => ChildBlockDef,
|
|
175
|
-
): IViewModel<
|
|
176
|
-
ChildT,
|
|
177
|
-
Computed<
|
|
178
|
-
Omit<BlockDef, keyof ChildBlockDef> &
|
|
179
|
-
ChildBlockDef & { "~meta": BlockDef[Meta] }
|
|
180
|
-
>,
|
|
181
|
-
ChildCtorArgs
|
|
182
|
-
> {
|
|
183
|
-
const newVM = new ViewModel<ChildT, any, ChildCtorArgs>(Ctor);
|
|
184
|
-
for (const [name, action] of this.#registeredActions) {
|
|
185
|
-
newVM["~setActionOrBinder"]("action", name, action as any);
|
|
186
|
-
}
|
|
187
|
-
for (const [name, binder] of this.#registeredBinders) {
|
|
188
|
-
newVM["~setActionOrBinder"]("binder", name, binder as any);
|
|
189
|
-
}
|
|
190
|
-
const helper = new AttributeDefHelper(newVM);
|
|
192
|
+
extend(
|
|
193
|
+
ChildCtor: new (...args: any[]) => any,
|
|
194
|
+
modelDefFn: (helper: AttributeDefHelper<any>) => any,
|
|
195
|
+
): ViewModelRuntime {
|
|
196
|
+
const newVMR = this.#clone(ChildCtor);
|
|
197
|
+
const helper = new AttributeDefHelper(newVMR);
|
|
191
198
|
const defResult = modelDefFn(helper);
|
|
192
199
|
helper["~assignActions"](defResult);
|
|
193
|
-
return
|
|
200
|
+
return newVMR;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
const runtimeViewModelSlot: unique symbol = Symbol("runtimeViewModel");
|
|
205
|
+
|
|
206
|
+
function isViewModel(value: unknown): value is IViewModel<any, any, any> {
|
|
207
|
+
return typeof value === "function" && runtimeViewModelSlot in value;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
export function createViewModel<
|
|
211
|
+
ModelT,
|
|
212
|
+
BlockDef extends AttributeBlockDefinition,
|
|
213
|
+
CtorArgs extends any[],
|
|
214
|
+
>(vmr: ViewModelRuntime): IViewModel<ModelT, BlockDef, CtorArgs> {
|
|
215
|
+
class ViewModelDescriptor implements IViewModelInstance {
|
|
216
|
+
declare static "~modelType": ModelT;
|
|
217
|
+
declare static "~ctorArgs": CtorArgs;
|
|
218
|
+
declare static "~namedDefinition": BlockDef;
|
|
219
|
+
|
|
220
|
+
static readonly [runtimeViewModelSlot] = vmr;
|
|
221
|
+
|
|
222
|
+
constructor() {
|
|
223
|
+
const name = new.target.name;
|
|
224
|
+
throw new Error(
|
|
225
|
+
`ViewModel cannot be constructed. Use static method instead: \`${name}.parse\`, \`${name}.extend\` etc.`,
|
|
226
|
+
);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
static parse(view: View<any>, ...args: CtorArgs): ModelT {
|
|
230
|
+
return vmr.parse(view, ...args);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
static bind(...args: any[]): IViewModel<any, any, any> {
|
|
234
|
+
if (args.length === 0) {
|
|
235
|
+
return this;
|
|
236
|
+
}
|
|
237
|
+
return createViewModel(vmr.bind(...args));
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
static narrow(_newMeta: any): IViewModel<any, any, any> {
|
|
241
|
+
return this;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
static extend(
|
|
245
|
+
Ctor: new (...args: any[]) => any,
|
|
246
|
+
modelDefFn: (helper: AttributeDefHelper<any>) => any,
|
|
247
|
+
): IViewModel<any, any, any> {
|
|
248
|
+
return createViewModel(vmr.extend(Ctor, modelDefFn));
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
declare "~viewModel": typeof ViewModelDescriptor;
|
|
252
|
+
declare static "~viewModel": typeof ViewModelDescriptor;
|
|
194
253
|
}
|
|
254
|
+
|
|
255
|
+
return ViewModelDescriptor as IViewModel<ModelT, BlockDef, CtorArgs>;
|
|
195
256
|
}
|
|
196
257
|
|
|
197
258
|
export interface SimpleAttributeOptions {
|
|
@@ -206,9 +267,9 @@ type WithSimpleOptions<Base, Options extends SimpleAttributeOptions> = Base &
|
|
|
206
267
|
: {});
|
|
207
268
|
|
|
208
269
|
export class AttributeDefHelper<ModelT> {
|
|
209
|
-
#
|
|
210
|
-
constructor(
|
|
211
|
-
this.#
|
|
270
|
+
#vmr: ViewModelRuntime;
|
|
271
|
+
constructor(vmr: ViewModelRuntime) {
|
|
272
|
+
this.#vmr = vmr;
|
|
212
273
|
}
|
|
213
274
|
|
|
214
275
|
static readonly #lazyActionSlot: unique symbol = Symbol("actionSlot");
|
|
@@ -228,22 +289,14 @@ export class AttributeDefHelper<ModelT> {
|
|
|
228
289
|
AttributeDefHelper.#lazyActionSlot,
|
|
229
290
|
);
|
|
230
291
|
if (actionDescriptor) {
|
|
231
|
-
this.#
|
|
232
|
-
"action",
|
|
233
|
-
name,
|
|
234
|
-
actionDescriptor.value,
|
|
235
|
-
);
|
|
292
|
+
this.#vmr.setActionOrBinder("action", name, actionDescriptor.value);
|
|
236
293
|
}
|
|
237
294
|
const binderDescriptor = Object.getOwnPropertyDescriptor(
|
|
238
295
|
value,
|
|
239
296
|
AttributeDefHelper.#lazyBinderSlot,
|
|
240
297
|
);
|
|
241
298
|
if (binderDescriptor) {
|
|
242
|
-
this.#
|
|
243
|
-
"binder",
|
|
244
|
-
name,
|
|
245
|
-
binderDescriptor.value,
|
|
246
|
-
);
|
|
299
|
+
this.#vmr.setActionOrBinder("binder", name, binderDescriptor.value);
|
|
247
300
|
}
|
|
248
301
|
}
|
|
249
302
|
}
|
|
@@ -273,14 +326,14 @@ export class AttributeDefHelper<ModelT> {
|
|
|
273
326
|
enumerable: true,
|
|
274
327
|
});
|
|
275
328
|
let lazyBinder: LazyAttributeActionOrBinder<ModelT>;
|
|
276
|
-
if (
|
|
277
|
-
lazyBinder = (model, positionals, named) =>
|
|
278
|
-
binder(model, positionals(), named);
|
|
279
|
-
} else if (binder) {
|
|
329
|
+
if (isViewModel(binder)) {
|
|
280
330
|
const vm = binder;
|
|
281
331
|
lazyBinder = (model, positionals, named) => {
|
|
282
332
|
return vm.parse(named);
|
|
283
333
|
};
|
|
334
|
+
} else if (typeof binder === "function") {
|
|
335
|
+
lazyBinder = (model, positionals, named) =>
|
|
336
|
+
binder(model, positionals(), named);
|
|
284
337
|
} else {
|
|
285
338
|
lazyBinder = () => {};
|
|
286
339
|
}
|
|
@@ -332,19 +385,37 @@ export class AttributeDefHelper<ModelT> {
|
|
|
332
385
|
|
|
333
386
|
export function defineViewModel<
|
|
334
387
|
T,
|
|
335
|
-
const BlockDef extends
|
|
388
|
+
const BlockDef extends PartialAttributeBlockDefinition,
|
|
336
389
|
CtorArgs extends any[] = [],
|
|
337
|
-
InitMeta =
|
|
390
|
+
InitMeta = unknown,
|
|
338
391
|
>(
|
|
339
392
|
Ctor: new (...args: CtorArgs) => T,
|
|
340
393
|
modelDefFn: (helper: AttributeDefHelper<T>) => BlockDef,
|
|
341
394
|
initMeta?: InitMeta,
|
|
342
395
|
): IViewModel<T, BlockDef & { "~meta": InitMeta }, CtorArgs> {
|
|
343
|
-
const
|
|
344
|
-
const helper = new AttributeDefHelper(
|
|
396
|
+
const vmr = new ViewModelRuntime(Ctor);
|
|
397
|
+
const helper = new AttributeDefHelper<T>(vmr);
|
|
345
398
|
const defResult = modelDefFn(helper);
|
|
346
399
|
helper["~assignActions"](defResult);
|
|
347
|
-
return
|
|
400
|
+
return createViewModel(vmr);
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
export function extendViewModel<
|
|
404
|
+
BaseViewModel extends IViewModel<any, any, any>,
|
|
405
|
+
ChildModelT extends BaseViewModel["~modelType"],
|
|
406
|
+
const ChildBlockDef extends PartialAttributeBlockDefinition,
|
|
407
|
+
ChildCtorArgs extends any[] = [],
|
|
408
|
+
>(
|
|
409
|
+
baseViewModel: BaseViewModel,
|
|
410
|
+
Ctor: new (...args: ChildCtorArgs) => ChildModelT,
|
|
411
|
+
modelDefFn: (helper: AttributeDefHelper<ChildModelT>) => ChildBlockDef,
|
|
412
|
+
): IExtendedViewModel<
|
|
413
|
+
BaseViewModel,
|
|
414
|
+
ChildModelT,
|
|
415
|
+
ChildBlockDef,
|
|
416
|
+
ChildCtorArgs
|
|
417
|
+
> {
|
|
418
|
+
return baseViewModel.extend(Ctor, modelDefFn);
|
|
348
419
|
}
|
|
349
420
|
|
|
350
421
|
export interface AttributeDefinition {
|
package/src/symbols.ts
DELETED