@wdywdy/electric-open-platform 0.0.0-stage → 1.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.
Files changed (84) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +585 -2
  3. package/dist/cjs/client.js +173 -0
  4. package/dist/cjs/client.js.map +1 -0
  5. package/dist/cjs/core/api.js +518 -0
  6. package/dist/cjs/core/api.js.map +1 -0
  7. package/dist/cjs/core/auth.js +293 -0
  8. package/dist/cjs/core/auth.js.map +1 -0
  9. package/dist/cjs/core/crypto.js +160 -0
  10. package/dist/cjs/core/crypto.js.map +1 -0
  11. package/dist/cjs/core/errors.js +114 -0
  12. package/dist/cjs/core/errors.js.map +1 -0
  13. package/dist/cjs/core/http.js +70 -0
  14. package/dist/cjs/core/http.js.map +1 -0
  15. package/dist/cjs/core/models.js +105 -0
  16. package/dist/cjs/core/models.js.map +1 -0
  17. package/dist/cjs/core/push.js +79 -0
  18. package/dist/cjs/core/push.js.map +1 -0
  19. package/dist/cjs/core/router.js +124 -0
  20. package/dist/cjs/core/router.js.map +1 -0
  21. package/dist/cjs/core/runtime.js +37 -0
  22. package/dist/cjs/core/runtime.js.map +1 -0
  23. package/dist/cjs/core/sign.js +75 -0
  24. package/dist/cjs/core/sign.js.map +1 -0
  25. package/dist/cjs/core/storage.js +152 -0
  26. package/dist/cjs/core/storage.js.map +1 -0
  27. package/dist/cjs/core/transport-fetch.js +57 -0
  28. package/dist/cjs/core/transport-fetch.js.map +1 -0
  29. package/dist/cjs/core/transport.js +41 -0
  30. package/dist/cjs/core/transport.js.map +1 -0
  31. package/dist/cjs/core/types.js +5 -0
  32. package/dist/cjs/core/types.js.map +1 -0
  33. package/dist/cjs/index.js +111 -0
  34. package/dist/cjs/index.js.map +1 -0
  35. package/dist/cjs/package.json +3 -0
  36. package/dist/esm/client.d.ts +73 -0
  37. package/dist/esm/client.js +169 -0
  38. package/dist/esm/client.js.map +1 -0
  39. package/dist/esm/core/api.d.ts +377 -0
  40. package/dist/esm/core/api.js +506 -0
  41. package/dist/esm/core/api.js.map +1 -0
  42. package/dist/esm/core/auth.d.ts +69 -0
  43. package/dist/esm/core/auth.js +289 -0
  44. package/dist/esm/core/auth.js.map +1 -0
  45. package/dist/esm/core/crypto.d.ts +24 -0
  46. package/dist/esm/core/crypto.js +154 -0
  47. package/dist/esm/core/crypto.js.map +1 -0
  48. package/dist/esm/core/errors.d.ts +86 -0
  49. package/dist/esm/core/errors.js +108 -0
  50. package/dist/esm/core/errors.js.map +1 -0
  51. package/dist/esm/core/http.d.ts +24 -0
  52. package/dist/esm/core/http.js +56 -0
  53. package/dist/esm/core/http.js.map +1 -0
  54. package/dist/esm/core/models.d.ts +441 -0
  55. package/dist/esm/core/models.js +102 -0
  56. package/dist/esm/core/models.js.map +1 -0
  57. package/dist/esm/core/push.d.ts +54 -0
  58. package/dist/esm/core/push.js +74 -0
  59. package/dist/esm/core/push.js.map +1 -0
  60. package/dist/esm/core/router.d.ts +44 -0
  61. package/dist/esm/core/router.js +120 -0
  62. package/dist/esm/core/router.js.map +1 -0
  63. package/dist/esm/core/runtime.d.ts +23 -0
  64. package/dist/esm/core/runtime.js +33 -0
  65. package/dist/esm/core/runtime.js.map +1 -0
  66. package/dist/esm/core/sign.d.ts +54 -0
  67. package/dist/esm/core/sign.js +67 -0
  68. package/dist/esm/core/sign.js.map +1 -0
  69. package/dist/esm/core/storage.d.ts +73 -0
  70. package/dist/esm/core/storage.js +141 -0
  71. package/dist/esm/core/storage.js.map +1 -0
  72. package/dist/esm/core/transport-fetch.d.ts +2 -0
  73. package/dist/esm/core/transport-fetch.js +54 -0
  74. package/dist/esm/core/transport-fetch.js.map +1 -0
  75. package/dist/esm/core/transport.d.ts +23 -0
  76. package/dist/esm/core/transport.js +36 -0
  77. package/dist/esm/core/transport.js.map +1 -0
  78. package/dist/esm/core/types.d.ts +76 -0
  79. package/dist/esm/core/types.js +2 -0
  80. package/dist/esm/core/types.js.map +1 -0
  81. package/dist/esm/index.d.ts +37 -0
  82. package/dist/esm/index.js +47 -0
  83. package/dist/esm/index.js.map +1 -0
  84. package/package.json +63 -4
@@ -0,0 +1,289 @@
1
+ /**
2
+ * OAuth2 lifecycle for the open platform.
3
+ *
4
+ * Two ways to obtain a token, both documented:
5
+ * 1. Redirect flow (`/oauth/authorize.as?client_id=…&response_type=code`) for a
6
+ * full web-login experience — the host app receives `?code=` and calls
7
+ * {@link AuthManager.exchangeCode}.
8
+ * 2. Headless flow (`POST /oauth/authverify2.as` with `uname`/`passwd`) — used
9
+ * by the plugin's `login()` convenience method.
10
+ *
11
+ * Once a token exists it is kept warm with the refresh endpoint, so a background
12
+ * poller never has to handle expiry itself.
13
+ */
14
+ import { ElectricOpenPlatformError, PlatformCodes, TransportCodes } from './errors.js';
15
+ import { postForm } from './http.js';
16
+ import { encodeForm, signAuthCodeSecret, signRefreshSecret } from './sign.js';
17
+ import { DEFAULT_BASE_URL } from './types.js';
18
+ const MIN_EXPIRES_IN_SECONDS = 60;
19
+ export class AuthManager {
20
+ constructor(store, config) {
21
+ this.tokens = null;
22
+ this.inflight = null;
23
+ this.timer = null;
24
+ this.store = store;
25
+ this.logger = config.logger;
26
+ this.config = {
27
+ appKey: config.appKey,
28
+ appSecret: config.appSecret,
29
+ redirectUri: config.redirectUri,
30
+ baseUrl: (config.baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, ''),
31
+ timeoutMs: config.timeoutMs ?? 20000,
32
+ tokenRefreshSkewMs: config.tokenRefreshSkewMs ?? 60000,
33
+ };
34
+ }
35
+ /** Hydrates tokens persisted by a previous app session. */
36
+ async restore() {
37
+ const saved = await this.store.readTokens();
38
+ if (saved && saved.accessToken) {
39
+ this.tokens = saved;
40
+ if (!this.isExpired(saved))
41
+ this.scheduleRefresh();
42
+ else
43
+ this.tokens = null;
44
+ return this.tokens;
45
+ }
46
+ return null;
47
+ }
48
+ get current() {
49
+ return this.tokens;
50
+ }
51
+ /** The redirect-flow login URL, for opening in a browser / InAppBrowser. */
52
+ getAuthorizeUrl(options = {}) {
53
+ const qs = encodeForm({
54
+ client_id: this.config.appKey,
55
+ response_type: 'code',
56
+ redirect_uri: this.config.redirectUri,
57
+ ...(options.state ? { state: options.state } : {}),
58
+ });
59
+ return `${this.config.baseUrl}/oauth/authorize.as?${qs}`;
60
+ }
61
+ /** Extracts `code` from a redirect URL such as `http://host/receive?code=abc`. */
62
+ static extractCode(url) {
63
+ const match = /[?&#]code=([^&#]+)/.exec(url);
64
+ return match ? decodeURIComponent(match[1]) : null;
65
+ }
66
+ /** Step 1 of the headless flow: POST `/oauth/authverify2.as` for a temporary code. */
67
+ async fetchCode(credentials) {
68
+ const body = encodeForm({
69
+ response_type: 'code',
70
+ client_id: this.config.appKey,
71
+ redirect_uri: this.config.redirectUri,
72
+ uname: credentials.username,
73
+ passwd: credentials.password,
74
+ });
75
+ const res = await postForm({
76
+ url: `${this.config.baseUrl}/oauth/authverify2.as`,
77
+ body,
78
+ timeoutMs: this.config.timeoutMs,
79
+ });
80
+ const payload = res.data;
81
+ if (!payload || typeof payload !== 'object' || !payload.code || String(payload.success) !== 'true') {
82
+ throw new ElectricOpenPlatformError(TransportCodes.OAUTH, `获取授权码失败:${(payload && payload.message) || '账号或密码不正确'}`, { details: res.data });
83
+ }
84
+ this.logger?.({ type: 'token', message: '已获取临时授权码 code', at: new Date().toISOString() });
85
+ return payload.code;
86
+ }
87
+ /**
88
+ * Steps 1+2 in one call: headless login with username/password, then store the token.
89
+ * Concurrent calls share the same in-flight handshake.
90
+ */
91
+ async loginWithPassword(username, password) {
92
+ const code = await this.fetchCode({ username, password });
93
+ return this.exchangeCode(code);
94
+ }
95
+ /** Step 2: exchange a code for an access token (`POST /oauth/token.as`). */
96
+ async exchangeCode(code) {
97
+ if (this.inflight)
98
+ return this.inflight;
99
+ this.inflight = this.doExchangeCode(code).finally(() => {
100
+ this.inflight = null;
101
+ });
102
+ return this.inflight;
103
+ }
104
+ async doExchangeCode(code) {
105
+ const clientSecret = signAuthCodeSecret({
106
+ appKey: this.config.appKey,
107
+ appSecret: this.config.appSecret,
108
+ redirectUri: this.config.redirectUri,
109
+ code,
110
+ });
111
+ const body = encodeForm({
112
+ client_id: this.config.appKey,
113
+ client_secret: clientSecret,
114
+ grant_type: 'authorization_code',
115
+ redirect_uri: this.config.redirectUri,
116
+ code,
117
+ });
118
+ const res = await postForm({
119
+ url: `${this.config.baseUrl}/oauth/token.as`,
120
+ body,
121
+ timeoutMs: this.config.timeoutMs,
122
+ });
123
+ return this.absorb(res.data, 'accessToken');
124
+ }
125
+ /**
126
+ * Returns a usable access token, renewing it first when it is within the skew
127
+ * window. Falls back to a full re-login when the refresh token is gone.
128
+ */
129
+ async getAccessToken(credentials) {
130
+ if (this.tokens && !this.isExpired(this.tokens))
131
+ return this.tokens.accessToken;
132
+ if (this.inflight)
133
+ return (await this.inflight).accessToken;
134
+ if (this.tokens?.refreshToken) {
135
+ try {
136
+ return (await this.refresh()).accessToken;
137
+ }
138
+ catch (err) {
139
+ // A dead refresh token is indistinguishable from an expired session;
140
+ // drop it and fall through to a full login when credentials exist.
141
+ this.emit('error', `刷新 accessToken 失败:${err.message}`);
142
+ this.tokens = null;
143
+ }
144
+ }
145
+ if (credentials?.username && credentials.password) {
146
+ return (await this.loginWithPassword(credentials.username, credentials.password)).accessToken;
147
+ }
148
+ throw new ElectricOpenPlatformError(TransportCodes.NOT_CONFIGURED, 'accessToken 已过期,请重新登录');
149
+ }
150
+ /** `POST /oauth/refresh.as` */
151
+ async refresh() {
152
+ if (this.inflight)
153
+ return this.inflight;
154
+ this.inflight = this.doRefresh().finally(() => {
155
+ this.inflight = null;
156
+ });
157
+ return this.inflight;
158
+ }
159
+ async doRefresh() {
160
+ const refreshToken = this.tokens?.refreshToken;
161
+ if (!refreshToken) {
162
+ throw new ElectricOpenPlatformError(TransportCodes.OAUTH, '缺少 refreshToken,无法刷新');
163
+ }
164
+ const clientSecret = signRefreshSecret({
165
+ appKey: this.config.appKey,
166
+ appSecret: this.config.appSecret,
167
+ redirectUri: this.config.redirectUri,
168
+ refreshToken,
169
+ });
170
+ const body = encodeForm({
171
+ client_id: this.config.appKey,
172
+ client_secret: clientSecret,
173
+ grant_type: 'refresh_token',
174
+ redirect_uri: this.config.redirectUri,
175
+ refresh_token: refreshToken,
176
+ });
177
+ const res = await postForm({
178
+ url: `${this.config.baseUrl}/oauth/refresh.as`,
179
+ body,
180
+ timeoutMs: this.config.timeoutMs,
181
+ });
182
+ return this.absorb(res.data, 'refresh');
183
+ }
184
+ /** Invalidates the platform-side session? No such endpoint exists — clear locally. */
185
+ async logout() {
186
+ this.tokens = null;
187
+ this.clearTimer();
188
+ await this.store.clear();
189
+ this.emit('token', '已清除本地授权');
190
+ }
191
+ /**
192
+ * Converts a platform "token invalid" answer into a fresh access token.
193
+ *
194
+ * Prefers the refresh token (no credential round-trip); falls back to a full
195
+ * headless login when credentials were configured.
196
+ */
197
+ async recover(credentials) {
198
+ if (this.tokens?.refreshToken) {
199
+ try {
200
+ return (await this.refresh()).accessToken;
201
+ }
202
+ catch (err) {
203
+ this.emit('error', `refresh 失败,改用账号密码重新登录:${err.message}`);
204
+ }
205
+ }
206
+ if (credentials?.username && credentials.password) {
207
+ return (await this.loginWithPassword(credentials.username, credentials.password)).accessToken;
208
+ }
209
+ await this.invalidate();
210
+ throw new ElectricOpenPlatformError(TransportCodes.NOT_CONFIGURED, '会话已失效,请重新登录');
211
+ }
212
+ /** Called by the client after the platform answers with code `"2"`. */
213
+ async invalidate() {
214
+ this.tokens = null;
215
+ this.clearTimer();
216
+ await this.store.clear();
217
+ }
218
+ dispose() {
219
+ this.clearTimer();
220
+ }
221
+ absorb(payload, origin) {
222
+ const envelope = payload;
223
+ if (!envelope || typeof envelope !== 'object' || !envelope.data) {
224
+ throw new ElectricOpenPlatformError(TransportCodes.OAUTH, '授权响应格式异常', { details: payload });
225
+ }
226
+ if (envelope.code !== undefined && envelope.code !== PlatformCodes.OK) {
227
+ throw new ElectricOpenPlatformError(envelope.code, envelope.message || '授权失败', {
228
+ details: payload,
229
+ });
230
+ }
231
+ const d = envelope.data;
232
+ const accessToken = d.accessToken ?? d.access_token;
233
+ const refreshToken = d.refreshToken ?? d.refresh_token ?? '';
234
+ const rawExpires = d.expiresIn ?? d.expires_in;
235
+ const expiresIn = Number(rawExpires ?? 3600);
236
+ if (!accessToken) {
237
+ throw new ElectricOpenPlatformError(TransportCodes.OAUTH, '授权响应中缺少 accessToken', {
238
+ details: payload,
239
+ });
240
+ }
241
+ const ttlSeconds = Number.isFinite(expiresIn) && expiresIn > 0 ? expiresIn : 3600;
242
+ const tokens = {
243
+ accessToken,
244
+ refreshToken,
245
+ tokenType: (d.tokenType ?? 'BEARER').toUpperCase(),
246
+ expiresAt: Date.now() + Math.max(ttlSeconds, MIN_EXPIRES_IN_SECONDS) * 1000,
247
+ };
248
+ this.tokens = tokens;
249
+ this.scheduleRefresh();
250
+ void this.store.writeTokens(tokens);
251
+ this.emit('token', origin === 'refresh' ? 'accessToken 已刷新' : 'accessToken 已获取', {
252
+ expiresIn: ttlSeconds,
253
+ });
254
+ return tokens;
255
+ }
256
+ isExpired(tokens) {
257
+ return tokens.expiresAt - this.config.tokenRefreshSkewMs <= Date.now();
258
+ }
259
+ /**
260
+ * Proactively refreshes shortly before expiry so that a 60 s poller never
261
+ * hits code `"2"`. Browsers throttle long timers, so the client *also* checks
262
+ * lazily on every request — belt and braces.
263
+ */
264
+ scheduleRefresh() {
265
+ this.clearTimer();
266
+ if (!this.tokens?.refreshToken)
267
+ return;
268
+ const delay = this.tokens.expiresAt - this.config.tokenRefreshSkewMs - Date.now();
269
+ if (delay <= 0 || delay > 2 ** 31 - 1)
270
+ return;
271
+ this.timer = setTimeout(() => {
272
+ this.refresh().catch((err) => {
273
+ this.emit('error', `定时刷新失败:${err.message}`);
274
+ });
275
+ }, delay);
276
+ // Node/SSR safety: an unref'd timer must not keep the test process alive.
277
+ this.timer.unref?.();
278
+ }
279
+ clearTimer() {
280
+ if (this.timer) {
281
+ clearTimeout(this.timer);
282
+ this.timer = null;
283
+ }
284
+ }
285
+ emit(type, message, detail) {
286
+ this.logger?.({ type, message, detail, at: new Date().toISOString() });
287
+ }
288
+ }
289
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../../src/core/auth.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Small, dependency-free crypto/time helpers.
3
+ *
4
+ * The plugin must stay framework free (no node:crypto, no js-sha1) because the
5
+ * exact same code runs inside a WebView, in the Vite demo page and in Node
6
+ * based unit tests.
7
+ */
8
+ /**
9
+ * MD5 of the UTF-8 encoding of `input`, lowercase hex (32 chars).
10
+ *
11
+ * The platform specifies MD5 over the UTF-8 byte stream (see the Java reference
12
+ * implementation in the docs: `md.update(param.getBytes("utf-8"))`), so the
13
+ * conversion below must be done on UTF-8 bytes, not on code units.
14
+ */
15
+ export declare function md5(input: string): string;
16
+ /**
17
+ * The platform's `timestamp` parameter: `yyyyMMddHHmmss` in **local time**
18
+ * (the docs say "当前时间截"), padded to two digits.
19
+ */
20
+ export declare function formatTimestamp(date?: Date): string;
21
+ /** Local `yyyy-MM-dd HH:mm` — the format GET_BOX_ALARM expects for start/end. */
22
+ export declare function formatAlarmTime(date: Date): string;
23
+ /** A stable, deterministic non-cryptographic id used for request correlation. */
24
+ export declare function randomId(length?: number): string;
@@ -0,0 +1,154 @@
1
+ /**
2
+ * Small, dependency-free crypto/time helpers.
3
+ *
4
+ * The plugin must stay framework free (no node:crypto, no js-sha1) because the
5
+ * exact same code runs inside a WebView, in the Vite demo page and in Node
6
+ * based unit tests.
7
+ */
8
+ const HEX = '0123456789abcdef';
9
+ /**
10
+ * MD5 of the UTF-8 encoding of `input`, lowercase hex (32 chars).
11
+ *
12
+ * The platform specifies MD5 over the UTF-8 byte stream (see the Java reference
13
+ * implementation in the docs: `md.update(param.getBytes("utf-8"))`), so the
14
+ * conversion below must be done on UTF-8 bytes, not on code units.
15
+ */
16
+ export function md5(input) {
17
+ const bytes = utf8Bytes(input);
18
+ const words = toWords(bytes);
19
+ const digest = md5Words(words, bytes.length);
20
+ let out = '';
21
+ for (let i = 0; i < 4; i++) {
22
+ const word = digest[i];
23
+ for (let j = 0; j < 4; j++) {
24
+ out += HEX.charAt((word >>> (j * 8 + 4)) & 0x0f);
25
+ out += HEX.charAt((word >>> (j * 8)) & 0x0f);
26
+ }
27
+ }
28
+ return out;
29
+ }
30
+ function utf8Bytes(input) {
31
+ const out = [];
32
+ for (let i = 0; i < input.length; i++) {
33
+ let cp = input.charCodeAt(i);
34
+ if (cp >= 0xd800 && cp <= 0xdbff && i + 1 < input.length) {
35
+ const next = input.charCodeAt(i + 1);
36
+ if (next >= 0xdc00 && next <= 0xdfff) {
37
+ cp = ((cp - 0xd800) << 10) + (next - 0xdc00) + 0x10000;
38
+ i++;
39
+ }
40
+ }
41
+ if (cp < 0x80) {
42
+ out.push(cp);
43
+ }
44
+ else if (cp < 0x800) {
45
+ out.push(0xc0 | (cp >> 6), 0x80 | (cp & 0x3f));
46
+ }
47
+ else if (cp < 0x10000) {
48
+ out.push(0xe0 | (cp >> 12), 0x80 | ((cp >> 6) & 0x3f), 0x80 | (cp & 0x3f));
49
+ }
50
+ else {
51
+ out.push(0xf0 | (cp >> 18), 0x80 | ((cp >> 12) & 0x3f), 0x80 | ((cp >> 6) & 0x3f), 0x80 | (cp & 0x3f));
52
+ }
53
+ }
54
+ return out;
55
+ }
56
+ function toWords(bytes) {
57
+ const bitLen = bytes.length * 8;
58
+ const withPadding = bytes.slice();
59
+ withPadding.push(0x80);
60
+ while (withPadding.length % 64 !== 56)
61
+ withPadding.push(0);
62
+ // 64-bit little-endian length; JS numbers stop being exact above 2^53, which
63
+ // is far beyond any string we would ever sign.
64
+ withPadding.push(bitLen & 0xff, (bitLen >>> 8) & 0xff, (bitLen >>> 16) & 0xff, (bitLen >>> 24) & 0xff);
65
+ withPadding.push(0, 0, 0, 0);
66
+ const words = [];
67
+ for (let i = 0; i < withPadding.length; i += 4) {
68
+ words.push(withPadding[i] | (withPadding[i + 1] << 8) | (withPadding[i + 2] << 16) | (withPadding[i + 3] << 24));
69
+ }
70
+ return words;
71
+ }
72
+ const S = [
73
+ 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9,
74
+ 14, 20, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15,
75
+ 21, 6, 10, 15, 21,
76
+ ];
77
+ const K = (() => {
78
+ const k = [];
79
+ for (let i = 0; i < 64; i++)
80
+ k.push(Math.floor(Math.abs(Math.sin(i + 1)) * 0x100000000) | 0);
81
+ return k;
82
+ })();
83
+ function md5Words(words, byteLen) {
84
+ let a0 = 0x67452301;
85
+ let b0 = 0xefcdab89;
86
+ let c0 = 0x98badcfe;
87
+ let d0 = 0x10325476;
88
+ for (let chunk = 0; chunk < words.length; chunk += 16) {
89
+ const M = words.slice(chunk, chunk + 16);
90
+ let A = a0;
91
+ let B = b0;
92
+ let C = c0;
93
+ let D = d0;
94
+ for (let i = 0; i < 64; i++) {
95
+ let F;
96
+ let g;
97
+ if (i < 16) {
98
+ F = (B & C) | (~B & D);
99
+ g = i;
100
+ }
101
+ else if (i < 32) {
102
+ F = (D & B) | (~D & C);
103
+ g = (5 * i + 1) % 16;
104
+ }
105
+ else if (i < 48) {
106
+ F = B ^ C ^ D;
107
+ g = (3 * i + 5) % 16;
108
+ }
109
+ else {
110
+ F = C ^ (B | ~D);
111
+ g = (7 * i) % 16;
112
+ }
113
+ F = (F + A + K[i] + M[g]) | 0;
114
+ A = D;
115
+ D = C;
116
+ C = B;
117
+ B = (B + ((F << S[i]) | (F >>> (32 - S[i])))) | 0;
118
+ }
119
+ a0 = (a0 + A) | 0;
120
+ b0 = (b0 + B) | 0;
121
+ c0 = (c0 + C) | 0;
122
+ d0 = (d0 + D) | 0;
123
+ }
124
+ void byteLen;
125
+ return [a0, b0, c0, d0];
126
+ }
127
+ /**
128
+ * The platform's `timestamp` parameter: `yyyyMMddHHmmss` in **local time**
129
+ * (the docs say "当前时间截"), padded to two digits.
130
+ */
131
+ export function formatTimestamp(date = new Date()) {
132
+ const pad = (n) => String(n).padStart(2, '0');
133
+ return (String(date.getFullYear()) +
134
+ pad(date.getMonth() + 1) +
135
+ pad(date.getDate()) +
136
+ pad(date.getHours()) +
137
+ pad(date.getMinutes()) +
138
+ pad(date.getSeconds()));
139
+ }
140
+ /** Local `yyyy-MM-dd HH:mm` — the format GET_BOX_ALARM expects for start/end. */
141
+ export function formatAlarmTime(date) {
142
+ const pad = (n) => String(n).padStart(2, '0');
143
+ return (`${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}` +
144
+ ` ${pad(date.getHours())}:${pad(date.getMinutes())}`);
145
+ }
146
+ /** A stable, deterministic non-cryptographic id used for request correlation. */
147
+ export function randomId(length = 12) {
148
+ let out = '';
149
+ const alphabet = 'abcdefghijklmnopqrstuvwxyz0123456789';
150
+ for (let i = 0; i < length; i++)
151
+ out += alphabet.charAt(Math.floor(Math.random() * alphabet.length));
152
+ return out;
153
+ }
154
+ //# sourceMappingURL=crypto.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crypto.js","sourceRoot":"","sources":["../../../src/core/crypto.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,86 @@
1
+ /**
2
+ * Error model for the Mtsci (snd02) open platform.
3
+ *
4
+ * Every failure — transport, OAuth or business return code — surfaces as an
5
+ * `ElectricOpenPlatformError` so callers can branch on `code` instead of
6
+ * parsing `message` strings.
7
+ */
8
+ export declare const PlatformCodes: {
9
+ readonly OK: "0";
10
+ readonly NOT_LOGGED_IN: "-1";
11
+ readonly FAILED: "1";
12
+ readonly TOKEN_EXPIRED: "2";
13
+ readonly BOX_OFFLINE: "1001";
14
+ readonly ILLEGAL_PARAM: "1002";
15
+ readonly ILLEGAL_OWNERSHIP: "1003";
16
+ readonly REMOTE_CONTROL_FORBIDDEN: "1004";
17
+ readonly INCOMPLETE_PROPERTY: "1005";
18
+ readonly VERIFY_FAILED: "1006";
19
+ readonly ALREADY_EXISTS: "1007";
20
+ readonly NOT_FOUND: "1008";
21
+ readonly OVER_LIMIT: "1009";
22
+ readonly DUPLICATE_OPERATION: "1010";
23
+ };
24
+ export type PlatformCode = (typeof PlatformCodes)[keyof typeof PlatformCodes] | string;
25
+ /** Failure classes that never come from the platform itself. */
26
+ export declare const TransportCodes: {
27
+ /** The device could not reach the server at all. */
28
+ readonly NETWORK: "E_NETWORK";
29
+ /** The server answered with a non-2xx status. */
30
+ readonly HTTP: "E_HTTP";
31
+ /** Response body was not the expected JSON envelope. */
32
+ readonly PARSE: "E_PARSE";
33
+ /** The plugin was used before `configure()` / `login()`. */
34
+ readonly NOT_CONFIGURED: "E_NOT_CONFIGURED";
35
+ /** Local guard rail rejected the call before hitting the network. */
36
+ readonly INVALID_ARGUMENT: "E_INVALID_ARGUMENT";
37
+ /** OAuth handshake (authverify2 / token / refresh) failed. */
38
+ readonly OAUTH: "E_OAUTH";
39
+ /** Daily per-interface quota exhausted (platform rejects with "限额"). */
40
+ readonly QUOTA: "E_QUOTA";
41
+ /**
42
+ * The method exists but this appKey is not authorized for it.
43
+ *
44
+ * The platform reports unprovisioned methods in two misleading ways:
45
+ * - `接口名称(X)无效!`
46
+ * - `无效的接口方法参数签名!` — which looks like a signing bug but, verified
47
+ * against the live server, is what you get for a method that is not
48
+ * enabled for the key. Only treat it as this code when the same key's
49
+ * other calls succeed, which the client knows.
50
+ */
51
+ readonly NOT_PROVISIONED: "E_NOT_PROVISIONED";
52
+ /** The call was aborted by the caller (AbortSignal). */
53
+ readonly ABORTED: "E_ABORTED";
54
+ };
55
+ export type TransportCode = (typeof TransportCodes)[keyof typeof TransportCodes];
56
+ export declare class ElectricOpenPlatformError extends Error {
57
+ /** Platform business code (`"0"`, `"1"`, `"2"`, `"1001"`…) or a `TransportCodes` value. */
58
+ readonly code: PlatformCode;
59
+ /** The `method` that failed, when the failure happened during a router call. */
60
+ readonly method?: string;
61
+ /** Raw server payload, kept for logging / bug reports. */
62
+ readonly details?: unknown;
63
+ /** HTTP status, when the failure happened at the transport layer. */
64
+ readonly httpStatus?: number;
65
+ constructor(code: PlatformCode, message?: string, options?: {
66
+ method?: string;
67
+ details?: unknown;
68
+ httpStatus?: number;
69
+ cause?: unknown;
70
+ });
71
+ /** True when the platform says the access token must be renewed. */
72
+ get isTokenExpired(): boolean;
73
+ /** True when a retry after a short delay is likely to succeed. */
74
+ get isRetryable(): boolean;
75
+ toJSON(): {
76
+ name: string;
77
+ code: string;
78
+ message: string;
79
+ method: string | undefined;
80
+ httpStatus: number | undefined;
81
+ details: unknown;
82
+ };
83
+ }
84
+ export declare function isElectricOpenPlatformError(e: unknown): e is ElectricOpenPlatformError;
85
+ /** Human readable Chinese description for a platform code. */
86
+ export declare function describeCode(code: PlatformCode): string;