@makefully/adaptfully 2.1.0 → 3.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/CHANGELOG.md +87 -64
- package/LICENSE +21 -21
- package/README.md +515 -430
- package/bin/adaptfully.js +7 -0
- package/bin/wrapfully-deploy.js +22 -7
- package/lib/node/archive.js +43 -34
- package/lib/node/config.js +42 -42
- package/lib/node/deploy.js +52 -69
- package/lib/node/fs-utils.js +49 -0
- package/lib/node/index.js +20 -18
- package/lib/node/paths.js +18 -0
- package/lib/node/pipeline.js +77 -0
- package/lib/node/prebuild.js +63 -0
- package/lib/node/registrations.js +314 -0
- package/lib/node/report.js +42 -42
- package/lib/runtime/auth/_helpers.js +38 -38
- package/lib/runtime/auth/dev-auth.js +78 -78
- package/lib/runtime/auth/google-auth.js +176 -176
- package/lib/runtime/auth/steam-auth.js +50 -50
- package/lib/runtime/core.js +56 -61
- package/lib/runtime/platform.js +89 -89
- package/package.json +62 -61
- package/lib/node/distribution.js +0 -138
|
@@ -1,176 +1,176 @@
|
|
|
1
|
-
/* global google, sessionStorage, window */
|
|
2
|
-
|
|
3
|
-
(function registerGoogleAuth(ns) {
|
|
4
|
-
const { configValue, getStorage } = ns.auth.helpers;
|
|
5
|
-
|
|
6
|
-
const DEFAULT_CLIENT_ID = '225754014403.apps.googleusercontent.com';
|
|
7
|
-
const DEFAULT_SCOPES = 'openid email profile';
|
|
8
|
-
const DEFAULT_TOKEN_KEY = 'adaptfully_google_token';
|
|
9
|
-
|
|
10
|
-
class GoogleAuthPlugin {
|
|
11
|
-
constructor() {
|
|
12
|
-
this.name = 'google';
|
|
13
|
-
this.tokenClient = null;
|
|
14
|
-
this.tokenKey = configValue('googleTokenKey', DEFAULT_TOKEN_KEY);
|
|
15
|
-
this.clientId = configValue('googleClientId', DEFAULT_CLIENT_ID);
|
|
16
|
-
this.scopes = configValue('googleScopes', DEFAULT_SCOPES);
|
|
17
|
-
this.accessToken = sessionStorage.getItem(this.tokenKey) || '';
|
|
18
|
-
this.user = null;
|
|
19
|
-
this.authenticated = false;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
whenReady(done) {
|
|
23
|
-
const setup = () => {
|
|
24
|
-
this.tokenClient = google.accounts.oauth2.initTokenClient({
|
|
25
|
-
client_id: this.clientId,
|
|
26
|
-
scope: this.scopes,
|
|
27
|
-
callback: () => {},
|
|
28
|
-
});
|
|
29
|
-
done();
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
if (window.google?.accounts?.oauth2) {
|
|
33
|
-
setup();
|
|
34
|
-
return;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
let attempts = 0;
|
|
38
|
-
const timer = window.setInterval(() => {
|
|
39
|
-
attempts += 1;
|
|
40
|
-
if (window.google?.accounts?.oauth2) {
|
|
41
|
-
window.clearInterval(timer);
|
|
42
|
-
setup();
|
|
43
|
-
} else if (attempts > 200) {
|
|
44
|
-
window.clearInterval(timer);
|
|
45
|
-
console.error('Google Identity Services failed to load.');
|
|
46
|
-
done({ error: 'Google Identity Services failed to load.' });
|
|
47
|
-
}
|
|
48
|
-
}, 50);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
#applyUserInfo(data) {
|
|
52
|
-
this.user = {
|
|
53
|
-
id: data.sub || data.id || '',
|
|
54
|
-
email: data.email || '',
|
|
55
|
-
};
|
|
56
|
-
this.authenticated = !!(this.user.id && this.user.email);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
#clearSession() {
|
|
60
|
-
this.accessToken = '';
|
|
61
|
-
this.user = null;
|
|
62
|
-
this.authenticated = false;
|
|
63
|
-
sessionStorage.removeItem(this.tokenKey);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
#hasPersistedLogin() {
|
|
67
|
-
const storage = getStorage();
|
|
68
|
-
return !!(storage?.get('lastLoggedIn'));
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
#fetchUserInfo(token, callback) {
|
|
72
|
-
fetch('https://www.googleapis.com/oauth2/v3/userinfo', {
|
|
73
|
-
headers: { Authorization: `Bearer ${token}` },
|
|
74
|
-
})
|
|
75
|
-
.then((response) => {
|
|
76
|
-
if (!response.ok) {
|
|
77
|
-
throw new Error('userinfo failed');
|
|
78
|
-
}
|
|
79
|
-
return response.json();
|
|
80
|
-
})
|
|
81
|
-
.then((data) => {
|
|
82
|
-
this.accessToken = token;
|
|
83
|
-
sessionStorage.setItem(this.tokenKey, token);
|
|
84
|
-
this.#applyUserInfo(data);
|
|
85
|
-
callback();
|
|
86
|
-
})
|
|
87
|
-
.catch(() => {
|
|
88
|
-
this.#clearSession();
|
|
89
|
-
callback();
|
|
90
|
-
});
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
#requestAccessToken(prompt, callback) {
|
|
94
|
-
this.tokenClient.callback = (response) => {
|
|
95
|
-
if (response.error || !response.access_token) {
|
|
96
|
-
this.#clearSession();
|
|
97
|
-
callback();
|
|
98
|
-
return;
|
|
99
|
-
}
|
|
100
|
-
this.#fetchUserInfo(response.access_token, callback);
|
|
101
|
-
};
|
|
102
|
-
this.tokenClient.requestAccessToken({ prompt: prompt || '' });
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
#restoreSession(callback) {
|
|
106
|
-
const trySilentGoogleLogin = () => {
|
|
107
|
-
if (this.#hasPersistedLogin()) {
|
|
108
|
-
this.#requestAccessToken('none', callback);
|
|
109
|
-
} else {
|
|
110
|
-
this.#clearSession();
|
|
111
|
-
callback();
|
|
112
|
-
}
|
|
113
|
-
};
|
|
114
|
-
|
|
115
|
-
if (this.accessToken) {
|
|
116
|
-
this.#fetchUserInfo(this.accessToken, () => {
|
|
117
|
-
if (this.authenticated) {
|
|
118
|
-
callback();
|
|
119
|
-
return;
|
|
120
|
-
}
|
|
121
|
-
trySilentGoogleLogin();
|
|
122
|
-
});
|
|
123
|
-
return;
|
|
124
|
-
}
|
|
125
|
-
trySilentGoogleLogin();
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
login(callback) {
|
|
129
|
-
if (this.authenticated) {
|
|
130
|
-
callback({ authenticated: true, user: this.getUser() });
|
|
131
|
-
return;
|
|
132
|
-
}
|
|
133
|
-
this.#requestAccessToken('select_account', () => {
|
|
134
|
-
callback({ authenticated: this.authenticated, user: this.getUser() });
|
|
135
|
-
});
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
silentLogin(callback) {
|
|
139
|
-
if (this.authenticated && this.user?.id) {
|
|
140
|
-
callback({ authenticated: true, user: this.getUser() });
|
|
141
|
-
return;
|
|
142
|
-
}
|
|
143
|
-
this.#restoreSession(() => {
|
|
144
|
-
callback({ authenticated: this.authenticated, user: this.getUser() });
|
|
145
|
-
});
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
logout(callback) {
|
|
149
|
-
const storage = getStorage();
|
|
150
|
-
const finish = () => {
|
|
151
|
-
this.#clearSession();
|
|
152
|
-
storage?.remove('lastLoggedIn');
|
|
153
|
-
callback();
|
|
154
|
-
};
|
|
155
|
-
|
|
156
|
-
if (this.accessToken && google.accounts?.oauth2) {
|
|
157
|
-
google.accounts.oauth2.revoke(this.accessToken, finish);
|
|
158
|
-
} else {
|
|
159
|
-
finish();
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
getUser() {
|
|
164
|
-
if (!this.authenticated || !this.user) {
|
|
165
|
-
return null;
|
|
166
|
-
}
|
|
167
|
-
return { id: this.user.id, email: this.user.email };
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
isAuthenticated() {
|
|
171
|
-
return !!this.authenticated;
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
ns.auth.Google = () => new GoogleAuthPlugin();
|
|
176
|
-
}(window.adaptfully));
|
|
1
|
+
/* global google, sessionStorage, window */
|
|
2
|
+
|
|
3
|
+
(function registerGoogleAuth(ns) {
|
|
4
|
+
const { configValue, getStorage } = ns.auth.helpers;
|
|
5
|
+
|
|
6
|
+
const DEFAULT_CLIENT_ID = '225754014403.apps.googleusercontent.com';
|
|
7
|
+
const DEFAULT_SCOPES = 'openid email profile';
|
|
8
|
+
const DEFAULT_TOKEN_KEY = 'adaptfully_google_token';
|
|
9
|
+
|
|
10
|
+
class GoogleAuthPlugin {
|
|
11
|
+
constructor() {
|
|
12
|
+
this.name = 'google';
|
|
13
|
+
this.tokenClient = null;
|
|
14
|
+
this.tokenKey = configValue('googleTokenKey', DEFAULT_TOKEN_KEY);
|
|
15
|
+
this.clientId = configValue('googleClientId', DEFAULT_CLIENT_ID);
|
|
16
|
+
this.scopes = configValue('googleScopes', DEFAULT_SCOPES);
|
|
17
|
+
this.accessToken = sessionStorage.getItem(this.tokenKey) || '';
|
|
18
|
+
this.user = null;
|
|
19
|
+
this.authenticated = false;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
whenReady(done) {
|
|
23
|
+
const setup = () => {
|
|
24
|
+
this.tokenClient = google.accounts.oauth2.initTokenClient({
|
|
25
|
+
client_id: this.clientId,
|
|
26
|
+
scope: this.scopes,
|
|
27
|
+
callback: () => {},
|
|
28
|
+
});
|
|
29
|
+
done();
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
if (window.google?.accounts?.oauth2) {
|
|
33
|
+
setup();
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
let attempts = 0;
|
|
38
|
+
const timer = window.setInterval(() => {
|
|
39
|
+
attempts += 1;
|
|
40
|
+
if (window.google?.accounts?.oauth2) {
|
|
41
|
+
window.clearInterval(timer);
|
|
42
|
+
setup();
|
|
43
|
+
} else if (attempts > 200) {
|
|
44
|
+
window.clearInterval(timer);
|
|
45
|
+
console.error('Google Identity Services failed to load.');
|
|
46
|
+
done({ error: 'Google Identity Services failed to load.' });
|
|
47
|
+
}
|
|
48
|
+
}, 50);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
#applyUserInfo(data) {
|
|
52
|
+
this.user = {
|
|
53
|
+
id: data.sub || data.id || '',
|
|
54
|
+
email: data.email || '',
|
|
55
|
+
};
|
|
56
|
+
this.authenticated = !!(this.user.id && this.user.email);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
#clearSession() {
|
|
60
|
+
this.accessToken = '';
|
|
61
|
+
this.user = null;
|
|
62
|
+
this.authenticated = false;
|
|
63
|
+
sessionStorage.removeItem(this.tokenKey);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
#hasPersistedLogin() {
|
|
67
|
+
const storage = getStorage();
|
|
68
|
+
return !!(storage?.get('lastLoggedIn'));
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
#fetchUserInfo(token, callback) {
|
|
72
|
+
fetch('https://www.googleapis.com/oauth2/v3/userinfo', {
|
|
73
|
+
headers: { Authorization: `Bearer ${token}` },
|
|
74
|
+
})
|
|
75
|
+
.then((response) => {
|
|
76
|
+
if (!response.ok) {
|
|
77
|
+
throw new Error('userinfo failed');
|
|
78
|
+
}
|
|
79
|
+
return response.json();
|
|
80
|
+
})
|
|
81
|
+
.then((data) => {
|
|
82
|
+
this.accessToken = token;
|
|
83
|
+
sessionStorage.setItem(this.tokenKey, token);
|
|
84
|
+
this.#applyUserInfo(data);
|
|
85
|
+
callback();
|
|
86
|
+
})
|
|
87
|
+
.catch(() => {
|
|
88
|
+
this.#clearSession();
|
|
89
|
+
callback();
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
#requestAccessToken(prompt, callback) {
|
|
94
|
+
this.tokenClient.callback = (response) => {
|
|
95
|
+
if (response.error || !response.access_token) {
|
|
96
|
+
this.#clearSession();
|
|
97
|
+
callback();
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
this.#fetchUserInfo(response.access_token, callback);
|
|
101
|
+
};
|
|
102
|
+
this.tokenClient.requestAccessToken({ prompt: prompt || '' });
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
#restoreSession(callback) {
|
|
106
|
+
const trySilentGoogleLogin = () => {
|
|
107
|
+
if (this.#hasPersistedLogin()) {
|
|
108
|
+
this.#requestAccessToken('none', callback);
|
|
109
|
+
} else {
|
|
110
|
+
this.#clearSession();
|
|
111
|
+
callback();
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
if (this.accessToken) {
|
|
116
|
+
this.#fetchUserInfo(this.accessToken, () => {
|
|
117
|
+
if (this.authenticated) {
|
|
118
|
+
callback();
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
trySilentGoogleLogin();
|
|
122
|
+
});
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
trySilentGoogleLogin();
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
login(callback) {
|
|
129
|
+
if (this.authenticated) {
|
|
130
|
+
callback({ authenticated: true, user: this.getUser() });
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
this.#requestAccessToken('select_account', () => {
|
|
134
|
+
callback({ authenticated: this.authenticated, user: this.getUser() });
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
silentLogin(callback) {
|
|
139
|
+
if (this.authenticated && this.user?.id) {
|
|
140
|
+
callback({ authenticated: true, user: this.getUser() });
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
this.#restoreSession(() => {
|
|
144
|
+
callback({ authenticated: this.authenticated, user: this.getUser() });
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
logout(callback) {
|
|
149
|
+
const storage = getStorage();
|
|
150
|
+
const finish = () => {
|
|
151
|
+
this.#clearSession();
|
|
152
|
+
storage?.remove('lastLoggedIn');
|
|
153
|
+
callback();
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
if (this.accessToken && google.accounts?.oauth2) {
|
|
157
|
+
google.accounts.oauth2.revoke(this.accessToken, finish);
|
|
158
|
+
} else {
|
|
159
|
+
finish();
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
getUser() {
|
|
164
|
+
if (!this.authenticated || !this.user) {
|
|
165
|
+
return null;
|
|
166
|
+
}
|
|
167
|
+
return { id: this.user.id, email: this.user.email };
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
isAuthenticated() {
|
|
171
|
+
return !!this.authenticated;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
ns.auth.Google = () => new GoogleAuthPlugin();
|
|
176
|
+
}(window.adaptfully));
|
|
@@ -1,50 +1,50 @@
|
|
|
1
|
-
/* global window */
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Steam auth plugin — placeholder for Electron / NW.js Steam deployments.
|
|
5
|
-
* Wire Steamworks login here; games only talk to adaptfully.get('auth').
|
|
6
|
-
*/
|
|
7
|
-
(function registerSteamAuth(ns) {
|
|
8
|
-
const { getStorage } = ns.auth.helpers;
|
|
9
|
-
|
|
10
|
-
class SteamAuthPlugin {
|
|
11
|
-
constructor() {
|
|
12
|
-
this.name = 'steam';
|
|
13
|
-
this.user = null;
|
|
14
|
-
this.authenticated = false;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
whenReady(done) {
|
|
18
|
-
done();
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
login(callback) {
|
|
22
|
-
callback({ authenticated: this.authenticated, user: this.getUser() });
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
silentLogin(callback) {
|
|
26
|
-
callback({ authenticated: this.authenticated, user: this.getUser() });
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
logout(callback) {
|
|
30
|
-
const storage = getStorage();
|
|
31
|
-
this.user = null;
|
|
32
|
-
this.authenticated = false;
|
|
33
|
-
storage?.remove('lastLoggedIn');
|
|
34
|
-
callback();
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
getUser() {
|
|
38
|
-
if (!this.authenticated || !this.user) {
|
|
39
|
-
return null;
|
|
40
|
-
}
|
|
41
|
-
return { id: this.user.id, email: this.user.email || '' };
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
isAuthenticated() {
|
|
45
|
-
return !!this.authenticated;
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
ns.auth.Steam = () => new SteamAuthPlugin();
|
|
50
|
-
}(window.adaptfully));
|
|
1
|
+
/* global window */
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Steam auth plugin — placeholder for Electron / NW.js Steam deployments.
|
|
5
|
+
* Wire Steamworks login here; games only talk to adaptfully.get('auth').
|
|
6
|
+
*/
|
|
7
|
+
(function registerSteamAuth(ns) {
|
|
8
|
+
const { getStorage } = ns.auth.helpers;
|
|
9
|
+
|
|
10
|
+
class SteamAuthPlugin {
|
|
11
|
+
constructor() {
|
|
12
|
+
this.name = 'steam';
|
|
13
|
+
this.user = null;
|
|
14
|
+
this.authenticated = false;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
whenReady(done) {
|
|
18
|
+
done();
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
login(callback) {
|
|
22
|
+
callback({ authenticated: this.authenticated, user: this.getUser() });
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
silentLogin(callback) {
|
|
26
|
+
callback({ authenticated: this.authenticated, user: this.getUser() });
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
logout(callback) {
|
|
30
|
+
const storage = getStorage();
|
|
31
|
+
this.user = null;
|
|
32
|
+
this.authenticated = false;
|
|
33
|
+
storage?.remove('lastLoggedIn');
|
|
34
|
+
callback();
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
getUser() {
|
|
38
|
+
if (!this.authenticated || !this.user) {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
return { id: this.user.id, email: this.user.email || '' };
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
isAuthenticated() {
|
|
45
|
+
return !!this.authenticated;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
ns.auth.Steam = () => new SteamAuthPlugin();
|
|
50
|
+
}(window.adaptfully));
|
package/lib/runtime/core.js
CHANGED
|
@@ -1,61 +1,56 @@
|
|
|
1
|
-
/* global window */
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Adaptfully — shared platform services for Makefully games.
|
|
5
|
-
*
|
|
6
|
-
* adaptfully.register('auth', adaptfully.auth.Google);
|
|
7
|
-
* const platform = adaptfully.get('auth');
|
|
8
|
-
*/
|
|
9
|
-
(function initAdaptfully(global) {
|
|
10
|
-
class Adaptfully {
|
|
11
|
-
/** @type {Record<string, unknown>} */
|
|
12
|
-
#registry = {};
|
|
13
|
-
|
|
14
|
-
/** @type {import('./platform.js').Platform | null} */
|
|
15
|
-
#authPlatform = null;
|
|
16
|
-
|
|
17
|
-
register(key, value) {
|
|
18
|
-
if (key === 'auth') {
|
|
19
|
-
this.#authPlatform = null;
|
|
20
|
-
}
|
|
21
|
-
this.#registry[key] = value;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
get(key) {
|
|
25
|
-
if (key === 'auth') {
|
|
26
|
-
if (!this.#authPlatform) {
|
|
27
|
-
const factory = this.#registry.auth;
|
|
28
|
-
if (!factory) {
|
|
29
|
-
throw new Error(
|
|
30
|
-
'adaptfully: no auth registered — call adaptfully.register(\'auth\', ...) before the game loads',
|
|
31
|
-
);
|
|
32
|
-
}
|
|
33
|
-
const plugin = typeof factory === 'function' ? factory() : factory;
|
|
34
|
-
if (!this.Platform) {
|
|
35
|
-
throw new Error('adaptfully: Platform is not loaded');
|
|
36
|
-
}
|
|
37
|
-
this.#authPlatform = new this.Platform(plugin);
|
|
38
|
-
}
|
|
39
|
-
return this.#authPlatform;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
if (!(key in this.#registry)) {
|
|
43
|
-
throw new Error(`adaptfully: nothing registered for "${key}"`);
|
|
44
|
-
}
|
|
45
|
-
return this.#registry[key];
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
has(key) {
|
|
49
|
-
return key in this.#registry;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
const adaptfully = global.adaptfully || new Adaptfully();
|
|
59
|
-
adaptfully.auth = adaptfully.auth || {};
|
|
60
|
-
global.adaptfully = adaptfully;
|
|
61
|
-
}(typeof window !== 'undefined' ? window : globalThis));
|
|
1
|
+
/* global window */
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Adaptfully — shared platform services for Makefully games.
|
|
5
|
+
*
|
|
6
|
+
* adaptfully.register('auth', adaptfully.auth.Google);
|
|
7
|
+
* const platform = adaptfully.get('auth');
|
|
8
|
+
*/
|
|
9
|
+
(function initAdaptfully(global) {
|
|
10
|
+
class Adaptfully {
|
|
11
|
+
/** @type {Record<string, unknown>} */
|
|
12
|
+
#registry = {};
|
|
13
|
+
|
|
14
|
+
/** @type {import('./platform.js').Platform | null} */
|
|
15
|
+
#authPlatform = null;
|
|
16
|
+
|
|
17
|
+
register(key, value) {
|
|
18
|
+
if (key === 'auth') {
|
|
19
|
+
this.#authPlatform = null;
|
|
20
|
+
}
|
|
21
|
+
this.#registry[key] = value;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
get(key) {
|
|
25
|
+
if (key === 'auth') {
|
|
26
|
+
if (!this.#authPlatform) {
|
|
27
|
+
const factory = this.#registry.auth;
|
|
28
|
+
if (!factory) {
|
|
29
|
+
throw new Error(
|
|
30
|
+
'adaptfully: no auth registered — call adaptfully.register(\'auth\', ...) before the game loads',
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
const plugin = typeof factory === 'function' ? factory() : factory;
|
|
34
|
+
if (!this.Platform) {
|
|
35
|
+
throw new Error('adaptfully: Platform is not loaded');
|
|
36
|
+
}
|
|
37
|
+
this.#authPlatform = new this.Platform(plugin);
|
|
38
|
+
}
|
|
39
|
+
return this.#authPlatform;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (!(key in this.#registry)) {
|
|
43
|
+
throw new Error(`adaptfully: nothing registered for "${key}"`);
|
|
44
|
+
}
|
|
45
|
+
return this.#registry[key];
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
has(key) {
|
|
49
|
+
return key in this.#registry;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const adaptfully = global.adaptfully || new Adaptfully();
|
|
54
|
+
adaptfully.auth = adaptfully.auth || {};
|
|
55
|
+
global.adaptfully = adaptfully;
|
|
56
|
+
}(typeof window !== 'undefined' ? window : globalThis));
|