iotas-ts 0.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/LICENSE +674 -0
- package/dist/src/api/iotasClient.d.ts +27 -0
- package/dist/src/api/iotasClient.js +123 -0
- package/dist/src/api/iotasClient.js.map +1 -0
- package/dist/src/api/jwt.d.ts +7 -0
- package/dist/src/api/jwt.js +13 -0
- package/dist/src/api/jwt.js.map +1 -0
- package/dist/src/api/session.d.ts +43 -0
- package/dist/src/api/session.js +137 -0
- package/dist/src/api/session.js.map +1 -0
- package/dist/src/api/transport.d.ts +21 -0
- package/dist/src/api/transport.js +49 -0
- package/dist/src/api/transport.js.map +1 -0
- package/dist/src/cache/featureCache.d.ts +55 -0
- package/dist/src/cache/featureCache.js +180 -0
- package/dist/src/cache/featureCache.js.map +1 -0
- package/dist/src/index.d.ts +6 -0
- package/dist/src/index.js +7 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/logger.d.ts +12 -0
- package/dist/src/logger.js +2 -0
- package/dist/src/logger.js.map +1 -0
- package/dist/src/types.d.ts +148 -0
- package/dist/src/types.js +2 -0
- package/dist/src/types.js.map +1 -0
- package/dist/src/utils.d.ts +4 -0
- package/dist/src/utils.js +5 -0
- package/dist/src/utils.js.map +1 -0
- package/package.json +59 -0
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
const DEFAULT_POLL_INTERVAL_MS = 30_000;
|
|
2
|
+
const DEFAULT_WRITE_BARRIER_MS = 5_000;
|
|
3
|
+
const DEFAULT_POLL_BACKOFF_BASE_MS = 5_000;
|
|
4
|
+
const DEFAULT_POLL_BACKOFF_MAX_MS = 300_000; // 5 minutes max
|
|
5
|
+
/**
|
|
6
|
+
* FeatureCache provides cached feature values with background polling.
|
|
7
|
+
*
|
|
8
|
+
* - Seeded from discovery snapshot (no cold-start defaults)
|
|
9
|
+
* - Single getRooms() call per poll cycle
|
|
10
|
+
* - Write barrier prevents stale poll data overwriting recent onSet
|
|
11
|
+
* - Subscription model for pushing updates via updateValue
|
|
12
|
+
*/
|
|
13
|
+
export class FeatureCache {
|
|
14
|
+
log;
|
|
15
|
+
client;
|
|
16
|
+
values = new Map();
|
|
17
|
+
writeTimestamps = new Map();
|
|
18
|
+
subscriptions = new Set();
|
|
19
|
+
pollTimer = null;
|
|
20
|
+
consecutiveFailures = 0;
|
|
21
|
+
stopped = false;
|
|
22
|
+
pollIntervalMs;
|
|
23
|
+
writeBarrierMs;
|
|
24
|
+
pollBackoffBaseMs;
|
|
25
|
+
pollBackoffMaxMs;
|
|
26
|
+
constructor(log, client, options) {
|
|
27
|
+
this.log = log;
|
|
28
|
+
this.client = client;
|
|
29
|
+
this.pollIntervalMs = options?.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS;
|
|
30
|
+
this.writeBarrierMs = options?.writeBarrierMs ?? DEFAULT_WRITE_BARRIER_MS;
|
|
31
|
+
this.pollBackoffBaseMs = options?.pollBackoffBaseMs ?? DEFAULT_POLL_BACKOFF_BASE_MS;
|
|
32
|
+
this.pollBackoffMaxMs = options?.pollBackoffMaxMs ?? DEFAULT_POLL_BACKOFF_MAX_MS;
|
|
33
|
+
}
|
|
34
|
+
seed(rooms) {
|
|
35
|
+
for (const room of rooms) {
|
|
36
|
+
for (const device of room.devices) {
|
|
37
|
+
for (const feature of device.features) {
|
|
38
|
+
if (feature.value !== undefined) {
|
|
39
|
+
this.values.set(feature.id.toString(), feature.value);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
this.log.debug(`FeatureCache seeded with ${this.values.size} feature values`);
|
|
45
|
+
}
|
|
46
|
+
get(featureId) {
|
|
47
|
+
return this.values.get(featureId);
|
|
48
|
+
}
|
|
49
|
+
set(featureId, value) {
|
|
50
|
+
this.values.set(featureId, value);
|
|
51
|
+
this.writeTimestamps.set(featureId, Date.now());
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Subscribe to feature changes. Callback is invoked when any of the
|
|
55
|
+
* specified features are updated by the poller.
|
|
56
|
+
* Returns a dispose function to unsubscribe.
|
|
57
|
+
*/
|
|
58
|
+
subscribe(featureIds, callback) {
|
|
59
|
+
const subscription = {
|
|
60
|
+
featureIds: new Set(featureIds),
|
|
61
|
+
callback,
|
|
62
|
+
};
|
|
63
|
+
this.subscriptions.add(subscription);
|
|
64
|
+
return () => {
|
|
65
|
+
this.subscriptions.delete(subscription);
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
start() {
|
|
69
|
+
if (this.stopped || this.pollTimer !== null) {
|
|
70
|
+
return; // Already running or stopped
|
|
71
|
+
}
|
|
72
|
+
this.log.debug('FeatureCache polling started');
|
|
73
|
+
this.schedulePoll(this.pollIntervalMs);
|
|
74
|
+
}
|
|
75
|
+
stop() {
|
|
76
|
+
this.stopped = true;
|
|
77
|
+
if (this.pollTimer) {
|
|
78
|
+
clearTimeout(this.pollTimer);
|
|
79
|
+
this.pollTimer = null;
|
|
80
|
+
}
|
|
81
|
+
this.consecutiveFailures = 0;
|
|
82
|
+
this.log.debug('FeatureCache polling stopped');
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Reset for a fresh start (used when re-discovering devices).
|
|
86
|
+
*
|
|
87
|
+
* This clears all cached values, write timestamps, and subscriptions.
|
|
88
|
+
* Callers must re-register subscriptions after calling reset().
|
|
89
|
+
*
|
|
90
|
+
* Expected call order:
|
|
91
|
+
* 1) reset()
|
|
92
|
+
* 2) seed(rooms)
|
|
93
|
+
* 3) recreate accessory runtimes (which re-subscribe)
|
|
94
|
+
* 4) start()
|
|
95
|
+
*/
|
|
96
|
+
reset() {
|
|
97
|
+
this.stop();
|
|
98
|
+
this.stopped = false;
|
|
99
|
+
this.values.clear();
|
|
100
|
+
this.writeTimestamps.clear();
|
|
101
|
+
this.subscriptions.clear();
|
|
102
|
+
}
|
|
103
|
+
schedulePoll(delayMs) {
|
|
104
|
+
if (this.stopped) {
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
this.pollTimer = setTimeout(() => this.poll(), delayMs);
|
|
108
|
+
}
|
|
109
|
+
async poll() {
|
|
110
|
+
if (this.stopped) {
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
try {
|
|
114
|
+
const rooms = await this.client.getRooms();
|
|
115
|
+
this.updateFromSnapshot(rooms);
|
|
116
|
+
this.consecutiveFailures = 0;
|
|
117
|
+
this.schedulePoll(this.pollIntervalMs);
|
|
118
|
+
}
|
|
119
|
+
catch (error) {
|
|
120
|
+
this.consecutiveFailures++;
|
|
121
|
+
const backoffMs = Math.min(this.pollBackoffBaseMs * Math.pow(2, this.consecutiveFailures - 1), this.pollBackoffMaxMs);
|
|
122
|
+
this.log.error(`FeatureCache poll failed (attempt ${this.consecutiveFailures}), retrying in ${backoffMs / 1000}s:`, error);
|
|
123
|
+
this.schedulePoll(backoffMs);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
updateFromSnapshot(rooms) {
|
|
127
|
+
const now = Date.now();
|
|
128
|
+
const changedFeatureIds = new Set();
|
|
129
|
+
for (const room of rooms) {
|
|
130
|
+
for (const device of room.devices) {
|
|
131
|
+
for (const feature of device.features) {
|
|
132
|
+
if (feature.value === undefined) {
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
const featureId = feature.id.toString();
|
|
136
|
+
const lastWrite = this.writeTimestamps.get(featureId) ?? 0;
|
|
137
|
+
// Skip if within write barrier window
|
|
138
|
+
if (now - lastWrite < this.writeBarrierMs) {
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
// Clear expired write timestamp
|
|
142
|
+
if (this.writeTimestamps.has(featureId)) {
|
|
143
|
+
this.writeTimestamps.delete(featureId);
|
|
144
|
+
}
|
|
145
|
+
const oldValue = this.values.get(featureId);
|
|
146
|
+
if (oldValue !== feature.value) {
|
|
147
|
+
this.values.set(featureId, feature.value);
|
|
148
|
+
changedFeatureIds.add(featureId);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
// Notify subscribers of changed features
|
|
154
|
+
if (changedFeatureIds.size > 0) {
|
|
155
|
+
this.notifySubscribers(changedFeatureIds);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
notifySubscribers(changedFeatureIds) {
|
|
159
|
+
for (const subscription of this.subscriptions) {
|
|
160
|
+
const changed = new Map();
|
|
161
|
+
for (const id of subscription.featureIds) {
|
|
162
|
+
if (changedFeatureIds.has(id)) {
|
|
163
|
+
const value = this.values.get(id);
|
|
164
|
+
if (value !== undefined) {
|
|
165
|
+
changed.set(id, value);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
if (changed.size > 0) {
|
|
170
|
+
try {
|
|
171
|
+
subscription.callback(changed);
|
|
172
|
+
}
|
|
173
|
+
catch (error) {
|
|
174
|
+
this.log.error('FeatureCache subscription callback error:', error);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
//# sourceMappingURL=featureCache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"featureCache.js","sourceRoot":"","sources":["../../../src/cache/featureCache.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export type { IotasLogger } from './logger.js';
|
|
2
|
+
export { IotasClient } from './api/iotasClient.js';
|
|
3
|
+
export { FeatureCache } from './cache/featureCache.js';
|
|
4
|
+
export type { FeatureChangeCallback } from './cache/featureCache.js';
|
|
5
|
+
export type { Room, Rooms, Device, Feature, Residency, AuthResponse, AccountResponse, PhysicalDeviceDescription, IotasClientOptions, IotasTokens, FeatureCacheOptions, } from './types.js';
|
|
6
|
+
export { Temperature } from './utils.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAGA,aAAa;AACb,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAEnD,UAAU;AACV,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAkBvD,YAAY;AACZ,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Platform-agnostic logger interface.
|
|
3
|
+
*
|
|
4
|
+
* Both Homebridge's `Logging` and Matterbridge's `AnsiLogger`
|
|
5
|
+
* implement these methods natively, so no adapter is needed.
|
|
6
|
+
*/
|
|
7
|
+
export interface IotasLogger {
|
|
8
|
+
info(message: string, ...args: unknown[]): void;
|
|
9
|
+
warn(message: string, ...args: unknown[]): void;
|
|
10
|
+
error(message: string, ...args: unknown[]): void;
|
|
11
|
+
debug(message: string, ...args: unknown[]): void;
|
|
12
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/logger.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import type { IotasLogger } from './logger.js';
|
|
2
|
+
export type Rooms = Room[];
|
|
3
|
+
export interface IotasTokens {
|
|
4
|
+
jwt: string;
|
|
5
|
+
refresh: string;
|
|
6
|
+
}
|
|
7
|
+
export interface IotasClientOptions {
|
|
8
|
+
log: IotasLogger;
|
|
9
|
+
email: string;
|
|
10
|
+
unitName?: string;
|
|
11
|
+
authenticate: () => Promise<{
|
|
12
|
+
username: string;
|
|
13
|
+
password: string;
|
|
14
|
+
}>;
|
|
15
|
+
onTokensChanged?: (tokens: IotasTokens) => void;
|
|
16
|
+
initialTokens?: IotasTokens;
|
|
17
|
+
/** Base URL for the IOTAS API. Default: 'https://api.iotashome.com/api/v1' */
|
|
18
|
+
baseUrl?: string;
|
|
19
|
+
/** Auth retry delays in ms (one entry per retry). Default: [60_000, 300_000, 600_000] */
|
|
20
|
+
authRetryDelaysMs?: number[];
|
|
21
|
+
/** Max 401 retries per request before failing. Default: 1 */
|
|
22
|
+
maxRequestAuthRetries?: number;
|
|
23
|
+
/** Config for redundant feature updates (Z-Wave reliability). */
|
|
24
|
+
reliableUpdate?: {
|
|
25
|
+
/** Number of redundant PUT calls. Default: 3 */
|
|
26
|
+
attempts?: number;
|
|
27
|
+
/** Delay between redundant calls in ms. Default: 500 */
|
|
28
|
+
delayMs?: number;
|
|
29
|
+
};
|
|
30
|
+
/** Injected fetch function for testing. Default: globalThis.fetch */
|
|
31
|
+
fetch?: typeof fetch;
|
|
32
|
+
/** Injected delay function for testing. Default: setTimeout-based sleep */
|
|
33
|
+
delay?: (ms: number) => Promise<void>;
|
|
34
|
+
}
|
|
35
|
+
export interface FeatureCacheOptions {
|
|
36
|
+
/** Polling interval in ms. Default: 30_000 */
|
|
37
|
+
pollIntervalMs?: number;
|
|
38
|
+
/** Write barrier duration in ms. Default: 5_000 */
|
|
39
|
+
writeBarrierMs?: number;
|
|
40
|
+
/** Base delay for exponential backoff on poll failure in ms. Default: 5_000 */
|
|
41
|
+
pollBackoffBaseMs?: number;
|
|
42
|
+
/** Maximum backoff delay on poll failure in ms. Default: 300_000 */
|
|
43
|
+
pollBackoffMaxMs?: number;
|
|
44
|
+
}
|
|
45
|
+
export interface Room {
|
|
46
|
+
id: number;
|
|
47
|
+
unit: number;
|
|
48
|
+
name: string;
|
|
49
|
+
devices: Device[];
|
|
50
|
+
}
|
|
51
|
+
export interface PhysicalDeviceDescription {
|
|
52
|
+
id: number;
|
|
53
|
+
name: string;
|
|
54
|
+
manufacturer: string;
|
|
55
|
+
model: string;
|
|
56
|
+
secure: boolean;
|
|
57
|
+
movable: boolean;
|
|
58
|
+
external: boolean;
|
|
59
|
+
protocol: string;
|
|
60
|
+
deviceSpecificKey: boolean;
|
|
61
|
+
isActive: boolean;
|
|
62
|
+
}
|
|
63
|
+
export interface Device {
|
|
64
|
+
id: number;
|
|
65
|
+
room: number;
|
|
66
|
+
roomName?: string;
|
|
67
|
+
deviceTemplateId: number;
|
|
68
|
+
deviceType: number;
|
|
69
|
+
triggerTags?: string[];
|
|
70
|
+
name: string;
|
|
71
|
+
category: string;
|
|
72
|
+
icon?: string;
|
|
73
|
+
active: boolean;
|
|
74
|
+
movable: boolean;
|
|
75
|
+
secure: boolean;
|
|
76
|
+
paired: boolean;
|
|
77
|
+
serialNumber?: string;
|
|
78
|
+
features: Feature[];
|
|
79
|
+
physicalDevice?: number;
|
|
80
|
+
physicalDeviceDescription?: PhysicalDeviceDescription;
|
|
81
|
+
}
|
|
82
|
+
export interface Feature {
|
|
83
|
+
id: number;
|
|
84
|
+
device: number;
|
|
85
|
+
featureType: number;
|
|
86
|
+
featureTypeName: string;
|
|
87
|
+
featureTypeCategory: string;
|
|
88
|
+
name: string;
|
|
89
|
+
isLight: boolean;
|
|
90
|
+
eventType?: number;
|
|
91
|
+
eventTypeName?: string;
|
|
92
|
+
physical?: number;
|
|
93
|
+
physicalFeatureDescription?: number;
|
|
94
|
+
featureTypeSettable?: boolean;
|
|
95
|
+
value?: number;
|
|
96
|
+
values?: string;
|
|
97
|
+
uiStoredValue?: number;
|
|
98
|
+
}
|
|
99
|
+
export interface Residency {
|
|
100
|
+
id: string;
|
|
101
|
+
accountId: number;
|
|
102
|
+
unit: number;
|
|
103
|
+
buildingId: number;
|
|
104
|
+
unitName: string;
|
|
105
|
+
dateFrom: string;
|
|
106
|
+
tenant: boolean;
|
|
107
|
+
unitAdmin: boolean;
|
|
108
|
+
email: string;
|
|
109
|
+
firstName: string;
|
|
110
|
+
lastName: string;
|
|
111
|
+
phoneNumber?: string;
|
|
112
|
+
createdAt: string;
|
|
113
|
+
suspended: boolean;
|
|
114
|
+
account: {
|
|
115
|
+
id: number;
|
|
116
|
+
email: string;
|
|
117
|
+
firstName: string;
|
|
118
|
+
lastName: string;
|
|
119
|
+
phoneNumber?: string;
|
|
120
|
+
hasPassword: boolean;
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
export interface AuthResponse {
|
|
124
|
+
jwt: string;
|
|
125
|
+
refresh: string;
|
|
126
|
+
}
|
|
127
|
+
export interface AccountResponse {
|
|
128
|
+
id: number;
|
|
129
|
+
email: string;
|
|
130
|
+
firstName: string;
|
|
131
|
+
lastName: string;
|
|
132
|
+
hasPassword?: boolean;
|
|
133
|
+
phoneNumber?: string;
|
|
134
|
+
passwordSetAt?: string;
|
|
135
|
+
passwordFirstSetAt?: string;
|
|
136
|
+
createdAt?: string;
|
|
137
|
+
keepConnected?: boolean;
|
|
138
|
+
shareData?: boolean;
|
|
139
|
+
accessibilityColor?: boolean;
|
|
140
|
+
onboardingComplete?: boolean;
|
|
141
|
+
soSecureRegistered?: boolean;
|
|
142
|
+
phoneNumberVerified?: boolean;
|
|
143
|
+
isAdmin?: boolean;
|
|
144
|
+
isSuperAdmin?: boolean;
|
|
145
|
+
mfaEnabled?: boolean;
|
|
146
|
+
mfaPopup?: boolean;
|
|
147
|
+
showPairingInstructions?: boolean;
|
|
148
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/utils.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,YAAY,EAAE,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,EAAE;IAC7C,SAAS,EAAE,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC;CACpC,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "iotas-ts",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Wrapper around the IOTAS API for use in matterbridge and homebridge ",
|
|
5
|
+
"author": "Augusto Meza <mezaugusto@proton.me>",
|
|
6
|
+
"license": "Apache-2.0",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"main": "dist/src/index.js",
|
|
9
|
+
"types": "dist/src/index.d.ts",
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"import": "./dist/src/index.js",
|
|
13
|
+
"types": "./dist/src/index.d.ts"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "git+https://github.com/mezaugusto/iotas-ts.git"
|
|
19
|
+
},
|
|
20
|
+
"keywords": [
|
|
21
|
+
"iotas",
|
|
22
|
+
"smart-home",
|
|
23
|
+
"api-client",
|
|
24
|
+
"homebridge",
|
|
25
|
+
"matterbridge"
|
|
26
|
+
],
|
|
27
|
+
"engines": {
|
|
28
|
+
"node": "^20.18.0 || ^22.10.0 || ^24.0.0"
|
|
29
|
+
},
|
|
30
|
+
"files": [
|
|
31
|
+
"dist/src",
|
|
32
|
+
"README.md",
|
|
33
|
+
"CHANGELOG.md"
|
|
34
|
+
],
|
|
35
|
+
"scripts": {
|
|
36
|
+
"build": "rm -rf ./dist && tsc",
|
|
37
|
+
"lint": "eslint . --max-warnings=0",
|
|
38
|
+
"format": "prettier --write .",
|
|
39
|
+
"format:check": "prettier --check .",
|
|
40
|
+
"test": "tsc && node --test dist/test/*.test.js",
|
|
41
|
+
"prepublishOnly": "npm run lint && npm run build"
|
|
42
|
+
},
|
|
43
|
+
"devDependencies": {
|
|
44
|
+
"@eslint/js": "^9.17.0",
|
|
45
|
+
"@types/node": "^22.10.2",
|
|
46
|
+
"eslint": "^9.17.0",
|
|
47
|
+
"eslint-config-prettier": "^10.1.8",
|
|
48
|
+
"prettier": "^3.8.1",
|
|
49
|
+
"typescript": "^5.7.2",
|
|
50
|
+
"typescript-eslint": "^8.18.2"
|
|
51
|
+
},
|
|
52
|
+
"prettier": {
|
|
53
|
+
"singleQuote": true,
|
|
54
|
+
"trailingComma": "all",
|
|
55
|
+
"tabWidth": 2,
|
|
56
|
+
"semi": true,
|
|
57
|
+
"printWidth": 120
|
|
58
|
+
}
|
|
59
|
+
}
|