wiki-plugin-mech 0.1.19 → 0.1.20

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
@@ -519,11 +519,22 @@
519
519
  // http://localhost:3000/plugin/mech/run/testing-mechs-synchronization/5e269010fc81aebe?args=WyJoZWxsbyIsIndvcmxkIl0
520
520
  async function get_emit({elem,command,args,body,state}) {
521
521
  if (!body) return trouble(elem,`GET expects indented commands to run on the server.`)
522
- const site = state.context.site
522
+ let share = {}
523
+ let where = state.context.site
524
+ if (args.length) {
525
+ for(const arg of args) {
526
+ if (arg in state) {
527
+ inspect(elem,arg,state)
528
+ share[arg] = state[arg]}
529
+ else if (arg.match(/\./)) where=arg
530
+ else {return trouble(elem,`GET expected "${arg}" to name state or site.`)}
531
+ }
532
+ }
533
+ // const site = state.context.site
523
534
  const slug = state.context.slug
524
535
  const itemId = state.context.itemId
525
- const query = `mech=${btoa(JSON.stringify(body))}`
526
- const url = `//${site}/plugin/mech/run/${slug}/${itemId}?${query}`
536
+ const query = `mech=${btoa(JSON.stringify(body))}&state=${btoa(JSON.stringify(share))}`
537
+ const url = `//${where}/plugin/mech/run/${slug}/${itemId}?${query}`
527
538
  elem.innerHTML = command + ` ⇒ in progress`
528
539
  const start = Date.now()
529
540
  let result
@@ -539,10 +550,40 @@
539
550
  if('status' in arg) elem.innerHTML = arg.command + ` ⇒ ${arg.status}`
540
551
  if('trouble' in arg) trouble(elem,arg.trouble)
541
552
  }
553
+ if('debug' in result.state) delete result.state.debug
554
+ Object.assign(state,result.state)
542
555
  const elapsed = ((Date.now() - start)/1000).toFixed(3)
543
556
  elem.innerHTML = command + ` ⇒ ${elapsed} seconds`
544
557
  }
545
558
 
559
+ function delta_emit({elem,command,args,body,state}) {
560
+ const copy = obj => JSON.parse(JSON.stringify(obj))
561
+ const size = obj => JSON.stringify(obj).length
562
+ if (args.length < 1) return trouble(elem,`DELTA expects argument, "have" or "apply" on client.`)
563
+ if (body) return trouble(elem,`DELTA doesn't expect indented input.`)
564
+ switch (args[0]) {
565
+ case 'have':
566
+ const edits = state.context.page.journal
567
+ .filter(item => item.type != 'fork')
568
+ state.recent = edits[edits.length-1].date
569
+ elem.innerHTML = command + ` ⇒ ${new Date(state.recent).toLocaleString()}`
570
+ break
571
+ case 'apply':
572
+ if(!('actions' in state)) return trouble(elem,`DELTA apply expect "actions" as input.`)
573
+ inspect(elem,'actions',state)
574
+ const page = copy(state.context.page)
575
+ const before = size(page)
576
+ for (const action of state.actions)
577
+ apply(page,action)
578
+ state.page = page
579
+ const after = size(page)
580
+ elem.innerHTML = command + ` ⇒ ∆ ${((after-before)/before*100).toFixed(1)}%`
581
+ break
582
+ default:
583
+ trouble(elem,`DELTA doesn't know "${args[0]}".`)
584
+ }
585
+ }
586
+
546
587
 
547
588
  // C A T A L O G
548
589
 
@@ -566,7 +607,8 @@
566
607
  RANDOM: {emit:random_emit},
567
608
  SLEEP: {emit:sleep_emit},
568
609
  TOGETHER:{emit:together_emit},
569
- GET: {emit:get_emit}
610
+ GET: {emit:get_emit},
611
+ DELTA: {emit:delta_emit}
570
612
  }
571
613
 
572
614
 
@@ -792,4 +834,83 @@
792
834
  return this.direction}
793
835
  }
794
836
 
837
+ // adapted from wiki-client/lib/revision.coffee
838
+
839
+ // This module interprets journal actions in order to update
840
+ // a story or even regenerate a complete story from some or
841
+ // all of a journal.
842
+
843
+ function apply(page, action) {
844
+ const order = () => {
845
+ return (page.story || []).map(item => item?.id);
846
+ };
847
+
848
+ const add = (after, item) => {
849
+ const index = order().indexOf(after) + 1;
850
+ page.story.splice(index, 0, item);
851
+ };
852
+
853
+ const remove = () => {
854
+ const index = order().indexOf(action.id);
855
+ if (index !== -1) {
856
+ page.story.splice(index, 1);
857
+ }
858
+ };
859
+
860
+ page.story = page.story || [];
861
+
862
+ switch (action.type) {
863
+ case 'create':
864
+ if (action.item) {
865
+ if (action.item.title != null) {
866
+ page.title = action.item.title;
867
+ }
868
+ if (action.item.story != null) {
869
+ page.story = action.item.story.slice();
870
+ }
871
+ }
872
+ break;
873
+ case 'add':
874
+ add(action.after, action.item);
875
+ break;
876
+ case 'edit':
877
+ const index = order().indexOf(action.id);
878
+ if (index !== -1) {
879
+ page.story.splice(index, 1, action.item);
880
+ } else {
881
+ page.story.push(action.item);
882
+ }
883
+ break;
884
+ case 'move':
885
+ // construct relative addresses from absolute order
886
+ const moveIndex = action.order.indexOf(action.id);
887
+ const after = action.order[moveIndex - 1];
888
+ const item = page.story[order().indexOf(action.id)];
889
+ remove();
890
+ add(after, item);
891
+ break;
892
+ case 'remove':
893
+ remove();
894
+ break;
895
+ }
896
+
897
+ page.journal = page.journal || [];
898
+ if (action.fork) {
899
+ // implicit fork
900
+ page.journal.push({ type: 'fork', site: action.fork, date: action.date - 1 });
901
+ }
902
+ page.journal.push(action);
903
+ }
904
+
905
+ function create(revIndex, data) {
906
+ revIndex = +revIndex;
907
+ const revJournal = data.journal.slice(0, revIndex + 1);
908
+ const revPage = { title: data.title, story: [] };
909
+ for (const action of revJournal) {
910
+ apply(revPage, action || {});
911
+ }
912
+ return revPage;
913
+ }
914
+
915
+
795
916
  }).call(this)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wiki-plugin-mech",
3
- "version": "0.1.19",
3
+ "version": "0.1.20",
4
4
  "description": "Federated Wiki - Mechanism Scripting Plugin",
5
5
  "keywords": [
6
6
  "mech",
package/server/server.js CHANGED
@@ -8,23 +8,24 @@
8
8
  const path = require('path')
9
9
  const process = require('process')
10
10
 
11
+ function cors (req, res, next) {
12
+ res.header('Access-Control-Allow-Origin', '*')
13
+ next()
14
+ }
15
+
11
16
  function startServer(params) {
12
17
  var app = params.app,
13
18
  argv = params.argv
14
19
 
15
- return app.get('/plugin/mech/run/:slug([a-z-]+)/:itemId', (req, res, next) => {
20
+ return app.get('/plugin/mech/run/:slug([a-z-]+)/:itemId', cors, (req, res, next) => {
16
21
  console.log(req.params)
17
22
  try {
18
23
  const slug = req.params.slug
19
24
  const itemId = req.params.itemId
20
25
  const mech = JSON.parse(atob(req.query.mech || 'W10='))
21
- // fs.readFile(path,(err,data) => {
22
- // const page = JSON.parse(data)
23
- // const item = page.story.find(item => item.id == itemId) || null
24
- // return res.json({err,item,mech});
25
- // })
26
+ const share = JSON.parse(atob(req.query.state ||'W10='))
26
27
  const context = {argv,slug}
27
- const state = {context}
28
+ const state = Object.assign(share,{context})
28
29
  run(mech,state)
29
30
  .then(() => {delete state.context; return res.json({mech,state})})
30
31
  .catch(err => {console.log(err); return res.json({err:err.message+' from promise'})})
@@ -123,6 +124,17 @@
123
124
  status(elem,`${(all.bytes/1000000).toFixed(3)} mb in ${all.files} files`)
124
125
  }
125
126
 
127
+ async function delta_emit ({elem,args,state}) {
128
+ const readFile = path => new Promise((res,rej) =>
129
+ fs.readFile(path,(e,v) => e ? rej(e) : res(v)));
130
+ if(!state.recent) return trouble(elem,`DELTA expects "recent" update time in state.`)
131
+ const file = path.join(state.context.argv.db,state.context.slug)
132
+ const page = JSON.parse(await readFile(file))
133
+ state.actions = page.journal
134
+ .filter(action => action.date > state.recent)
135
+ status(elem,`${state.actions.length} recent actions`)
136
+ }
137
+
126
138
 
127
139
  // C A T A L O G
128
140
 
@@ -130,7 +142,8 @@
130
142
  HELLO: {emit:hello_emit},
131
143
  UPTIME: {emit:uptime_emit},
132
144
  SLEEP: {emit:sleep_emit},
133
- COMMONS: {emit:commons_emit}
145
+ COMMONS: {emit:commons_emit},
146
+ DELTA: {emit:delta_emit}
134
147
  }
135
148
 
136
149