@slimr/dbsync 0.0.3

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 (122) hide show
  1. package/README.md +183 -0
  2. package/cjs/DbRepository.d.ts +59 -0
  3. package/cjs/DbRepository.js +78 -0
  4. package/cjs/DbRepository.js.map +1 -0
  5. package/cjs/DbSync.d.ts +51 -0
  6. package/cjs/DbSync.js +123 -0
  7. package/cjs/DbSync.js.map +1 -0
  8. package/cjs/DbTransaction.d.ts +60 -0
  9. package/cjs/DbTransaction.js +82 -0
  10. package/cjs/DbTransaction.js.map +1 -0
  11. package/cjs/DbTxRepository.d.ts +41 -0
  12. package/cjs/DbTxRepository.js +56 -0
  13. package/cjs/DbTxRepository.js.map +1 -0
  14. package/cjs/MigrationManager.d.ts +60 -0
  15. package/cjs/MigrationManager.js +69 -0
  16. package/cjs/MigrationManager.js.map +1 -0
  17. package/cjs/Repository.d.ts +59 -0
  18. package/cjs/Repository.js +78 -0
  19. package/cjs/Repository.js.map +1 -0
  20. package/cjs/adapters/RestAdapter.d.ts +13 -0
  21. package/cjs/adapters/RestAdapter.js +47 -0
  22. package/cjs/adapters/RestAdapter.js.map +1 -0
  23. package/cjs/adapters/index.d.ts +2 -0
  24. package/cjs/adapters/index.js +19 -0
  25. package/cjs/adapters/index.js.map +1 -0
  26. package/cjs/adapters/types.d.ts +11 -0
  27. package/cjs/adapters/types.js +3 -0
  28. package/cjs/adapters/types.js.map +1 -0
  29. package/cjs/index.d.ts +3 -0
  30. package/cjs/index.js +20 -0
  31. package/cjs/index.js.map +1 -0
  32. package/cjs/internal/AuthManager.d.ts +13 -0
  33. package/cjs/internal/AuthManager.js +34 -0
  34. package/cjs/internal/AuthManager.js.map +1 -0
  35. package/cjs/internal/DbTransaction.d.ts +60 -0
  36. package/cjs/internal/DbTransaction.js +82 -0
  37. package/cjs/internal/DbTransaction.js.map +1 -0
  38. package/cjs/internal/EventBus.d.ts +16 -0
  39. package/cjs/internal/EventBus.js +41 -0
  40. package/cjs/internal/EventBus.js.map +1 -0
  41. package/cjs/internal/MigrationManager.d.ts +60 -0
  42. package/cjs/internal/MigrationManager.js +69 -0
  43. package/cjs/internal/MigrationManager.js.map +1 -0
  44. package/cjs/internal/StorageManager.d.ts +20 -0
  45. package/cjs/internal/StorageManager.js +148 -0
  46. package/cjs/internal/StorageManager.js.map +1 -0
  47. package/cjs/internal/SyncEngine.d.ts +27 -0
  48. package/cjs/internal/SyncEngine.js +191 -0
  49. package/cjs/internal/SyncEngine.js.map +1 -0
  50. package/cjs/internal/utils.d.ts +1 -0
  51. package/cjs/internal/utils.js +7 -0
  52. package/cjs/internal/utils.js.map +1 -0
  53. package/cjs/react.d.ts +1 -0
  54. package/cjs/react.js +18 -0
  55. package/cjs/react.js.map +1 -0
  56. package/cjs/useDbQuery.d.ts +13 -0
  57. package/cjs/useDbQuery.js +59 -0
  58. package/cjs/useDbQuery.js.map +1 -0
  59. package/cjs/util/promiseWithResolvers.d.ts +11 -0
  60. package/cjs/util/promiseWithResolvers.js +19 -0
  61. package/cjs/util/promiseWithResolvers.js.map +1 -0
  62. package/esm/DbRepository.d.ts +59 -0
  63. package/esm/DbRepository.js +74 -0
  64. package/esm/DbRepository.js.map +1 -0
  65. package/esm/DbSync.d.ts +51 -0
  66. package/esm/DbSync.js +119 -0
  67. package/esm/DbSync.js.map +1 -0
  68. package/esm/DbTransaction.d.ts +60 -0
  69. package/esm/DbTransaction.js +78 -0
  70. package/esm/DbTransaction.js.map +1 -0
  71. package/esm/DbTxRepository.d.ts +41 -0
  72. package/esm/DbTxRepository.js +52 -0
  73. package/esm/DbTxRepository.js.map +1 -0
  74. package/esm/MigrationManager.d.ts +60 -0
  75. package/esm/MigrationManager.js +65 -0
  76. package/esm/MigrationManager.js.map +1 -0
  77. package/esm/Repository.d.ts +59 -0
  78. package/esm/Repository.js +74 -0
  79. package/esm/Repository.js.map +1 -0
  80. package/esm/adapters/RestAdapter.d.ts +13 -0
  81. package/esm/adapters/RestAdapter.js +43 -0
  82. package/esm/adapters/RestAdapter.js.map +1 -0
  83. package/esm/adapters/index.d.ts +2 -0
  84. package/esm/adapters/index.js +3 -0
  85. package/esm/adapters/index.js.map +1 -0
  86. package/esm/adapters/types.d.ts +11 -0
  87. package/esm/adapters/types.js +2 -0
  88. package/esm/adapters/types.js.map +1 -0
  89. package/esm/index.d.ts +3 -0
  90. package/esm/index.js +4 -0
  91. package/esm/index.js.map +1 -0
  92. package/esm/internal/AuthManager.d.ts +13 -0
  93. package/esm/internal/AuthManager.js +30 -0
  94. package/esm/internal/AuthManager.js.map +1 -0
  95. package/esm/internal/DbTransaction.d.ts +60 -0
  96. package/esm/internal/DbTransaction.js +78 -0
  97. package/esm/internal/DbTransaction.js.map +1 -0
  98. package/esm/internal/EventBus.d.ts +16 -0
  99. package/esm/internal/EventBus.js +37 -0
  100. package/esm/internal/EventBus.js.map +1 -0
  101. package/esm/internal/MigrationManager.d.ts +60 -0
  102. package/esm/internal/MigrationManager.js +65 -0
  103. package/esm/internal/MigrationManager.js.map +1 -0
  104. package/esm/internal/StorageManager.d.ts +20 -0
  105. package/esm/internal/StorageManager.js +144 -0
  106. package/esm/internal/StorageManager.js.map +1 -0
  107. package/esm/internal/SyncEngine.d.ts +27 -0
  108. package/esm/internal/SyncEngine.js +187 -0
  109. package/esm/internal/SyncEngine.js.map +1 -0
  110. package/esm/internal/utils.d.ts +1 -0
  111. package/esm/internal/utils.js +4 -0
  112. package/esm/internal/utils.js.map +1 -0
  113. package/esm/react.d.ts +1 -0
  114. package/esm/react.js +2 -0
  115. package/esm/react.js.map +1 -0
  116. package/esm/useDbQuery.d.ts +13 -0
  117. package/esm/useDbQuery.js +56 -0
  118. package/esm/useDbQuery.js.map +1 -0
  119. package/esm/util/promiseWithResolvers.d.ts +11 -0
  120. package/esm/util/promiseWithResolvers.js +16 -0
  121. package/esm/util/promiseWithResolvers.js.map +1 -0
  122. package/package.json +44 -0
@@ -0,0 +1,187 @@
1
+ import { promiseWithResolvers } from "../util/promiseWithResolvers.js";
2
+ export class SyncEngine {
3
+ config;
4
+ syncInterval;
5
+ events;
6
+ storage;
7
+ auth;
8
+ adapter;
9
+ onSchemaChange;
10
+ syncSetInterval = null;
11
+ constructor(config, syncInterval, events, storage, auth, adapter, onSchemaChange) {
12
+ this.config = config;
13
+ this.syncInterval = syncInterval;
14
+ this.events = events;
15
+ this.storage = storage;
16
+ this.auth = auth;
17
+ this.adapter = adapter;
18
+ this.onSchemaChange = onSchemaChange;
19
+ }
20
+ enable() {
21
+ if (!this.syncSetInterval) {
22
+ this.syncSetInterval = setInterval(() => this.sync(), this.syncInterval);
23
+ }
24
+ }
25
+ disable() {
26
+ if (this.syncSetInterval) {
27
+ clearInterval(this.syncSetInterval);
28
+ this.syncSetInterval = null;
29
+ }
30
+ }
31
+ get isEnabled() {
32
+ return !!this.syncSetInterval;
33
+ }
34
+ get isLive() {
35
+ const lastSuccess = localStorage.getItem("dbsync-lastSuccessAt");
36
+ if (!lastSuccess)
37
+ return false;
38
+ return Date.now() - new Date(lastSuccess).getTime() < this.syncInterval * 4;
39
+ }
40
+ async waitForLive() {
41
+ const { promise, resolve, reject } = promiseWithResolvers();
42
+ if (!this.isEnabled) {
43
+ reject(new Error("Sync disabled"));
44
+ return promise;
45
+ }
46
+ const check = setInterval(() => {
47
+ if (this.isLive) {
48
+ clearInterval(check);
49
+ resolve();
50
+ }
51
+ }, this.syncInterval);
52
+ return promise;
53
+ }
54
+ async triggerSync() {
55
+ await this.sync();
56
+ }
57
+ async sync() {
58
+ if (typeof navigator !== "undefined" && navigator.locks) {
59
+ await navigator.locks.request("dbsync-leader", async () => {
60
+ await this.performSync();
61
+ });
62
+ }
63
+ else {
64
+ await this.performSync();
65
+ }
66
+ }
67
+ async performSync() {
68
+ this.events.setState("syncing");
69
+ try {
70
+ await this.syncPull();
71
+ await this.syncPush();
72
+ this.events.setState("idle");
73
+ this.auth.isAuth = true;
74
+ localStorage.setItem("dbsync-lastSuccessAt", new Date().toISOString());
75
+ }
76
+ catch (err) {
77
+ if (err.status === 401) {
78
+ this.auth.isAuth = false;
79
+ this.disable();
80
+ }
81
+ this.events.setState("error");
82
+ }
83
+ }
84
+ get schemaSignature() {
85
+ const tables = Object.keys(this.config.tables)
86
+ .sort()
87
+ .map((table) => {
88
+ return {
89
+ table,
90
+ indexes: this.config.tables[table].indexes?.slice().sort() || [],
91
+ };
92
+ });
93
+ return JSON.stringify(tables);
94
+ }
95
+ async syncPull() {
96
+ let hasMore = true;
97
+ while (hasMore) {
98
+ const cursor = localStorage.getItem("dbsync-pullSyncedUpTo") || "";
99
+ const data = await this.adapter.pull(cursor);
100
+ if (data.items && data.items.length > 0) {
101
+ const tx = this.storage.getTransaction();
102
+ data.items.forEach((post) => {
103
+ if (post.variant === "__dbsync_system" && post.id === "version") {
104
+ const remoteContent = JSON.parse(post.content);
105
+ if (this.config.version !== undefined) {
106
+ if (remoteContent.version && remoteContent.version > this.config.version) {
107
+ this.onSchemaChange();
108
+ }
109
+ }
110
+ else {
111
+ const currentSignature = this.schemaSignature;
112
+ if (remoteContent.signature && remoteContent.signature !== currentSignature) {
113
+ this.onSchemaChange();
114
+ }
115
+ }
116
+ return;
117
+ }
118
+ const storeName = post.variant;
119
+ if (post.isDeleted)
120
+ tx.delete(storeName, post.id);
121
+ else
122
+ tx.put(storeName, { id: post.id, ...JSON.parse(post.content) });
123
+ });
124
+ await tx.commit();
125
+ localStorage.setItem("dbsync-pullSyncedUpTo", data.items[data.items.length - 1].updatedAt);
126
+ }
127
+ hasMore = data.hasMore;
128
+ }
129
+ }
130
+ async syncPush() {
131
+ const dirty = await this.storage.findAll("dirtyQueue");
132
+ const deleted = await this.storage.findAll("deletedQueue");
133
+ const payload = [
134
+ ...dirty.map((d) => ({
135
+ id: d.id,
136
+ variant: d.table,
137
+ content: JSON.stringify(d.payload),
138
+ isDeleted: false,
139
+ updatedAt: new Date(d.timestamp).toISOString(),
140
+ })),
141
+ ...deleted.map((d) => ({
142
+ id: d.id,
143
+ variant: d.table,
144
+ content: "{}",
145
+ isDeleted: true,
146
+ updatedAt: new Date(d.timestamp).toISOString(),
147
+ })),
148
+ ];
149
+ if (this.config.version !== undefined) {
150
+ const localVersion = Number(localStorage.getItem("dbsync-version") || "0");
151
+ if (this.config.version > localVersion) {
152
+ payload.push({
153
+ id: "version",
154
+ variant: "__dbsync_system",
155
+ content: JSON.stringify({ version: this.config.version }),
156
+ isDeleted: false,
157
+ updatedAt: new Date().toISOString(),
158
+ });
159
+ }
160
+ }
161
+ else {
162
+ const currentSignature = this.schemaSignature;
163
+ const storedSyncSig = localStorage.getItem("dbsync-sync-signature") || "";
164
+ if (currentSignature !== storedSyncSig) {
165
+ payload.push({
166
+ id: "version",
167
+ variant: "__dbsync_system",
168
+ content: JSON.stringify({ signature: currentSignature }),
169
+ isDeleted: false,
170
+ updatedAt: new Date().toISOString(),
171
+ });
172
+ }
173
+ }
174
+ if (payload.length > 0) {
175
+ await this.adapter.push(payload);
176
+ if (this.config.version !== undefined)
177
+ localStorage.setItem("dbsync-version", String(this.config.version));
178
+ else
179
+ localStorage.setItem("dbsync-sync-signature", this.schemaSignature);
180
+ const tx = this.storage.getTransaction();
181
+ dirty.forEach((d) => tx.delete("dirtyQueue", d.id));
182
+ deleted.forEach((d) => tx.delete("deletedQueue", d.id));
183
+ await tx.commit();
184
+ }
185
+ }
186
+ }
187
+ //# sourceMappingURL=SyncEngine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SyncEngine.js","sourceRoot":"","sources":["../../src/internal/SyncEngine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare function genUuid(): `${string}-${string}-${string}-${string}-${string}`;
@@ -0,0 +1,4 @@
1
+ export function genUuid() {
2
+ return crypto.randomUUID();
3
+ }
4
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/internal/utils.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,OAAO;IACtB,OAAO,MAAM,CAAC,UAAU,EAAE,CAAA;AAC3B,CAAC"}
package/esm/react.d.ts ADDED
@@ -0,0 +1 @@
1
+ export * from "./useDbQuery.js";
package/esm/react.js ADDED
@@ -0,0 +1,2 @@
1
+ export * from "./useDbQuery.js";
2
+ //# sourceMappingURL=react.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"react.js","sourceRoot":"","sources":["../src/react.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAA"}
@@ -0,0 +1,13 @@
1
+ import type { DbSync } from "./DbSync.js";
2
+ /**
3
+ * A React hook that subscribes to one or more `DbSync` tables and natively
4
+ * re-evaluates a strictly typed query function whenever local mutations or
5
+ * background sync events alter the underlying data.
6
+ *
7
+ * @param db The initialized `DbSync` instance.
8
+ * @param stores A string or array of strings containing the table names the query function reads from.
9
+ * @param queryFn An asynchronous function invoked to pull data from IndexedDB.
10
+ * @param deps A standard React dependency array for parameters referenced inside the `queryFn`.
11
+ * @returns The resolved data of the `queryFn`, or `undefined` while the initial fetch evaluates.
12
+ */
13
+ export declare function useDbQuery<T>(db: DbSync, stores: string | string[], queryFn: () => Promise<T>, deps?: any[]): T | undefined;
@@ -0,0 +1,56 @@
1
+ import { useEffect, useState } from "react";
2
+ /**
3
+ * A React hook that subscribes to one or more `DbSync` tables and natively
4
+ * re-evaluates a strictly typed query function whenever local mutations or
5
+ * background sync events alter the underlying data.
6
+ *
7
+ * @param db The initialized `DbSync` instance.
8
+ * @param stores A string or array of strings containing the table names the query function reads from.
9
+ * @param queryFn An asynchronous function invoked to pull data from IndexedDB.
10
+ * @param deps A standard React dependency array for parameters referenced inside the `queryFn`.
11
+ * @returns The resolved data of the `queryFn`, or `undefined` while the initial fetch evaluates.
12
+ */
13
+ export function useDbQuery(db, stores, queryFn, deps = []) {
14
+ const [data, setData] = useState(undefined);
15
+ const storeArray = Array.isArray(stores) ? stores : [stores];
16
+ useEffect(() => {
17
+ let isMounted = true;
18
+ const fetchData = async () => {
19
+ if (!db.initted) {
20
+ // If attempting to query before init(), safely wait
21
+ await new Promise((resolve) => {
22
+ const check = setInterval(() => {
23
+ if (!isMounted || db.initted) {
24
+ clearInterval(check);
25
+ resolve();
26
+ }
27
+ }, 50);
28
+ });
29
+ }
30
+ try {
31
+ const result = await queryFn();
32
+ if (isMounted)
33
+ setData(result);
34
+ }
35
+ catch (err) {
36
+ console.error("[dbsync useDbQuery]: Query failed", err);
37
+ }
38
+ };
39
+ // Initial fetch
40
+ fetchData();
41
+ // Subscribe to relevant stores
42
+ const sub = db.subscribe((updatedStores) => {
43
+ const shouldUpdate = updatedStores.some((s) => storeArray.includes(s));
44
+ if (shouldUpdate) {
45
+ fetchData();
46
+ }
47
+ });
48
+ return () => {
49
+ isMounted = false;
50
+ sub.close();
51
+ };
52
+ // eslint-disable-next-line react-hooks/exhaustive-deps
53
+ }, [db, JSON.stringify(storeArray), ...deps]);
54
+ return data;
55
+ }
56
+ //# sourceMappingURL=useDbQuery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useDbQuery.js","sourceRoot":"","sources":["../src/useDbQuery.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAG3C;;;;;;;;;;GAUG;AACH,MAAM,UAAU,UAAU,CACzB,EAAU,EACV,MAAyB,EACzB,OAAyB,EACzB,OAAc,EAAE;IAEhB,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAgB,SAAS,CAAC,CAAA;IAC1D,MAAM,UAAU,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAA;IAE5D,SAAS,CAAC,GAAG,EAAE;QACd,IAAI,SAAS,GAAG,IAAI,CAAA;QAEpB,MAAM,SAAS,GAAG,KAAK,IAAI,EAAE;YAC5B,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC;gBACjB,oDAAoD;gBACpD,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;oBACnC,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE;wBAC9B,IAAI,CAAC,SAAS,IAAI,EAAE,CAAC,OAAO,EAAE,CAAC;4BAC9B,aAAa,CAAC,KAAK,CAAC,CAAA;4BACpB,OAAO,EAAE,CAAA;wBACV,CAAC;oBACF,CAAC,EAAE,EAAE,CAAC,CAAA;gBACP,CAAC,CAAC,CAAA;YACH,CAAC;YACD,IAAI,CAAC;gBACJ,MAAM,MAAM,GAAG,MAAM,OAAO,EAAE,CAAA;gBAC9B,IAAI,SAAS;oBAAE,OAAO,CAAC,MAAM,CAAC,CAAA;YAC/B,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACd,OAAO,CAAC,KAAK,CAAC,mCAAmC,EAAE,GAAG,CAAC,CAAA;YACxD,CAAC;QACF,CAAC,CAAA;QAED,gBAAgB;QAChB,SAAS,EAAE,CAAA;QAEX,+BAA+B;QAC/B,MAAM,GAAG,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC,aAAa,EAAE,EAAE;YAC1C,MAAM,YAAY,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAA;YACtE,IAAI,YAAY,EAAE,CAAC;gBAClB,SAAS,EAAE,CAAA;YACZ,CAAC;QACF,CAAC,CAAC,CAAA;QAEF,OAAO,GAAG,EAAE;YACX,SAAS,GAAG,KAAK,CAAA;YACjB,GAAG,CAAC,KAAK,EAAE,CAAA;QACZ,CAAC,CAAA;QACD,uDAAuD;IACxD,CAAC,EAAE,CAAC,EAAE,EAAE,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC,CAAA;IAE7C,OAAO,IAAI,CAAA;AACZ,CAAC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Creates a promise together with its external resolve and reject handlers.
3
+ *
4
+ * This mirrors `Promise.withResolvers()` in environments that do not provide
5
+ * the built-in helper yet.
6
+ */
7
+ export declare function promiseWithResolvers<T>(): {
8
+ promise: Promise<T>;
9
+ resolve: (value: T | PromiseLike<T>) => void;
10
+ reject: (reason?: any) => void;
11
+ };
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Creates a promise together with its external resolve and reject handlers.
3
+ *
4
+ * This mirrors `Promise.withResolvers()` in environments that do not provide
5
+ * the built-in helper yet.
6
+ */
7
+ export function promiseWithResolvers() {
8
+ let resolve;
9
+ let reject;
10
+ const promise = new Promise((res, rej) => {
11
+ resolve = res;
12
+ reject = rej;
13
+ });
14
+ return { promise, resolve, reject };
15
+ }
16
+ //# sourceMappingURL=promiseWithResolvers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"promiseWithResolvers.js","sourceRoot":"","sources":["../../src/util/promiseWithResolvers.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB;IACnC,IAAI,OAA6C,CAAA;IACjD,IAAI,MAA+B,CAAA;IACnC,MAAM,OAAO,GAAG,IAAI,OAAO,CAAI,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;QAC3C,OAAO,GAAG,GAAG,CAAA;QACb,MAAM,GAAG,GAAG,CAAA;IACb,CAAC,CAAC,CAAA;IACF,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,CAAA;AACpC,CAAC"}
package/package.json ADDED
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "@slimr/dbsync",
3
+ "version": "0.0.3",
4
+ "author": "Brian Dombrowski",
5
+ "license": "ISC",
6
+ "private": false,
7
+ "main": "cjs/index.js",
8
+ "module": "esm/index.js",
9
+ "sideEffects": false,
10
+ "exports": {
11
+ ".": {
12
+ "require": "./cjs/index.js",
13
+ "import": "./esm/index.js"
14
+ },
15
+ "./adapters": {
16
+ "require": "./cjs/adapters/index.js",
17
+ "import": "./esm/adapters/index.js"
18
+ },
19
+ "./react": {
20
+ "require": "./cjs/react.js",
21
+ "import": "./esm/react.js"
22
+ }
23
+ },
24
+ "repository": {
25
+ "type": "git",
26
+ "url": "git+https://github.com/bdombro/slimr.git"
27
+ },
28
+ "type": "module",
29
+ "scripts": {
30
+ "build": "run-p build:*",
31
+ "build:esm": "OUT=esm; tsc -d --outDir $OUT --noEmit false",
32
+ "build:cjs": "OUT=cjs; tsc -d -m commonjs --moduleResolution node --outDir $OUT --noEmit false",
33
+ "clean": "rm -rf esm cjs",
34
+ "start": "nodemon -w src -e '*' -x 'npm run build && cd ../demo && npm start'",
35
+ "test": "vitest run",
36
+ "test:e2e": "playwright test",
37
+ "typecheck:test": "tsc -p tsconfig.test.json --noEmit",
38
+ "typecheck": "tsc -noEmit && npm run typecheck:test"
39
+ },
40
+ "files": [
41
+ "cjs",
42
+ "esm"
43
+ ]
44
+ }