@arcticnotes/node-wsh 0.0.10 → 0.0.12

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/lib/index.js CHANGED
@@ -1 +1,2 @@
1
1
  export { WindowsScriptingHost} from './node/node-wsh.js';
2
+ export { Collection} from './node/utils.js';
@@ -3,8 +3,8 @@ import PATH from 'node:path';
3
3
  import { Syncline} from "@arcticnotes/syncline";
4
4
 
5
5
  const COMMAND = 'cscript.exe';
6
- const ARGS = [ '//E:jscript', '//NoLogo'];
7
- const SCRIPT_FILE = PATH.join( PATH.dirname( import.meta.dirname), 'wsh', 'host.js');
6
+ const ARGS = [ '//NoLogo'];
7
+ const SCRIPT_FILE = PATH.join( PATH.dirname( import.meta.dirname), 'wsh', 'host.wsf');
8
8
 
9
9
  export class WindowsScriptingHost extends EventEmitter {
10
10
 
@@ -12,84 +12,24 @@ export class WindowsScriptingHost extends EventEmitter {
12
12
  const command = options.command || COMMAND;
13
13
  const args = options.args || ARGS;
14
14
  const scriptFile = options.scriptFile || SCRIPT_FILE;
15
- const trace = options.trace || 0;
16
- return new WindowsScriptingHost( await Syncline.spawn( command, [ ...args, scriptFile], { trace}));
15
+ return new WindowsScriptingHost( await Syncline.spawn( command, [ ...args, scriptFile], options.syncline), options);
17
16
  }
18
17
 
19
18
  #syncline;
19
+ #closed = false;
20
20
  #finalizer = new FinalizationRegistry( this.#finalized.bind( this));
21
- #ref2proxy = new Map();
22
- #proxy2ref = new WeakMap();
21
+ #ref2proxy = new Map(); // Map< string, WeakRef< Proxy | <custom-mapped>>>
22
+ #proxy2ref = new WeakMap(); // Map< Proxy | <custom-mapped>, string>
23
23
 
24
- #objectHandler = {
25
-
26
- wsh: this,
27
-
28
- get( target, prop) {
29
- if( prop === Symbol.toPrimitive)
30
- return () => `ref#${ target.ref}`;
31
- const encodedTarget = this.wsh.#encode( target.proxy);
32
- const encodedProp = this.wsh.#encode( prop);
33
- const output = JSON.parse( this.wsh.#syncline.exchange( JSON.stringify( [ 'get', encodedTarget, encodedProp])));
34
- switch( output[ 0]) {
35
- case 'value': return this.wsh.#decode( output[ 1]);
36
- case 'error': throw new Error( output[ 1]);
37
- default: throw new Error( `unknown status: ${ output[ 0]}`);
38
- }
39
- },
40
-
41
- set( target, prop, value) {
42
- const encodedTarget = this.wsh.#encode( target.proxy);
43
- const encodedProp = this.wsh.#encode( prop);
44
- const encodedValue = this.wsh.#encode( value);
45
- const output = JSON.parse( this.wsh.#syncline.exchange( JSON.stringify( [ 'set', encodedTarget, encodedProp, encodedValue])));
46
- switch( output[ 0]) {
47
- case 'set': return;
48
- case 'error': throw new Error( output[ 1]);
49
- default: throw new Error( `unknown status: ${ output[ 0]}`);
50
- }
51
- },
52
- };
53
-
54
- #functionHandler = {
55
-
56
- wsh: this,
57
-
58
- get( target, prop) {
59
- if( prop === Symbol.toPrimitive)
60
- return () => `ref#${ target.ref}`;
61
- return undefined;
62
- },
63
-
64
- apply( target, thisArg, argumentList) {
65
- const encodedTarget = this.wsh.#encode( target.proxy);
66
- const encodedThisArg = this.wsh.#encode( thisArg);
67
- const encodedArgumentList = this.wsh.#encode( argumentList);
68
- const output = JSON.parse( this.wsh.#syncline.exchange( JSON.stringify( [ 'apply', encodedTarget, encodedThisArg, encodedArgumentList])));
69
- switch( output[ 0]) {
70
- case 'value': return this.wsh.#decode( output[ 1]);
71
- case 'error': throw new Error( output[ 1]);
72
- default: throw new Error( `unknown status: ${ output[ 0]}`);
73
- }
74
- },
75
-
76
- construct( target, argumentList) {
77
- const encodedTarget = this.wsh.#encode( target.proxy);
78
- const encodedArgumentList = this.wsh.#encode( argumentList);
79
- const output = JSON.parse( this.wsh.#syncline.exchange( JSON.stringify( [ 'construct', encodedTarget, encodedArgumentList])));
80
- switch( output[ 0]) {
81
- case 'value': return this.wsh.#decode( output[ 1]);
82
- case 'error': throw new Error( output[ 1]);
83
- default: throw new Error( `unknown status: ${ output[ 0]}`);
84
- }
85
- },
86
- };
87
-
88
- constructor( syncline) {
24
+ constructor( syncline, options) {
89
25
  super();
90
26
  this.#syncline = syncline;
91
- this.#syncline.on( 'stderr', line => console.log( 'wsh:', line));
92
- this.#syncline.on( 'stdout', line => console.log( 'wsh:', line));
27
+ this.#syncline.on( 'stderr', line => console.log( 'wsh-stderr:', line));
28
+ this.#syncline.on( 'stdout', line => console.log( 'wsh-stdout:', line));
29
+ if( options.printSynclineIO) {
30
+ this.#syncline.on( 'input', line => console.log( 'syncline-input:', line));
31
+ this.#syncline.on( 'output', line => console.log( 'syncline-output', line));
32
+ }
93
33
  }
94
34
 
95
35
  get remoteObjects() {
@@ -101,90 +41,21 @@ export class WindowsScriptingHost extends EventEmitter {
101
41
  };
102
42
  }
103
43
 
104
- global( name) {
44
+ global( name, mapper = undefined) {
105
45
  const output = JSON.parse( this.#syncline.exchange( JSON.stringify( [ 'global', name])));
106
46
  switch( output[ 0]) {
107
- case 'value': return this.#decode( output[ 1]);
47
+ case 'value': return this.#decode( output[ 1], mapper);
108
48
  case 'error': throw new Error( output[ 1]);
109
- default: throw new Error( `unknown status: ${ output[ 0]}`);
49
+ default: throw new Error( `unknown status: ${ output[ 0]}`); // bug
110
50
  }
111
51
  }
112
52
 
113
53
  async disconnect() {
54
+ this.#closed = true;
114
55
  await this.#syncline.close();
115
56
  }
116
57
 
117
- #getOrCreateObject( ref) {
118
- return this.#getOrCreate( ref, this.#objectHandler);
119
- }
120
-
121
- #getOrCreateFunction( ref) {
122
- return this.#getOrCreate( ref, this.#functionHandler);
123
- }
124
-
125
- #getOrCreate( ref, handler) {
126
- const existingWeakRef = this.#ref2proxy.get( ref);
127
- const existingProxy = existingWeakRef && existingWeakRef.deref();
128
- if( existingProxy)
129
- return existingProxy;
130
-
131
- const target = handler === this.#objectHandler? new RemoteObject( ref): new RemoteFunction( ref);
132
- const newProxy = new Proxy( target, handler);
133
- target.proxy = newProxy;
134
- this.#ref2proxy.set( ref, new WeakRef( newProxy)); // may be overwriting a dead WeakRef
135
- this.#proxy2ref.set( newProxy, ref);
136
- this.#finalizer.register( newProxy, ref);
137
- this.emit( 'ref', ref, newProxy);
138
- return newProxy;
139
- }
140
-
141
- #finalized( ref) {
142
- if( this.#ref2proxy.get( ref).deref() === undefined) // otherwise, it's overwritten by a refreshed proxy
143
- this.#ref2proxy.delete( ref);
144
- const output = this.#syncline.exchange( JSON.stringify( [ 'unref', ref]));
145
- this.emit( 'unref', ref);
146
- }
147
-
148
- #encode( decoded) {
149
- switch( typeof decoded) {
150
- case 'boolean':
151
- case 'number':
152
- case 'string':
153
- return decoded;
154
- case 'undefined':
155
- return { type: 'undefined'};
156
- case 'object':
157
- if( decoded === null)
158
- return decoded;
159
- if( decoded instanceof Array) {
160
- const encoded = [];
161
- for( const item of decoded)
162
- encoded.push( this.#encode( item));
163
- return encoded;
164
- }
165
- if( decoded instanceof RemoteObject) {
166
- const objref = this.#proxy2ref.get( decoded);
167
- if( objref === undefined) // not because garbage-collected, because clearly `decoded` is still alive
168
- throw new Error( `remote object reference not found: ${ decoded}`);
169
- return { type: 'objref', value: objref};
170
- }
171
- const encoded = { type: 'object', value: {}};
172
- for( const [ name, value] of Object.entries( decoded))
173
- encoded.value[ name] = this.#encode( value);
174
- return encoded;
175
- case 'function':
176
- const funref = this.#proxy2ref.get( decoded);
177
- if( funref === undefined) // not because garbage-collected, because clearly `decoded` is still alive
178
- throw new Error( `functions from node are disallowed: ${ decoded}`);
179
- return { type: 'funref', value: funref};
180
- case 'bigint':
181
- case 'symbol':
182
- default:
183
- throw new Error( `unsupported value: ${ decoded}`);
184
- }
185
- }
186
-
187
- #decode( encoded) {
58
+ #decode( encoded, mapper) {
188
59
  switch( typeof encoded) {
189
60
  case 'boolean':
190
61
  case 'number':
@@ -193,10 +64,10 @@ export class WindowsScriptingHost extends EventEmitter {
193
64
  case 'object':
194
65
  if( encoded === null)
195
66
  return encoded;
196
- if( encoded instanceof Array) {
67
+ if( Array.isArray( encoded)) {
197
68
  const decoded = [];
198
69
  for( const item of encoded)
199
- decoded.push( this.#decode( item));
70
+ decoded.push( this.#decode( item, mapper));
200
71
  return decoded;
201
72
  }
202
73
  switch( encoded.type) {
@@ -205,12 +76,10 @@ export class WindowsScriptingHost extends EventEmitter {
205
76
  case 'object':
206
77
  const decoded = {};
207
78
  for( const [ name, value] of Object.entries( encoded.value))
208
- decoded[ name] = this.#decode( value);
79
+ decoded[ name] = this.#decode( value, mapper);
209
80
  return decoded;
210
- case 'objref':
211
- return this.#getOrCreateObject( encoded.value);
212
- case 'funref':
213
- return this.#getOrCreateFunction( encoded.value);
81
+ case 'ref':
82
+ return this.#getOrCreate( encoded.value, mapper);
214
83
  default:
215
84
  throw new Error( `illegal value: ${ encoded}`);
216
85
  }
@@ -222,49 +91,147 @@ export class WindowsScriptingHost extends EventEmitter {
222
91
  throw new Error( `illegal value: ${ encoded}`);
223
92
  }
224
93
  }
225
- }
226
-
227
- class RemoteObject {
228
94
 
229
- #ref;
230
- #proxy;
231
-
232
- constructor( ref) {
233
- this.#ref = ref;
95
+ #encode( decoded) {
96
+ switch( typeof decoded) {
97
+ case 'boolean':
98
+ case 'number':
99
+ case 'string':
100
+ return decoded;
101
+ case 'undefined':
102
+ return { type: 'undefined'};
103
+ case 'object': {
104
+ if( decoded === null)
105
+ return decoded;
106
+ const ref = this.#proxy2ref.get( decoded);
107
+ if( ref !== undefined)
108
+ return { type: 'ref', value: ref};
109
+ if( Array.isArray( decoded)) {
110
+ const encoded = [];
111
+ for( const item of decoded)
112
+ encoded.push( this.#encode( item));
113
+ return encoded;
114
+ }
115
+ const encoded = { type: 'object', value: {}};
116
+ for( const [ name, value] of Object.entries( decoded))
117
+ encoded.value[ name] = this.#encode( value);
118
+ return encoded;
119
+ }
120
+ case 'function': {
121
+ const ref = this.#proxy2ref.get( decoded);
122
+ if( ref !== undefined)
123
+ return { type: 'ref', value: ref};
124
+ throw new Error( `functions from node cannot be sent: ${ decoded}`);
125
+ }
126
+ case 'bigint':
127
+ case 'symbol':
128
+ default:
129
+ throw new Error( `unsupported value: ${ decoded}`);
130
+ }
234
131
  }
235
132
 
236
- get ref() {
237
- return this.#ref;
238
- }
133
+ #getOrCreate( ref, mapper) {
134
+ const existingWeakRef = this.#ref2proxy.get( ref);
135
+ const existingProxy = existingWeakRef && existingWeakRef.deref();
136
+ if( existingProxy)
137
+ return existingProxy;
239
138
 
240
- get proxy() {
241
- return this.#proxy;
139
+ const newProxy = new RemoteObject( this.#syncline, this.#encode.bind( this), this.#decode.bind( this), ref, mapper).proxy;
140
+ if( this.#proxy2ref.has( newProxy)) // sanity check, doesn't catch all misbehaving mappers
141
+ throw new Error( `mapper must return new objects: ${ newProxy}`);
142
+ this.#ref2proxy.set( ref, new WeakRef( newProxy)); // may be overwriting a dead WeakRef
143
+ this.#proxy2ref.set( newProxy, ref);
144
+ this.#finalizer.register( newProxy, ref);
145
+ this.emit( 'ref', ref, newProxy);
146
+ return newProxy;
242
147
  }
243
148
 
244
- set proxy( proxy) {
245
- this.#proxy = proxy;
149
+ #finalized( ref) {
150
+ if( this.#ref2proxy.get( ref).deref() === undefined) // otherwise, it's overwritten by a refreshed proxy
151
+ this.#ref2proxy.delete( ref);
152
+ if( !this.#closed)
153
+ this.#syncline.exchange( JSON.stringify( [ 'unref', ref]));
154
+ this.emit( 'unref', ref);
246
155
  }
247
156
  }
248
157
 
249
- class RemoteFunction extends Function {
158
+ class RemoteObject extends Function {
159
+
160
+ static #handler = {
161
+ get: ( ticket, prop) => ticket.get( prop, undefined),
162
+ set: ( ticket, prop, value) => ticket.set( prop, value),
163
+ apply: ( ticket, thisArg, argumentsList) => ticket.apply( thisArg, argumentsList, undefined),
164
+ construct: ( ticket, argumentsList) => ticket.construct( argumentsList, undefined),
165
+ };
250
166
 
167
+ #syncline;
168
+ #encode;
169
+ #decode;
251
170
  #ref;
252
171
  #proxy;
253
172
 
254
- constructor( ref) {
173
+ constructor( syncline, encode, decode, ref, mapper) {
255
174
  super();
175
+ this.#syncline = syncline;
176
+ this.#encode = encode;
177
+ this.#decode = decode;
256
178
  this.#ref = ref;
257
- }
258
-
259
- get ref() {
260
- return this.#ref;
179
+ this.#proxy = mapper? mapper( this): this.newProxy();
261
180
  }
262
181
 
263
182
  get proxy() {
264
183
  return this.#proxy;
265
184
  }
266
185
 
267
- set proxy( proxy) {
268
- this.#proxy = proxy;
186
+ newProxy() {
187
+ return new Proxy( this, RemoteObject.#handler);
188
+ }
189
+
190
+ get( prop, mapper) {
191
+ if( prop === Symbol.toPrimitive)
192
+ return () => `ref#${ this.#ref}`;
193
+ const encodedTarget = this.#encode( this.#proxy);
194
+ const encodedProp = this.#encode( prop);
195
+ const output = JSON.parse( this.#syncline.exchange( JSON.stringify( [ 'get', encodedTarget, encodedProp])));
196
+ switch( output[ 0]) {
197
+ case 'value': return this.#decode( output[ 1], mapper);
198
+ case 'error': throw new Error( output[ 1]);
199
+ default: throw new Error( `unknown status: ${ output[ 0]}`);
200
+ }
201
+ }
202
+
203
+ set( prop, value) {
204
+ const encodedTarget = this.#encode( this.#proxy);
205
+ const encodedProp = this.#encode( prop);
206
+ const encodedValue = this.#encode( value);
207
+ const output = JSON.parse( this.#syncline.exchange( JSON.stringify( [ 'set', encodedTarget, encodedProp, encodedValue])));
208
+ switch( output[ 0]) {
209
+ case 'set': return true;
210
+ case 'error': throw new Error( output[ 1]);
211
+ default: throw new Error( `unknown status: ${ output[ 0]}`);
212
+ }
213
+ }
214
+
215
+ apply( thisArg, argumentsList, mapper) {
216
+ const encodedTarget = this.#encode( this.#proxy);
217
+ const encodedThisArg = this.#encode( thisArg);
218
+ const encodedArgumentList = this.#encode( [ ...argumentsList]); // argumentsList may not be instanceof Array
219
+ const output = JSON.parse( this.#syncline.exchange( JSON.stringify( [ 'apply', encodedTarget, encodedThisArg, encodedArgumentList])));
220
+ switch( output[ 0]) {
221
+ case 'value': return this.#decode( output[ 1], mapper);
222
+ case 'error': throw new Error( output[ 1]);
223
+ default: throw new Error( `unknown status: ${ output[ 0]}`);
224
+ }
225
+ }
226
+
227
+ construct( argumentsList, mapper) {
228
+ const encodedTarget = this.#encode( this.#proxy);
229
+ const encodedArgumentList = this.#encode( [ ...argumentsList]); // argumentsList may not be instanceof Array
230
+ const output = JSON.parse( this.#syncline.exchange( JSON.stringify( [ 'construct', encodedTarget, encodedArgumentList])));
231
+ switch( output[ 0]) {
232
+ case 'value': return this.#decode( output[ 1], mapper);
233
+ case 'error': throw new Error( output[ 1]);
234
+ default: throw new Error( `unknown status: ${ output[ 0]}`);
235
+ }
269
236
  }
270
237
  }
@@ -0,0 +1,24 @@
1
+ export class Collection {
2
+
3
+ #ticket;
4
+ #type;
5
+
6
+ constructor( ticket, type) {
7
+ this.#ticket = ticket;
8
+ this.#type = type;
9
+ }
10
+
11
+ get length() {
12
+ return this.#ticket.get( 'Count');
13
+ }
14
+
15
+ get( indexBase0) {
16
+ return this.#ticket.get( 'Item', t2 => t2.apply.bind( t2))( this, [ indexBase0 + 1], t3 => new this.#type( t3));
17
+ }
18
+
19
+ *[ Symbol.iterator]() {
20
+ const length = this.length; // expect anomoly if the underlying collect is changing
21
+ for( let i = 0; i < length; i++)
22
+ yield this.get( i);
23
+ }
24
+ }
package/lib/wsh/host.js CHANGED
@@ -1,5 +1,13 @@
1
1
  // This file is in JScript, not in JavaScript. It is executed in Windows Scripting Host (WSH).
2
2
 
3
+ function CreateVBArray( jsArray) {
4
+ var dict = new ActiveXObject( 'Scripting.Dictionary');
5
+ for( var i = 0; i < jsArray.length; i++)
6
+ dict.Add( i, jsArray[ i]);
7
+ dict.Add( 'length', jsArray.length);
8
+ return Dict2VBArray( dict);
9
+ }
10
+
3
11
  var FSO = new ActiveXObject( 'Scripting.FileSystemObject');
4
12
  var OBJECT_TOSTRING = Object.toString();
5
13
  var GLOBAL = this;
@@ -34,21 +42,12 @@ function decode( encoded) {
34
42
  for( i in encoded.value)
35
43
  decoded[ i] = decode( encoded.value[ i]);
36
44
  return decoded;
37
- case 'objref':
38
- item = REFERENCES[ encoded.value];
39
- if( item === undefined)
40
- throw new Error( 'reference not found: ' + encoded.value);
41
- if( item.type !== 'obj')
42
- throw new Error( 'reference type mismatch: ' + encoded.value);
43
- return item.value;
44
- case 'funref':
45
+ case 'ref':
45
46
  item = REFERENCES[ encoded.value];
46
47
  if( item === undefined)
47
48
  throw new Error( 'reference not found: ' + encoded.value);
48
49
  if( item.type === 'potential-method')
49
50
  throw new Error( 'potentially a method, cannot be evaluated standalone: ' + encoded.value);
50
- if( item.type !== 'fun')
51
- throw new Error( 'reference type mismatch: ' + encoded.value);
52
51
  return item.value;
53
52
  default:
54
53
  throw new Error( 'unknown object type: ' + encoded.type);
@@ -87,19 +86,15 @@ function encode( decoded) {
87
86
  encoded.value[ i] = encode( decoded[ i]);
88
87
  return encoded;
89
88
  }
90
- for( i in REFERENCES)
91
- if( REFERENCES[ i].value === decoded)
92
- return { type: 'objref', value: i};
93
- i = '' + nextRefId++;
94
- REFERENCES[ i] = { type: 'obj', value: decoded};
95
- return { type: 'objref', value: i};
89
+ // warning: intentional fall-through here!
90
+ case 'unknown':
96
91
  case 'function':
97
92
  for( i in REFERENCES)
98
93
  if( REFERENCES[ i].value === decoded)
99
- return { type: 'funref', value: i};
94
+ return { type: 'ref', value: i};
100
95
  i = '' + nextRefId++;
101
- REFERENCES[ i] = { type: 'fun', value: decoded};
102
- return { type: 'funref', value: i};
96
+ REFERENCES[ i] = { value: decoded};
97
+ return { type: 'ref', value: i};
103
98
  case 'symbol':
104
99
  case 'bigint':
105
100
  default:
@@ -112,22 +107,22 @@ function encodePotentialMethod( target, prop) {
112
107
  var item;
113
108
  for( i in REFERENCES) {
114
109
  item = REFERENCES[ i];
115
- if( item.type === 'potential-method' && item.target === target, item.prop === prop)
116
- return { type: 'funref', value: i};
110
+ if( item.type === 'potential-method' && item.target === target && item.prop === prop)
111
+ return { type: 'ref', value: i};
117
112
  }
118
113
  i = '' + nextRefId++;
119
114
  REFERENCES[ i] = { type: 'potential-method', target: target, prop: prop};
120
- return { type: 'funref', value: i};
115
+ return { type: 'ref', value: i};
121
116
  }
122
117
 
123
118
  function decodePotentialMethod( encoded) {
124
119
  var item;
125
- if( typeof encoded === 'object' && encoded.type === 'funref') {
120
+ if( typeof encoded === 'object' && encoded.type === 'ref') {
126
121
  item = REFERENCES[ encoded.value];
127
122
  if( item.type === 'potential-method')
128
- return { 'potential-method': true, target: item.target, prop: item.prop};
123
+ return item;
129
124
  }
130
- return { 'potential-method': false, value: decode( encoded)}
125
+ return { type: 'regular', value: decode( encoded)};
131
126
  }
132
127
 
133
128
  ( function() {
@@ -174,11 +169,11 @@ function decodePotentialMethod( encoded) {
174
169
  target = decodePotentialMethod( input[ 1]);
175
170
  thisArg = decode( input[ 2]);
176
171
  args = decode( input[ 3]);
177
- if( target[ 'potential-method']) {
172
+ if( target.type === 'potential-method') {
178
173
  if( thisArg === undefined)
179
- throw new Error( 'potentially a method, can only be used as such');
174
+ throw new Error( 'potentially a method, use with a "this"');
180
175
  if( thisArg !== target.target)
181
- throw new Error( 'potentially a method, can only be used as such');
176
+ throw new Error( 'potentially a method, "this" has changed');
182
177
  switch( args.length) {
183
178
  case 0: output = [ 'value', encode( target.target[ target.prop]())]; break;
184
179
  case 1: output = [ 'value', encode( target.target[ target.prop]( args[ 0]))]; break;
@@ -0,0 +1,9 @@
1
+ Function Dict2VBArray( dict)
2
+ Dim vbArray()
3
+ ReDim vbArray( dict.Item( "length") - 1)
4
+ Dim I
5
+ For I = 0 To dict.Item( "length") - 1
6
+ vbArray( I) = dict.Item( I)
7
+ Next
8
+ Dict2VBArray = vbArray
9
+ End Function
@@ -0,0 +1,4 @@
1
+ <job>
2
+ <script language="VBScript" src="host.vbs" />
3
+ <script language="JScript" src="host.js" />
4
+ </job>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arcticnotes/node-wsh",
3
- "version": "0.0.10",
3
+ "version": "0.0.12",
4
4
  "description": "A Node.js package that runs Windows Scripting Host (WSH) as a child process and exposes the resources from the WSH world to the Node.js world",
5
5
  "author": "Paul <paul@arcticnotes.com>",
6
6
  "license": "MIT",
@@ -21,7 +21,7 @@
21
21
  ".": "./lib/index.js"
22
22
  },
23
23
  "dependencies": {
24
- "@arcticnotes/syncline": "0.0.3"
24
+ "@arcticnotes/syncline": "0.0.4"
25
25
  },
26
26
  "files": [
27
27
  "/lib/"