@rs-x/vue 2.0.0-next.9 → 2.0.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/dist/index.d.ts CHANGED
@@ -8,4 +8,7 @@ declare function getExpressionManager(): IExpressionManager;
8
8
 
9
9
  declare function useRsxExpression<T>(expression: IExpression<T>): vue.Ref<any, any> extends T | null ? vue.ShallowRef<null, null> | (T extends T & vue.Ref<any, any> ? _vue_shared.IfAny<T, vue.ShallowRef<T, T>, T> : vue.ShallowRef<T, T>) : vue.ShallowRef<T | null, T | null>;
10
10
 
11
- export { getExpressionFactory, getExpressionManager, useRsxExpression };
11
+ type FieldFilter = (model: object, field: string) => boolean;
12
+ declare function useRsxModel<TModel extends object>(model: TModel, mustWatch?: FieldFilter): TModel;
13
+
14
+ export { type FieldFilter, getExpressionFactory, getExpressionManager, useRsxExpression, useRsxModel };
package/dist/index.js CHANGED
@@ -7,7 +7,7 @@ import { RsXExpressionParserInjectionTokens, RsXExpressionParserModule } from "@
7
7
  var factoryInstance;
8
8
  function getExpressionFactory() {
9
9
  if (!factoryInstance) {
10
- if (!InjectionContainer.isBound(RsXExpressionParserInjectionTokens.IExpressionFactory)) {
10
+ if (!InjectionContainer.isBound(RsXExpressionParserInjectionTokens.IExpressionParser)) {
11
11
  InjectionContainer.load(RsXExpressionParserModule);
12
12
  }
13
13
  factoryInstance = InjectionContainer.get(RsXExpressionParserInjectionTokens.IExpressionFactory);
@@ -22,7 +22,7 @@ import { RsXExpressionParserInjectionTokens as RsXExpressionParserInjectionToken
22
22
  var expressionManager;
23
23
  function getExpressionManager() {
24
24
  if (!expressionManager) {
25
- if (!InjectionContainer2.isBound(RsXExpressionParserInjectionTokens2.IExpressionManager)) {
25
+ if (!InjectionContainer2.isBound(RsXExpressionParserInjectionTokens2.IExpressionParser)) {
26
26
  InjectionContainer2.load(RsXExpressionParserModule2);
27
27
  }
28
28
  expressionManager = InjectionContainer2.get(RsXExpressionParserInjectionTokens2.IExpressionManager);
@@ -33,15 +33,18 @@ __name(getExpressionManager, "getExpressionManager");
33
33
 
34
34
  // src/hooks/use-rsx-expression.ts
35
35
  import { getCurrentScope, onScopeDispose, shallowRef } from "vue";
36
- import { AbstractExpression } from "@rs-x/expression-parser";
36
+ import { AbstractExpression, CompiledExpression } from "@rs-x/expression-parser";
37
37
  function useRsxExpression(expression) {
38
- if (!(expression instanceof AbstractExpression)) {
38
+ if (!(expression instanceof AbstractExpression) && !(expression instanceof CompiledExpression)) {
39
39
  throw new Error("useRsxExpression: expression must be an IExpression");
40
40
  }
41
41
  const expressionTree = expression;
42
- const value = shallowRef(expressionTree.value ?? null);
42
+ const getCurrentValue = /* @__PURE__ */ __name(() => {
43
+ return expressionTree.value ?? null;
44
+ }, "getCurrentValue");
45
+ const value = shallowRef(getCurrentValue());
43
46
  const subscription = expressionTree.changed.subscribe(() => {
44
- value.value = expressionTree.value ?? null;
47
+ value.value = getCurrentValue();
45
48
  });
46
49
  if (getCurrentScope()) {
47
50
  onScopeDispose(() => {
@@ -51,8 +54,72 @@ function useRsxExpression(expression) {
51
54
  return value;
52
55
  }
53
56
  __name(useRsxExpression, "useRsxExpression");
57
+
58
+ // src/hooks/use-rsx-model.ts
59
+ import { getCurrentInstance, getCurrentScope as getCurrentScope2, markRaw, onScopeDispose as onScopeDispose2 } from "vue";
60
+ import { truePredicate, Type, UnsupportedException } from "@rs-x/core";
61
+ import { rsx } from "@rs-x/expression-parser";
62
+ function useRsxModel(model, mustWatch) {
63
+ const expressionCache = /* @__PURE__ */ new Map();
64
+ const subscriptions = [];
65
+ const shouldWatch = mustWatch ?? truePredicate;
66
+ const currentInstance = getCurrentInstance();
67
+ const forceUpdate = /* @__PURE__ */ __name(() => {
68
+ currentInstance?.proxy?.$forceUpdate();
69
+ }, "forceUpdate");
70
+ const getOrCreateExpression = /* @__PURE__ */ __name((parent, field) => {
71
+ let fieldMap = expressionCache.get(parent);
72
+ if (!fieldMap) {
73
+ fieldMap = /* @__PURE__ */ new Map();
74
+ expressionCache.set(parent, fieldMap);
75
+ }
76
+ let expression = fieldMap.get(field);
77
+ if (!expression) {
78
+ expression = rsx(field)(parent);
79
+ fieldMap.set(field, expression);
80
+ }
81
+ return expression;
82
+ }, "getOrCreateExpression");
83
+ const disposeExpressions = /* @__PURE__ */ __name(() => {
84
+ for (const subscription of subscriptions) {
85
+ subscription.unsubscribe();
86
+ }
87
+ for (const fieldMap of expressionCache.values()) {
88
+ for (const expression of fieldMap.values()) {
89
+ expression.dispose();
90
+ }
91
+ }
92
+ }, "disposeExpressions");
93
+ if (getCurrentScope2()) {
94
+ onScopeDispose2(() => {
95
+ disposeExpressions();
96
+ });
97
+ }
98
+ const bindObject = /* @__PURE__ */ __name((sourceObject) => {
99
+ for (const [field, value] of Object.entries(sourceObject)) {
100
+ if (!shouldWatch(sourceObject, field) || Type.isMethod(value) || Type.isArrowFunction(value)) {
101
+ continue;
102
+ }
103
+ if (Type.isIterableCollection(value)) {
104
+ throw new UnsupportedException("Collections are not supported by useRsxModel yet.");
105
+ }
106
+ if (Type.isPlainObject(value)) {
107
+ bindObject(value);
108
+ continue;
109
+ }
110
+ const expression = getOrCreateExpression(sourceObject, field);
111
+ subscriptions.push(expression.changed.subscribe(() => {
112
+ forceUpdate();
113
+ }));
114
+ }
115
+ }, "bindObject");
116
+ bindObject(model);
117
+ return markRaw(model);
118
+ }
119
+ __name(useRsxModel, "useRsxModel");
54
120
  export {
55
121
  getExpressionFactory,
56
122
  getExpressionManager,
57
- useRsxExpression
123
+ useRsxExpression,
124
+ useRsxModel
58
125
  };
package/package.json CHANGED
@@ -1,16 +1,22 @@
1
1
  {
2
2
  "name": "@rs-x/vue",
3
- "version": "2.0.0-next.9",
3
+ "version": "2.0.0",
4
4
  "description": "Vue extension for the RS-X framework with composables to bind RS-X expressions to Vue components",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
7
- "module": "./dist/index.js",
8
7
  "types": "./dist/index.d.ts",
9
8
  "exports": {
10
9
  ".": {
11
10
  "types": "./dist/index.d.ts",
12
- "import": "./dist/index.js"
13
- }
11
+ "import": "./dist/index.js",
12
+ "default": "./dist/index.js"
13
+ },
14
+ "./testing": {
15
+ "types": "./dist/testing/index.d.ts",
16
+ "import": "./dist/testing/index.js",
17
+ "default": "./dist/testing/index.js"
18
+ },
19
+ "./package.json": "./package.json"
14
20
  },
15
21
  "sideEffects": false,
16
22
  "files": [
@@ -32,24 +38,24 @@
32
38
  "vue": ">=3.3.0"
33
39
  },
34
40
  "dependencies": {
35
- "@rs-x/core": "2.0.0-next.9",
36
- "@rs-x/expression-parser": "2.0.0-next.9",
37
- "@rs-x/state-manager": "2.0.0-next.9"
41
+ "@rs-x/state-manager": "2.0.0",
42
+ "@rs-x/core": "2.0.0",
43
+ "@rs-x/expression-parser": "2.0.0"
38
44
  },
39
45
  "devDependencies": {
40
- "@vitejs/plugin-vue": "^6.0.1",
41
- "eslint": "^10.0.1",
42
- "eslint-plugin-vue": "^10.5.1",
43
- "globals": "^17.3.0",
46
+ "@vitejs/plugin-vue": "^6.0.5",
47
+ "eslint": "^10.2.0",
48
+ "eslint-plugin-vue": "^10.8.0",
49
+ "globals": "^17.4.0",
44
50
  "prettier": "^3.8.1",
45
51
  "rimraf": "^6.1.3",
46
52
  "tsup": "^8.5.1",
47
- "typescript": "^5.9.3",
48
- "vite": "^7.3.1",
53
+ "typescript": "^6.0.2",
54
+ "vite": "^8.0.7",
49
55
  "vite-tsconfig-paths": "^6.1.1",
50
- "vue-eslint-parser": "^10.2.0",
51
- "vitest": "^4.0.18",
52
- "vue": "^3.5.0"
56
+ "vitest": "^4.1.3",
57
+ "vue": "^3.5.32",
58
+ "vue-eslint-parser": "^10.4.0"
53
59
  },
54
60
  "engines": {
55
61
  "node": ">=24"
@@ -63,7 +69,7 @@
63
69
  "composable"
64
70
  ],
65
71
  "scripts": {
66
- "build": "tsup src/index.ts --format esm --dts --external vue --tsconfig ../tsconfig.build.json",
72
+ "build": "tsup src/index.ts --format esm --dts --external vue",
67
73
  "test": "vitest run",
68
74
  "clean": "rimraf dist"
69
75
  }