cspell-io 8.16.0 → 8.17.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.
@@ -1,14 +1,19 @@
1
1
  import type { BufferEncoding } from './models/BufferEncoding.js';
2
2
  import type { FileReference, TextFileResource, UrlOrFilename, UrlOrReference } from './models/FileResource.js';
3
3
  import type { DirEntry, Stats } from './models/index.js';
4
+ export interface ReadFileOptions {
5
+ signal?: AbortSignal;
6
+ encoding?: BufferEncoding;
7
+ }
8
+ export type ReadFileOptionsOrEncoding = ReadFileOptions | BufferEncoding;
4
9
  export interface CSpellIO {
5
10
  /**
6
11
  * Read a file
7
12
  * @param urlOrFilename - uri of the file to read
8
- * @param encoding - optional encoding.
13
+ * @param options - optional options for reading the file.
9
14
  * @returns A TextFileResource.
10
15
  */
11
- readFile(urlOrFilename: UrlOrReference, encoding?: BufferEncoding): Promise<TextFileResource>;
16
+ readFile(urlOrFilename: UrlOrReference, options?: ReadFileOptionsOrEncoding): Promise<TextFileResource>;
12
17
  /**
13
18
  * Read a file in Sync mode.
14
19
  * Note: `http` requests will fail.
@@ -88,4 +93,5 @@ export interface CSpellIO {
88
93
  */
89
94
  urlDirname(urlOrFilename: UrlOrReference): URL;
90
95
  }
96
+ export declare function toReadFileOptions(options?: ReadFileOptionsOrEncoding): ReadFileOptions | undefined;
91
97
  //# sourceMappingURL=CSpellIO.d.ts.map
@@ -1,2 +1,9 @@
1
- export {};
1
+ export function toReadFileOptions(options) {
2
+ if (!options)
3
+ return options;
4
+ if (typeof options === 'string') {
5
+ return { encoding: options };
6
+ }
7
+ return options;
8
+ }
2
9
  //# sourceMappingURL=CSpellIO.js.map
@@ -1,10 +1,10 @@
1
1
  import { ServiceBus } from '@cspell/cspell-service-bus';
2
- import type { CSpellIO } from './CSpellIO.js';
2
+ import type { CSpellIO, ReadFileOptionsOrEncoding } from './CSpellIO.js';
3
3
  import type { BufferEncoding, DirEntry, FileReference, Stats, TextFileResource, UrlOrReference } from './models/index.js';
4
4
  export declare class CSpellIONode implements CSpellIO {
5
5
  readonly serviceBus: ServiceBus;
6
6
  constructor(serviceBus?: ServiceBus);
7
- readFile(urlOrFilename: UrlOrReference, encoding?: BufferEncoding): Promise<TextFileResource>;
7
+ readFile(urlOrFilename: UrlOrReference, options?: ReadFileOptionsOrEncoding): Promise<TextFileResource>;
8
8
  readDirectory(urlOrFilename: string | URL): Promise<DirEntry[]>;
9
9
  readFileSync(urlOrFilename: UrlOrReference, encoding?: BufferEncoding): TextFileResource;
10
10
  writeFile(urlOrFilename: UrlOrReference, content: string | ArrayBufferView): Promise<FileReference>;
@@ -1,7 +1,8 @@
1
1
  import { isServiceResponseSuccess, ServiceBus } from '@cspell/cspell-service-bus';
2
- import { isFileReference, toFileReference } from './common/CFileReference.js';
2
+ import { isFileReference, toFileReference, toFileResourceRequest } from './common/CFileReference.js';
3
3
  import { CFileResource } from './common/CFileResource.js';
4
4
  import { compareStats } from './common/stat.js';
5
+ import { toReadFileOptions } from './CSpellIO.js';
5
6
  import { ErrorNotImplemented } from './errors/errors.js';
6
7
  import { registerHandlers } from './handlers/node/file.js';
7
8
  import { toFileURL, toURL, urlBasename, urlDirname } from './node/file/url.js';
@@ -14,8 +15,9 @@ export class CSpellIONode {
14
15
  this.serviceBus = serviceBus;
15
16
  registerHandlers(serviceBus);
16
17
  }
17
- readFile(urlOrFilename, encoding) {
18
- const ref = toFileReference(urlOrFilename, encoding);
18
+ readFile(urlOrFilename, options) {
19
+ const readOptions = toReadFileOptions(options);
20
+ const ref = toFileResourceRequest(urlOrFilename, readOptions?.encoding, readOptions?.signal);
19
21
  const res = this.serviceBus.dispatch(RequestFsReadFile.create(ref));
20
22
  if (!isServiceResponseSuccess(res)) {
21
23
  throw genError(res.error, 'readFile');
@@ -118,7 +118,7 @@ function fsPassThroughCore(fs) {
118
118
  providerInfo: { name: 'default' },
119
119
  hasProvider: true,
120
120
  stat: async (url) => gfs(url, 'stat').stat(url),
121
- readFile: async (url) => gfs(url, 'readFile').readFile(url),
121
+ readFile: async (url, options) => gfs(url, 'readFile').readFile(url, options),
122
122
  writeFile: async (file) => gfs(file, 'writeFile').writeFile(file),
123
123
  readDirectory: async (url) => gfs(url, 'readDirectory')
124
124
  .readDirectory(url)
@@ -13,6 +13,10 @@ export declare enum FSCapabilityFlags {
13
13
  export interface FileSystemProviderInfo {
14
14
  name: string;
15
15
  }
16
+ export interface ReadFileOptions {
17
+ signal?: AbortSignal;
18
+ encoding?: BufferEncoding;
19
+ }
16
20
  export interface VFileSystemCore {
17
21
  /**
18
22
  * Read a file.
@@ -20,7 +24,14 @@ export interface VFileSystemCore {
20
24
  * @param encoding - optional encoding
21
25
  * @returns A FileResource, the content will not be decoded. Use `.getText()` to get the decoded text.
22
26
  */
23
- readFile(url: UrlOrReference, encoding?: BufferEncoding): Promise<TextFileResource>;
27
+ readFile(url: UrlOrReference, encoding: BufferEncoding): Promise<TextFileResource>;
28
+ /**
29
+ * Read a file.
30
+ * @param url - URL to read
31
+ * @param options - options for reading the file.
32
+ * @returns A FileResource, the content will not be decoded. Use `.getText()` to get the decoded text.
33
+ */
34
+ readFile(url: UrlOrReference, options?: ReadFileOptions | BufferEncoding): Promise<TextFileResource>;
24
35
  /**
25
36
  * Write a file
26
37
  * @param file - the file to write
@@ -2,8 +2,8 @@ import type { CSpellIO } from '../CSpellIO.js';
2
2
  import type { BufferEncoding, DirEntry, FileReference, FileResource, TextFileResource } from '../models/index.js';
3
3
  import { FileType } from '../models/index.js';
4
4
  import type { LogEvent } from '../models/LogEvent.js';
5
- import { FileSystemProviderInfo, FSCapabilities, FSCapabilityFlags, UrlOrReference, VFileSystemCore, VfsDirEntry, VfsStat } from '../VFileSystem.js';
6
- import { VFileSystemProvider, VProviderFileSystem } from '../VirtualFS.js';
5
+ import { FileSystemProviderInfo, FSCapabilities, FSCapabilityFlags, ReadFileOptions, UrlOrReference, VFileSystemCore, VfsDirEntry, VfsStat } from '../VFileSystem.js';
6
+ import type { VFileSystemProvider, VProviderFileSystem } from '../VirtualFS.js';
7
7
  export declare function cspellIOToFsProvider(cspellIO: CSpellIO): VFileSystemProvider;
8
8
  export declare class VFSError extends Error {
9
9
  constructor(message: string, options?: {
@@ -12,9 +12,9 @@ export declare class VFSError extends Error {
12
12
  }
13
13
  export declare class VFSErrorUnsupportedRequest extends VFSError {
14
14
  readonly request: string;
15
- readonly parameters?: unknown;
15
+ readonly parameters?: unknown | undefined;
16
16
  readonly url?: string | undefined;
17
- constructor(request: string, url?: URL | string, parameters?: unknown);
17
+ constructor(request: string, url?: URL | string, parameters?: unknown | undefined);
18
18
  }
19
19
  export declare function fsCapabilities(flags: FSCapabilityFlags): FSCapabilities;
20
20
  export declare class WrappedProviderFs implements VFileSystemCore {
@@ -28,7 +28,7 @@ export declare class WrappedProviderFs implements VFileSystemCore {
28
28
  private logEvent;
29
29
  getCapabilities(url: URL): FSCapabilities;
30
30
  stat(urlRef: UrlOrReference): Promise<VfsStat>;
31
- readFile(urlRef: UrlOrReference, encoding?: BufferEncoding): Promise<TextFileResource>;
31
+ readFile(urlRef: UrlOrReference, optionsOrEncoding?: BufferEncoding | ReadFileOptions): Promise<TextFileResource>;
32
32
  readDirectory(url: URL): Promise<VfsDirEntry[]>;
33
33
  writeFile(file: FileResource): Promise<FileReference>;
34
34
  static disposeOf<V extends VFileSystemCore>(fs: V): void;
@@ -14,7 +14,7 @@ export function cspellIOToFsProvider(cspellIO) {
14
14
  const fs = {
15
15
  providerInfo: { name },
16
16
  stat: (url) => cspellIO.getStat(url),
17
- readFile: (url) => cspellIO.readFile(url),
17
+ readFile: (url, options) => cspellIO.readFile(url, options),
18
18
  readDirectory: (url) => cspellIO.readDirectory(url),
19
19
  writeFile: (file) => cspellIO.writeFile(file.url, file.content),
20
20
  dispose: () => undefined,
@@ -115,13 +115,14 @@ export class WrappedProviderFs {
115
115
  this.logEvent('stat', 'end', traceID, url);
116
116
  }
117
117
  }
118
- async readFile(urlRef, encoding) {
118
+ async readFile(urlRef, optionsOrEncoding) {
119
119
  const traceID = performance.now();
120
120
  const url = urlOrReferenceToUrl(urlRef);
121
121
  this.logEvent('readFile', 'start', traceID, url);
122
122
  try {
123
123
  checkCapabilityOrThrow(this.fs, this.capabilities, FSCapabilityFlags.Read, 'readFile', url);
124
- return createTextFileResource(await this.fs.readFile(urlRef), encoding);
124
+ const readOptions = toOptions(optionsOrEncoding);
125
+ return createTextFileResource(await this.fs.readFile(urlRef, readOptions), readOptions?.encoding);
125
126
  }
126
127
  catch (e) {
127
128
  this.logEvent('readFile', 'error', traceID, url, e instanceof Error ? e.message : '');
@@ -247,4 +248,7 @@ export function chopUrl(url) {
247
248
  export function rPad(str, len, ch = ' ') {
248
249
  return str.padEnd(len, ch);
249
250
  }
251
+ function toOptions(val) {
252
+ return typeof val === 'string' ? { encoding: val } : val;
253
+ }
250
254
  //# sourceMappingURL=WrappedProviderFs.js.map
@@ -93,9 +93,9 @@ function remapFS(name, fs, shadowFs, publicRoot, privateRoot, options) {
93
93
  const stat = await fs.stat(url2);
94
94
  return stat;
95
95
  },
96
- readFile: async (url) => {
96
+ readFile: async (url, options) => {
97
97
  const url2 = mapUrlOrReferenceToPrivate(url);
98
- const file = await fs.readFile(url2);
98
+ const file = await fs.readFile(url2, options);
99
99
  return mapFileResourceToPublic(file);
100
100
  },
101
101
  readDirectory: async (url) => {
@@ -26,8 +26,13 @@ export interface VirtualFS extends Disposable {
26
26
  loggingEnabled: boolean;
27
27
  enableLogging(value?: boolean): void;
28
28
  }
29
+ export interface OptionAbort {
30
+ signal?: AbortSignal;
31
+ }
32
+ export type VProviderFileSystemReadFileOptions = OptionAbort;
33
+ export type VProviderFileSystemReadDirectoryOptions = OptionAbort;
29
34
  export interface VProviderFileSystem extends Disposable {
30
- readFile(url: UrlOrReference): Promise<FileResource>;
35
+ readFile(url: UrlOrReference, options?: VProviderFileSystemReadFileOptions): Promise<FileResource>;
31
36
  writeFile(file: FileResource): Promise<FileReference>;
32
37
  /**
33
38
  * Information about the provider.
@@ -1,5 +1,5 @@
1
1
  import type { BufferEncoding } from '../models/BufferEncoding.js';
2
- import type { FileReference, UrlOrReference } from '../models/FileResource.js';
2
+ import type { FileReference, FileResourceRequest, UrlOrReference } from '../models/FileResource.js';
3
3
  export declare class CFileReference implements FileReference {
4
4
  readonly url: URL;
5
5
  readonly encoding: BufferEncoding | undefined;
@@ -32,4 +32,5 @@ export declare class CFileReference implements FileReference {
32
32
  export declare function toFileReference(file: UrlOrReference, encoding?: BufferEncoding, baseFilename?: string, gz?: boolean | undefined): FileReference;
33
33
  export declare function isFileReference(ref: UrlOrReference): ref is FileReference;
34
34
  export declare function renameFileReference(ref: FileReference, newUrl: URL): FileReference;
35
+ export declare function toFileResourceRequest(file: UrlOrReference, encoding?: BufferEncoding, signal?: AbortSignal): FileResourceRequest;
35
36
  //# sourceMappingURL=CFileReference.d.ts.map
@@ -54,4 +54,10 @@ export function isFileReference(ref) {
54
54
  export function renameFileReference(ref, newUrl) {
55
55
  return new CFileReference(newUrl, ref.encoding, ref.baseFilename, ref.gz);
56
56
  }
57
+ export function toFileResourceRequest(file, encoding, signal) {
58
+ const fileReference = typeof file === 'string' ? toFileURL(file) : file;
59
+ if (fileReference instanceof URL)
60
+ return { url: fileReference, encoding, signal };
61
+ return { url: fileReference.url, encoding: encoding ?? fileReference.encoding, signal };
62
+ }
57
63
  //# sourceMappingURL=CFileReference.js.map
@@ -10,6 +10,7 @@ export declare class CFileResource implements TextFileResource {
10
10
  constructor(url: URL, content: string | ArrayBufferView, encoding: BufferEncoding | undefined, baseFilename: string | undefined, gz: boolean | undefined);
11
11
  get gz(): boolean;
12
12
  getText(encoding?: BufferEncoding): string;
13
+ getBytes(): Uint8Array;
13
14
  toJson(): {
14
15
  url: string;
15
16
  content: string;
@@ -1,5 +1,5 @@
1
1
  import { assert } from '../errors/assert.js';
2
- import { decode, isGZipped } from './encode-decode.js';
2
+ import { decode, encodeString, isGZipped } from './encode-decode.js';
3
3
  export class CFileResource {
4
4
  url;
5
5
  content;
@@ -30,6 +30,12 @@ export class CFileResource {
30
30
  this._text = text;
31
31
  return text;
32
32
  }
33
+ getBytes() {
34
+ const arrayBufferview = typeof this.content === 'string' ? encodeString(this.content, this.encoding) : this.content;
35
+ return arrayBufferview instanceof Uint8Array
36
+ ? arrayBufferview
37
+ : new Uint8Array(arrayBufferview.buffer, arrayBufferview.byteOffset, arrayBufferview.byteLength);
38
+ }
33
39
  toJson() {
34
40
  return {
35
41
  url: this.url.href,
@@ -6,7 +6,7 @@ const BOM_LE = 0xfffe;
6
6
  const decoderUTF8 = new TextDecoder('utf8');
7
7
  const decoderUTF16LE = new TextDecoder('utf-16le');
8
8
  const decoderUTF16BE = createTextDecoderUtf16BE();
9
- // const encoderUTF8 = new TextEncoder();
9
+ const encoderUTF8 = new TextEncoder();
10
10
  // const encoderUTF16LE = new TextEncoder('utf-16le');
11
11
  export function decodeUtf16LE(data) {
12
12
  const buf = asUint8Array(data);
@@ -60,6 +60,11 @@ export function decode(data, encoding) {
60
60
  }
61
61
  export function encodeString(str, encoding, bom) {
62
62
  switch (encoding) {
63
+ case undefined:
64
+ case 'utf-8':
65
+ case 'utf8': {
66
+ return encoderUTF8.encode(str);
67
+ }
63
68
  case 'utf-16be':
64
69
  case 'utf16be': {
65
70
  return encodeUtf16BE(str, bom);
@@ -53,10 +53,10 @@ const supportedFetchProtocols = { 'http:': true, 'https:': true };
53
53
  * Handle fetching a file from http
54
54
  */
55
55
  const handleRequestFsReadFileHttp = RequestFsReadFile.createRequestHandler((req, next) => {
56
- const { url } = req.params;
56
+ const { url, signal, encoding } = req.params;
57
57
  if (!(url.protocol in supportedFetchProtocols))
58
58
  return next(req);
59
- return createResponse(fetchURL(url).then((content) => CFileResource.from({ ...req.params, content })));
59
+ return createResponse(fetchURL(url, signal).then((content) => CFileResource.from({ url, encoding, content })));
60
60
  }, undefined, 'Node: Read Http(s) file.');
61
61
  /**
62
62
  * Handle decoding a data url
@@ -20,6 +20,20 @@ export interface FileReference {
20
20
  */
21
21
  readonly gz?: boolean | undefined;
22
22
  }
23
+ export interface FileResourceRequest {
24
+ /**
25
+ * The URL of the File
26
+ */
27
+ readonly url: URL;
28
+ /**
29
+ * The encoding to use when reading the file.
30
+ */
31
+ readonly encoding?: BufferEncoding | undefined;
32
+ /**
33
+ * The signal to use to abort the request.
34
+ */
35
+ readonly signal?: AbortSignal | undefined;
36
+ }
23
37
  export interface FileResource extends FileReference {
24
38
  /**
25
39
  * The contents of the file
@@ -34,6 +48,10 @@ export interface TextFileResource extends FileResource {
34
48
  * If the content is a string, then the encoding is ignored.
35
49
  */
36
50
  getText(encoding?: BufferEncoding): string;
51
+ /**
52
+ * Get the bytes of the file.
53
+ */
54
+ getBytes(): Uint8Array;
37
55
  }
38
56
  export type UrlOrFilename = string | URL;
39
57
  export type UrlOrReference = UrlOrFilename | FileReference;
@@ -1,3 +1,3 @@
1
1
  export declare function fetchHead(request: string | URL): Promise<Headers>;
2
- export declare function fetchURL(url: URL): Promise<Buffer>;
2
+ export declare function fetchURL(url: URL, signal?: AbortSignal): Promise<Buffer>;
3
3
  //# sourceMappingURL=fetch.d.ts.map
@@ -14,9 +14,11 @@ export async function fetchHead(request) {
14
14
  throw toFetchUrlError(e, url);
15
15
  }
16
16
  }
17
- export async function fetchURL(url) {
17
+ export async function fetchURL(url, signal) {
18
18
  try {
19
- const response = await fetch(url);
19
+ // eslint-disable-next-line n/no-unsupported-features/node-builtins
20
+ const request = signal ? new Request(url, { signal }) : url;
21
+ const response = await fetch(request);
20
22
  if (!response.ok) {
21
23
  throw FetchUrlError.create(url, response.status);
22
24
  }
@@ -1,11 +1,5 @@
1
1
  import type { ServiceRequestFactoryRequestType } from '@cspell/cspell-service-bus';
2
- import type { BufferEncoding } from '../models/BufferEncoding.js';
3
- import type { TextFileResource } from '../models/FileResource.js';
4
- interface RequestParams {
5
- readonly url: URL;
6
- readonly encoding?: BufferEncoding | undefined;
7
- }
8
- export declare const RequestFsReadFile: import("@cspell/cspell-service-bus").ServiceRequestFactory<import("@cspell/cspell-service-bus").ServiceRequest<"fs:readFile", RequestParams, Promise<TextFileResource>>, RequestParams, "fs:readFile">;
2
+ import type { FileResourceRequest, TextFileResource } from '../models/FileResource.js';
3
+ export declare const RequestFsReadFile: import("@cspell/cspell-service-bus").ServiceRequestFactory<import("@cspell/cspell-service-bus").ServiceRequest<"fs:readFile", FileResourceRequest, Promise<TextFileResource>>, FileResourceRequest, "fs:readFile">;
9
4
  export type RequestFsReadFile = ServiceRequestFactoryRequestType<typeof RequestFsReadFile>;
10
- export {};
11
5
  //# sourceMappingURL=RequestFsReadFile.d.ts.map
@@ -2,7 +2,7 @@ import type { ServiceRequestFactoryRequestType } from '@cspell/cspell-service-bu
2
2
  interface RequestParams {
3
3
  readonly data: ArrayBufferView;
4
4
  }
5
- export declare const RequestZlibInflate: import("@cspell/cspell-service-bus").ServiceRequestFactory<import("@cspell/cspell-service-bus").ServiceRequest<"zlib:inflate", RequestParams, ArrayBufferView>, RequestParams, "zlib:inflate">;
5
+ export declare const RequestZlibInflate: import("@cspell/cspell-service-bus").ServiceRequestFactory<import("@cspell/cspell-service-bus").ServiceRequest<"zlib:inflate", RequestParams, ArrayBufferView<ArrayBufferLike>>, RequestParams, "zlib:inflate">;
6
6
  export type RequestZlibInflate = ServiceRequestFactoryRequestType<typeof RequestZlibInflate>;
7
7
  export {};
8
8
  //# sourceMappingURL=RequestZlibInflate.d.ts.map
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "access": "public",
5
5
  "provenance": true
6
6
  },
7
- "version": "8.16.0",
7
+ "version": "8.17.0",
8
8
  "description": "A library of useful I/O functions used across various cspell tools.",
9
9
  "type": "module",
10
10
  "sideEffects": false,
@@ -53,11 +53,12 @@
53
53
  },
54
54
  "devDependencies": {
55
55
  "lorem-ipsum": "^2.0.8",
56
- "typescript": "~5.6.3"
56
+ "typescript": "~5.7.2",
57
+ "vitest-fetch-mock": "^0.4.2"
57
58
  },
58
59
  "dependencies": {
59
- "@cspell/cspell-service-bus": "8.16.0",
60
- "@cspell/url": "8.16.0"
60
+ "@cspell/cspell-service-bus": "8.17.0",
61
+ "@cspell/url": "8.17.0"
61
62
  },
62
- "gitHead": "41cd50f9ba34033b6da32408855d7fc3b888c5e0"
63
+ "gitHead": "cac17fe7b993db5965aa441648b1c22cb5486929"
63
64
  }