@environment-safe/file 0.1.2 → 0.2.0

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@environment-safe/file",
3
- "version": "0.1.2",
3
+ "version": "0.2.0",
4
4
  "type": "module",
5
5
  "main": "dist/index.mjs",
6
6
  "module": "src/index.mjs",
@@ -76,7 +76,7 @@
76
76
  "@environment-safe/chai": "^0.1.0",
77
77
  "@environment-safe/commonjs-builder": "^0.0.3",
78
78
  "@environment-safe/jsdoc-builder": "^0.0.2",
79
- "@open-automaton/moka": "^0.4.1",
79
+ "@open-automaton/moka": "^0.4.2",
80
80
  "babel-plugin-search-and-replace": "^1.1.1",
81
81
  "babel-plugin-transform-import-meta": "^2.2.0",
82
82
  "chai": "^4.3.7",
@@ -88,7 +88,7 @@
88
88
  "scripts": {
89
89
  "lint": "./node_modules/.bin/eslint src/*.mjs test/*.mjs",
90
90
  "test": "npm run import-test; npm run browser-test; npm run require-test",
91
- "import-test": "./node_modules/.bin/mocha test/test.mjs",
91
+ "import-test": "moka test/test.mjs",
92
92
  "import-file-test": "moka --file test/test.html --browser safari file://$(pwd)/test/test.mjs",
93
93
  "browser-file-test": "moka --verbose --file test/test.html --local-browser file://$(pwd)/test/test.mjs",
94
94
  "require-test": "./node_modules/.bin/mocha test/test.cjs",
package/src/buffer.mjs CHANGED
@@ -19,24 +19,41 @@ import { isBrowser, isJsDom } from 'browser-or-node';
19
19
 
20
20
  let InternalBuffer = null;
21
21
 
22
+ const base64ToArrayBuffer = (base64)=>{
23
+ var binaryString = atob(base64);
24
+ var bytes = new Uint8Array(binaryString.length);
25
+ for (var i = 0; i < binaryString.length; i++) {
26
+ bytes[i] = binaryString.charCodeAt(i);
27
+ }
28
+ return bytes.buffer;
29
+ }
30
+
22
31
  if(isBrowser || isJsDom){
23
- InternalBuffer = function(){};
32
+ InternalBuffer = function(value, type){
33
+ if(InternalBuffer.is(value)) return value;
34
+ if(type === 'base64') return base64ToArrayBuffer(value);
35
+ return InternalBuffer.from(value);
36
+ };
24
37
  const enc = new TextEncoder();
25
38
  const dec = new TextDecoder(); //'utf-8'
26
39
  InternalBuffer.from = (ob)=>{
27
40
  const type = Array.isArray(ob)?'array':(typeof ob);
28
- if(InternalBuffer.is(ob)) return ob;
41
+ if(InternalBuffer.is(ob)){
42
+ return ob;
43
+ }
29
44
  switch(type){
30
45
  case 'object':
31
46
  case 'array':
32
47
  case 'string':
33
48
  return enc.encode(ob).buffer;
49
+ break;
34
50
  case '':
35
51
  }
36
52
  };
37
53
  InternalBuffer.is = (buffer)=>{
38
54
  return buffer instanceof ArrayBuffer;
39
55
  };
56
+ const toBinString = (bytes) => bytes.reduce((str, byte) => str + byte.toString(2).padStart(8, '0'), '');
40
57
  InternalBuffer.to = (type, buffer)=>{
41
58
  let result = null;
42
59
  switch(type){
@@ -44,9 +61,24 @@ if(isBrowser || isJsDom){
44
61
  case 'array':
45
62
  case 'string':
46
63
  result = dec.decode(buffer);
47
- return result;
48
- case '':
64
+ break;
65
+ case 'binary-string':
66
+ result = toBinString(Uint8Array.from(buffer));
67
+ break;
68
+ case 'base64':
69
+ result = btoa(InternalBuffer.to('binary-string', buffer));
70
+ break;
71
+ }
72
+ return result;
73
+ };
74
+ InternalBuffer.toString = (type, buffer)=>{
75
+ let result = null;
76
+ if(type === 'base64'){
77
+ result = InternalBuffer.to(type, buffer);;
78
+ }else{
79
+ result = InternalBuffer.to('string', buffer);
49
80
  }
81
+ return result;
50
82
  };
51
83
  InternalBuffer.alloc = (size, fill, encoding='utf-8')=>{
52
84
  const result = new Uint8Array(size);
@@ -58,10 +90,15 @@ if(isBrowser || isJsDom){
58
90
  //todo: convert encoding to byte offset
59
91
  };
60
92
  }else{
61
- InternalBuffer = function(){};
93
+ InternalBuffer = function(value, type){
94
+ return new Buffer(value, type)
95
+ };
62
96
  InternalBuffer.from = (ob='')=>{
63
97
  return Buffer.from(ob);
64
98
  };
99
+ InternalBuffer.is = (buffer)=>{
100
+ return Buffer.isBuffer(buffer);
101
+ };
65
102
  //InternalBuffer = Buffer;
66
103
  InternalBuffer.to = (type, buffer)=>{
67
104
  switch(type){
@@ -71,9 +108,16 @@ if(isBrowser || isJsDom){
71
108
  return buffer.toJSON();
72
109
  case 'string':
73
110
  return buffer.toString();
111
+ case 'base64':
112
+ return btoa(buffer.toString());
74
113
  case '':
114
+
75
115
  }
76
116
  };
117
+ InternalBuffer.toString = (type, buffer)=>{
118
+ if(type === 'base64') return InternalBuffer.to(type, buffer);
119
+ return InternalBuffer.to('string', buffer);
120
+ };
77
121
  }
78
122
 
79
123
  export const FileBuffer = InternalBuffer;
@@ -22,7 +22,6 @@ import {
22
22
  } from '@environment-safe/runtime-context';
23
23
  import { Path } from './path.mjs';
24
24
  //TODO: Streaming
25
-
26
25
  //TODO: browser filesystem contexts
27
26
 
28
27
  const mimesBySuffix = {
@@ -343,6 +342,15 @@ export const serverFile = {
343
342
  return await new Promise((resolve, reject)=>{
344
343
  fs.writeFile(url, buffer, (err)=>{
345
344
  if(err) return reject(err);
345
+ if(globalThis.handleWrite) globalThis.handleWrite({
346
+ path,
347
+ url,
348
+ buffer,
349
+ text: ()=>{
350
+ return FileBuffer.toString('string', buffer)
351
+ },
352
+ arrayBuffer: ()=> buffer,
353
+ });
346
354
  resolve();
347
355
  });
348
356
  });
@@ -427,17 +435,27 @@ export const remote = {
427
435
  },
428
436
  write: async (path, buffer, options={})=>{
429
437
  return await new Promise((resolve, reject)=>{
430
- var element = document.createElement('a');
431
- element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(
432
- FileBuffer.to('string', buffer)
433
- ));
434
- const filename = path.split('/').pop();
435
- element.setAttribute('download', filename);
436
- element.style.display = 'none';
437
- document.body.appendChild(element);
438
- element.click();
439
- document.body.removeChild(element);
440
- resolve();
438
+ try{
439
+ var element = document.createElement('a');
440
+ const type = options.mimeType || 'text/plain';
441
+ const format = options.format || 'charset=utf-8';
442
+ const representation = (
443
+ type === 'text/plain'?
444
+ FileBuffer.toString('text', buffer):
445
+ FileBuffer.toString('base64', buffer)
446
+ );
447
+ const dataURI = `data:${type};${format},${representation}`;
448
+ element.setAttribute('href', dataURI);
449
+ const filename = path.split('/').pop();
450
+ element.setAttribute('download', filename);
451
+ element.style.display = 'none';
452
+ document.body.appendChild(element);
453
+ element.click();
454
+ document.body.removeChild(element);
455
+ resolve();
456
+ }catch(ex){
457
+ reject(ex);
458
+ }
441
459
  });
442
460
  },
443
461
  delete: async (path, options={})=>{
package/src/index.mjs CHANGED
@@ -15,7 +15,7 @@ import {
15
15
  } from '@environment-safe/runtime-context';
16
16
  import { localFile as lf, serverFile as sf, file as f, remote as r, setInputHandler, bindInput} from './filesystem.mjs';
17
17
  import { Path } from './path.mjs';
18
- export { Path, setInputHandler, bindInput };
18
+ export { Path, setInputHandler, bindInput, FileBuffer };
19
19
  const handleCanonicalPath = (dir, os, user)=>{
20
20
 
21
21
  };
@@ -129,6 +129,37 @@ export const remove = async (path)=>{
129
129
 
130
130
  const internalCache = {};
131
131
 
132
+ const mimeTypes = [
133
+ {
134
+ check: [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a],
135
+ mime: 'image/png'
136
+ },
137
+ {
138
+ check: [0xff, 0xd8, 0xff],
139
+ mime: 'image/jpeg'
140
+ },
141
+ {
142
+ check: [0x47, 0x49, 0x46, 0x38],
143
+ mime: 'image/gif'
144
+ }
145
+ ];
146
+
147
+ const checkOne = (headers)=>{
148
+ return (buffers, options = { offset: 0 }) =>
149
+ headers.every(
150
+ (header, index) => header === buffers[options.offset + index]
151
+ );
152
+ };
153
+
154
+ const checks = {};
155
+
156
+ const mimeFromBuffer = (buffer)=>{
157
+ return mimeTypes.reduce((agg, type)=>{
158
+ if(!checks[type.check]) checks[type.check] = checkOne(type.check);
159
+ return agg || (checks[type.check](buffer) && type.mime)
160
+ }, false);
161
+ };
162
+
132
163
  export class File{
133
164
  constructor(path, options={}){
134
165
  //todo: clean this rats nest up
@@ -164,9 +195,27 @@ export class File{
164
195
  body(value){
165
196
  if(value === null || value === undefined) return this.buffer;
166
197
  this.setBuffer(FileBuffer.from(value));
198
+ this.options.mimeType = this.mimeType();
199
+ this.options.format = this.format(this.options.mimeType);
167
200
  return this;
168
201
  }
169
202
 
203
+ mimeType(){
204
+ if(!this.derivedMIMEType){
205
+ this.derivedMIMEType = File.deriveMIMEType(this.body());
206
+ }
207
+ return this.derivedMIMEType;
208
+ }
209
+
210
+ format(){
211
+ if(!this.derivedMIMEType) this.mimeType();
212
+ return File.deriveFormat(this.derivedMIMEType);
213
+ }
214
+
215
+ toDataURL(){
216
+ return `data:${this.mimeType()};${this.format()},${FileBuffer.toString('base64', this.body())}`
217
+ }
218
+
170
219
  async info(){
171
220
  //return await info(this.path);
172
221
  }
@@ -176,6 +225,23 @@ export class File{
176
225
  return this;
177
226
  }
178
227
 
228
+ static deriveMIMEType(bytes){
229
+ //if we can't detect a binary format and it wasn't manually set, assume it's text
230
+ // TODO: manually detect incompatible bytes and provide optional warning
231
+ return mimeFromBuffer(bytes) || 'text/plain';
232
+ }
233
+
234
+ static deriveFormat(mimeType){
235
+ switch(mimeType.toLowerCase()){
236
+ case 'image/png':
237
+ case 'image/jpeg':
238
+ case 'image/gif':
239
+ return 'base64';
240
+ case 'text/plain':
241
+ return 'charset=utf-8';
242
+ }
243
+ }
244
+
179
245
  static async exists(path, directory){
180
246
  return await exists(path, directory);
181
247
  }
@@ -212,6 +278,15 @@ export class Download{
212
278
  }
213
279
  }
214
280
 
281
+ const saveListeners = [];
282
+ export const addEventListener = (event, handler) =>{
283
+ //TODO: support more than save
284
+ if(event !== 'write') throw new Error('unsupported');
285
+ saveListeners.push(handler);
286
+ };
287
+
288
+
289
+
215
290
  (()=>{
216
291
  globalThis.handleDownload = async (download)=>{
217
292
  const root = Path.location('downloads');
@@ -219,6 +294,11 @@ export class Download{
219
294
  const path = Path.join(root, file);
220
295
  await download.saveAs(path);
221
296
  };
297
+ globalThis.handleWrite = async (save)=>{
298
+ saveListeners.forEach((handler)=>{
299
+ handler(save);
300
+ });
301
+ };
222
302
  if(variables.moka && variables.moka.bind){
223
303
  //bind the input mechanics of File to moka
224
304
  variables.moka.bind(bindInput());
package/src/path.mjs CHANGED
@@ -144,6 +144,13 @@ export class Path{
144
144
  static join(...parts){
145
145
  return join(osName, ...parts);
146
146
  }
147
+
148
+ static parent(path){
149
+ const newPath = new Path(path);
150
+ if(newPath.parsed && newPath.parsed.posix) return newPath.parsed.posix.dir;
151
+ if(newPath.parsed && newPath.parsed.windows) return newPath.parsed.windows.dir;
152
+ //TODO: handle link reference
153
+ }
147
154
 
148
155
  constructor(url){
149
156
  const result = {};
package/test/test.html CHANGED
@@ -18,7 +18,6 @@
18
18
  "@babel/core": "../node_modules/@babel/core/./lib/index.js",
19
19
  "@babel/plugin-transform-modules-commonjs": "../node_modules/@babel/plugin-transform-modules-commonjs/./lib/index.js",
20
20
  "@environment-safe/chai": "../node_modules/@environment-safe/chai/./src/index.mjs",
21
- "@environment-safe/commonjs-builder": "../node_modules/@environment-safe/commonjs-builder/./src/index.mjs",
22
21
  "@open-automaton/moka": "../node_modules/@open-automaton/moka/./src/index.mjs",
23
22
  "babel-plugin-search-and-replace": "../node_modules/babel-plugin-search-and-replace/lib/index.js",
24
23
  "babel-plugin-transform-import-meta": "../node_modules/babel-plugin-transform-import-meta/lib/index.esm.mjs",
@@ -43,13 +42,12 @@
43
42
  "@babel/template": "../node_modules/@babel/template/./lib/index.js",
44
43
  "@babel/traverse": "../node_modules/@babel/traverse/./lib/index.js",
45
44
  "@babel/types": "../node_modules/@babel/types/./lib/index.js",
45
+ "@nicolo-ribaudo/semver-v6": "../node_modules/@nicolo-ribaudo/semver-v6/semver.js",
46
46
  "debug": "../node_modules/debug/./src/index.js",
47
47
  "gensync": "../node_modules/gensync/index.js",
48
48
  "json5": "../node_modules/json5/dist/index.mjs",
49
- "semver": "../node_modules/semver/semver.js",
50
49
  "@babel/helper-plugin-utils": "../node_modules/@babel/helper-plugin-utils/./lib/index.js",
51
50
  "@babel/helper-simple-access": "../node_modules/@babel/helper-simple-access/./lib/index.js",
52
- "async-arrays": "../node_modules/async-arrays/async-arrays.mjs",
53
51
  "@environment-safe/import-introspect": "../node_modules/@environment-safe/import-introspect/./src/index.mjs",
54
52
  "@open-automaton/automaton": "../node_modules/@open-automaton/automaton/src/automaton.js",
55
53
  "@open-automaton/cheerio-mining-engine": "../node_modules/@open-automaton/cheerio-mining-engine/src/cheerio.js",
@@ -91,6 +89,7 @@
91
89
  "globals": "../node_modules/globals/",
92
90
  "graphemer": "../node_modules/graphemer/./lib/index.js",
93
91
  "ignore": "../node_modules/ignore/",
92
+ "import-fresh": "../node_modules/import-fresh/",
94
93
  "imurmurhash": "../node_modules/imurmurhash/imurmurhash.js",
95
94
  "is-glob": "../node_modules/is-glob/index.js",
96
95
  "is-path-inside": "../node_modules/is-path-inside/",
@@ -102,6 +101,7 @@
102
101
  "natural-compare": "../node_modules/natural-compare/index.js",
103
102
  "optionator": "../node_modules/optionator/./lib/",
104
103
  "strip-ansi": "../node_modules/strip-ansi/",
104
+ "strip-json-comments": "../node_modules/strip-json-comments/",
105
105
  "text-table": "../node_modules/text-table/index.js",
106
106
  "ansi-colors": "../node_modules/ansi-colors/index.js",
107
107
  "browser-stdout": "../node_modules/browser-stdout/index.js",
@@ -112,7 +112,6 @@
112
112
  "ms": "../node_modules/ms/./index",
113
113
  "nanoid": "../node_modules/nanoid/./index.js",
114
114
  "serialize-javascript": "../node_modules/serialize-javascript/index.js",
115
- "strip-json-comments": "../node_modules/strip-json-comments/",
116
115
  "supports-color": "../node_modules/supports-color/",
117
116
  "workerpool": "../node_modules/workerpool/src/index.js",
118
117
  "yargs-parser": "../node_modules/yargs-parser/./build/lib/index.js",
@@ -125,6 +124,7 @@
125
124
  "once": "../node_modules/once/once.js",
126
125
  "path-is-absolute": "../node_modules/path-is-absolute/",
127
126
  "pify": "../node_modules/pify/",
127
+ "semver": "../node_modules/semver/index.js",
128
128
  "@jridgewell/gen-mapping": "../node_modules/@jridgewell/gen-mapping/dist/gen-mapping.mjs",
129
129
  "@babel/highlight": "../node_modules/@babel/highlight/./lib/index.js",
130
130
  "jsesc": "../node_modules/jsesc/jsesc.js",
@@ -139,12 +139,12 @@
139
139
  "@babel/helper-hoist-variables": "../node_modules/@babel/helper-hoist-variables/./lib/index.js",
140
140
  "@babel/helper-string-parser": "../node_modules/@babel/helper-string-parser/./lib/index.js",
141
141
  "to-fast-properties": "../node_modules/to-fast-properties/",
142
- "sift": "../node_modules/sift/./es5m/index.js",
143
142
  "es-module-lexer": "../node_modules/es-module-lexer/./dist/lexer.js",
144
143
  "@open-automaton/automaton-engine": "../node_modules/@open-automaton/automaton-engine/src/automaton-engine.js",
144
+ "async-arrays": "../node_modules/async-arrays/async-arrays.mjs",
145
145
  "carlton": "../node_modules/carlton/carlton.js",
146
146
  "clone": "../node_modules/clone/clone.js",
147
- "extended-emitter": "../node_modules/extended-emitter/./extended-emitter.mjs",
147
+ "extended-emitter": "../node_modules/extended-emitter/extended-emitter.mjs",
148
148
  "html-parser": "../node_modules/html-parser/./src/parser.js",
149
149
  "libxmljs2": "../node_modules/libxmljs2/./index",
150
150
  "postman-request": "../node_modules/postman-request/index.js",
@@ -153,7 +153,6 @@
153
153
  "cheerio": "../node_modules/cheerio/./lib/esm/index.js",
154
154
  "async-fn-callback": "../node_modules/async-fn-callback/",
155
155
  "jsdom": "../node_modules/jsdom/./lib/api.js",
156
- "playwright": "../node_modules/playwright/./index.mjs",
157
156
  "puppeteer": "../node_modules/puppeteer/./cjs-entry.js",
158
157
  "puppeteer-extra": "../node_modules/puppeteer-extra/dist/index.esm.js",
159
158
  "puppeteer-extra-plugin-stealth": "../node_modules/puppeteer-extra-plugin-stealth/index.js",
@@ -165,7 +164,6 @@
165
164
  "require-directory": "../node_modules/require-directory/index.js",
166
165
  "string-width": "../node_modules/string-width/",
167
166
  "y18n": "../node_modules/y18n/./build/lib/index.js",
168
- "import-fresh": "../node_modules/import-fresh/",
169
167
  "@humanwhocodes/object-schema": "../node_modules/@humanwhocodes/object-schema/src/index.js",
170
168
  "@nodelib/fs.scandir": "../node_modules/@nodelib/fs.scandir/out/index.js",
171
169
  "fastq": "../node_modules/fastq/queue.js",
@@ -183,6 +181,8 @@
183
181
  "flat-cache": "../node_modules/flat-cache/src/cache.js",
184
182
  "locate-path": "../node_modules/locate-path/",
185
183
  "path-exists": "../node_modules/path-exists/",
184
+ "parent-module": "../node_modules/parent-module/",
185
+ "resolve-from": "../node_modules/resolve-from/",
186
186
  "is-extglob": "../node_modules/is-extglob/index.js",
187
187
  "argparse": "../node_modules/argparse/argparse.js",
188
188
  "prelude-ls": "../node_modules/prelude-ls/lib/",
@@ -211,8 +211,10 @@
211
211
  "electron-to-chromium": "../node_modules/electron-to-chromium/index.js",
212
212
  "update-browserslist-db": "../node_modules/update-browserslist-db/",
213
213
  "yallist": "../node_modules/yallist/yallist.js",
214
- "libxmljs": "../node_modules/libxmljs/dist/index.js",
214
+ "libxmljs": "../node_modules/libxmljs/./index",
215
+ "sift": "../node_modules/sift/./es5m/index.js",
215
216
  "es6-template-strings": "../node_modules/es6-template-strings/",
217
+ "wolfy87-eventemitter": "../node_modules/wolfy87-eventemitter/EventEmitter.js",
216
218
  "@mapbox/node-pre-gyp": "../node_modules/@mapbox/node-pre-gyp/./lib/node-pre-gyp.js",
217
219
  "bindings": "../node_modules/bindings/./bindings.js",
218
220
  "nan": "../node_modules/nan/include_dirs.js",
@@ -273,7 +275,6 @@
273
275
  "whatwg-url": "../node_modules/whatwg-url/index.js",
274
276
  "ws": "../node_modules/ws/./wrapper.mjs",
275
277
  "xml-name-validator": "../node_modules/xml-name-validator/lib/xml-name-validator.js",
276
- "playwright-core": "../node_modules/playwright-core/./index.mjs",
277
278
  "cross-fetch": "../node_modules/cross-fetch/dist/node-ponyfill.js",
278
279
  "extract-zip": "../node_modules/extract-zip/index.js",
279
280
  "pkg-dir": "../node_modules/pkg-dir/",
@@ -288,8 +289,6 @@
288
289
  "wrap-ansi": "../node_modules/wrap-ansi/",
289
290
  "emoji-regex": "../node_modules/emoji-regex/index.js",
290
291
  "is-fullwidth-code-point": "../node_modules/is-fullwidth-code-point/",
291
- "parent-module": "../node_modules/parent-module/",
292
- "resolve-from": "../node_modules/resolve-from/",
293
292
  "@nodelib/fs.stat": "../node_modules/@nodelib/fs.stat/out/index.js",
294
293
  "run-parallel": "../node_modules/run-parallel/index.js",
295
294
  "reusify": "../node_modules/reusify/reusify.js",
@@ -297,8 +296,8 @@
297
296
  "shebang-regex": "../node_modules/shebang-regex/",
298
297
  "isexe": "../node_modules/isexe/index.js",
299
298
  "flatted": "../node_modules/flatted/./esm/index.js",
300
- "keyv": "../node_modules/keyv/src/index.js",
301
299
  "p-locate": "../node_modules/p-locate/",
300
+ "callsites": "../node_modules/callsites/",
302
301
  "balanced-match": "../node_modules/balanced-match/index.js",
303
302
  "concat-map": "../node_modules/concat-map/index.js",
304
303
  "picomatch": "../node_modules/picomatch/index.js",
@@ -346,10 +345,8 @@
346
345
  "through": "../node_modules/through/index.js",
347
346
  "merge-deep": "../node_modules/merge-deep/index.js",
348
347
  "puppeteer-extra-plugin-user-data-dir": "../node_modules/puppeteer-extra-plugin-user-data-dir/index.js",
349
- "callsites": "../node_modules/callsites/",
350
348
  "queue-microtask": "../node_modules/queue-microtask/index.js",
351
349
  "color-name": "../node_modules/color-name/index.js",
352
- "json-buffer": "../node_modules/json-buffer/",
353
350
  "p-limit": "../node_modules/p-limit/",
354
351
  "to-regex-range": "../node_modules/to-regex-range/index.js",
355
352
  "es6-iterator": "../node_modules/es6-iterator/",
@@ -449,7 +446,7 @@
449
446
  </script>
450
447
  <script src="/node_modules/mocha/mocha.js"></script>
451
448
 
452
- <script>mocha.setup({ui:'bdd', reporter: 'json-stream'})</script>
449
+ <script>mocha.setup('bdd')</script>
453
450
  <script type="module" src="/test/test.mjs"></script>
454
451
 
455
452
  <script type="module">
package/test/test.mjs CHANGED
@@ -1,4 +1,5 @@
1
1
  /* global describe:false */
2
+ import { isServer } from '@environment-safe/runtime-context';
2
3
  import { chai } from '@environment-safe/chai';
3
4
  import { it, configure, interactive } from '@open-automaton/moka';
4
5
  import { File, Path, Download } from '../src/index.mjs';
@@ -14,12 +15,17 @@ describe('@environment-safe/file', ()=>{
14
15
  const fileProtocolName = `file://${Path.join(Path.current, 'src', 'index.mjs')}`;
15
16
  const missingFileProtocolName = `file://${Path.join(Path.current, 'src', 'unknown.mjs')}`;
16
17
  const fileRelativeName = Path.join('..', 'src', 'index.mjs');
18
+ const fileRelativeSaveName = Path.join(Path.location('downloads'), 'index.mjs');
17
19
  const missingFileRelativeName = Path.join('..', 'src', 'unknown.mjs');
18
20
  const download = new Download();
21
+ if(isServer){
22
+
23
+ }
19
24
  configure({
20
25
  dialog : async (context, actions)=> await actions.confirm(), // OK everything,
21
26
  wantsInput : async (context, actions)=> await actions.click('#mocha'), // click everything
22
- downloads: (dl)=> download.observe(dl)
27
+ downloads: (dl)=> download.observe(dl),
28
+ write: (dl)=> download.observe(dl)
23
29
  });
24
30
  /**********************************************************
25
31
  * Until Playwright supports the filesystem APIs this must
@@ -57,7 +63,7 @@ describe('@environment-safe/file', ()=>{
57
63
  file.body().cast('string').length.should.be.above(1);
58
64
  });
59
65
 
60
- it(`examines & loads ${fileProtocolName}`, async function(){
66
+ it.skip(`examines & loads ${fileProtocolName}`, async function(){
61
67
  this.timeout(40000);
62
68
  should.exist(File);
63
69
  (await File.exists(missingFileProtocolName)).should.equal(false);
@@ -84,9 +90,9 @@ describe('@environment-safe/file', ()=>{
84
90
  should.exist(File);
85
91
  (await File.exists(fileRelativeName)).should.equal(true);
86
92
  const file = new File(fileRelativeName, { cache: true });
87
- //we're going to live dangerously and replace the source, because we save to downloads
88
93
  await file.load();
89
- file.body('foo!');
94
+ file.path = fileRelativeSaveName; //change path
95
+ file.body('foo!'); //replace source
90
96
  const anticipatedDownload = download.expect();
91
97
  await file.save();
92
98
  const result = await anticipatedDownload;