@makefully/adaptfully 3.0.3 → 3.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/CHANGELOG.md +11 -0
- package/README.md +20 -4
- package/lib/node/registrations.js +8 -0
- package/lib/runtime/auth/_helpers.js +2 -29
- package/lib/runtime/storage/_helpers.js +5 -0
- package/lib/runtime/storage/indexed-db.js +87 -0
- package/lib/runtime/storage/local-storage.js +50 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project are documented in this file.
|
|
4
4
|
|
|
5
|
+
## 3.1.0 — 2026-06-18
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- Built-in storage plugins: `localStorage` (sync) and `indexedDB` (async).
|
|
10
|
+
- Register with `"storage": "localStorage"` or `"storage": "indexedDB"` in `config.platforms.<platform>.registrations`.
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
|
|
14
|
+
- Auth helpers use registered `storage` only (no implicit fallbacks).
|
|
15
|
+
|
|
5
16
|
## 3.0.3 — 2026-06-18
|
|
6
17
|
|
|
7
18
|
### Added
|
package/README.md
CHANGED
|
@@ -45,6 +45,21 @@ const platform = adaptfully.get('auth');
|
|
|
45
45
|
platform.login(function (result) { /* ... */ });
|
|
46
46
|
```
|
|
47
47
|
|
|
48
|
+
### Storage plugins
|
|
49
|
+
|
|
50
|
+
| Plugin key | Registration | Runtime |
|
|
51
|
+
|------------|--------------|---------|
|
|
52
|
+
| `localStorage` | `adaptfully.register('storage', adaptfully.storage.LocalStorage())` | Sync key/value storage in the browser |
|
|
53
|
+
| `indexedDB` | `adaptfully.register('storage', adaptfully.storage.IndexedDB())` | Async key/value storage for larger payloads |
|
|
54
|
+
|
|
55
|
+
In-game:
|
|
56
|
+
|
|
57
|
+
```javascript
|
|
58
|
+
const storage = adaptfully.get('storage');
|
|
59
|
+
storage.set('playerName', 'Ada');
|
|
60
|
+
storage.getObject('currentGame');
|
|
61
|
+
```
|
|
62
|
+
|
|
48
63
|
### Auth plugins
|
|
49
64
|
|
|
50
65
|
| Plugin key | Registration | Runtime |
|
|
@@ -61,18 +76,19 @@ Use plugin keys in `config.platforms.<platform>.registrations`. Custom deploy sc
|
|
|
61
76
|
"platforms": {
|
|
62
77
|
"steam": {
|
|
63
78
|
"registrations": {
|
|
64
|
-
"
|
|
65
|
-
"
|
|
79
|
+
"storage": "localStorage",
|
|
80
|
+
"auth": "steam-auth"
|
|
66
81
|
}
|
|
67
82
|
},
|
|
68
83
|
"web": {
|
|
69
84
|
"registrations": {
|
|
70
|
-
"
|
|
71
|
-
"
|
|
85
|
+
"storage": "localStorage",
|
|
86
|
+
"auth": "google-auth"
|
|
72
87
|
}
|
|
73
88
|
},
|
|
74
89
|
"dev": {
|
|
75
90
|
"registrations": {
|
|
91
|
+
"storage": "localStorage",
|
|
76
92
|
"auth": "dev-auth"
|
|
77
93
|
}
|
|
78
94
|
}
|
|
@@ -25,6 +25,14 @@ export const STANDARD_PLUGINS = {
|
|
|
25
25
|
scripts: ['core.js', 'platform.js', 'auth/_helpers.js', 'auth/dev-auth.js'],
|
|
26
26
|
registration: (key) => `adaptfully.register('${key}', adaptfully.auth.Dev);`,
|
|
27
27
|
},
|
|
28
|
+
localStorage: {
|
|
29
|
+
scripts: ['core.js', 'storage/_helpers.js', 'storage/local-storage.js'],
|
|
30
|
+
registration: (key) => `adaptfully.register('${key}', adaptfully.storage.LocalStorage());`,
|
|
31
|
+
},
|
|
32
|
+
indexedDB: {
|
|
33
|
+
scripts: ['core.js', 'storage/_helpers.js', 'storage/indexed-db.js'],
|
|
34
|
+
registration: (key) => `adaptfully.register('${key}', adaptfully.storage.IndexedDB());`,
|
|
35
|
+
},
|
|
28
36
|
};
|
|
29
37
|
|
|
30
38
|
/** Default Wrapfully builder → config.platforms key */
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/* global
|
|
1
|
+
/* global window */
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* @typedef {{ id: string, email: string }} AuthUser
|
|
@@ -17,27 +17,6 @@
|
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
19
|
(function registerAuthHelpers(ns) {
|
|
20
|
-
/** @type {ReturnType<typeof createDefaultStorage> | undefined} */
|
|
21
|
-
let defaultStorage;
|
|
22
|
-
|
|
23
|
-
function createDefaultStorage() {
|
|
24
|
-
if (typeof localStorage !== 'undefined') {
|
|
25
|
-
return {
|
|
26
|
-
get(key) {
|
|
27
|
-
const value = localStorage.getItem(key);
|
|
28
|
-
return value === null ? undefined : value;
|
|
29
|
-
},
|
|
30
|
-
set(key, value) {
|
|
31
|
-
localStorage.setItem(key, value == null ? '' : String(value));
|
|
32
|
-
},
|
|
33
|
-
remove(key) {
|
|
34
|
-
localStorage.removeItem(key);
|
|
35
|
-
},
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
return null;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
20
|
const helpers = {
|
|
42
21
|
configValue(key, fallback) {
|
|
43
22
|
if (!ns.has('config')) {
|
|
@@ -51,13 +30,7 @@
|
|
|
51
30
|
},
|
|
52
31
|
|
|
53
32
|
getStorage() {
|
|
54
|
-
|
|
55
|
-
return ns.get('storage');
|
|
56
|
-
}
|
|
57
|
-
if (defaultStorage === undefined) {
|
|
58
|
-
defaultStorage = createDefaultStorage();
|
|
59
|
-
}
|
|
60
|
-
return defaultStorage;
|
|
33
|
+
return ns.has('storage') ? ns.get('storage') : null;
|
|
61
34
|
},
|
|
62
35
|
};
|
|
63
36
|
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/* global indexedDB, window */
|
|
2
|
+
|
|
3
|
+
(function registerIndexedDBStorage(ns) {
|
|
4
|
+
function configValue(key, fallback) {
|
|
5
|
+
if (!ns.has('config')) {
|
|
6
|
+
return fallback;
|
|
7
|
+
}
|
|
8
|
+
const config = ns.get('config');
|
|
9
|
+
return config?.[key] != null ? config[key] : fallback;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
ns.storage.IndexedDB = function indexedDBFactory() {
|
|
13
|
+
const dbName = configValue('indexedDBName', 'adaptfully');
|
|
14
|
+
const storeName = configValue('indexedDBStoreName', 'storage');
|
|
15
|
+
/** @type {Promise<IDBDatabase> | null} */
|
|
16
|
+
let dbPromise = null;
|
|
17
|
+
|
|
18
|
+
function openDb() {
|
|
19
|
+
if (!dbPromise) {
|
|
20
|
+
dbPromise = new Promise((resolve, reject) => {
|
|
21
|
+
const request = indexedDB.open(dbName, 1);
|
|
22
|
+
request.onupgradeneeded = () => {
|
|
23
|
+
request.result.createObjectStore(storeName);
|
|
24
|
+
};
|
|
25
|
+
request.onsuccess = () => resolve(request.result);
|
|
26
|
+
request.onerror = () => reject(request.error);
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
return dbPromise;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function withStore(mode, fn) {
|
|
33
|
+
return openDb().then((db) => new Promise((resolve, reject) => {
|
|
34
|
+
const tx = db.transaction(storeName, mode);
|
|
35
|
+
const store = tx.objectStore(storeName);
|
|
36
|
+
const request = fn(store);
|
|
37
|
+
request.onsuccess = () => resolve(request.result);
|
|
38
|
+
request.onerror = () => reject(request.error);
|
|
39
|
+
}));
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return {
|
|
43
|
+
name: 'indexedDB',
|
|
44
|
+
async get(field) {
|
|
45
|
+
try {
|
|
46
|
+
const value = await withStore('readonly', (store) => store.get(field));
|
|
47
|
+
return value === undefined ? false : value;
|
|
48
|
+
} catch {
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
async set(field, value) {
|
|
53
|
+
await this.remove(field);
|
|
54
|
+
try {
|
|
55
|
+
await withStore('readwrite', (store) => store.put(value, field));
|
|
56
|
+
} catch {
|
|
57
|
+
// ignore
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
async remove(field) {
|
|
61
|
+
try {
|
|
62
|
+
await withStore('readwrite', (store) => store.delete(field));
|
|
63
|
+
} catch {
|
|
64
|
+
// ignore
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
async getObject(field) {
|
|
68
|
+
const raw = await this.get(field);
|
|
69
|
+
if (!raw) {
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
try {
|
|
73
|
+
return JSON.parse(raw);
|
|
74
|
+
} catch {
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
async setObject(field, obj) {
|
|
79
|
+
try {
|
|
80
|
+
await this.set(field, JSON.stringify(obj));
|
|
81
|
+
} catch {
|
|
82
|
+
// ignore
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
};
|
|
86
|
+
};
|
|
87
|
+
}(window.adaptfully));
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/* global localStorage, window */
|
|
2
|
+
|
|
3
|
+
(function registerLocalStorage(ns) {
|
|
4
|
+
ns.storage.LocalStorage = function localStorageFactory() {
|
|
5
|
+
return {
|
|
6
|
+
name: 'localStorage',
|
|
7
|
+
get(field) {
|
|
8
|
+
try {
|
|
9
|
+
const value = localStorage.getItem(field);
|
|
10
|
+
return value === null ? false : value;
|
|
11
|
+
} catch {
|
|
12
|
+
return false;
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
set(field, value) {
|
|
16
|
+
this.remove(field);
|
|
17
|
+
try {
|
|
18
|
+
localStorage.setItem(field, value);
|
|
19
|
+
} catch {
|
|
20
|
+
// quota or private browsing
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
remove(field) {
|
|
24
|
+
try {
|
|
25
|
+
localStorage.removeItem(field);
|
|
26
|
+
} catch {
|
|
27
|
+
// ignore
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
getObject(field) {
|
|
31
|
+
const raw = this.get(field);
|
|
32
|
+
if (!raw) {
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
try {
|
|
36
|
+
return JSON.parse(raw);
|
|
37
|
+
} catch {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
setObject(field, obj) {
|
|
42
|
+
try {
|
|
43
|
+
this.set(field, JSON.stringify(obj));
|
|
44
|
+
} catch {
|
|
45
|
+
// ignore
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
};
|
|
50
|
+
}(window.adaptfully));
|