@medyll/idae-idbql 0.0.1 → 0.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/README.md +156 -30
- package/dist/collection/collection.d.ts +1 -1
- package/dist/collection/collection.js +17 -24
- package/dist/idbqlCore/idbqlCore.d.ts +8 -8
- package/dist/idbqlCore/idbqlCore.js +12 -12
- package/dist/idbqlCore/idbqlSchema.js +4 -8
- package/dist/path/pathResolver.d.ts +2 -2
- package/dist/path/pathResolver.js +1 -2
- package/dist/state/idbqlEvent.svelte.d.ts +1 -1
- package/dist/state/idbqlEvent.svelte.js +10 -10
- package/dist/state/idbstate.svelte.d.ts +3 -3
- package/dist/state/idbstate.svelte.js +5 -5
- package/package.json +6 -4
package/README.md
CHANGED
|
@@ -1,58 +1,184 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @medyll/idae-idbql
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A powerful and flexible IndexedDB query library for TypeScript and JavaScript applications.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## Features
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
- MongoDB-like query interface for IndexedDB
|
|
8
|
+
- Strong TypeScript support with full type inference
|
|
9
|
+
- Reactive state management for real-time UI updates
|
|
10
|
+
- Support for complex CRUD operations and advanced querying
|
|
11
|
+
- Flexible data modeling with automatic schema creation
|
|
12
|
+
- Built-in indexing and optimization features
|
|
13
|
+
- Easy integration with front-end frameworks, especially Svelte
|
|
14
|
+
- Robust error handling and logging
|
|
15
|
+
- Versioning and database migration support
|
|
16
|
+
- Support for svelte 5 state
|
|
8
17
|
|
|
9
|
-
|
|
18
|
+
## Installation
|
|
10
19
|
|
|
11
20
|
```bash
|
|
12
|
-
|
|
13
|
-
|
|
21
|
+
npm install @medyll/idae-idbql
|
|
22
|
+
```
|
|
14
23
|
|
|
15
|
-
|
|
16
|
-
|
|
24
|
+
## Quick Start
|
|
25
|
+
|
|
26
|
+
```typescript
|
|
27
|
+
import { createIdbqDb } from '@medyll/idae-idbql';
|
|
28
|
+
|
|
29
|
+
// Define your data model
|
|
30
|
+
const exampleModel = {
|
|
31
|
+
messages: {
|
|
32
|
+
keyPath: "++id, chatId, created_at",
|
|
33
|
+
ts: {} as ChatMessage,
|
|
34
|
+
},
|
|
35
|
+
chat: {
|
|
36
|
+
keyPath: "&chatId, created_at, dateLastMessage",
|
|
37
|
+
ts: {} as Chat,
|
|
38
|
+
template: {},
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
// Create a database instance
|
|
43
|
+
const idbqStore = createIdbqDb(exampleModel, 1);
|
|
44
|
+
const { idbql, idbqlState, idbDatabase, idbqModel } = idbqStore.create("myDatabase");
|
|
45
|
+
|
|
46
|
+
// Perform database operations
|
|
47
|
+
async function fetchMessages() {
|
|
48
|
+
const messages = await idbql.messages.where({ chatId: "123" }).toArray();
|
|
49
|
+
console.log(messages);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
fetchMessages();
|
|
17
53
|
```
|
|
18
54
|
|
|
19
|
-
##
|
|
55
|
+
## API Reference
|
|
20
56
|
|
|
21
|
-
|
|
57
|
+
### createIdbqDb(model, version)
|
|
22
58
|
|
|
23
|
-
|
|
24
|
-
|
|
59
|
+
Creates an IndexedDB database instance with the specified model and version.
|
|
60
|
+
|
|
61
|
+
### idbql
|
|
62
|
+
|
|
63
|
+
The main interface for database operations. Provides methods for each collection defined in your model.
|
|
64
|
+
|
|
65
|
+
### idbqlState
|
|
66
|
+
|
|
67
|
+
A reactive state object that reflects the current state of your database.
|
|
68
|
+
|
|
69
|
+
### idbDatabase
|
|
70
|
+
|
|
71
|
+
Provides low-level access to the IndexedDB instance.
|
|
25
72
|
|
|
26
|
-
|
|
27
|
-
|
|
73
|
+
### idbqModel
|
|
74
|
+
|
|
75
|
+
Contains the database model definition.
|
|
76
|
+
|
|
77
|
+
## Query Operations
|
|
78
|
+
|
|
79
|
+
```typescript
|
|
80
|
+
// Add a new item
|
|
81
|
+
await idbql.messages.add({ chatId: "123", content: "Hello" });
|
|
82
|
+
|
|
83
|
+
// Update an item
|
|
84
|
+
await idbql.messages.put({ id: 1, content: "Updated message" });
|
|
85
|
+
|
|
86
|
+
// Delete an item
|
|
87
|
+
await idbql.messages.delete(1);
|
|
88
|
+
|
|
89
|
+
// Query items
|
|
90
|
+
const recentMessages = await idbql.messages
|
|
91
|
+
.where({ created_at: { gt: new Date(Date.now() - 86400000) } })
|
|
92
|
+
.toArray();
|
|
28
93
|
```
|
|
29
94
|
|
|
30
|
-
|
|
95
|
+
## Transactions
|
|
31
96
|
|
|
32
|
-
|
|
97
|
+
idbql supports complex transactions across multiple object stores:
|
|
33
98
|
|
|
34
|
-
|
|
99
|
+
```typescript
|
|
100
|
+
const result = await idbql.transaction(
|
|
101
|
+
["users", "posts"],
|
|
102
|
+
"readwrite",
|
|
103
|
+
async (tx) => {
|
|
104
|
+
const userStore = tx.objectStore("users");
|
|
105
|
+
const postStore = tx.objectStore("posts");
|
|
35
106
|
|
|
36
|
-
|
|
37
|
-
|
|
107
|
+
const userId = await userStore.add({ name: "Alice", email: "alice@example.com" });
|
|
108
|
+
const postId = await postStore.add({ userId, title: "Alice's First Post", content: "Hello, World!" });
|
|
109
|
+
|
|
110
|
+
return { userId, postId };
|
|
111
|
+
}
|
|
112
|
+
);
|
|
38
113
|
```
|
|
39
114
|
|
|
40
|
-
|
|
115
|
+
## Reactive State Management
|
|
41
116
|
|
|
42
|
-
```
|
|
43
|
-
|
|
117
|
+
```typescript
|
|
118
|
+
import { derived } from 'svelte/store';
|
|
119
|
+
|
|
120
|
+
const activeUsers = $derived(idbqlState.users.where({ isActive: true }));
|
|
44
121
|
```
|
|
45
122
|
|
|
46
|
-
|
|
123
|
+
## Integration with Svelte
|
|
47
124
|
|
|
48
|
-
|
|
125
|
+
```svelte
|
|
126
|
+
<script>
|
|
127
|
+
import { derived } from 'svelte/store';
|
|
128
|
+
import { idbqlState } from './store';
|
|
49
129
|
|
|
50
|
-
|
|
130
|
+
const messages = $derived(idbqlState.messages.where({ chatId: "123" }));
|
|
131
|
+
</script>
|
|
51
132
|
|
|
52
|
-
|
|
133
|
+
{#each $messages as message}
|
|
134
|
+
<p>{message.content}</p>
|
|
135
|
+
{/each}
|
|
136
|
+
```
|
|
53
137
|
|
|
54
|
-
|
|
138
|
+
## Versioning and Migrations
|
|
139
|
+
|
|
140
|
+
```typescript
|
|
141
|
+
const idbqStore = createIdbqDb(myModel, 2);
|
|
142
|
+
const { idbDatabase } = idbqStore.create("myDb", {
|
|
143
|
+
upgrade(oldVersion, newVersion, transaction) {
|
|
144
|
+
if (oldVersion < 2) {
|
|
145
|
+
const userStore = transaction.objectStore("users");
|
|
146
|
+
userStore.createIndex("emailIndex", "email", { unique: true });
|
|
147
|
+
}
|
|
148
|
+
},
|
|
149
|
+
});
|
|
150
|
+
```
|
|
55
151
|
|
|
56
|
-
|
|
57
|
-
|
|
152
|
+
## Error Handling
|
|
153
|
+
|
|
154
|
+
```typescript
|
|
155
|
+
try {
|
|
156
|
+
await idbql.users.add({ username: "existing_user" });
|
|
157
|
+
} catch (error) {
|
|
158
|
+
if (error instanceof UniqueConstraintError) {
|
|
159
|
+
console.error("Username already exists");
|
|
160
|
+
} else {
|
|
161
|
+
console.error("An unexpected error occurred", error);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
58
164
|
```
|
|
165
|
+
|
|
166
|
+
## Performance Tips
|
|
167
|
+
|
|
168
|
+
- Use appropriate indexes
|
|
169
|
+
- Limit result sets with `.limit(n)`
|
|
170
|
+
- Use `.count()` instead of `.toArray().length`
|
|
171
|
+
- Optimize queries to use indexes effectively
|
|
172
|
+
|
|
173
|
+
## Contributing
|
|
174
|
+
|
|
175
|
+
Contributions are welcome! Please read our [Contributing Guide](CONTRIBUTING.md) for details on our code of conduct and the process for submitting pull requests.
|
|
176
|
+
|
|
177
|
+
## License
|
|
178
|
+
|
|
179
|
+
This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details.
|
|
180
|
+
|
|
181
|
+
## Support
|
|
182
|
+
|
|
183
|
+
If you encounter any issues or have questions, please file an issue on the GitHub repository.
|
|
184
|
+
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type Where, type ResultsetOptions, type ResultSet } from
|
|
1
|
+
import { type Where, type ResultsetOptions, type ResultSet } from '@medyll/idae-query';
|
|
2
2
|
export declare class CollectionCore<T = any> {
|
|
3
3
|
protected _store: string;
|
|
4
4
|
private version?;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/* path: src\lib\scripts\collection\collection.ts */
|
|
2
|
-
import { Query, getResultset } from
|
|
3
|
-
import {} from
|
|
4
|
-
import { idbqlEvent } from
|
|
2
|
+
import { Query, getResultset } from '@medyll/idae-query';
|
|
3
|
+
import {} from '@medyll/idae-query';
|
|
4
|
+
import { idbqlEvent } from '../state/idbqlEvent.svelte.js';
|
|
5
5
|
export class CollectionCore {
|
|
6
6
|
_store;
|
|
7
7
|
version;
|
|
@@ -12,7 +12,7 @@ export class CollectionCore {
|
|
|
12
12
|
this._store = store;
|
|
13
13
|
this.version = args.version;
|
|
14
14
|
this.dbName = args.dbName;
|
|
15
|
-
this.keyPath = keyPath.split(
|
|
15
|
+
this.keyPath = keyPath.split(',')[0].replace(/[\s+]/g, '').replace(/&/, '');
|
|
16
16
|
}
|
|
17
17
|
get name() {
|
|
18
18
|
return this._store;
|
|
@@ -30,7 +30,7 @@ export class CollectionCore {
|
|
|
30
30
|
if (!db.objectStoreNames.contains(this._store)) {
|
|
31
31
|
throw new Error(`Collection ${this._store} not found`);
|
|
32
32
|
}
|
|
33
|
-
return db.transaction(this._store,
|
|
33
|
+
return db.transaction(this._store, 'readwrite').objectStore(this._store);
|
|
34
34
|
}
|
|
35
35
|
/**
|
|
36
36
|
* Retrieves the data from the collection based on the provided query.
|
|
@@ -53,7 +53,7 @@ export class CollectionCore {
|
|
|
53
53
|
const storeObj = await this.getCollection();
|
|
54
54
|
const get = storeObj.get(value);
|
|
55
55
|
get.onsuccess = () => resolve(get.result);
|
|
56
|
-
get.onerror = () => reject(
|
|
56
|
+
get.onerror = () => reject('not found');
|
|
57
57
|
});
|
|
58
58
|
}
|
|
59
59
|
getAll() {
|
|
@@ -64,7 +64,7 @@ export class CollectionCore {
|
|
|
64
64
|
resolve(getAll.result);
|
|
65
65
|
};
|
|
66
66
|
getAll.onerror = function () {
|
|
67
|
-
reject(
|
|
67
|
+
reject('not found');
|
|
68
68
|
};
|
|
69
69
|
});
|
|
70
70
|
}
|
|
@@ -73,7 +73,7 @@ export class CollectionCore {
|
|
|
73
73
|
return this.put({
|
|
74
74
|
[this.keyPath]: keyPathValue,
|
|
75
75
|
...dta,
|
|
76
|
-
...data
|
|
76
|
+
...data
|
|
77
77
|
});
|
|
78
78
|
}
|
|
79
79
|
async updateWhere(where, data) {
|
|
@@ -84,7 +84,7 @@ export class CollectionCore {
|
|
|
84
84
|
const newData = {
|
|
85
85
|
[this.keyPath]: dta[this.keyPath],
|
|
86
86
|
...dta,
|
|
87
|
-
...data
|
|
87
|
+
...data
|
|
88
88
|
};
|
|
89
89
|
return this.put(newData);
|
|
90
90
|
}
|
|
@@ -108,7 +108,7 @@ export class CollectionCore {
|
|
|
108
108
|
resolve(updatedData);
|
|
109
109
|
};
|
|
110
110
|
put.onerror = function () {
|
|
111
|
-
reject(
|
|
111
|
+
reject('data not put');
|
|
112
112
|
};
|
|
113
113
|
});
|
|
114
114
|
}
|
|
@@ -132,10 +132,10 @@ export class CollectionCore {
|
|
|
132
132
|
const storeObj = await this.getCollection();
|
|
133
133
|
let objectStoreRequest = storeObj.delete(keyPathValue);
|
|
134
134
|
objectStoreRequest.onsuccess = () => {
|
|
135
|
-
idbqlEvent.registerEvent(
|
|
135
|
+
idbqlEvent.registerEvent('delete', {
|
|
136
136
|
collection: this._store,
|
|
137
137
|
data: keyPathValue,
|
|
138
|
-
keyPath: this.keyPath
|
|
138
|
+
keyPath: this.keyPath
|
|
139
139
|
});
|
|
140
140
|
resolve(true);
|
|
141
141
|
};
|
|
@@ -170,15 +170,8 @@ function createIDBStoreProxy(store) {
|
|
|
170
170
|
return new Proxy(instance, {
|
|
171
171
|
get(target, prop, receiver) {
|
|
172
172
|
const origMethod = target[prop];
|
|
173
|
-
if (typeof origMethod ===
|
|
174
|
-
[
|
|
175
|
-
"update",
|
|
176
|
-
"updateWhere",
|
|
177
|
-
"put",
|
|
178
|
-
"add",
|
|
179
|
-
"delete",
|
|
180
|
-
"deleteWhere",
|
|
181
|
-
].includes(String(prop))) {
|
|
173
|
+
if (typeof origMethod === 'function' &&
|
|
174
|
+
['update', 'updateWhere', 'put', 'add', 'delete', 'deleteWhere'].includes(String(prop))) {
|
|
182
175
|
return function (...args) {
|
|
183
176
|
return new Promise(async (resolve, reject) => {
|
|
184
177
|
origMethod
|
|
@@ -187,7 +180,7 @@ function createIDBStoreProxy(store) {
|
|
|
187
180
|
idbqlEvent.registerEvent(prop, {
|
|
188
181
|
collection: instance._store,
|
|
189
182
|
data: res,
|
|
190
|
-
keyPath: instance.keyPath
|
|
183
|
+
keyPath: instance.keyPath
|
|
191
184
|
});
|
|
192
185
|
resolve(res);
|
|
193
186
|
})
|
|
@@ -199,8 +192,8 @@ function createIDBStoreProxy(store) {
|
|
|
199
192
|
};
|
|
200
193
|
}
|
|
201
194
|
return Reflect.get(target, prop, receiver);
|
|
202
|
-
}
|
|
195
|
+
}
|
|
203
196
|
});
|
|
204
|
-
}
|
|
197
|
+
}
|
|
205
198
|
});
|
|
206
199
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { CollectionCore } from
|
|
2
|
-
import { type StateCollectionDyn } from
|
|
1
|
+
import { CollectionCore } from '../collection/collection.js';
|
|
2
|
+
import { type StateCollectionDyn } from '../state/idbstate.svelte.js';
|
|
3
3
|
export declare enum enumPrimitive {
|
|
4
4
|
id = "id",
|
|
5
5
|
any = "any",
|
|
@@ -23,7 +23,7 @@ type CombineElements<T extends string, U extends string = T> = T extends any ? T
|
|
|
23
23
|
type CombinedArgs = CombineElements<TplProperties>;
|
|
24
24
|
type IdbObjectify<T extends string> = `array-of-${T}` | `object-${T}`;
|
|
25
25
|
export type TplCollectionFields = Record<string, string>;
|
|
26
|
-
export type TplFieldPrimitive<T = {}> = keyof typeof enumPrimitive | `text-${
|
|
26
|
+
export type TplFieldPrimitive<T = {}> = keyof typeof enumPrimitive | `text-${'tiny' | 'short' | 'medium' | 'long' | 'area'}` | `${string}.${string}` | `fk-${string}.${string}`;
|
|
27
27
|
export type TplObjectFieldPrimitive = IdbObjectify<TplFieldPrimitive>;
|
|
28
28
|
export type TplFieldFk = `fk-${string}.${string}`;
|
|
29
29
|
export type TplFkObject = IdbObjectify<TplFieldFk>;
|
|
@@ -44,8 +44,8 @@ export type IdbqModel<T = Record<string, Record<string, any>>> = {
|
|
|
44
44
|
readonly [K in keyof T]: CollectionModel<T[K]>;
|
|
45
45
|
};
|
|
46
46
|
export type TplCollectionName<T = TplCollectionFields> = keyof IdbqModel<T>;
|
|
47
|
-
export type Tpl<T = TplCollectionFields> = CollectionModel<T>[
|
|
48
|
-
export type TplFields<T = TplCollectionFields> = CollectionModel<T>[
|
|
47
|
+
export type Tpl<T = TplCollectionFields> = CollectionModel<T>['template'];
|
|
48
|
+
export type TplFields<T = TplCollectionFields> = CollectionModel<T>['template']['fields'];
|
|
49
49
|
export type CollectionModel<T = TplCollectionFields> = {
|
|
50
50
|
keyPath: string | any;
|
|
51
51
|
/** @deprecated use ts instead */
|
|
@@ -53,7 +53,7 @@ export type CollectionModel<T = TplCollectionFields> = {
|
|
|
53
53
|
ts: any;
|
|
54
54
|
template: {
|
|
55
55
|
index: string;
|
|
56
|
-
presentation: CombineElements<keyof CollectionModel<T>[
|
|
56
|
+
presentation: CombineElements<keyof CollectionModel<T>['ts']>;
|
|
57
57
|
fields: {
|
|
58
58
|
[K in keyof T]: TplFieldRules;
|
|
59
59
|
};
|
|
@@ -67,10 +67,10 @@ export type CollectionModel<T = TplCollectionFields> = {
|
|
|
67
67
|
};
|
|
68
68
|
};
|
|
69
69
|
type ReadonlyCollections<T extends IdbqModel> = {
|
|
70
|
-
[K in keyof T]: CollectionCore<T[K][
|
|
70
|
+
[K in keyof T]: CollectionCore<T[K]['ts']>;
|
|
71
71
|
};
|
|
72
72
|
type StateCollections<T extends IdbqModel> = {
|
|
73
|
-
[K in keyof T]: StateCollectionDyn<T[K][
|
|
73
|
+
[K in keyof T]: StateCollectionDyn<T[K]['ts']>;
|
|
74
74
|
};
|
|
75
75
|
/**
|
|
76
76
|
* Represents the IndexedDB wrapper for managing database operations.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/* src\lib\scripts\idbqlCore\idbqlCore.ts */
|
|
2
|
-
import { Collection, CollectionCore } from
|
|
3
|
-
import { createIdbqlState
|
|
4
|
-
import { Schema } from
|
|
2
|
+
import { Collection, CollectionCore } from '../collection/collection.js';
|
|
3
|
+
import { createIdbqlState } from '../state/idbstate.svelte.js';
|
|
4
|
+
import { Schema } from './idbqlSchema.js';
|
|
5
5
|
export var enumPrimitive;
|
|
6
6
|
(function (enumPrimitive) {
|
|
7
7
|
enumPrimitive["id"] = "id";
|
|
@@ -23,7 +23,7 @@ export var TplProperties;
|
|
|
23
23
|
TplProperties["readonly"] = "readonly";
|
|
24
24
|
TplProperties["required"] = "required";
|
|
25
25
|
})(TplProperties || (TplProperties = {}));
|
|
26
|
-
const a =
|
|
26
|
+
const a = 'object-any (readonly private)';
|
|
27
27
|
/**
|
|
28
28
|
* Represents the IndexedDB wrapper for managing database operations.
|
|
29
29
|
* @template T - The type of data stored in the IndexedDB.
|
|
@@ -45,13 +45,13 @@ export class IdbqlIndexedCore {
|
|
|
45
45
|
const stores = {};
|
|
46
46
|
Object.keys(idbqModel).forEach((modelName) => {
|
|
47
47
|
const modelInfo = idbqModel[modelName];
|
|
48
|
-
stores[modelName] = modelInfo.keyPath ||
|
|
48
|
+
stores[modelName] = modelInfo.keyPath || '';
|
|
49
49
|
Object.defineProperty(this, modelName, {
|
|
50
50
|
// @ts-ignore
|
|
51
51
|
value: undefined,
|
|
52
52
|
writable: true,
|
|
53
53
|
enumerable: true,
|
|
54
|
-
configurable: true
|
|
54
|
+
configurable: true
|
|
55
55
|
});
|
|
56
56
|
});
|
|
57
57
|
this.stores(stores);
|
|
@@ -68,7 +68,7 @@ export class IdbqlIndexedCore {
|
|
|
68
68
|
* @returns {object} - An object with a `stores` method to define the object stores.
|
|
69
69
|
*/
|
|
70
70
|
async stores(args) {
|
|
71
|
-
if (typeof indexedDB !==
|
|
71
|
+
if (typeof indexedDB !== 'undefined') {
|
|
72
72
|
return new Promise((resolve, reject) => {
|
|
73
73
|
this.#schema = args;
|
|
74
74
|
const dbConnection = indexedDB.open(this.databaseName, this.dbVersion);
|
|
@@ -98,7 +98,7 @@ export class IdbqlIndexedCore {
|
|
|
98
98
|
}
|
|
99
99
|
async transaction(storeNames, mode, callback) {
|
|
100
100
|
if (!this.idbDatabase) {
|
|
101
|
-
throw new Error(
|
|
101
|
+
throw new Error('Database not initialized');
|
|
102
102
|
}
|
|
103
103
|
return new Promise((resolve, reject) => {
|
|
104
104
|
const tx = this.idbDatabase.transaction(storeNames, mode);
|
|
@@ -120,11 +120,11 @@ export class IdbqlIndexedCore {
|
|
|
120
120
|
// @ts-ignore
|
|
121
121
|
value: new Collection(storeName, this.#schema[storeName], {
|
|
122
122
|
dbName: this.databaseName,
|
|
123
|
-
version
|
|
123
|
+
version // @ts-ignore
|
|
124
124
|
}),
|
|
125
125
|
writable: true,
|
|
126
126
|
enumerable: true,
|
|
127
|
-
configurable: true
|
|
127
|
+
configurable: true
|
|
128
128
|
});
|
|
129
129
|
});
|
|
130
130
|
}
|
|
@@ -147,9 +147,9 @@ export const createIdbqDb = (model, version) => {
|
|
|
147
147
|
idbDatabase: idb_,
|
|
148
148
|
idbql: idb_,
|
|
149
149
|
idbqlState: createIdbqlState(idb_).state,
|
|
150
|
-
idbqModel: model
|
|
150
|
+
idbqModel: model
|
|
151
151
|
};
|
|
152
|
-
}
|
|
152
|
+
}
|
|
153
153
|
};
|
|
154
154
|
};
|
|
155
155
|
// main export is here ?
|
|
@@ -32,13 +32,9 @@ export class Schema {
|
|
|
32
32
|
async createSchema(db, storeListFields) {
|
|
33
33
|
const results = [];
|
|
34
34
|
for (const [storeName, storeConfig] of Object.entries(storeListFields)) {
|
|
35
|
-
const fields = storeConfig.split(
|
|
36
|
-
const incrementField = fields
|
|
37
|
-
|
|
38
|
-
?.replace("++", "");
|
|
39
|
-
const declaredIndex = fields
|
|
40
|
-
.find((field) => field.startsWith("&"))
|
|
41
|
-
?.replace("&", "");
|
|
35
|
+
const fields = storeConfig.split(',').map((field) => field.trim());
|
|
36
|
+
const incrementField = fields.find((field) => field.startsWith('++'))?.replace('++', '');
|
|
37
|
+
const declaredIndex = fields.find((field) => field.startsWith('&'))?.replace('&', '');
|
|
42
38
|
const keyPath = incrementField || declaredIndex || fields[0];
|
|
43
39
|
const increment = Boolean(incrementField);
|
|
44
40
|
const store = this.createStore(db, storeName, keyPath, increment);
|
|
@@ -57,7 +53,7 @@ export class Schema {
|
|
|
57
53
|
* @returns The cleaned index name.
|
|
58
54
|
*/
|
|
59
55
|
cleanIndexName(indexName) {
|
|
60
|
-
return indexName.replace(/[&+]/g,
|
|
56
|
+
return indexName.replace(/[&+]/g, '').trim();
|
|
61
57
|
}
|
|
62
58
|
/**
|
|
63
59
|
* Creates an index in the object store.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export type DotPath<T> = T extends object ? {
|
|
2
|
-
[K in keyof T]: T[K] extends null | undefined ? K & string : `${K & string}${
|
|
3
|
-
}[keyof T] :
|
|
2
|
+
[K in keyof T]: T[K] extends null | undefined ? K & string : `${K & string}${'' extends DotPath<T[K]> ? '' : '.'}${DotPath<T[K]>}`;
|
|
3
|
+
}[keyof T] : '';
|
|
4
4
|
/**
|
|
5
5
|
* Resolves a dot path on an object and returns the value at that path.
|
|
6
6
|
* If the path does not exist, it returns the defaultValue.
|
|
@@ -9,6 +9,5 @@
|
|
|
9
9
|
* @returns The value at the specified path, or the defaultValue if the path does not exist.
|
|
10
10
|
*/
|
|
11
11
|
export function dotPath(object, path, defaultValue) {
|
|
12
|
-
return (path.split(
|
|
13
|
-
defaultValue);
|
|
12
|
+
return (path.split('.').reduce((r, s) => (r ? r[s] : defaultValue), object) ?? defaultValue);
|
|
14
13
|
}
|
|
@@ -13,24 +13,24 @@ class IdbqlStateEvent {
|
|
|
13
13
|
this.#dataState[collection] = [];
|
|
14
14
|
}
|
|
15
15
|
switch (event) {
|
|
16
|
-
case
|
|
16
|
+
case 'set':
|
|
17
17
|
if (data) {
|
|
18
18
|
this.#dataState[collection] = Array.isArray(data) ? data : [data];
|
|
19
19
|
}
|
|
20
20
|
break;
|
|
21
|
-
case
|
|
21
|
+
case 'add':
|
|
22
22
|
if (data) {
|
|
23
23
|
this.#dataState[collection].push(data);
|
|
24
24
|
}
|
|
25
25
|
break;
|
|
26
|
-
case
|
|
27
|
-
case
|
|
26
|
+
case 'put':
|
|
27
|
+
case 'update':
|
|
28
28
|
if (data && keyPath) {
|
|
29
29
|
const index = this.#dataState[collection].findIndex((item) => item[keyPath] === data[keyPath]);
|
|
30
30
|
if (index !== -1) {
|
|
31
31
|
this.#dataState[collection][index] = {
|
|
32
32
|
...this.#dataState[collection][index],
|
|
33
|
-
...data
|
|
33
|
+
...data
|
|
34
34
|
};
|
|
35
35
|
}
|
|
36
36
|
else {
|
|
@@ -38,20 +38,20 @@ class IdbqlStateEvent {
|
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
40
|
break;
|
|
41
|
-
case
|
|
42
|
-
if (data && typeof data ===
|
|
41
|
+
case 'updateWhere':
|
|
42
|
+
if (data && typeof data === 'object') {
|
|
43
43
|
this.#dataState[collection] = this.#dataState[collection].map((item) => Object.entries(data).every(([key, value]) => item[key] === value)
|
|
44
44
|
? { ...item, ...data }
|
|
45
45
|
: item);
|
|
46
46
|
}
|
|
47
47
|
break;
|
|
48
|
-
case
|
|
48
|
+
case 'delete':
|
|
49
49
|
if (data && keyPath) {
|
|
50
50
|
this.#dataState[collection] = this.#dataState[collection].filter((item) => item[keyPath] !== data[keyPath]);
|
|
51
51
|
}
|
|
52
52
|
break;
|
|
53
|
-
case
|
|
54
|
-
if (data && typeof data ===
|
|
53
|
+
case 'deleteWhere':
|
|
54
|
+
if (data && typeof data === 'object') {
|
|
55
55
|
this.#dataState[collection] = this.#dataState[collection].filter((item) => !Object.entries(data).every(([key, value]) => item[key] === value));
|
|
56
56
|
}
|
|
57
57
|
break;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { IdbqlIndexedCore } from
|
|
2
|
-
import { type Where, type ResultSet, type ResultsetOptions } from
|
|
1
|
+
import type { IdbqlIndexedCore } from '../idbqlCore/idbqlCore.js';
|
|
2
|
+
import { type Where, type ResultSet, type ResultsetOptions } from '@medyll/idae-query';
|
|
3
3
|
/**
|
|
4
4
|
* Main entry point.
|
|
5
5
|
* Creates a state object with indexedDB synchronization.
|
|
@@ -26,7 +26,7 @@ export declare class StateCollectionDyn<T> {
|
|
|
26
26
|
get collectionState(): any;
|
|
27
27
|
private testIdbql;
|
|
28
28
|
private feed;
|
|
29
|
-
where(qy: Where<T>, options?: ResultsetOptions):
|
|
29
|
+
where(qy: Where<T>, options?: ResultsetOptions): any;
|
|
30
30
|
update(keyPathValue: string | number, data: Partial<T>): void;
|
|
31
31
|
get(value: any, pathKey?: string): T[];
|
|
32
32
|
getOne(value: any, pathKey?: string): T;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { idbqlEvent } from
|
|
1
|
+
import { idbqlEvent } from './idbqlEvent.svelte.js';
|
|
2
2
|
//
|
|
3
|
-
import { Operators, getResultset
|
|
3
|
+
import { Operators, getResultset } from '@medyll/idae-query';
|
|
4
4
|
//
|
|
5
5
|
/**
|
|
6
6
|
* Main entry point.
|
|
@@ -34,7 +34,7 @@ export const createIdbqlState = (idbBase) => {
|
|
|
34
34
|
return collections;
|
|
35
35
|
},
|
|
36
36
|
onCollection: addCollection,
|
|
37
|
-
addCollection: addCollection
|
|
37
|
+
addCollection: addCollection
|
|
38
38
|
};
|
|
39
39
|
};
|
|
40
40
|
/**
|
|
@@ -81,10 +81,10 @@ export class StateCollectionDyn {
|
|
|
81
81
|
this.idbBase[this.collectionName].update(keyPathValue, data);
|
|
82
82
|
}
|
|
83
83
|
}
|
|
84
|
-
get(value, pathKey =
|
|
84
|
+
get(value, pathKey = 'id') {
|
|
85
85
|
return this.collectionState.filter((d) => d[pathKey] === value);
|
|
86
86
|
}
|
|
87
|
-
getOne(value, pathKey =
|
|
87
|
+
getOne(value, pathKey = 'id') {
|
|
88
88
|
return this.collectionState.filter((d) => d[pathKey] === value)?.[0];
|
|
89
89
|
}
|
|
90
90
|
getAll() {
|
package/package.json
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@medyll/idae-idbql",
|
|
3
3
|
"scope": "@medyll",
|
|
4
|
-
"version": "0.0
|
|
4
|
+
"version": "0.1.0",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"dev": "vite dev",
|
|
7
7
|
"build": "vite build && npm run package",
|
|
8
8
|
"preview": "vite preview",
|
|
9
9
|
"package": "svelte-kit sync && svelte-package && publint",
|
|
10
|
+
"package:watch": "svelte-kit sync && svelte-package --watch",
|
|
10
11
|
"prepublishOnly": "npm run package",
|
|
11
12
|
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
|
12
13
|
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch"
|
|
@@ -23,9 +24,10 @@
|
|
|
23
24
|
"!dist/**/*.spec.*"
|
|
24
25
|
],
|
|
25
26
|
"peerDependencies": {
|
|
26
|
-
"svelte": "^5.0.0-next.
|
|
27
|
+
"svelte": "^5.0.0-next.1"
|
|
27
28
|
},
|
|
28
29
|
"devDependencies": {
|
|
30
|
+
"@medyll/idae-prettier-config": "^1.0.0",
|
|
29
31
|
"@sveltejs/adapter-auto": "^3.0.0",
|
|
30
32
|
"@sveltejs/kit": "^2.0.0",
|
|
31
33
|
"@sveltejs/package": "^2.0.0",
|
|
@@ -41,6 +43,6 @@
|
|
|
41
43
|
"types": "./dist/index.d.ts",
|
|
42
44
|
"type": "module",
|
|
43
45
|
"dependencies": {
|
|
44
|
-
"@medyll/idae-query": "^0.0
|
|
46
|
+
"@medyll/idae-query": "^0.1.0"
|
|
45
47
|
}
|
|
46
|
-
}
|
|
48
|
+
}
|