wiki-plugin-mech 0.1.17 → 0.1.19

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/client/mech.js CHANGED
@@ -236,6 +236,11 @@
236
236
  inspect(elem,'items',state)
237
237
  story.push(...state.items)
238
238
  break
239
+ case 'page':
240
+ if(!('page' in state)) return trouble(elem,`"page" preview expects "page" state, like from "FROM".`)
241
+ inspect(elem,'page',state)
242
+ story.push(...state.page.story)
243
+ break
239
244
  case 'synopsis':
240
245
  {const text = `This page created with Mech command: "${command}". See [[${state.context.title}]].`
241
246
  story.push({type:'paragraph',text,id:state.context.itemId})}
@@ -282,30 +287,42 @@
282
287
  state.aspect = [{id:item.dataset.id,result:aspects}]
283
288
  }
284
289
 
285
- function tick_emit ({elem,args,body,state}) {
290
+ function tick_emit ({elem,command,args,body,state}) {
286
291
  if(elem.innerHTML.match(/button/)) return
287
292
  if (!body?.length) return trouble(elem,`TICK expects indented blocks to follow.`)
288
293
  const count = args[0] || '1'
289
294
  if (!count.match(/^[1-9][0-9]?$/)) return trouble(elem,`TICK expects a count from 1 to 99`)
290
295
  let clock = null
291
- elem.innerHTML += '<button style="border-width:0;">▶</button>'
292
- elem.querySelector('button').addEventListener('click',event => {
296
+ ready()
297
+ function ready () {
298
+ elem.innerHTML = command+'<button style="border-width:0;">▶</button>'
299
+ elem.querySelector('button').addEventListener('click',start)
300
+ }
301
+ function start (event) {
293
302
  state.debug = event.shiftKey
303
+ const status = ticks => {elem.innerHTML = command + ` ⇒ ${ticks} remaining`}
294
304
  if(clock){
295
305
  clock = clearInterval(clock)
296
306
  delete state.tick
297
307
  } else {
308
+ let working
298
309
  state.tick = +count
299
- run(body,state)
310
+ status(state.tick)
311
+ working = true; run(body,state).then(() => working = false)
300
312
  clock = setInterval(()=>{
313
+ if(working) return
301
314
  if(state.debug) console.log({tick:state.tick})
302
- if(('tick' in state) && --state.tick > 0)
303
- run(body,state)
304
- else
315
+ if(('tick' in state) && --state.tick > 0) {
316
+ status(state.tick)
317
+ working = true; run(body,state).then(() => working = false)
318
+ }
319
+ else {
305
320
  clock = clearInterval(clock)
321
+ ready()
322
+ }
306
323
  },1000)
307
324
  }
308
- })
325
+ }
309
326
  }
310
327
 
311
328
  function until_emit ({elem,command,args,body,state}) {
@@ -450,7 +467,7 @@
450
467
  return trouble(elem,`SHOW expects a slug or site/slug to open in the lineup.`)
451
468
  }
452
469
  } else {
453
- const info = args[0]
470
+ const info = args[0];
454
471
  [site,slug] = info.includes('/')
455
472
  ? info.split(/\//)
456
473
  : [null,info]
@@ -505,18 +522,19 @@
505
522
  const site = state.context.site
506
523
  const slug = state.context.slug
507
524
  const itemId = state.context.itemId
508
- const query = `args=${btoa(JSON.stringify(body))}`
525
+ const query = `mech=${btoa(JSON.stringify(body))}`
509
526
  const url = `//${site}/plugin/mech/run/${slug}/${itemId}?${query}`
510
527
  elem.innerHTML = command + ` ⇒ in progress`
511
528
  const start = Date.now()
512
529
  let result
513
530
  try {
514
531
  result = await fetch(url).then(res => res.ok ? res.json() : res.status)
532
+ if('err' in result) return trouble(elem,`RUN received error "${result.err}"`)
515
533
  } catch(err) {
516
534
  return trouble(elem,`RUN failed with "${err.message}"`)
517
535
  }
518
536
  state.result = result
519
- for(const arg of result.args.flat(9)){
537
+ for(const arg of result.mech.flat(9)){
520
538
  const elem = document.getElementById(arg.key)
521
539
  if('status' in arg) elem.innerHTML = arg.command + ` ⇒ ${arg.status}`
522
540
  if('trouble' in arg) trouble(elem,arg.trouble)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wiki-plugin-mech",
3
- "version": "0.1.17",
3
+ "version": "0.1.19",
4
4
  "description": "Federated Wiki - Mechanism Scripting Plugin",
5
5
  "keywords": [
6
6
  "mech",
package/server/server.js CHANGED
@@ -5,31 +5,31 @@
5
5
  (function() {
6
6
 
7
7
  const fs = require('fs')
8
+ const path = require('path')
8
9
  const process = require('process')
9
10
 
10
11
  function startServer(params) {
11
12
  var app = params.app,
12
13
  argv = params.argv
13
14
 
14
- return app.get('/plugin/mech/run/:slug([a-z-]+)/:itemId', async (req, res) => {
15
+ return app.get('/plugin/mech/run/:slug([a-z-]+)/:itemId', (req, res, next) => {
15
16
  console.log(req.params)
16
17
  try {
17
18
  const slug = req.params.slug
18
19
  const itemId = req.params.itemId
19
- const args = JSON.parse(atob(req.query.args || 'W10='))
20
- const path = `${argv.db}/${slug}`
20
+ const mech = JSON.parse(atob(req.query.mech || 'W10='))
21
21
  // fs.readFile(path,(err,data) => {
22
22
  // const page = JSON.parse(data)
23
23
  // const item = page.story.find(item => item.id == itemId) || null
24
- // return res.json({err,item,args});
24
+ // return res.json({err,item,mech});
25
25
  // })
26
- const context = {path}
26
+ const context = {argv,slug}
27
27
  const state = {context}
28
- run(args,state)
29
- return res.json({args,state})
30
-
28
+ run(mech,state)
29
+ .then(() => {delete state.context; return res.json({mech,state})})
30
+ .catch(err => {console.log(err); return res.json({err:err.message+' from promise'})})
31
31
  } catch(err) {
32
- return res.json({err:err.message})
32
+ return res.json({err:err.message+' from try'})
33
33
  }
34
34
  })
35
35
  }
@@ -60,7 +60,7 @@
60
60
  const stuff = {command,op,args,body,elem,state}
61
61
  if(state.debug) console.log(stuff)
62
62
  if (blocks[op])
63
- blocks[op].emit.apply(null,[stuff])
63
+ await blocks[op].emit.apply(null,[stuff])
64
64
  else
65
65
  if (op.match(/^[A-Z]+$/))
66
66
  trouble(elem,`${op} doesn't name a block we know.`)
@@ -85,12 +85,52 @@
85
85
  status(elem,uptime)
86
86
  }
87
87
 
88
+ function sleep_emit ({elem,command,args,body,state}) {
89
+ let count = args[0] || '1'
90
+ if (!count.match(/^[1-9][0-9]?$/)) return trouble(elem,`SLEEP expects seconds from 1 to 99`)
91
+ return new Promise(resolve => {
92
+ if(body)
93
+ run(body,state)
94
+ .then(result => {if(state.debug) console.log(command,'children', result)})
95
+ setTimeout(() => {
96
+ resolve()
97
+ },1000*count)
98
+ })
99
+ }
100
+
101
+ async function commons_emit ({elem,args,state}) {
102
+ const readdir = dir => new Promise((res,rej) =>
103
+ fs.readdir(dir,(e,v) => e ? rej(e) : res(v)));
104
+ const stat = file => new Promise((res,rej) =>
105
+ fs.stat(file,(e,v) => e ? rej(e) : res(v)));
106
+ const tally = async dir => {
107
+ const count = {files:0,bytes:0}
108
+ const items = await readdir(dir)
109
+ for(const item of items) {
110
+ const itemPath = path.join(dir, item)
111
+ const stats = await stat(itemPath)
112
+ if (state.debug) console.log({itemPath,stats})
113
+ if (stats.isFile()) {
114
+ count.files++
115
+ count.bytes+=stats.size
116
+ }
117
+ }
118
+ return count
119
+ }
120
+ const all = await tally(state.context.argv.commons)
121
+ const here = await tally(path.join(state.context.argv.data,'assets','plugins','image'))
122
+ state.commons = {all,here}
123
+ status(elem,`${(all.bytes/1000000).toFixed(3)} mb in ${all.files} files`)
124
+ }
125
+
88
126
 
89
127
  // C A T A L O G
90
128
 
91
129
  const blocks = {
92
130
  HELLO: {emit:hello_emit},
93
- UPTIME: {emit:uptime_emit}
131
+ UPTIME: {emit:uptime_emit},
132
+ SLEEP: {emit:sleep_emit},
133
+ COMMONS: {emit:commons_emit}
94
134
  }
95
135
 
96
136