@communecter/cocolight-api-client 1.0.17 → 1.0.18
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/dist/123.cocolight-api-client.browser.js +1 -0
- package/dist/123.cocolight-api-client.cjs +1 -0
- package/dist/774.cocolight-api-client.mjs.js +1 -0
- package/dist/cocolight-api-client.browser.js +2 -2
- package/dist/cocolight-api-client.cjs +1 -1
- package/dist/cocolight-api-client.mjs.js +1 -1
- package/package.json +1 -1
- package/src/ApiClient.js +5 -0
- package/src/api/User.js +1 -0
- package/src/index.js +3 -1
- package/src/utils/MultiServerFileStorageStrategy.node.js +65 -0
- package/src/utils/MultiServerTokenStorageStrategy.js +131 -0
- package/src/utils/createDefaultMultiServerTokenStorageStrategy.js +45 -0
- package/src/utils/createDefaultTokenStorageStrategy.js +0 -2
package/package.json
CHANGED
package/src/ApiClient.js
CHANGED
|
@@ -12,6 +12,7 @@ import pino from "pino";
|
|
|
12
12
|
import MongoID from "./EJSONType.js";
|
|
13
13
|
import endpointsJson from "./endpoints.module.js";
|
|
14
14
|
import { ApiClientError, ApiResponseError, ApiValidationError, CircuitBreakerError } from "./error.js";
|
|
15
|
+
import { MultiServerTokenStorageStrategy } from "./utils/MultiServerTokenStorageStrategy.js";
|
|
15
16
|
import { MemoryStorageStrategy } from "./utils/TokenStorage.js";
|
|
16
17
|
|
|
17
18
|
|
|
@@ -150,6 +151,10 @@ export default class ApiClient extends EventEmitter {
|
|
|
150
151
|
this._accessToken = null;
|
|
151
152
|
this._refreshToken = null;
|
|
152
153
|
|
|
154
|
+
if (tokenStorageStrategy instanceof MultiServerTokenStorageStrategy) {
|
|
155
|
+
tokenStorageStrategy.use(this._baseURL);
|
|
156
|
+
}
|
|
157
|
+
|
|
153
158
|
this._tokenStorage = tokenStorageStrategy || new MemoryStorageStrategy();
|
|
154
159
|
|
|
155
160
|
if (
|
package/src/api/User.js
CHANGED
package/src/index.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import Api from "./Api.js";
|
|
2
2
|
import ApiClient from "./ApiClient.js";
|
|
3
3
|
import * as error from "./error.js";
|
|
4
|
+
import { createDefaultMultiServerTokenStorageStrategy } from "./utils/createDefaultMultiServerTokenStorageStrategy.js";
|
|
4
5
|
import { createDefaultTokenStorageStrategy } from "./utils/createDefaultTokenStorageStrategy.js";
|
|
6
|
+
import { MultiServerTokenStorageStrategy } from "./utils/MultiServerTokenStorageStrategy.js";
|
|
5
7
|
import OfflineClientManager from "./utils/OfflineClientManager.js";
|
|
6
8
|
import { TokenStorageStrategy } from "./utils/TokenStorage.js";
|
|
7
9
|
|
|
8
|
-
export default { ApiClient, Api, error, tokenStorageStrategy: { createDefaultTokenStorageStrategy, TokenStorageStrategy }, OfflineClientManager };
|
|
10
|
+
export default { ApiClient, Api, error, tokenStorageStrategy: { createDefaultTokenStorageStrategy, TokenStorageStrategy, createDefaultMultiServerTokenStorageStrategy, MultiServerTokenStorageStrategy }, OfflineClientManager };
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import os from "os";
|
|
3
|
+
import path from "path";
|
|
4
|
+
|
|
5
|
+
import { MultiServerTokenStorageStrategy } from "./MultiServerTokenStorageStrategy.js";
|
|
6
|
+
|
|
7
|
+
export class MultiServerFileStorageStrategy extends MultiServerTokenStorageStrategy {
|
|
8
|
+
constructor(filename = "tokens.json", dir = path.join(os.homedir(), ".config", "cocolight")) {
|
|
9
|
+
super();
|
|
10
|
+
this.filePath = path.join(dir, filename);
|
|
11
|
+
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
_readFile() {
|
|
15
|
+
if (!fs.existsSync(this.filePath)) return {};
|
|
16
|
+
try {
|
|
17
|
+
return JSON.parse(fs.readFileSync(this.filePath, "utf8"));
|
|
18
|
+
} catch {
|
|
19
|
+
return {};
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
_writeFile(data) {
|
|
24
|
+
fs.writeFileSync(this.filePath, JSON.stringify(data, null, 2), "utf8");
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
getAccessToken() {
|
|
28
|
+
this._ensureContext();
|
|
29
|
+
return this._readFile()[this._currentBaseURL]?.accessToken || null;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
setAccessToken(token) {
|
|
33
|
+
this._ensureContext();
|
|
34
|
+
const all = this._readFile();
|
|
35
|
+
all[this._currentBaseURL] = { ...(all[this._currentBaseURL] || {}), accessToken: token };
|
|
36
|
+
this._writeFile(all);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
getRefreshToken() {
|
|
40
|
+
this._ensureContext();
|
|
41
|
+
return this._readFile()[this._currentBaseURL]?.refreshToken || null;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
setRefreshToken(token) {
|
|
45
|
+
this._ensureContext();
|
|
46
|
+
const all = this._readFile();
|
|
47
|
+
all[this._currentBaseURL] = { ...(all[this._currentBaseURL] || {}), refreshToken: token };
|
|
48
|
+
this._writeFile(all);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
clear() {
|
|
52
|
+
this._ensureContext();
|
|
53
|
+
const all = this._readFile();
|
|
54
|
+
delete all[this._currentBaseURL];
|
|
55
|
+
this._writeFile(all);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
getServers() {
|
|
59
|
+
return Object.keys(this._readFile());
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
exportAll() {
|
|
63
|
+
return this._readFile();
|
|
64
|
+
}
|
|
65
|
+
}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
// MultiServerTokenStorageStrategy.js
|
|
2
|
+
import { TokenStorageStrategy } from "./TokenStorage.js";
|
|
3
|
+
|
|
4
|
+
export class MultiServerTokenStorageStrategy extends TokenStorageStrategy {
|
|
5
|
+
constructor() {
|
|
6
|
+
super();
|
|
7
|
+
this._currentBaseURL = null;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
use(baseURL) {
|
|
11
|
+
if (!baseURL) throw new Error("baseURL est requis");
|
|
12
|
+
this._currentBaseURL = baseURL.replace(/\/+$/, "");
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
_ensureContext() {
|
|
16
|
+
if (!this._currentBaseURL) throw new Error("baseURL non défini. Appelez use(baseURL)");
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
getServers() {
|
|
20
|
+
throw new Error("getServers() doit être implémenté");
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
exportAll() {
|
|
24
|
+
throw new Error("exportAll() doit être implémenté");
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Mémoire
|
|
29
|
+
export class MultiServerMemoryStorageStrategy extends MultiServerTokenStorageStrategy {
|
|
30
|
+
constructor() {
|
|
31
|
+
super();
|
|
32
|
+
this._storage = new Map();
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
getAccessToken() {
|
|
36
|
+
this._ensureContext();
|
|
37
|
+
return this._storage.get(this._currentBaseURL)?.accessToken || null;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
setAccessToken(token) {
|
|
41
|
+
this._ensureContext();
|
|
42
|
+
const current = this._storage.get(this._currentBaseURL) || {};
|
|
43
|
+
this._storage.set(this._currentBaseURL, { ...current, accessToken: token });
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
getRefreshToken() {
|
|
47
|
+
this._ensureContext();
|
|
48
|
+
return this._storage.get(this._currentBaseURL)?.refreshToken || null;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
setRefreshToken(token) {
|
|
52
|
+
this._ensureContext();
|
|
53
|
+
const current = this._storage.get(this._currentBaseURL) || {};
|
|
54
|
+
this._storage.set(this._currentBaseURL, { ...current, refreshToken: token });
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
clear() {
|
|
58
|
+
this._ensureContext();
|
|
59
|
+
this._storage.delete(this._currentBaseURL);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
getServers() {
|
|
63
|
+
return [...this._storage.keys()];
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
exportAll() {
|
|
67
|
+
return Object.fromEntries(this._storage.entries());
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Navigateur (localStorage)
|
|
72
|
+
export class MultiServerLocalStorageStrategy extends MultiServerTokenStorageStrategy {
|
|
73
|
+
constructor(prefix = "cocolight") {
|
|
74
|
+
super();
|
|
75
|
+
this.prefix = prefix;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
_key(baseURL) {
|
|
79
|
+
return `${this.prefix}_tokens_${baseURL}`;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
_getData() {
|
|
83
|
+
this._ensureContext();
|
|
84
|
+
const raw = localStorage.getItem(this._key(this._currentBaseURL));
|
|
85
|
+
return raw ? JSON.parse(raw) : {};
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
_setData(data) {
|
|
89
|
+
localStorage.setItem(this._key(this._currentBaseURL), JSON.stringify(data));
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
getAccessToken() {
|
|
93
|
+
return this._getData().accessToken || null;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
setAccessToken(token) {
|
|
97
|
+
const data = this._getData();
|
|
98
|
+
data.accessToken = token;
|
|
99
|
+
this._setData(data);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
getRefreshToken() {
|
|
103
|
+
return this._getData().refreshToken || null;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
setRefreshToken(token) {
|
|
107
|
+
const data = this._getData();
|
|
108
|
+
data.refreshToken = token;
|
|
109
|
+
this._setData(data);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
clear() {
|
|
113
|
+
localStorage.removeItem(this._key(this._currentBaseURL));
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
getServers() {
|
|
117
|
+
const keys = Object.keys(localStorage);
|
|
118
|
+
return keys
|
|
119
|
+
.filter(k => k.startsWith(`${this.prefix}_tokens_`))
|
|
120
|
+
.map(k => k.replace(`${this.prefix}_tokens_`, ""));
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
exportAll() {
|
|
124
|
+
const result = {};
|
|
125
|
+
for (const baseURL of this.getServers()) {
|
|
126
|
+
const raw = localStorage.getItem(this._key(baseURL));
|
|
127
|
+
if (raw) result[baseURL] = JSON.parse(raw);
|
|
128
|
+
}
|
|
129
|
+
return result;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import {
|
|
2
|
+
MultiServerMemoryStorageStrategy,
|
|
3
|
+
MultiServerLocalStorageStrategy,
|
|
4
|
+
} from "./MultiServerTokenStorageStrategy.js";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Crée une stratégie de stockage de tokens multi-serveurs adaptée à l’environnement.
|
|
8
|
+
*
|
|
9
|
+
* @param {string} [strategyType="auto"] - Type de stockage souhaité :
|
|
10
|
+
* - "memory" : en mémoire (non persistant)
|
|
11
|
+
* - "localStorage" : navigateur uniquement
|
|
12
|
+
* - "file" : Node.js uniquement
|
|
13
|
+
* - "auto" : choisit automatiquement selon l’environnement
|
|
14
|
+
* @returns {Promise<MultiServerTokenStorageStrategy>}
|
|
15
|
+
*/
|
|
16
|
+
export async function createDefaultMultiServerTokenStorageStrategy(strategyType = "auto") {
|
|
17
|
+
if (strategyType === "memory") {
|
|
18
|
+
return new MultiServerMemoryStorageStrategy();
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (strategyType === "localStorage") {
|
|
22
|
+
if (typeof window !== "undefined" && window.localStorage) {
|
|
23
|
+
return new MultiServerLocalStorageStrategy();
|
|
24
|
+
} else {
|
|
25
|
+
throw new Error("localStorage n’est pas disponible dans cet environnement.");
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (strategyType === "file") {
|
|
30
|
+
if (typeof window !== "undefined" && window.localStorage) {
|
|
31
|
+
throw new Error("Le stockage fichier n’est pas disponible côté navigateur.");
|
|
32
|
+
}
|
|
33
|
+
const { MultiServerFileStorageStrategy } = await import("./MultiServerFileStorageStrategy.node.js");
|
|
34
|
+
return new MultiServerFileStorageStrategy();
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// stratégie "auto"
|
|
38
|
+
if (typeof window !== "undefined" && window.localStorage) {
|
|
39
|
+
return new MultiServerLocalStorageStrategy();
|
|
40
|
+
} else {
|
|
41
|
+
const { MultiServerFileStorageStrategy } = await import("./MultiServerTokenStorageStrategy.js");
|
|
42
|
+
return new MultiServerFileStorageStrategy();
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|