1 | 'use strict';
|
2 |
|
3 | Object.defineProperty(exports, '__esModule', { value: true });
|
4 |
|
5 | var fs = require('fs');
|
6 |
|
7 | const hookKeys = Object.getOwnPropertyNames(Reflect);
|
8 | class DeepProxy {
|
9 | constructor(root = {}) {
|
10 | this._paths = new WeakMap();
|
11 | if (typeof root !== "object") {
|
12 | throw TypeError("Root value has to be of type object");
|
13 | }
|
14 | this._root = root;
|
15 | const handler = {};
|
16 | for (const hook of hookKeys) {
|
17 | handler[hook] = (t, ...args) => {
|
18 | const path = this._paths.get(t);
|
19 | if (!path)
|
20 | throw Error("Path not found");
|
21 |
|
22 | return this[hook](path,
|
23 |
|
24 | ...args);
|
25 | };
|
26 | }
|
27 | this._handler = handler;
|
28 | this.proxy = this.addPath([], Object.getPrototypeOf(this._root));
|
29 | }
|
30 | addPath(path, proto) {
|
31 | const t = Array.isArray(proto) ? [] : Object.create(proto);
|
32 | this._paths.set(t, path);
|
33 | return new Proxy(t, this._handler);
|
34 | }
|
35 | getByPath(path) {
|
36 | try {
|
37 | const obj = path.reduce((o, k) => o[k], this._root);
|
38 | if (!obj)
|
39 | throw Error();
|
40 | return obj;
|
41 | }
|
42 | catch (e) {
|
43 |
|
44 | throw Error(`Trying to access property ${path.join(".")} failed. Probably because it was removed.`);
|
45 | }
|
46 | }
|
47 | |
48 |
|
49 |
|
50 |
|
51 | getOwnPropertyDescriptor(path, prop) {
|
52 | const target = this.getByPath(path);
|
53 | const descriptor = Reflect.getOwnPropertyDescriptor(target, prop);
|
54 | if (!descriptor)
|
55 | return undefined;
|
56 | return Object.assign(descriptor, { configurable: true });
|
57 | }
|
58 | get(path, prop) {
|
59 | const target = this.getByPath(path);
|
60 | const val = Reflect.get(target, prop);
|
61 | if (typeof val === "object" && val) {
|
62 | return this.addPath([...path, prop], Object.getPrototypeOf(val));
|
63 | }
|
64 | return val;
|
65 | }
|
66 | }
|
67 | for (const key of Object.getOwnPropertyNames(Reflect)) {
|
68 |
|
69 | if (DeepProxy.prototype[key])
|
70 | continue;
|
71 |
|
72 | DeepProxy.prototype[key] = function (path, ...args) {
|
73 | const target = this.getByPath(path);
|
74 | return Reflect[key](target,
|
75 |
|
76 | ...args);
|
77 | };
|
78 | }
|
79 |
|
80 | class BaseProxyStore extends DeepProxy {
|
81 | constructor(root = {}) {
|
82 | super(root);
|
83 | }
|
84 | get store() {
|
85 | return this.proxy;
|
86 | }
|
87 | set store(store) {
|
88 |
|
89 | this._root = store;
|
90 | this.set([], BaseProxyStore.ROOT);
|
91 | }
|
92 | }
|
93 | BaseProxyStore.ROOT = Symbol("ProxyStore root");
|
94 |
|
95 |
|
96 |
|
97 |
|
98 |
|
99 |
|
100 |
|
101 |
|
102 |
|
103 |
|
104 |
|
105 |
|
106 |
|
107 |
|
108 |
|
109 |
|
110 | function __awaiter(thisArg, _arguments, P, generator) {
|
111 | return new (P || (P = Promise))(function (resolve, reject) {
|
112 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
113 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
114 | function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
115 | step((generator = generator.apply(thisArg, _arguments || [])).next());
|
116 | });
|
117 | }
|
118 |
|
119 | function readJSON(path, fallback, reviver) {
|
120 | try {
|
121 | const json = fs.readFileSync(path).toString();
|
122 | return JSON.parse(json, reviver);
|
123 | }
|
124 | catch (e) {
|
125 | if (typeof fallback === "undefined")
|
126 | throw e;
|
127 | return fallback;
|
128 | }
|
129 | }
|
130 | function writeJSON(path, obj, { pretty } = {}, replacer) {
|
131 | if (pretty === true)
|
132 | pretty = 2;
|
133 | else if (pretty === false)
|
134 | pretty = undefined;
|
135 | fs.writeFileSync(path, JSON.stringify(obj, replacer, pretty));
|
136 | }
|
137 | class ProxyStore extends BaseProxyStore {
|
138 | constructor(root = {}, { init = false, path, pretty = false, watch = false, replacer, reviver } = {
|
139 | path: ""
|
140 | }) {
|
141 | if (typeof path !== "string" || !path) {
|
142 | throw TypeError(`Invalid option path="${path}"`);
|
143 | }
|
144 | let r = root;
|
145 | if (init) {
|
146 | r = readJSON(path, r, reviver);
|
147 | }
|
148 | super(r);
|
149 | this.replacer = replacer;
|
150 | this.reviver = reviver;
|
151 | this.path = path;
|
152 | this.pretty = pretty;
|
153 | if (watch) {
|
154 | this.watcher = fs.watch(this.path, () => this.load());
|
155 | }
|
156 | }
|
157 | load() {
|
158 | this._root = readJSON(this.path, this._root, this.reviver);
|
159 | }
|
160 | save() {
|
161 | return __awaiter(this, void 0, void 0, function* () {
|
162 | writeJSON(this.path, this._root, { pretty: this.pretty }, this.replacer);
|
163 | });
|
164 | }
|
165 |
|
166 | set(path, prop, val) {
|
167 | const ret = prop === ProxyStore.ROOT ? true : super.set(path, prop, val);
|
168 | this.save();
|
169 | return ret;
|
170 | }
|
171 |
|
172 | deleteProperty(path, prop) {
|
173 | const ret = super.deleteProperty(path, prop);
|
174 | this.save();
|
175 | return ret;
|
176 | }
|
177 | }
|
178 |
|
179 | function isProxyStoreConstructor(obj) {
|
180 | return (BaseProxyStore === obj || Object.prototype.isPrototypeOf.call(BaseProxyStore, obj));
|
181 | }
|
182 | function proxy(param1, param2, param3) {
|
183 |
|
184 | if (isProxyStoreConstructor(param1)) {
|
185 | const PS = param1;
|
186 | return new PS({}, param2).store;
|
187 | }
|
188 |
|
189 | if (isProxyStoreConstructor(param2)) {
|
190 | const PS = param2;
|
191 | return new PS(param1, param3).store;
|
192 | }
|
193 |
|
194 | throw TypeError("No ProxyStore or derivative of it provided");
|
195 | }
|
196 |
|
197 | exports.DeepProxy = DeepProxy;
|
198 | exports.ProxyStore = BaseProxyStore;
|
199 | exports.ProxyStoreJSON = ProxyStore;
|
200 | exports.default = proxy;
|
201 | exports.proxy = proxy;
|