wuira 0.1.3 → 0.1.4
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 +69 -0
- package/lib/index.d.ts +2 -0
- package/lib/index.lua +5 -0
- package/lib/store/index.d.ts +37 -0
- package/lib/store/index.lua +921 -0
- package/package.json +8 -1
- package/tools/build-library.mjs +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -9,6 +9,17 @@ with the release date and highlight breaking changes explicitly.
|
|
|
9
9
|
|
|
10
10
|
No changes yet.
|
|
11
11
|
|
|
12
|
+
## 0.1.4 — 2026-10-14
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
|
|
16
|
+
- Class-based stores with optional stable tokens, one-time readonly snapshots,
|
|
17
|
+
transactional callback updates, and observer subscriptions.
|
|
18
|
+
- Memory-only stores when no token is declared; SavedVariables-backed records
|
|
19
|
+
when a token and registry persistence configuration are provided.
|
|
20
|
+
- SavedVariables initialization after the owning addon's `ADDON_LOADED` event,
|
|
21
|
+
default restoration, collision checks, and serializable data validation.
|
|
22
|
+
|
|
12
23
|
## 0.1.3 — 2026-10-14
|
|
13
24
|
|
|
14
25
|
### Added
|
package/README.md
CHANGED
|
@@ -309,6 +309,75 @@ Relative output paths resolve from the project directory. Absolute paths can tar
|
|
|
309
309
|
|
|
310
310
|
The CLI, configuration, and build plugin use ESM (`.mjs`). Only Lua and TOC files are needed in game. `npm run build` in the framework repository generates distributable Lua modules and TypeScript declarations in `lib/`; addon builds include the framework modules they import.
|
|
311
311
|
|
|
312
|
+
## Stores
|
|
313
|
+
|
|
314
|
+
Use data classes to define defaults. Without a static token, records live only
|
|
315
|
+
in memory and are keyed by the class itself:
|
|
316
|
+
|
|
317
|
+
```ts
|
|
318
|
+
import { Store, StoreRegistry } from "wuira/store";
|
|
319
|
+
|
|
320
|
+
class SessionSettings extends Store {
|
|
321
|
+
CastSpellId = 1232;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
const store = new StoreRegistry();
|
|
325
|
+
const snapshot = store.get(SessionSettings); // One-time, deeply readonly copy.
|
|
326
|
+
|
|
327
|
+
const unsubscribe = store.subscribe(SessionSettings, settings => {
|
|
328
|
+
console.log("New spell:", settings.CastSpellId);
|
|
329
|
+
});
|
|
330
|
+
|
|
331
|
+
store.set(SessionSettings, settings => {
|
|
332
|
+
settings.CastSpellId = 635;
|
|
333
|
+
return settings;
|
|
334
|
+
});
|
|
335
|
+
|
|
336
|
+
unsubscribe();
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
`get()` does not subscribe. `subscribe()` observes future commits and returns an
|
|
340
|
+
unsubscribe function; call `get()` for initial data. Each subscriber receives an
|
|
341
|
+
independent snapshot. `set()` works on a detached draft, validates the returned
|
|
342
|
+
data, commits it, and sends one notification per observer. If the updater throws,
|
|
343
|
+
the previous record is preserved. Stores contain data fields, not class methods.
|
|
344
|
+
|
|
345
|
+
For persistence, declare a stable token and the owning addon's SavedVariables:
|
|
346
|
+
|
|
347
|
+
```toc
|
|
348
|
+
## SavedVariables: LumaUIDB
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
```ts
|
|
352
|
+
class LumaSettings extends Store {
|
|
353
|
+
static readonly Token = "luma.settings";
|
|
354
|
+
CastSpellId = 1232;
|
|
355
|
+
Width = 220;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
const store = new StoreRegistry({ addon: "LumaUI", variable: "LumaUIDB" });
|
|
359
|
+
store.onReady(() => {
|
|
360
|
+
console.log(store.get(LumaSettings).Width);
|
|
361
|
+
store.set(LumaSettings, settings => {
|
|
362
|
+
settings.Width = 240;
|
|
363
|
+
return settings;
|
|
364
|
+
});
|
|
365
|
+
});
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
Add the TOC declaration to the addon's `addon.toc.in`. The registry waits for
|
|
369
|
+
`ADDON_LOADED` before opening persistent records. Tokenless records can still be
|
|
370
|
+
used immediately. WoW writes the saved table on normal logout/reload; `set()`
|
|
371
|
+
does not force a disk flush. Keep tokens stable across versions. New default
|
|
372
|
+
fields are filled in and incompatible saved field types fall back to defaults;
|
|
373
|
+
renaming keys or changing schema meaning still requires an application migration.
|
|
374
|
+
|
|
375
|
+
Supported values are finite numbers, strings, booleans, arrays, and nested data
|
|
376
|
+
objects. Functions, cycles, and secret values cannot be saved. Two classes cannot
|
|
377
|
+
claim the same token within a registry. Share one registry instance per database.
|
|
378
|
+
`Dispose()` removes its observers and pending initialization listener. Profile
|
|
379
|
+
selection, schema migrations, and reactive widget binding are separate features.
|
|
380
|
+
|
|
312
381
|
## Development
|
|
313
382
|
|
|
314
383
|
```sh
|
package/lib/index.d.ts
CHANGED
|
@@ -4,3 +4,5 @@ export { wuira } from "./wuira";
|
|
|
4
4
|
export { UI } from "./ui/primitives/jsx";
|
|
5
5
|
export type { Element, Component } from "./ui/primitives/jsx";
|
|
6
6
|
export type { Cell } from "./ui/Cell";
|
|
7
|
+
export { Store, StoreRegistry } from "./store";
|
|
8
|
+
export type { StoreClass, ReadonlyData, SavedStoreOptions } from "./store";
|
package/lib/index.lua
CHANGED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/// <reference path="../platform/forever.d.ts" />
|
|
2
|
+
/** Extend with data fields and defaults. A stable static Token opts into persistence. */
|
|
3
|
+
export declare abstract class Store {
|
|
4
|
+
}
|
|
5
|
+
export interface StoreClass<T extends Store> {
|
|
6
|
+
new (): T;
|
|
7
|
+
readonly Token?: string;
|
|
8
|
+
}
|
|
9
|
+
export type ReadonlyData<T> = T extends object ? {
|
|
10
|
+
readonly [K in keyof T]: ReadonlyData<T[K]>;
|
|
11
|
+
} : T;
|
|
12
|
+
export interface SavedStoreOptions {
|
|
13
|
+
addon: string;
|
|
14
|
+
variable: string;
|
|
15
|
+
}
|
|
16
|
+
export declare class StoreRegistry {
|
|
17
|
+
private readonly options?;
|
|
18
|
+
private readonly memory;
|
|
19
|
+
private readonly observers;
|
|
20
|
+
private readonly tokens;
|
|
21
|
+
private readonly updating;
|
|
22
|
+
private saved?;
|
|
23
|
+
private listener?;
|
|
24
|
+
private readyCallbacks;
|
|
25
|
+
constructor(options?: SavedStoreOptions | undefined);
|
|
26
|
+
private Load;
|
|
27
|
+
get IsReady(): boolean;
|
|
28
|
+
onReady(callback: () => void): void;
|
|
29
|
+
private Read;
|
|
30
|
+
/** One-time detached snapshot, with no subscription or mutable access to stored data. */
|
|
31
|
+
get<T extends Store>(schema: StoreClass<T>): ReadonlyData<T>;
|
|
32
|
+
/** Commit only after the updater succeeds; observers receive detached snapshots. */
|
|
33
|
+
set<T extends Store>(schema: StoreClass<T>, update: (settings: T) => T): void;
|
|
34
|
+
/** Observe future commits. Call get() separately for the initial snapshot. */
|
|
35
|
+
subscribe<T extends Store>(schema: StoreClass<T>, observer: (settings: ReadonlyData<T>) => void): () => void;
|
|
36
|
+
Dispose(): void;
|
|
37
|
+
}
|
|
@@ -0,0 +1,921 @@
|
|
|
1
|
+
--[[ Generated with https://github.com/TypeScriptToLua/TypeScriptToLua ]]
|
|
2
|
+
-- Lua Library inline imports
|
|
3
|
+
local function __TS__Class(self)
|
|
4
|
+
local c = {prototype = {}}
|
|
5
|
+
c.prototype.__index = c.prototype
|
|
6
|
+
c.prototype.constructor = c
|
|
7
|
+
return c
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
local __TS__Symbol, Symbol
|
|
11
|
+
do
|
|
12
|
+
local symbolMetatable = {__tostring = function(self)
|
|
13
|
+
return ("Symbol(" .. (self.description or "")) .. ")"
|
|
14
|
+
end}
|
|
15
|
+
function __TS__Symbol(description)
|
|
16
|
+
return setmetatable({description = description}, symbolMetatable)
|
|
17
|
+
end
|
|
18
|
+
Symbol = {
|
|
19
|
+
asyncDispose = __TS__Symbol("Symbol.asyncDispose"),
|
|
20
|
+
dispose = __TS__Symbol("Symbol.dispose"),
|
|
21
|
+
iterator = __TS__Symbol("Symbol.iterator"),
|
|
22
|
+
hasInstance = __TS__Symbol("Symbol.hasInstance"),
|
|
23
|
+
species = __TS__Symbol("Symbol.species"),
|
|
24
|
+
toStringTag = __TS__Symbol("Symbol.toStringTag")
|
|
25
|
+
}
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
local __TS__Iterator
|
|
29
|
+
do
|
|
30
|
+
local function iteratorGeneratorStep(self)
|
|
31
|
+
local co = self.____coroutine
|
|
32
|
+
local status, value = coroutine.resume(co)
|
|
33
|
+
if not status then
|
|
34
|
+
error(value, 0)
|
|
35
|
+
end
|
|
36
|
+
if coroutine.status(co) == "dead" then
|
|
37
|
+
return
|
|
38
|
+
end
|
|
39
|
+
return true, value
|
|
40
|
+
end
|
|
41
|
+
local function iteratorIteratorStep(self)
|
|
42
|
+
local result = self:next()
|
|
43
|
+
if result.done then
|
|
44
|
+
return
|
|
45
|
+
end
|
|
46
|
+
return true, result.value
|
|
47
|
+
end
|
|
48
|
+
local function iteratorStringStep(self, index)
|
|
49
|
+
index = index + 1
|
|
50
|
+
if index > #self then
|
|
51
|
+
return
|
|
52
|
+
end
|
|
53
|
+
return index, string.sub(self, index, index)
|
|
54
|
+
end
|
|
55
|
+
function __TS__Iterator(iterable)
|
|
56
|
+
if type(iterable) == "string" then
|
|
57
|
+
return iteratorStringStep, iterable, 0
|
|
58
|
+
elseif iterable.____coroutine ~= nil then
|
|
59
|
+
return iteratorGeneratorStep, iterable
|
|
60
|
+
elseif iterable[Symbol.iterator] then
|
|
61
|
+
local iterator = iterable[Symbol.iterator](iterable)
|
|
62
|
+
return iteratorIteratorStep, iterator
|
|
63
|
+
else
|
|
64
|
+
return ipairs(iterable)
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
local function __TS__New(target, ...)
|
|
70
|
+
local instance = setmetatable({}, target.prototype)
|
|
71
|
+
instance:____constructor(...)
|
|
72
|
+
return instance
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
local Set
|
|
76
|
+
do
|
|
77
|
+
Set = __TS__Class()
|
|
78
|
+
Set.name = "Set"
|
|
79
|
+
function Set.prototype.____constructor(self, values)
|
|
80
|
+
self[Symbol.toStringTag] = "Set"
|
|
81
|
+
self.size = 0
|
|
82
|
+
self.nextKey = {}
|
|
83
|
+
self.previousKey = {}
|
|
84
|
+
if values == nil then
|
|
85
|
+
return
|
|
86
|
+
end
|
|
87
|
+
local iterable = values
|
|
88
|
+
if iterable[Symbol.iterator] then
|
|
89
|
+
local iterator = iterable[Symbol.iterator](iterable)
|
|
90
|
+
while true do
|
|
91
|
+
local result = iterator:next()
|
|
92
|
+
if result.done then
|
|
93
|
+
break
|
|
94
|
+
end
|
|
95
|
+
self:add(result.value)
|
|
96
|
+
end
|
|
97
|
+
else
|
|
98
|
+
local array = values
|
|
99
|
+
for ____, value in ipairs(array) do
|
|
100
|
+
self:add(value)
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
function Set.prototype.add(self, value)
|
|
105
|
+
local isNewValue = not self:has(value)
|
|
106
|
+
if isNewValue then
|
|
107
|
+
self.size = self.size + 1
|
|
108
|
+
end
|
|
109
|
+
if self.firstKey == nil then
|
|
110
|
+
self.firstKey = value
|
|
111
|
+
self.lastKey = value
|
|
112
|
+
elseif isNewValue then
|
|
113
|
+
self.nextKey[self.lastKey] = value
|
|
114
|
+
self.previousKey[value] = self.lastKey
|
|
115
|
+
self.lastKey = value
|
|
116
|
+
end
|
|
117
|
+
return self
|
|
118
|
+
end
|
|
119
|
+
function Set.prototype.clear(self)
|
|
120
|
+
self.nextKey = {}
|
|
121
|
+
self.previousKey = {}
|
|
122
|
+
self.firstKey = nil
|
|
123
|
+
self.lastKey = nil
|
|
124
|
+
self.size = 0
|
|
125
|
+
end
|
|
126
|
+
function Set.prototype.delete(self, value)
|
|
127
|
+
local contains = self:has(value)
|
|
128
|
+
if contains then
|
|
129
|
+
self.size = self.size - 1
|
|
130
|
+
local next = self.nextKey[value]
|
|
131
|
+
local previous = self.previousKey[value]
|
|
132
|
+
if next ~= nil and previous ~= nil then
|
|
133
|
+
self.nextKey[previous] = next
|
|
134
|
+
self.previousKey[next] = previous
|
|
135
|
+
elseif next ~= nil then
|
|
136
|
+
self.firstKey = next
|
|
137
|
+
self.previousKey[next] = nil
|
|
138
|
+
elseif previous ~= nil then
|
|
139
|
+
self.lastKey = previous
|
|
140
|
+
self.nextKey[previous] = nil
|
|
141
|
+
else
|
|
142
|
+
self.firstKey = nil
|
|
143
|
+
self.lastKey = nil
|
|
144
|
+
end
|
|
145
|
+
self.nextKey[value] = nil
|
|
146
|
+
self.previousKey[value] = nil
|
|
147
|
+
end
|
|
148
|
+
return contains
|
|
149
|
+
end
|
|
150
|
+
function Set.prototype.forEach(self, callback)
|
|
151
|
+
for ____, key in __TS__Iterator(self:keys()) do
|
|
152
|
+
callback(nil, key, key, self)
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
function Set.prototype.has(self, value)
|
|
156
|
+
return self.nextKey[value] ~= nil or self.lastKey == value
|
|
157
|
+
end
|
|
158
|
+
Set.prototype[Symbol.iterator] = function(self)
|
|
159
|
+
return self:values()
|
|
160
|
+
end
|
|
161
|
+
function Set.prototype.entries(self)
|
|
162
|
+
local function getFirstKey()
|
|
163
|
+
return self.firstKey
|
|
164
|
+
end
|
|
165
|
+
local nextKey = self.nextKey
|
|
166
|
+
local key
|
|
167
|
+
local started = false
|
|
168
|
+
return {
|
|
169
|
+
[Symbol.iterator] = function(self)
|
|
170
|
+
return self
|
|
171
|
+
end,
|
|
172
|
+
next = function(self)
|
|
173
|
+
if not started then
|
|
174
|
+
started = true
|
|
175
|
+
key = getFirstKey(nil)
|
|
176
|
+
else
|
|
177
|
+
key = nextKey[key]
|
|
178
|
+
end
|
|
179
|
+
return {done = not key, value = {key, key}}
|
|
180
|
+
end
|
|
181
|
+
}
|
|
182
|
+
end
|
|
183
|
+
function Set.prototype.keys(self)
|
|
184
|
+
local function getFirstKey()
|
|
185
|
+
return self.firstKey
|
|
186
|
+
end
|
|
187
|
+
local nextKey = self.nextKey
|
|
188
|
+
local key
|
|
189
|
+
local started = false
|
|
190
|
+
return {
|
|
191
|
+
[Symbol.iterator] = function(self)
|
|
192
|
+
return self
|
|
193
|
+
end,
|
|
194
|
+
next = function(self)
|
|
195
|
+
if not started then
|
|
196
|
+
started = true
|
|
197
|
+
key = getFirstKey(nil)
|
|
198
|
+
else
|
|
199
|
+
key = nextKey[key]
|
|
200
|
+
end
|
|
201
|
+
return {done = not key, value = key}
|
|
202
|
+
end
|
|
203
|
+
}
|
|
204
|
+
end
|
|
205
|
+
function Set.prototype.values(self)
|
|
206
|
+
local function getFirstKey()
|
|
207
|
+
return self.firstKey
|
|
208
|
+
end
|
|
209
|
+
local nextKey = self.nextKey
|
|
210
|
+
local key
|
|
211
|
+
local started = false
|
|
212
|
+
return {
|
|
213
|
+
[Symbol.iterator] = function(self)
|
|
214
|
+
return self
|
|
215
|
+
end,
|
|
216
|
+
next = function(self)
|
|
217
|
+
if not started then
|
|
218
|
+
started = true
|
|
219
|
+
key = getFirstKey(nil)
|
|
220
|
+
else
|
|
221
|
+
key = nextKey[key]
|
|
222
|
+
end
|
|
223
|
+
return {done = not key, value = key}
|
|
224
|
+
end
|
|
225
|
+
}
|
|
226
|
+
end
|
|
227
|
+
function Set.prototype.union(self, other)
|
|
228
|
+
local result = __TS__New(Set, self)
|
|
229
|
+
for ____, item in __TS__Iterator(other) do
|
|
230
|
+
result:add(item)
|
|
231
|
+
end
|
|
232
|
+
return result
|
|
233
|
+
end
|
|
234
|
+
function Set.prototype.intersection(self, other)
|
|
235
|
+
local result = __TS__New(Set)
|
|
236
|
+
for ____, item in __TS__Iterator(self) do
|
|
237
|
+
if other:has(item) then
|
|
238
|
+
result:add(item)
|
|
239
|
+
end
|
|
240
|
+
end
|
|
241
|
+
return result
|
|
242
|
+
end
|
|
243
|
+
function Set.prototype.difference(self, other)
|
|
244
|
+
local result = __TS__New(Set, self)
|
|
245
|
+
for ____, item in __TS__Iterator(other) do
|
|
246
|
+
result:delete(item)
|
|
247
|
+
end
|
|
248
|
+
return result
|
|
249
|
+
end
|
|
250
|
+
function Set.prototype.symmetricDifference(self, other)
|
|
251
|
+
local result = __TS__New(Set, self)
|
|
252
|
+
for ____, item in __TS__Iterator(other) do
|
|
253
|
+
if self:has(item) then
|
|
254
|
+
result:delete(item)
|
|
255
|
+
else
|
|
256
|
+
result:add(item)
|
|
257
|
+
end
|
|
258
|
+
end
|
|
259
|
+
return result
|
|
260
|
+
end
|
|
261
|
+
function Set.prototype.isSubsetOf(self, other)
|
|
262
|
+
for ____, item in __TS__Iterator(self) do
|
|
263
|
+
if not other:has(item) then
|
|
264
|
+
return false
|
|
265
|
+
end
|
|
266
|
+
end
|
|
267
|
+
return true
|
|
268
|
+
end
|
|
269
|
+
function Set.prototype.isSupersetOf(self, other)
|
|
270
|
+
for ____, item in __TS__Iterator(other) do
|
|
271
|
+
if not self:has(item) then
|
|
272
|
+
return false
|
|
273
|
+
end
|
|
274
|
+
end
|
|
275
|
+
return true
|
|
276
|
+
end
|
|
277
|
+
function Set.prototype.isDisjointFrom(self, other)
|
|
278
|
+
for ____, item in __TS__Iterator(self) do
|
|
279
|
+
if other:has(item) then
|
|
280
|
+
return false
|
|
281
|
+
end
|
|
282
|
+
end
|
|
283
|
+
return true
|
|
284
|
+
end
|
|
285
|
+
Set[Symbol.species] = Set
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
local function __TS__NumberIsFinite(value)
|
|
289
|
+
return type(value) == "number" and value == value and value ~= math.huge and value ~= -math.huge
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
local function __TS__ObjectEntries(obj)
|
|
293
|
+
local result = {}
|
|
294
|
+
local len = 0
|
|
295
|
+
for key in pairs(obj) do
|
|
296
|
+
len = len + 1
|
|
297
|
+
result[len] = {key, obj[key]}
|
|
298
|
+
end
|
|
299
|
+
return result
|
|
300
|
+
end
|
|
301
|
+
|
|
302
|
+
local function __TS__TypeOf(value)
|
|
303
|
+
local luaType = type(value)
|
|
304
|
+
if luaType == "table" then
|
|
305
|
+
return "object"
|
|
306
|
+
elseif luaType == "nil" then
|
|
307
|
+
return "undefined"
|
|
308
|
+
else
|
|
309
|
+
return luaType
|
|
310
|
+
end
|
|
311
|
+
end
|
|
312
|
+
|
|
313
|
+
local function __TS__ArrayIsArray(value)
|
|
314
|
+
return type(value) == "table" and (value[1] ~= nil or next(value) == nil)
|
|
315
|
+
end
|
|
316
|
+
|
|
317
|
+
local Map
|
|
318
|
+
do
|
|
319
|
+
Map = __TS__Class()
|
|
320
|
+
Map.name = "Map"
|
|
321
|
+
function Map.prototype.____constructor(self, entries)
|
|
322
|
+
self[Symbol.toStringTag] = "Map"
|
|
323
|
+
self.items = {}
|
|
324
|
+
self.size = 0
|
|
325
|
+
self.nextKey = {}
|
|
326
|
+
self.previousKey = {}
|
|
327
|
+
if entries == nil then
|
|
328
|
+
return
|
|
329
|
+
end
|
|
330
|
+
local iterable = entries
|
|
331
|
+
if iterable[Symbol.iterator] then
|
|
332
|
+
local iterator = iterable[Symbol.iterator](iterable)
|
|
333
|
+
while true do
|
|
334
|
+
local result = iterator:next()
|
|
335
|
+
if result.done then
|
|
336
|
+
break
|
|
337
|
+
end
|
|
338
|
+
local value = result.value
|
|
339
|
+
self:set(value[1], value[2])
|
|
340
|
+
end
|
|
341
|
+
else
|
|
342
|
+
local array = entries
|
|
343
|
+
for ____, kvp in ipairs(array) do
|
|
344
|
+
self:set(kvp[1], kvp[2])
|
|
345
|
+
end
|
|
346
|
+
end
|
|
347
|
+
end
|
|
348
|
+
function Map.prototype.clear(self)
|
|
349
|
+
self.items = {}
|
|
350
|
+
self.nextKey = {}
|
|
351
|
+
self.previousKey = {}
|
|
352
|
+
self.firstKey = nil
|
|
353
|
+
self.lastKey = nil
|
|
354
|
+
self.size = 0
|
|
355
|
+
end
|
|
356
|
+
function Map.prototype.delete(self, key)
|
|
357
|
+
local contains = self:has(key)
|
|
358
|
+
if contains then
|
|
359
|
+
self.size = self.size - 1
|
|
360
|
+
local next = self.nextKey[key]
|
|
361
|
+
local previous = self.previousKey[key]
|
|
362
|
+
if next ~= nil and previous ~= nil then
|
|
363
|
+
self.nextKey[previous] = next
|
|
364
|
+
self.previousKey[next] = previous
|
|
365
|
+
elseif next ~= nil then
|
|
366
|
+
self.firstKey = next
|
|
367
|
+
self.previousKey[next] = nil
|
|
368
|
+
elseif previous ~= nil then
|
|
369
|
+
self.lastKey = previous
|
|
370
|
+
self.nextKey[previous] = nil
|
|
371
|
+
else
|
|
372
|
+
self.firstKey = nil
|
|
373
|
+
self.lastKey = nil
|
|
374
|
+
end
|
|
375
|
+
self.nextKey[key] = nil
|
|
376
|
+
self.previousKey[key] = nil
|
|
377
|
+
end
|
|
378
|
+
self.items[key] = nil
|
|
379
|
+
return contains
|
|
380
|
+
end
|
|
381
|
+
function Map.prototype.forEach(self, callback)
|
|
382
|
+
for ____, key in __TS__Iterator(self:keys()) do
|
|
383
|
+
callback(nil, self.items[key], key, self)
|
|
384
|
+
end
|
|
385
|
+
end
|
|
386
|
+
function Map.prototype.get(self, key)
|
|
387
|
+
return self.items[key]
|
|
388
|
+
end
|
|
389
|
+
function Map.prototype.has(self, key)
|
|
390
|
+
return self.nextKey[key] ~= nil or self.lastKey == key
|
|
391
|
+
end
|
|
392
|
+
function Map.prototype.set(self, key, value)
|
|
393
|
+
local isNewValue = not self:has(key)
|
|
394
|
+
if isNewValue then
|
|
395
|
+
self.size = self.size + 1
|
|
396
|
+
end
|
|
397
|
+
self.items[key] = value
|
|
398
|
+
if self.firstKey == nil then
|
|
399
|
+
self.firstKey = key
|
|
400
|
+
self.lastKey = key
|
|
401
|
+
elseif isNewValue then
|
|
402
|
+
self.nextKey[self.lastKey] = key
|
|
403
|
+
self.previousKey[key] = self.lastKey
|
|
404
|
+
self.lastKey = key
|
|
405
|
+
end
|
|
406
|
+
return self
|
|
407
|
+
end
|
|
408
|
+
Map.prototype[Symbol.iterator] = function(self)
|
|
409
|
+
return self:entries()
|
|
410
|
+
end
|
|
411
|
+
function Map.prototype.entries(self)
|
|
412
|
+
local function getFirstKey()
|
|
413
|
+
return self.firstKey
|
|
414
|
+
end
|
|
415
|
+
local items = self.items
|
|
416
|
+
local nextKey = self.nextKey
|
|
417
|
+
local key
|
|
418
|
+
local started = false
|
|
419
|
+
return {
|
|
420
|
+
[Symbol.iterator] = function(self)
|
|
421
|
+
return self
|
|
422
|
+
end,
|
|
423
|
+
next = function(self)
|
|
424
|
+
if not started then
|
|
425
|
+
started = true
|
|
426
|
+
key = getFirstKey(nil)
|
|
427
|
+
else
|
|
428
|
+
key = nextKey[key]
|
|
429
|
+
end
|
|
430
|
+
return {done = not key, value = {key, items[key]}}
|
|
431
|
+
end
|
|
432
|
+
}
|
|
433
|
+
end
|
|
434
|
+
function Map.prototype.keys(self)
|
|
435
|
+
local function getFirstKey()
|
|
436
|
+
return self.firstKey
|
|
437
|
+
end
|
|
438
|
+
local nextKey = self.nextKey
|
|
439
|
+
local key
|
|
440
|
+
local started = false
|
|
441
|
+
return {
|
|
442
|
+
[Symbol.iterator] = function(self)
|
|
443
|
+
return self
|
|
444
|
+
end,
|
|
445
|
+
next = function(self)
|
|
446
|
+
if not started then
|
|
447
|
+
started = true
|
|
448
|
+
key = getFirstKey(nil)
|
|
449
|
+
else
|
|
450
|
+
key = nextKey[key]
|
|
451
|
+
end
|
|
452
|
+
return {done = not key, value = key}
|
|
453
|
+
end
|
|
454
|
+
}
|
|
455
|
+
end
|
|
456
|
+
function Map.prototype.values(self)
|
|
457
|
+
local function getFirstKey()
|
|
458
|
+
return self.firstKey
|
|
459
|
+
end
|
|
460
|
+
local items = self.items
|
|
461
|
+
local nextKey = self.nextKey
|
|
462
|
+
local key
|
|
463
|
+
local started = false
|
|
464
|
+
return {
|
|
465
|
+
[Symbol.iterator] = function(self)
|
|
466
|
+
return self
|
|
467
|
+
end,
|
|
468
|
+
next = function(self)
|
|
469
|
+
if not started then
|
|
470
|
+
started = true
|
|
471
|
+
key = getFirstKey(nil)
|
|
472
|
+
else
|
|
473
|
+
key = nextKey[key]
|
|
474
|
+
end
|
|
475
|
+
return {done = not key, value = items[key]}
|
|
476
|
+
end
|
|
477
|
+
}
|
|
478
|
+
end
|
|
479
|
+
Map[Symbol.species] = Map
|
|
480
|
+
end
|
|
481
|
+
|
|
482
|
+
local function __TS__StringTrim(self)
|
|
483
|
+
local result = string.gsub(self, "^[%s ]*(.-)[%s ]*$", "%1")
|
|
484
|
+
return result
|
|
485
|
+
end
|
|
486
|
+
|
|
487
|
+
local function __TS__StringAccess(self, index)
|
|
488
|
+
if index >= 0 and index < #self then
|
|
489
|
+
return string.sub(self, index + 1, index + 1)
|
|
490
|
+
end
|
|
491
|
+
end
|
|
492
|
+
|
|
493
|
+
local __TS__Unpack = table.unpack or unpack
|
|
494
|
+
|
|
495
|
+
local function __TS__Spread(iterable)
|
|
496
|
+
local arr = {}
|
|
497
|
+
if type(iterable) == "string" then
|
|
498
|
+
for i = 0, #iterable - 1 do
|
|
499
|
+
arr[i + 1] = __TS__StringAccess(iterable, i)
|
|
500
|
+
end
|
|
501
|
+
else
|
|
502
|
+
local len = 0
|
|
503
|
+
for ____, item in __TS__Iterator(iterable) do
|
|
504
|
+
len = len + 1
|
|
505
|
+
arr[len] = item
|
|
506
|
+
end
|
|
507
|
+
end
|
|
508
|
+
return __TS__Unpack(arr)
|
|
509
|
+
end
|
|
510
|
+
|
|
511
|
+
local function __TS__CloneDescriptor(____bindingPattern0)
|
|
512
|
+
local value
|
|
513
|
+
local writable
|
|
514
|
+
local set
|
|
515
|
+
local get
|
|
516
|
+
local configurable
|
|
517
|
+
local enumerable
|
|
518
|
+
enumerable = ____bindingPattern0.enumerable
|
|
519
|
+
configurable = ____bindingPattern0.configurable
|
|
520
|
+
get = ____bindingPattern0.get
|
|
521
|
+
set = ____bindingPattern0.set
|
|
522
|
+
writable = ____bindingPattern0.writable
|
|
523
|
+
value = ____bindingPattern0.value
|
|
524
|
+
local descriptor = {enumerable = enumerable == true, configurable = configurable == true}
|
|
525
|
+
local hasGetterOrSetter = get ~= nil or set ~= nil
|
|
526
|
+
local hasValueOrWritableAttribute = writable ~= nil or value ~= nil
|
|
527
|
+
if hasGetterOrSetter and hasValueOrWritableAttribute then
|
|
528
|
+
error("Invalid property descriptor. Cannot both specify accessors and a value or writable attribute.", 0)
|
|
529
|
+
end
|
|
530
|
+
if get or set then
|
|
531
|
+
descriptor.get = get
|
|
532
|
+
descriptor.set = set
|
|
533
|
+
else
|
|
534
|
+
descriptor.value = value
|
|
535
|
+
descriptor.writable = writable == true
|
|
536
|
+
end
|
|
537
|
+
return descriptor
|
|
538
|
+
end
|
|
539
|
+
|
|
540
|
+
local __TS__DescriptorGet
|
|
541
|
+
do
|
|
542
|
+
local getmetatable = _G.getmetatable
|
|
543
|
+
local ____rawget = _G.rawget
|
|
544
|
+
function __TS__DescriptorGet(self, metatable, key)
|
|
545
|
+
while metatable do
|
|
546
|
+
local rawResult = ____rawget(metatable, key)
|
|
547
|
+
if rawResult ~= nil then
|
|
548
|
+
return rawResult
|
|
549
|
+
end
|
|
550
|
+
local descriptors = ____rawget(metatable, "_descriptors")
|
|
551
|
+
if descriptors then
|
|
552
|
+
local descriptor = descriptors[key]
|
|
553
|
+
if descriptor ~= nil then
|
|
554
|
+
if descriptor.get then
|
|
555
|
+
return descriptor.get(self)
|
|
556
|
+
end
|
|
557
|
+
return descriptor.value
|
|
558
|
+
end
|
|
559
|
+
end
|
|
560
|
+
metatable = getmetatable(metatable)
|
|
561
|
+
end
|
|
562
|
+
end
|
|
563
|
+
end
|
|
564
|
+
|
|
565
|
+
local __TS__DescriptorSet
|
|
566
|
+
do
|
|
567
|
+
local getmetatable = _G.getmetatable
|
|
568
|
+
local ____rawget = _G.rawget
|
|
569
|
+
local rawset = _G.rawset
|
|
570
|
+
function __TS__DescriptorSet(self, metatable, key, value)
|
|
571
|
+
while metatable do
|
|
572
|
+
local descriptors = ____rawget(metatable, "_descriptors")
|
|
573
|
+
if descriptors then
|
|
574
|
+
local descriptor = descriptors[key]
|
|
575
|
+
if descriptor ~= nil then
|
|
576
|
+
if descriptor.set then
|
|
577
|
+
descriptor.set(self, value)
|
|
578
|
+
else
|
|
579
|
+
if descriptor.writable == false then
|
|
580
|
+
error(
|
|
581
|
+
((("Cannot assign to read only property '" .. key) .. "' of object '") .. tostring(self)) .. "'",
|
|
582
|
+
0
|
|
583
|
+
)
|
|
584
|
+
end
|
|
585
|
+
descriptor.value = value
|
|
586
|
+
end
|
|
587
|
+
return
|
|
588
|
+
end
|
|
589
|
+
end
|
|
590
|
+
metatable = getmetatable(metatable)
|
|
591
|
+
end
|
|
592
|
+
rawset(self, key, value)
|
|
593
|
+
end
|
|
594
|
+
end
|
|
595
|
+
|
|
596
|
+
local __TS__SetDescriptor
|
|
597
|
+
do
|
|
598
|
+
local getmetatable = _G.getmetatable
|
|
599
|
+
local function descriptorIndex(self, key)
|
|
600
|
+
return __TS__DescriptorGet(
|
|
601
|
+
self,
|
|
602
|
+
getmetatable(self),
|
|
603
|
+
key
|
|
604
|
+
)
|
|
605
|
+
end
|
|
606
|
+
local function descriptorNewIndex(self, key, value)
|
|
607
|
+
return __TS__DescriptorSet(
|
|
608
|
+
self,
|
|
609
|
+
getmetatable(self),
|
|
610
|
+
key,
|
|
611
|
+
value
|
|
612
|
+
)
|
|
613
|
+
end
|
|
614
|
+
function __TS__SetDescriptor(target, key, desc, isPrototype)
|
|
615
|
+
if isPrototype == nil then
|
|
616
|
+
isPrototype = false
|
|
617
|
+
end
|
|
618
|
+
local ____isPrototype_0
|
|
619
|
+
if isPrototype then
|
|
620
|
+
____isPrototype_0 = target
|
|
621
|
+
else
|
|
622
|
+
____isPrototype_0 = getmetatable(target)
|
|
623
|
+
end
|
|
624
|
+
local metatable = ____isPrototype_0
|
|
625
|
+
if not metatable then
|
|
626
|
+
metatable = {}
|
|
627
|
+
setmetatable(target, metatable)
|
|
628
|
+
end
|
|
629
|
+
if not isPrototype and not rawget(metatable, "_isOwnDescriptorMetatable") then
|
|
630
|
+
local instanceMetatable = {}
|
|
631
|
+
instanceMetatable._isOwnDescriptorMetatable = true
|
|
632
|
+
setmetatable(instanceMetatable, metatable)
|
|
633
|
+
setmetatable(target, instanceMetatable)
|
|
634
|
+
metatable = instanceMetatable
|
|
635
|
+
end
|
|
636
|
+
local value = rawget(target, key)
|
|
637
|
+
if value ~= nil then
|
|
638
|
+
rawset(target, key, nil)
|
|
639
|
+
end
|
|
640
|
+
if not rawget(metatable, "_descriptors") then
|
|
641
|
+
metatable._descriptors = {}
|
|
642
|
+
end
|
|
643
|
+
metatable._descriptors[key] = __TS__CloneDescriptor(desc)
|
|
644
|
+
metatable.__index = descriptorIndex
|
|
645
|
+
metatable.__newindex = descriptorNewIndex
|
|
646
|
+
end
|
|
647
|
+
end
|
|
648
|
+
-- End of Lua Library inline imports
|
|
649
|
+
local ____exports = {}
|
|
650
|
+
--- Extend with data fields and defaults. A stable static Token opts into persistence.
|
|
651
|
+
____exports.Store = __TS__Class()
|
|
652
|
+
local Store = ____exports.Store
|
|
653
|
+
Store.name = "Store"
|
|
654
|
+
function Store.prototype.____constructor(self)
|
|
655
|
+
end
|
|
656
|
+
local function copy(self, value, seen)
|
|
657
|
+
if seen == nil then
|
|
658
|
+
seen = __TS__New(Set)
|
|
659
|
+
end
|
|
660
|
+
if issecretvalue(value) then
|
|
661
|
+
error("Secret values cannot be stored", 0)
|
|
662
|
+
end
|
|
663
|
+
if value == nil or type(value) == "string" or type(value) == "boolean" then
|
|
664
|
+
return value
|
|
665
|
+
end
|
|
666
|
+
if type(value) == "number" and __TS__NumberIsFinite(value) then
|
|
667
|
+
return value
|
|
668
|
+
end
|
|
669
|
+
if value == nil or type(value) ~= "table" then
|
|
670
|
+
error("Store supports only finite numbers, strings, booleans, arrays and data objects", 0)
|
|
671
|
+
end
|
|
672
|
+
if seen:has(value) then
|
|
673
|
+
error("Store does not support cyclic data", 0)
|
|
674
|
+
end
|
|
675
|
+
seen:add(value)
|
|
676
|
+
local fields = {}
|
|
677
|
+
for ____, ____value in ipairs(__TS__ObjectEntries(value)) do
|
|
678
|
+
local key = ____value[1]
|
|
679
|
+
local field = ____value[2]
|
|
680
|
+
fields[key] = copy(nil, field, seen)
|
|
681
|
+
end
|
|
682
|
+
seen:delete(value)
|
|
683
|
+
return fields
|
|
684
|
+
end
|
|
685
|
+
--- Fill new fields and reject incompatible saved field types using current defaults.
|
|
686
|
+
local function restore(self, defaults, saved)
|
|
687
|
+
if saved == nil or __TS__TypeOf(saved) ~= __TS__TypeOf(defaults) or saved == nil then
|
|
688
|
+
return copy(nil, defaults)
|
|
689
|
+
end
|
|
690
|
+
if __TS__ArrayIsArray(defaults) then
|
|
691
|
+
local ____Array_isArray_result_0
|
|
692
|
+
if __TS__ArrayIsArray(saved) then
|
|
693
|
+
____Array_isArray_result_0 = copy(nil, saved)
|
|
694
|
+
else
|
|
695
|
+
____Array_isArray_result_0 = copy(nil, defaults)
|
|
696
|
+
end
|
|
697
|
+
return ____Array_isArray_result_0
|
|
698
|
+
end
|
|
699
|
+
if type(defaults) == "table" and defaults ~= nil then
|
|
700
|
+
if __TS__ArrayIsArray(saved) then
|
|
701
|
+
return copy(nil, defaults)
|
|
702
|
+
end
|
|
703
|
+
local result = copy(nil, saved)
|
|
704
|
+
for ____, ____value in ipairs(__TS__ObjectEntries(defaults)) do
|
|
705
|
+
local key = ____value[1]
|
|
706
|
+
local value = ____value[2]
|
|
707
|
+
result[key] = restore(nil, value, result[key])
|
|
708
|
+
end
|
|
709
|
+
return result
|
|
710
|
+
end
|
|
711
|
+
return copy(nil, saved)
|
|
712
|
+
end
|
|
713
|
+
____exports.StoreRegistry = __TS__Class()
|
|
714
|
+
local StoreRegistry = ____exports.StoreRegistry
|
|
715
|
+
StoreRegistry.name = "StoreRegistry"
|
|
716
|
+
function StoreRegistry.prototype.____constructor(self, options)
|
|
717
|
+
self.options = options
|
|
718
|
+
self.memory = __TS__New(Map)
|
|
719
|
+
self.observers = __TS__New(Map)
|
|
720
|
+
self.tokens = __TS__New(Map)
|
|
721
|
+
self.updating = __TS__New(Set)
|
|
722
|
+
self.readyCallbacks = {}
|
|
723
|
+
if options == nil then
|
|
724
|
+
return
|
|
725
|
+
end
|
|
726
|
+
if string.match(options.variable, "^[%a_][%w_]*$") == nil then
|
|
727
|
+
error("Invalid SavedVariables name", 0)
|
|
728
|
+
end
|
|
729
|
+
local ____opt_1 = C_AddOns and C_AddOns.IsAddOnLoaded
|
|
730
|
+
if ____opt_1 and ____opt_1(options.addon) then
|
|
731
|
+
self:Load()
|
|
732
|
+
return
|
|
733
|
+
end
|
|
734
|
+
self.listener = CreateFrame("Frame", nil, UIParent)
|
|
735
|
+
self.listener:RegisterEvent("ADDON_LOADED")
|
|
736
|
+
self.listener:SetScript(
|
|
737
|
+
"OnEvent",
|
|
738
|
+
function(_frame, _event, addon)
|
|
739
|
+
if addon ~= options.addon then
|
|
740
|
+
return
|
|
741
|
+
end
|
|
742
|
+
self:Load()
|
|
743
|
+
local ____opt_5 = self.listener
|
|
744
|
+
if ____opt_5 ~= nil then
|
|
745
|
+
____opt_5:UnregisterAllEvents()
|
|
746
|
+
end
|
|
747
|
+
local ____opt_7 = self.listener
|
|
748
|
+
if ____opt_7 ~= nil then
|
|
749
|
+
____opt_7:SetScript("OnEvent", nil)
|
|
750
|
+
end
|
|
751
|
+
local ____opt_9 = self.listener
|
|
752
|
+
if ____opt_9 ~= nil then
|
|
753
|
+
____opt_9:Hide()
|
|
754
|
+
end
|
|
755
|
+
self.listener = nil
|
|
756
|
+
local callbacks = self.readyCallbacks
|
|
757
|
+
self.readyCallbacks = {}
|
|
758
|
+
for ____, callback in ipairs(callbacks) do
|
|
759
|
+
callback(nil)
|
|
760
|
+
end
|
|
761
|
+
end
|
|
762
|
+
)
|
|
763
|
+
end
|
|
764
|
+
function StoreRegistry.prototype.Load(self)
|
|
765
|
+
local name = self.options.variable
|
|
766
|
+
local saved = _G[name]
|
|
767
|
+
self.saved = saved ~= nil and type(saved) == "table" and saved or ({})
|
|
768
|
+
_G[name] = self.saved
|
|
769
|
+
end
|
|
770
|
+
function StoreRegistry.prototype.onReady(self, callback)
|
|
771
|
+
if self.IsReady then
|
|
772
|
+
callback(nil)
|
|
773
|
+
else
|
|
774
|
+
local ____self_readyCallbacks_11 = self.readyCallbacks
|
|
775
|
+
____self_readyCallbacks_11[#____self_readyCallbacks_11 + 1] = callback
|
|
776
|
+
end
|
|
777
|
+
end
|
|
778
|
+
function StoreRegistry.prototype.Read(self, schema)
|
|
779
|
+
local token = schema.Token
|
|
780
|
+
if token == nil then
|
|
781
|
+
if not self.memory:has(schema) then
|
|
782
|
+
self.memory:set(
|
|
783
|
+
schema,
|
|
784
|
+
copy(
|
|
785
|
+
nil,
|
|
786
|
+
__TS__New(schema)
|
|
787
|
+
)
|
|
788
|
+
)
|
|
789
|
+
end
|
|
790
|
+
return self.memory:get(schema)
|
|
791
|
+
end
|
|
792
|
+
if type(token) ~= "string" or __TS__StringTrim(token) == "" then
|
|
793
|
+
error("Store Token must be a nonempty stable string", 0)
|
|
794
|
+
end
|
|
795
|
+
if self.options == nil then
|
|
796
|
+
error("Persistent stores require SavedVariables configuration", 0)
|
|
797
|
+
end
|
|
798
|
+
if self.saved == nil then
|
|
799
|
+
error("SavedVariables are not loaded; use registry.onReady()", 0)
|
|
800
|
+
end
|
|
801
|
+
local owner = self.tokens:get(token)
|
|
802
|
+
if owner ~= nil and owner ~= schema then
|
|
803
|
+
error("Different Store classes cannot share a Token", 0)
|
|
804
|
+
end
|
|
805
|
+
if owner == nil then
|
|
806
|
+
local defaults = copy(
|
|
807
|
+
nil,
|
|
808
|
+
__TS__New(schema)
|
|
809
|
+
)
|
|
810
|
+
local value
|
|
811
|
+
do
|
|
812
|
+
local function ____catch()
|
|
813
|
+
value = defaults
|
|
814
|
+
end
|
|
815
|
+
local ____try = pcall(function()
|
|
816
|
+
value = restore(nil, defaults, self.saved[token])
|
|
817
|
+
end)
|
|
818
|
+
if not ____try then
|
|
819
|
+
____catch()
|
|
820
|
+
end
|
|
821
|
+
end
|
|
822
|
+
self.saved[token] = value
|
|
823
|
+
self.tokens:set(token, schema)
|
|
824
|
+
end
|
|
825
|
+
return self.saved[token]
|
|
826
|
+
end
|
|
827
|
+
function StoreRegistry.prototype.get(self, schema)
|
|
828
|
+
return copy(
|
|
829
|
+
nil,
|
|
830
|
+
self:Read(schema)
|
|
831
|
+
)
|
|
832
|
+
end
|
|
833
|
+
function StoreRegistry.prototype.set(self, schema, update)
|
|
834
|
+
if self.updating:has(schema) then
|
|
835
|
+
error("Reentrant updates of the same Store are not allowed", 0)
|
|
836
|
+
end
|
|
837
|
+
local draft = copy(
|
|
838
|
+
nil,
|
|
839
|
+
self:Read(schema)
|
|
840
|
+
)
|
|
841
|
+
self.updating:add(schema)
|
|
842
|
+
local committed
|
|
843
|
+
do
|
|
844
|
+
local ____try, ____error = pcall(function()
|
|
845
|
+
local next = update(nil, draft)
|
|
846
|
+
if next == nil or type(next) ~= "table" then
|
|
847
|
+
error("Store updater must return settings", 0)
|
|
848
|
+
end
|
|
849
|
+
committed = copy(nil, next)
|
|
850
|
+
end)
|
|
851
|
+
do
|
|
852
|
+
self.updating:delete(schema)
|
|
853
|
+
end
|
|
854
|
+
if not ____try then
|
|
855
|
+
error(____error, 0)
|
|
856
|
+
end
|
|
857
|
+
end
|
|
858
|
+
if schema.Token == nil then
|
|
859
|
+
self.memory:set(schema, committed)
|
|
860
|
+
else
|
|
861
|
+
self.saved[schema.Token] = committed
|
|
862
|
+
end
|
|
863
|
+
local listeners = {__TS__Spread(self.observers:get(schema) or ({}))}
|
|
864
|
+
for ____, observer in ipairs(listeners) do
|
|
865
|
+
do
|
|
866
|
+
local function ____catch()
|
|
867
|
+
print("|cffff5555[wuira] Store observer failed after commit|r")
|
|
868
|
+
end
|
|
869
|
+
local ____try = pcall(function()
|
|
870
|
+
observer(
|
|
871
|
+
nil,
|
|
872
|
+
copy(nil, committed)
|
|
873
|
+
)
|
|
874
|
+
end)
|
|
875
|
+
if not ____try then
|
|
876
|
+
____catch()
|
|
877
|
+
end
|
|
878
|
+
end
|
|
879
|
+
end
|
|
880
|
+
end
|
|
881
|
+
function StoreRegistry.prototype.subscribe(self, schema, observer)
|
|
882
|
+
self:Read(schema)
|
|
883
|
+
local listeners = self.observers:get(schema)
|
|
884
|
+
if listeners == nil then
|
|
885
|
+
listeners = __TS__New(Set)
|
|
886
|
+
self.observers:set(schema, listeners)
|
|
887
|
+
end
|
|
888
|
+
local function listener(____, value)
|
|
889
|
+
return observer(nil, value)
|
|
890
|
+
end
|
|
891
|
+
listeners:add(listener)
|
|
892
|
+
return function()
|
|
893
|
+
listeners:delete(listener)
|
|
894
|
+
end
|
|
895
|
+
end
|
|
896
|
+
function StoreRegistry.prototype.Dispose(self)
|
|
897
|
+
local ____opt_12 = self.listener
|
|
898
|
+
if ____opt_12 ~= nil then
|
|
899
|
+
____opt_12:UnregisterAllEvents()
|
|
900
|
+
end
|
|
901
|
+
local ____opt_14 = self.listener
|
|
902
|
+
if ____opt_14 ~= nil then
|
|
903
|
+
____opt_14:SetScript("OnEvent", nil)
|
|
904
|
+
end
|
|
905
|
+
local ____opt_16 = self.listener
|
|
906
|
+
if ____opt_16 ~= nil then
|
|
907
|
+
____opt_16:Hide()
|
|
908
|
+
end
|
|
909
|
+
self.listener = nil
|
|
910
|
+
self.observers:clear()
|
|
911
|
+
self.readyCallbacks = {}
|
|
912
|
+
end
|
|
913
|
+
__TS__SetDescriptor(
|
|
914
|
+
StoreRegistry.prototype,
|
|
915
|
+
"IsReady",
|
|
916
|
+
{get = function(self)
|
|
917
|
+
return self.options == nil or self.saved ~= nil
|
|
918
|
+
end},
|
|
919
|
+
true
|
|
920
|
+
)
|
|
921
|
+
return ____exports
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wuira",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"author": {
|
|
5
5
|
"name": "Kerim Cetinbas",
|
|
6
6
|
"email": "a.cetinbas@icloud.com"
|
|
@@ -20,6 +20,10 @@
|
|
|
20
20
|
"types": "./lib/datasources/index.d.ts",
|
|
21
21
|
"default": "./lib/datasources/index.lua"
|
|
22
22
|
},
|
|
23
|
+
"./store": {
|
|
24
|
+
"types": "./lib/store/index.d.ts",
|
|
25
|
+
"default": "./lib/store/index.lua"
|
|
26
|
+
},
|
|
23
27
|
"./console-polyfill": {
|
|
24
28
|
"types": "./lib/console-polyfill.d.ts",
|
|
25
29
|
"default": "./lib/console-polyfill.lua"
|
|
@@ -36,6 +40,9 @@
|
|
|
36
40
|
"datasources": [
|
|
37
41
|
"lib/datasources/index.d.ts"
|
|
38
42
|
],
|
|
43
|
+
"store": [
|
|
44
|
+
"lib/store/index.d.ts"
|
|
45
|
+
],
|
|
39
46
|
"console-polyfill": [
|
|
40
47
|
"lib/console-polyfill.d.ts"
|
|
41
48
|
]
|
package/tools/build-library.mjs
CHANGED
|
@@ -8,7 +8,7 @@ const result = spawnSync(process.execPath, [require.resolve("typescript-to-lua/d
|
|
|
8
8
|
if (result.status !== 0) process.exit(result.status || 1);
|
|
9
9
|
fs.mkdirSync(path.join(root, "lib/platform"), { recursive: true });
|
|
10
10
|
fs.copyFileSync(path.join(root, "src/platform/forever.d.ts"), path.join(root, "lib/platform/forever.d.ts"));
|
|
11
|
-
for (const file of ["index.d.ts", "ui/index.d.ts", "datasources/index.d.ts"]) {
|
|
11
|
+
for (const file of ["index.d.ts", "ui/index.d.ts", "datasources/index.d.ts", "store/index.d.ts"]) {
|
|
12
12
|
const target = path.join(root, "lib", file);
|
|
13
13
|
const reference = file === "index.d.ts" ? "./platform/forever.d.ts" : "../platform/forever.d.ts";
|
|
14
14
|
fs.writeFileSync(target, `/// <reference path="${reference}" />\n` + fs.readFileSync(target, "utf8"));
|