@vue-modeler/model 1.0.7-beta.1 → 1.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +191 -3
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  ## What is @vue-modeler/model
4
4
 
5
- A state management library based on models for [VUE.js.](VUE.js.) The extremely simple API serves single purpose — creating models. It preserves types, supports OOP, DRY, and SOLID principles.
5
+ A state management library based on models for [Vue.js](https://vuejs.org/). The extremely simple API serves single purpose — creating models. It preserves types, supports OOP, DRY, and SOLID principles.
6
6
 
7
7
  ---
8
8
 
@@ -34,7 +34,7 @@ A state management library based on models for [VUE.js.](VUE.js.) The extremely
34
34
  Less code, fewer issues.
35
35
 
36
36
  #### **Use Classes and Interfaces**
37
- Both VUEX and Pinia employ custom approaches for managing stores and reusing common code. I wanted to use standard classes, interfaces, getters, and protected properties. That's why my models are built upon classes and support OOP patterns.
37
+ Both Vuex and Pinia employ custom approaches for managing stores and reusing common code. I wanted to use standard classes, interfaces, getters, and protected properties. That's why my models are built upon classes and support OOP patterns.
38
38
 
39
39
  #### **Reuse Business Logic Across Projects**
40
40
  Models are classes where dependencies are injected via constructors, so model files don't contain direct imports of external dependencies. Models can easily be extracted into separate modules and reused in other projects or with different UI libraries.
@@ -51,4 +51,192 @@ Models are classes where dependencies are injected via constructors, so model fi
51
51
 
52
52
  ---
53
53
 
54
- This library promises to simplify state management in [Vue.js](Vue.js) applications while promoting clean, scalable, and maintainable code.
54
+ This library promises to simplify state management in [Vue.js](https://vuejs.org/) applications while promoting clean, scalable, and maintainable code.
55
+
56
+ ## Installation
57
+
58
+ First, [install @vue-modeler/dc](https://github.com/vue-modeler/dc?tab=readme-ov-file#installation)
59
+
60
+ Then install @vue-modeler/model:
61
+
62
+ ```bash
63
+ npm add @vue-modeler/model
64
+ ```
65
+
66
+ ## Usage Examples
67
+
68
+ ### 1. Define Proto model
69
+
70
+ ```typescript
71
+ import { ProtoModel, action } from '@vue-modeler/model'
72
+
73
+ export interface Api {
74
+ fetchUser: () => Promise<UserDto>
75
+ patch: (dto: PatchDto) => Promise<void>
76
+ }
77
+
78
+ export interface UserDto {
79
+ name: string
80
+ email: string
81
+ }
82
+
83
+ export interface PatchDto {
84
+ name?: string
85
+ email?: string
86
+ }
87
+
88
+ // Define your model class extending ProtoModel
89
+ class User extends ProtoModel {
90
+
91
+ // Regular properties. It will be reactive after creation model
92
+ protected _name = ''
93
+ protected _email = ''
94
+
95
+ get name(): string {
96
+ return this._name
97
+ }
98
+
99
+ get email(): string {
100
+ return this._email
101
+ }
102
+
103
+ constructor(
104
+ private api: Api
105
+ ) {
106
+ super()
107
+
108
+ this.action(this.init).exec()
109
+ }
110
+
111
+ // Actions (async methods with @action decorator)
112
+ @action async init() {
113
+ if (this.action(this.patch).isPending) {
114
+ throw new Error('action execution conflict')
115
+ }
116
+
117
+ const userDto = await this.api.fetchUser()
118
+ this._name = userDto.name
119
+ this._email = userDto.email
120
+ }
121
+
122
+ @action async patch(dto: PatchDto): Promise<void> {
123
+ if (this.action(this.init).isPending) {
124
+ throw new Error('action execution conflict')
125
+ }
126
+
127
+ await this.api.patch(dto)
128
+ if (dto.name) this._name = dto.name
129
+ if (dto.email) this._email = dto.email
130
+ }
131
+ }
132
+ ```
133
+
134
+ ### 2. Create API
135
+
136
+ ```typescript
137
+ export const fetchUser = async (): Promise<UserDto> => {
138
+ const response = await fetch('/api/users/me')
139
+ return response.json()
140
+ }
141
+
142
+ export const patchUser = async (dto: PatchDto): Promise<void> => {
143
+ await fetch('/api/users/me', {
144
+ method: 'PATCH',
145
+ headers: { 'Content-Type': 'application/json' },
146
+ body: JSON.stringify(dto)
147
+ })
148
+ }
149
+ ```
150
+
151
+ ### 3. Compose all together and create model provider
152
+
153
+ ```typescript
154
+ import { model } from '@vue-modeler/model'
155
+
156
+ export const useUser = model(() => new User({
157
+ fetchUser,
158
+ patch: patchUser
159
+ }))
160
+ ```
161
+
162
+ ### 4. Using Models in Vue Components
163
+
164
+ ```html
165
+ <template>
166
+ <div>
167
+ <div v-if="user.init.isPending">Loading...</div>
168
+ <div v-else-if="user.init.error">Error: {{ user.init.error.message }}</div>
169
+ <div v-else>
170
+ <h2>{{ user.name }}</h2>
171
+ <p>{{ user.email }}</p>
172
+
173
+ <form @submit.prevent="saveUser" class="user-form">
174
+ <div class="form-group">
175
+ <label for="name">Name:</label>
176
+ <input
177
+ id="name"
178
+ v-model="formData.name"
179
+ type="text"
180
+ :disabled="user.init.isPending || user.patch.isPending"
181
+ required
182
+ />
183
+ </div>
184
+
185
+ <div class="form-group">
186
+ <label for="email">Email:</label>
187
+ <input
188
+ id="email"
189
+ v-model="formData.email"
190
+ type="email"
191
+ :disabled="user.init.isPending || user.patch.isPending"
192
+ required
193
+ />
194
+ </div>
195
+
196
+ <div class="form-actions">
197
+ <button type="button"
198
+ :disabled="user.init.isPending || user.patch.isPending"
199
+ @click="user.init.exec()"
200
+ >
201
+ Reload User
202
+ </button>
203
+
204
+ <button type="submit" :disabled="user.init.isPending || user.patch.isPending">
205
+ {{ user.patch.isPending ? 'Saving...' : 'Save Changes' }}
206
+ </button>
207
+ </div>
208
+ </form>
209
+ </div>
210
+ </div>
211
+ </template>
212
+
213
+ <script setup lang="ts">
214
+ import { ref, watch } from 'vue'
215
+ import { useUser } from './user-model'
216
+
217
+ const user = useUser()
218
+
219
+ // Form data for editing
220
+ const formData = ref({
221
+ name: user.name,
222
+ email: user.email
223
+ })
224
+
225
+ // Update form data when user data changes
226
+ watch(() => user.name, (newName) => {
227
+ formData.value.name = newName
228
+ })
229
+
230
+ watch(() => user.email, (newEmail) => {
231
+ formData.value.email = newEmail
232
+ })
233
+
234
+ const saveUser = () => {
235
+ user.patch.exec({
236
+ name: formData.value.name,
237
+ email: formData.value.email
238
+ })
239
+ }
240
+ </script>
241
+ ```
242
+
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@vue-modeler/model",
4
- "version": "1.0.7-beta.1",
4
+ "version": "1.0.7",
5
5
  "description": "A state management library based on models for Vue.js",
6
6
  "author": "abratko",
7
7
  "license": "MIT",