pinokiod 3.8.1 → 3.8.6

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 (50) hide show
  1. package/kernel/api/fs/index.js +6 -4
  2. package/kernel/api/index.js +102 -31
  3. package/kernel/bin/index.js +143 -4
  4. package/kernel/bin/node.js +9 -0
  5. package/kernel/index.js +32 -1
  6. package/kernel/info.js +1 -0
  7. package/kernel/prototype.js +47 -0
  8. package/kernel/shell.js +110 -54
  9. package/kernel/shells.js +16 -7
  10. package/kernel/store.js +58 -0
  11. package/kernel/util.js +106 -35
  12. package/package.json +1 -1
  13. package/script/index.js +12 -0
  14. package/server/index.js +466 -250
  15. package/server/public/SpaceMono-Bold.ttf +0 -0
  16. package/server/public/SpaceMono-BoldItalic.ttf +0 -0
  17. package/server/public/SpaceMono-Italic.ttf +0 -0
  18. package/server/public/SpaceMono-Regular.ttf +0 -0
  19. package/server/public/filepond-plugin-file-validate-type.min.js +9 -0
  20. package/server/public/filepond-plugin-image-crop.min.js +9 -0
  21. package/server/public/filepond-plugin-image-edit.min.css +8 -0
  22. package/server/public/filepond-plugin-image-edit.min.js +9 -0
  23. package/server/public/filepond-plugin-image-exif-orientation.min.js +9 -0
  24. package/server/public/filepond-plugin-image-preview.min.css +8 -0
  25. package/server/public/filepond-plugin-image-preview.min.js +9 -0
  26. package/server/public/filepond-plugin-image-resize.min.js +9 -0
  27. package/server/public/filepond-plugin-image-transform.min.js +9 -0
  28. package/server/public/filepond.min.css +8 -0
  29. package/server/public/filepond.min.js +9 -0
  30. package/server/public/fscreator.js +160 -0
  31. package/server/public/fseditor.js +189 -0
  32. package/server/public/github.png +0 -0
  33. package/server/public/opener.js +3 -1
  34. package/server/public/pinokio-black.png +0 -0
  35. package/server/public/pinokio-black2.png +0 -0
  36. package/server/public/style.css +131 -9
  37. package/server/socket.js +123 -37
  38. package/server/views/app.ejs +184 -11
  39. package/server/views/editor.ejs +12 -2
  40. package/server/views/explore.ejs +4 -3
  41. package/server/views/help.ejs +4 -2
  42. package/server/views/index.ejs +218 -80
  43. package/server/views/install.ejs +1 -1
  44. package/server/views/local_editor.ejs +282 -0
  45. package/server/views/minterm.ejs +692 -0
  46. package/server/views/partials/menu.ejs +7 -1
  47. package/server/views/prototypes.ejs +463 -0
  48. package/server/views/proxy.ejs +10 -4
  49. package/server/views/settings.ejs +4 -3
  50. package/server/views/terminal.ejs +99 -15
package/kernel/shell.js CHANGED
@@ -13,7 +13,6 @@ const pty = require('@homebridge/node-pty-prebuilt-multiarch')
13
13
  const path = require("path")
14
14
  const sudo = require("sudo-prompt-programfiles-x86");
15
15
  const unparse = require('yargs-unparser-custom-flag');
16
- const shellPath = require('shell-path');
17
16
  const Util = require('./util')
18
17
  const Environment = require('./environment')
19
18
  const home = os.homedir()
@@ -60,36 +59,9 @@ class Shell {
60
59
  }, 1)
61
60
 
62
61
  }
63
- async start(params, ondata) {
64
-
65
- /*
66
- params := {
67
- group: <group id>,
68
- id: <shell id>,
69
- path: <shell cwd (always absolute path)>,
70
- env: <environment value key pairs>
71
- }
72
- */
73
- this.cols = params.cols ? params.cols : 100;
74
- this.rows = params.rows ? params.rows : 30;
75
-
76
- this.vt = new Terminal({
77
- allowProposedApi: true,
78
- cols: this.cols,
79
- rows: this.rows,
80
- })
81
- this.vts = new SerializeAddon()
82
- this.vt.loadAddon(this.vts)
83
-
84
- // 1. id
85
- this.id = (params.id ? params.id : uuidv4())
86
-
87
- // 2. group id
88
- this.group = params.group
89
-
90
- // 2. env
91
- // default env
92
-
62
+ async init_env(params) {
63
+ console.log({ params })
64
+ console.time("> 1")
93
65
  this.env = Object.assign({}, process.env)
94
66
  // If the user has set PYTHONPATH, unset it.
95
67
  if (this.env.PYTHONPATH) {
@@ -103,6 +75,15 @@ class Shell {
103
75
  if (this.env.CMAKE_GENERATOR) {
104
76
  delete this.env.CMAKE_GENERATOR
105
77
  }
78
+
79
+ //this.env.PNPM_CONFIG_PREFIX = this.kernel.path("bin/npm")
80
+ //this.env.pnpm_config_prefix = this.kernel.path("bin/npm")
81
+ // this.env.PNPM_HOME = this.kernel.path("bin/npm")
82
+ // this.env.pnpm_home = this.kernel.path("bin/npm")
83
+
84
+ // this.env.NPM_CONFIG_PREFIX = this.kernel.path("bin/npm")
85
+ // this.env.npm_config_prefix = this.kernel.path("bin/npm")
86
+
106
87
 
107
88
  // if (this.env.CUDA_HOME) {
108
89
  // delete this.env.CUDA_HOME
@@ -117,16 +98,12 @@ class Shell {
117
98
  delete this.env[key]
118
99
  }
119
100
  }
101
+ console.timeEnd("> 1")
102
+ console.time("> 2")
120
103
 
121
104
  this.env.CMAKE_OBJECT_PATH_MAX = 1024
122
105
  this.env.PYTORCH_ENABLE_MPS_FALLBACK = 1
123
106
  this.env.TORCH_FORCE_NO_WEIGHTS_ONLY_LOAD = 1
124
- // if (this.platform === 'win32') {
125
- // this.env.USERPROFILE = this.kernel.homedir
126
- // } else {
127
- // this.env.HOME = this.kernel.homedir
128
- // }
129
-
130
107
  // this.env.PIP_REQUIRE_VIRTUALENV = "true"
131
108
  // this.env.NPM_CONFIG_USERCONFIG = this.kernel.path("user_npmrc")
132
109
  // this.env.NPM_CONFIG_GLOBALCONFIG = this.kernel.path("global_npmrc")
@@ -136,7 +113,9 @@ class Shell {
136
113
  // First override this.env with system env
137
114
  let system_env = await Environment.get(this.kernel.homedir)
138
115
  this.env = Object.assign(this.env, system_env)
116
+ console.timeEnd("> 2")
139
117
 
118
+ console.time("> 3")
140
119
  // if the shell is running from a script file, the params.$parent will include the path to the parent script
141
120
  // this means we need to apply app environment as well
142
121
  if (params.$parent) {
@@ -158,7 +137,7 @@ class Shell {
158
137
  if (this.platform === 'win32') {
159
138
  // ignore
160
139
  } else {
161
- this.env[PATH_KEY]= shellPath.sync() || [
140
+ this.env[PATH_KEY]= this.kernel.shellpath || [
162
141
  './node_modules/.bin',
163
142
  '/.nodebrew/current/bin',
164
143
  '/usr/local/bin',
@@ -177,6 +156,8 @@ class Shell {
177
156
  this.env[PATH_KEY] = this.env[PATH_KEY] + path.delimiter + path.resolve(this.kernel.homedir, 'bin')
178
157
 
179
158
 
159
+ console.timeEnd("> 3")
160
+ console.time("> 4")
180
161
  if (params.env) {
181
162
  for(let key in params.env) {
182
163
  // iterate through the env attributes
@@ -210,8 +191,10 @@ class Shell {
210
191
  }
211
192
  }
212
193
  }
194
+ console.timeEnd("> 4")
213
195
 
214
196
 
197
+ console.time("> 5")
215
198
  for(let key in this.env) {
216
199
  if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(key) && key !== "ProgramFiles(x86)") {
217
200
  delete this.env[key]
@@ -230,6 +213,61 @@ class Shell {
230
213
  delete this.env[key]
231
214
  }
232
215
  }
216
+ console.timeEnd("> 5")
217
+ }
218
+ async start(params, ondata) {
219
+ console.log("shell start", params)
220
+
221
+ /*
222
+ params := {
223
+ group: <group id>,
224
+ id: <shell id>,
225
+ path: <shell cwd (always absolute path)>,
226
+ env: <environment value key pairs>
227
+ }
228
+ */
229
+
230
+ this.cols = 100
231
+ this.rows = 30
232
+
233
+ if (params.cols) {
234
+ this.cols = params.cols
235
+ }
236
+ if (params.rows) {
237
+ this.rows = params.rows
238
+ }
239
+ if (params.client && params.client.cols) {
240
+ this.cols = params.client.cols
241
+ }
242
+ if (params.client && params.client.rows) {
243
+ this.rows = params.client.rows
244
+ }
245
+
246
+ console.log({ cols: this.cols, rows: this.rows })
247
+
248
+
249
+ this.vt = new Terminal({
250
+ allowProposedApi: true,
251
+ cols: this.cols,
252
+ rows: this.rows,
253
+ })
254
+ this.vts = new SerializeAddon()
255
+ this.vt.loadAddon(this.vts)
256
+
257
+ // 1. id
258
+ this.id = (params.id ? params.id : uuidv4())
259
+
260
+ // 2. group id
261
+ this.group = params.group
262
+
263
+ // 2. env
264
+ // default env
265
+ await this.init_env(params)
266
+
267
+
268
+
269
+
270
+
233
271
  // 3. path => path can be http, relative, absolute
234
272
  this.path = params.path
235
273
 
@@ -281,11 +319,12 @@ class Shell {
281
319
  return response
282
320
  } else {
283
321
  let response = await this.request(params, async (stream) => {
284
- if (stream.prompt) {
285
- this.resolve()
286
- } else {
287
- if (ondata) ondata(stream)
288
- }
322
+ if (ondata) ondata(stream)
323
+ // if (stream.prompt) {
324
+ // this.resolve()
325
+ // } else {
326
+ // if (ondata) ondata(stream)
327
+ // }
289
328
  })
290
329
  return response
291
330
  }
@@ -293,8 +332,13 @@ class Shell {
293
332
  // return this.id
294
333
  }
295
334
  emit(message) {
335
+ console.log("> 1", { message, input: this.input })
296
336
  if (this.ptyProcess) {
297
- this.ptyProcess.write(message)
337
+ console.log("> 2")
338
+ if (this.input) {
339
+ console.log("> 3")
340
+ this.ptyProcess.write(message)
341
+ }
298
342
  }
299
343
  }
300
344
  send(message, newline, cb) {
@@ -370,12 +414,16 @@ class Shell {
370
414
  return r
371
415
  }
372
416
  async request(params, cb) {
417
+ console.log("shell.request", params)
373
418
  // create the path if it doesn't exist
374
419
  await fs.promises.mkdir(params.path, { recursive: true }).catch((e) => { })
375
420
 
376
421
 
377
422
  // not connected => make a new connection => which means get a new prompt
378
423
  // if already connected => no need for a new prompt
424
+ if (params.input) {
425
+ this.input = params.input
426
+ }
379
427
  if (params.persistent) {
380
428
  this.persistent = params.persistent
381
429
  }
@@ -907,6 +955,7 @@ class Shell {
907
955
  }
908
956
  }
909
957
  kill(message, force) {
958
+ console.log("KILL")
910
959
 
911
960
  this.done = true
912
961
  this.ready = false
@@ -1014,6 +1063,11 @@ ${cleaned}
1014
1063
 
1015
1064
  }
1016
1065
  stream(msg, callback) {
1066
+ if (msg === "\u0007") {
1067
+ // Ignore bell sound escape character because it slows down everything and makes redundant sound
1068
+ callback()
1069
+ return
1070
+ }
1017
1071
  this.vt.write(msg, () => {
1018
1072
  let buf = this.vts.serialize()
1019
1073
  let cleaned = this.stripAnsi(buf)
@@ -1021,8 +1075,10 @@ ${cleaned}
1021
1075
  id: this.id,
1022
1076
  raw: msg,
1023
1077
  cleaned,
1024
- state: cleaned
1078
+ state: cleaned,
1079
+ shell_id: this.id
1025
1080
  }
1081
+ this.state = cleaned
1026
1082
  if (this.cb) this.cb(response)
1027
1083
 
1028
1084
  // Decide whether to kill or continue
@@ -1037,15 +1093,15 @@ ${cleaned}
1037
1093
  // todo: may need to handle cases when the command returns immediately with no output (example: 'which brew' returns immediately with no text if brew doesn't exist)
1038
1094
  setTimeout(() => {
1039
1095
  if (cache === cleaned) {
1040
- if (this.persistent) {
1041
- if (this.cb) this.cb({
1042
- //raw: cached_msg,
1043
- //raw: msg,
1044
- //raw: "",
1045
- cleaned,
1046
- state: cleaned,
1047
- prompt: true
1048
- })
1096
+ if (this.input || this.persistent) {
1097
+ // if (this.cb) this.cb({
1098
+ // //raw: cached_msg,
1099
+ // //raw: msg,
1100
+ // //raw: "",
1101
+ // cleaned,
1102
+ // state: cleaned,
1103
+ // prompt: true
1104
+ // })
1049
1105
  callback()
1050
1106
  } else {
1051
1107
  callback()
package/kernel/shells.js CHANGED
@@ -35,15 +35,20 @@ class Shells {
35
35
  } else {
36
36
  m = "ls"
37
37
  }
38
- let response = await sh.start({
39
- message: m,
38
+ console.time("init_env")
39
+ await sh.init_env({
40
40
  env: this.kernel.bin.envs({}),
41
- conda: {
42
- skip: true
43
- }
44
- }, async (stream) => {
45
- process.stdout.write(stream.raw)
46
41
  })
42
+ console.timeEnd("init_env")
43
+ // let response = await sh.start({
44
+ // message: m,
45
+ // env: this.kernel.bin.envs({}),
46
+ // conda: {
47
+ // skip: true
48
+ // }
49
+ // }, async (stream) => {
50
+ // process.stdout.write(stream.raw)
51
+ // })
47
52
 
48
53
  this.kernel.envs = sh.env
49
54
  // also set the uppercase variables if they're not set
@@ -76,6 +81,7 @@ class Shells {
76
81
  }
77
82
  }
78
83
  async _launch(params, options, ondata) {
84
+ console.log("_launch", { params, options })
79
85
  // iterate through all the envs
80
86
  params.env = this.kernel.bin.envs(params.env)
81
87
 
@@ -267,6 +273,7 @@ class Shells {
267
273
  }
268
274
  */
269
275
  let session = this.get(params.id)
276
+ console.log("EMIT", { session, params })
270
277
  if (session) {
271
278
  session.emit(params.emit)
272
279
  }
@@ -341,6 +348,7 @@ class Shells {
341
348
  }
342
349
  }
343
350
  async run(req, options, ondata) {
351
+ console.log("shells.run",req)
344
352
  let response = await this.launch(req, options, ondata)
345
353
  // req.id = id
346
354
  // let sh = this.get(id)
@@ -429,6 +437,7 @@ class Shells {
429
437
  }
430
438
  }
431
439
  rm(id) {
440
+ console.log("SHELL RM", id)
432
441
  for(let i=0; i<this.shells.length; i++) {
433
442
  let shell = this.shells[i]
434
443
  if (shell.id === id) {
@@ -0,0 +1,58 @@
1
+ const os = require('os')
2
+ const path = require('path')
3
+ const fs = require('fs')
4
+ class Store {
5
+ constructor() {
6
+ this.root = path.resolve(os.homedir(), ".pinokio")
7
+ if (!fs.existsSync(path.resolve(this.root))) {
8
+ fs.mkdirSync(path.resolve(this.root))
9
+ }
10
+ }
11
+ exists() {
12
+ let p = path.resolve(this.root, "config.json")
13
+ return fs.existsSync(p)
14
+ }
15
+ clone(old) {
16
+ console.log("clone", old)
17
+ let p = path.resolve(this.root, "config.json")
18
+ fs.writeFileSync(p, JSON.stringify(old, null, 2))
19
+ }
20
+ set(key, val) {
21
+ let o
22
+ try {
23
+ let str = fs.readFileSync(path.resolve(this.root, "config.json"), "utf8")
24
+ o = JSON.parse(str)
25
+ } catch(e) {
26
+ o = {}
27
+ }
28
+ o[key] = val
29
+ fs.writeFileSync(path.resolve(this.root, "config.json"), JSON.stringify(o, null, 2))
30
+ }
31
+ get(key) {
32
+ try {
33
+ let str = fs.readFileSync(path.resolve(this.root, "config.json"), "utf8")
34
+ let o = JSON.parse(str)
35
+ return o[key]
36
+ } catch (e) {
37
+ return null
38
+ }
39
+ }
40
+ delete(key) {
41
+ try {
42
+ let str = fs.readFileSync(path.resolve(this.root, "config.json"), "utf8")
43
+ let o = JSON.parse(str)
44
+ delete o[key]
45
+ fs.writeFileSync(path.resolve(this.root, "config.json"), JSON.stringify(o, null, 2))
46
+ } catch (e) {
47
+ }
48
+ }
49
+ store() {
50
+ try {
51
+ let str = fs.readFileSync(path.resolve(this.root, "config.json"), "utf8")
52
+ let o = JSON.parse(str)
53
+ return o
54
+ } catch (e) {
55
+ }
56
+ }
57
+ }
58
+ module.exports = Store
package/kernel/util.js CHANGED
@@ -14,6 +14,9 @@ const groupReplacement = "$$$";
14
14
  const h = "[^\\S\\r\\n]"; // simulate `\h`
15
15
  const returnPattern = /\r/g;
16
16
  const returnReplacement = "\\r";
17
+ const {
18
+ glob
19
+ } = require('glob')
17
20
 
18
21
 
19
22
  // asar handling for go-get-folder-size
@@ -36,26 +39,20 @@ const du = async (folderpath) => {
36
39
  const is_port_available = async (port) => {
37
40
  return new Promise((resolve) => {
38
41
  const server = http.createServer();
39
- console.log("> Checking port availability", port)
40
42
  try {
41
43
  server.listen(port, (err) => {
42
44
  if (err) {
43
- console.log("> [1 port not available]", err)
44
45
  resolve(false); // Port is occupied
45
46
  } else {
46
- console.log("> [2 port available] test server started. closing test server now.")
47
47
  server.close(() => {
48
- console.log("> Test server closed.")
49
48
  resolve(true); // Port is free
50
49
  }); // Close the server immediately after testing
51
50
  }
52
51
  });
53
52
  server.on('error', (err) => {
54
- console.log("> [3 port not available]", err);
55
53
  resolve(false); // Port is occupied
56
54
  });
57
55
  } catch (e) {
58
- console.log("> [4 port not available]", err)
59
56
  resolve(false) // port not available
60
57
  }
61
58
  });
@@ -94,39 +91,89 @@ const parse_env = async (filename) => {
94
91
  return {}
95
92
  }
96
93
  }
97
- const openfs = (dirPath, options) => {
94
+ const openfs = (dirPath, options, kernel) => {
98
95
  let command = '';
99
96
  const platform = os.platform()
100
- let mode = "view"
101
- if (options && options.mode) {
102
- mode = options.mode
103
- }
104
- if (mode === "view") {
105
- switch (platform) {
106
- case 'darwin':
107
- command = `open -R "${dirPath}"`;
108
- break;
109
- case 'win32':
110
- command = `explorer /select,"${dirPath}" & timeout /t 1 >nul`;
111
- break;
112
- default:
113
- command = `xdg-open "${dirPath}"`;
114
- break;
97
+ console.log("openfs", dirPath, options)
98
+ if (options && options.command) {
99
+ let mode = "view"
100
+ if (options && options.command) {
101
+ mode = options.command
102
+ }
103
+ console.log("> mode", mode)
104
+ if (mode === "view") {
105
+ switch (platform) {
106
+ case 'darwin':
107
+ command = `open -R "${dirPath}"`;
108
+ break;
109
+ case 'win32':
110
+ command = `explorer /select,"${dirPath}" & timeout /t 1 >nul`;
111
+ break;
112
+ default:
113
+ command = `xdg-open "${dirPath}"`;
114
+ break;
115
+ }
116
+ child_process.exec(command)
117
+ } else if (mode === "open") {
118
+ switch (platform) {
119
+ case 'darwin':
120
+ command = `open "${dirPath}"`;
121
+ break;
122
+ case 'win32':
123
+ command = `explorer "${dirPath}"`;
124
+ break;
125
+ default:
126
+ command = `xdg-open "${dirPath}"`;
127
+ break;
128
+ }
129
+ child_process.exec(command)
130
+ } else {
131
+ command = `${mode} "${dirPath}"`
132
+ console.log("> command", command)
133
+ if (kernel) {
134
+ kernel.exec({
135
+ message: command,
136
+ }, (e) => {
137
+ process.stdout.write(e.raw)
138
+ }).then(() => {
139
+ console.log("DONE")
140
+ })
141
+ } else {
142
+ child_process.exec(command)
143
+ }
144
+ }
145
+ } else {
146
+ let mode = "view"
147
+ if (options && options.mode) {
148
+ mode = options.mode
115
149
  }
116
- } else if (mode === "open") {
117
- switch (platform) {
118
- case 'darwin':
119
- command = `open "${dirPath}"`;
120
- break;
121
- case 'win32':
122
- command = `explorer "${dirPath}"`;
123
- break;
124
- default:
125
- command = `xdg-open "${dirPath}"`;
126
- break;
150
+ if (mode === "view") {
151
+ switch (platform) {
152
+ case 'darwin':
153
+ command = `open -R "${dirPath}"`;
154
+ break;
155
+ case 'win32':
156
+ command = `explorer /select,"${dirPath}" & timeout /t 1 >nul`;
157
+ break;
158
+ default:
159
+ command = `xdg-open "${dirPath}"`;
160
+ break;
161
+ }
162
+ } else if (mode === "open") {
163
+ switch (platform) {
164
+ case 'darwin':
165
+ command = `open "${dirPath}"`;
166
+ break;
167
+ case 'win32':
168
+ command = `explorer "${dirPath}"`;
169
+ break;
170
+ default:
171
+ command = `xdg-open "${dirPath}"`;
172
+ break;
173
+ }
127
174
  }
175
+ child_process.exec(command)
128
176
  }
129
- child_process.exec(command)
130
177
  }
131
178
  const parse_env_detail = async (filename) => {
132
179
  // takes env and returns an array
@@ -199,6 +246,30 @@ const escapeStringRegexp = (string) => {
199
246
  .replace(/-/g, '\\x2d');
200
247
  }
201
248
 
249
+ const find_python = async (root) => {
250
+ let python_pattern
251
+ if (os.platform() === "win32") {
252
+ python_pattern = "**/python.exe";
253
+ } else {
254
+ python_pattern = "**/python"; // Matches python, python3, python3.x
255
+ }
256
+ const pythonBinaries = await glob(python_pattern, { nodir: true, cwd: root });
257
+ return pythonBinaries
258
+ }
259
+ const find_venv = async (root) => {
260
+ let python_pattern
261
+ if (os.platform() === "win32") {
262
+ python_pattern = "**/python.exe";
263
+ } else {
264
+ python_pattern = "**/python"; // Matches python, python3, python3.x
265
+ }
266
+ const pythonBinaries = await glob(python_pattern, { nodir: true, cwd: root, absolute: true });
267
+ const venvs = pythonBinaries.map((p) => {
268
+ return path.resolve(p, "../..")
269
+ })
270
+ return venvs
271
+ }
272
+
202
273
  const update_env = async (filepath, changes) => {
203
274
  console.log("UPDATE_ENV", { filepath, changes })
204
275
  const env = await fs.promises.readFile(filepath, "utf8")
@@ -237,5 +308,5 @@ const update_env = async (filepath, changes) => {
237
308
  await fs.promises.writeFile(filepath, newval)
238
309
  };
239
310
  module.exports = {
240
- parse_env, log_path, api_path, update_env, parse_env_detail, openfs, port_running, du, is_port_available
311
+ parse_env, log_path, api_path, update_env, parse_env_detail, openfs, port_running, du, is_port_available, find_python, find_venv
241
312
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pinokiod",
3
- "version": "3.8.1",
3
+ "version": "3.8.6",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/script/index.js CHANGED
@@ -4,6 +4,16 @@ const os = require('os')
4
4
  const platform = os.platform()
5
5
  const Server = require('../server')
6
6
  class Store {
7
+ constructor() {
8
+ let o
9
+ try {
10
+ let str = fs.readFileSync(path.resolve(__dirname, "pinokio.json"), "utf8")
11
+ o = JSON.parse(str)
12
+ } catch(e) {
13
+ o = {}
14
+ }
15
+ this.store = o
16
+ }
7
17
  set(key, val) {
8
18
  let o
9
19
  try {
@@ -13,6 +23,7 @@ class Store {
13
23
  o = {}
14
24
  }
15
25
  o[key] = val
26
+ this.store = o
16
27
  fs.writeFileSync(path.resolve(__dirname, "pinokio.json"), JSON.stringify(o, null, 2))
17
28
  }
18
29
  get(key) {
@@ -31,6 +42,7 @@ class Store {
31
42
  console.log("before delete", o)
32
43
  delete o[key]
33
44
  console.log("after delete", o)
45
+ this.store = o
34
46
  fs.writeFileSync(path.resolve(__dirname, "pinokio.json"), JSON.stringify(o, null, 2))
35
47
  } catch (e) {
36
48
  }