sliftutils 1.2.37 → 1.2.39

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/index.d.ts CHANGED
@@ -156,6 +156,11 @@ declare module "sliftutils/misc/https/dns" {
156
156
  }
157
157
 
158
158
  declare module "sliftutils/misc/https/httpsCerts" {
159
+ /// <reference path="node-forge-ed25519.d.ts" />
160
+ /// <reference path="../../storage/storage.d.ts" />
161
+ /// <reference types="node" />
162
+ /// <reference types="node" />
163
+ import * as forge from "node-forge";
159
164
  /** NOTE: We also generate the domain *.domain */
160
165
  export declare const getHTTPSCert: {
161
166
  (key: string): Promise<{
@@ -174,6 +179,18 @@ declare module "sliftutils/misc/https/httpsCerts" {
174
179
  cert: string;
175
180
  }> | undefined;
176
181
  };
182
+ export declare const getAccountKey: (domain: string) => Promise<string>;
183
+ export declare function parseCert(PEMorDER: string | Buffer): forge.pki.Certificate;
184
+ export declare function normalizeCertToPEM(PEMorDER: string | Buffer): string;
185
+ export declare function generateCert(config: {
186
+ accountKey: string;
187
+ domain: string;
188
+ altDomains?: string[];
189
+ }): Promise<{
190
+ domains: string[];
191
+ key: string;
192
+ cert: string;
193
+ }>;
177
194
 
178
195
  }
179
196
 
@@ -929,6 +946,9 @@ declare module "sliftutils/storage/FileFolderAPI" {
929
946
  size: number;
930
947
  lastModified: number;
931
948
  arrayBuffer(): Promise<ArrayBuffer>;
949
+ slice(start: number, end: number): {
950
+ arrayBuffer(): Promise<ArrayBuffer>;
951
+ };
932
952
  }>;
933
953
  createWritable(config?: {
934
954
  keepExistingData?: boolean;
@@ -1026,6 +1046,10 @@ declare module "sliftutils/storage/IStorage" {
1026
1046
  };
1027
1047
  export type IStorageRaw = {
1028
1048
  get(key: string): Promise<Buffer | undefined>;
1049
+ getRange(key: string, config: {
1050
+ start: number;
1051
+ end: number;
1052
+ }): Promise<Buffer | undefined>;
1029
1053
  append(key: string, value: Buffer): Promise<void>;
1030
1054
  set(key: string, value: Buffer): Promise<void>;
1031
1055
  remove(key: string): Promise<void>;
@@ -1117,6 +1141,10 @@ declare module "sliftutils/storage/PrivateFileSystemStorage" {
1117
1141
  private getFileHandle;
1118
1142
  private fileExists;
1119
1143
  get(key: string): Promise<Buffer | undefined>;
1144
+ getRange(key: string, config: {
1145
+ start: number;
1146
+ end: number;
1147
+ }): Promise<Buffer | undefined>;
1120
1148
  set(key: string, value: Buffer): Promise<void>;
1121
1149
  append(key: string, value: Buffer): Promise<void>;
1122
1150
  remove(key: string): Promise<void>;
@@ -1,3 +1,8 @@
1
+ /// <reference path="node-forge-ed25519.d.ts" />
2
+ /// <reference path="../../storage/storage.d.ts" />
3
+ /// <reference types="node" />
4
+ /// <reference types="node" />
5
+ import * as forge from "node-forge";
1
6
  /** NOTE: We also generate the domain *.domain */
2
7
  export declare const getHTTPSCert: {
3
8
  (key: string): Promise<{
@@ -16,3 +21,15 @@ export declare const getHTTPSCert: {
16
21
  cert: string;
17
22
  }> | undefined;
18
23
  };
24
+ export declare const getAccountKey: (domain: string) => Promise<string>;
25
+ export declare function parseCert(PEMorDER: string | Buffer): forge.pki.Certificate;
26
+ export declare function normalizeCertToPEM(PEMorDER: string | Buffer): string;
27
+ export declare function generateCert(config: {
28
+ accountKey: string;
29
+ domain: string;
30
+ altDomains?: string[];
31
+ }): Promise<{
32
+ domains: string[];
33
+ key: string;
34
+ cert: string;
35
+ }>;
@@ -91,7 +91,7 @@ export const getHTTPSCert = cache(async (domain: string): Promise<{ key: string;
91
91
  });
92
92
 
93
93
 
94
- const getAccountKey = async function getAccountKey(domain: string) {
94
+ export const getAccountKey = async function getAccountKey(domain: string) {
95
95
  let accountKey = getKeyStore<string>(domain, "letsEncryptAccountKey");
96
96
  let secret = await accountKey.get();
97
97
  if (!secret) {
@@ -105,11 +105,11 @@ const getAccountKey = async function getAccountKey(domain: string) {
105
105
  };
106
106
 
107
107
 
108
- function parseCert(PEMorDER: string | Buffer) {
108
+ export function parseCert(PEMorDER: string | Buffer) {
109
109
  return forge.pki.certificateFromPem(normalizeCertToPEM(PEMorDER));
110
110
  }
111
111
 
112
- function normalizeCertToPEM(PEMorDER: string | Buffer): string {
112
+ export function normalizeCertToPEM(PEMorDER: string | Buffer): string {
113
113
  if (PEMorDER.toString().startsWith("-----BEGIN CERTIFICATE-----")) {
114
114
  return PEMorDER.toString();
115
115
  }
@@ -118,7 +118,7 @@ function normalizeCertToPEM(PEMorDER: string | Buffer): string {
118
118
  }
119
119
 
120
120
 
121
- async function generateCert(config: {
121
+ export async function generateCert(config: {
122
122
  accountKey: string;
123
123
  domain: string;
124
124
  altDomains?: string[];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sliftutils",
3
- "version": "1.2.37",
3
+ "version": "1.2.39",
4
4
  "main": "index.js",
5
5
  "license": "MIT",
6
6
  "files": [
@@ -32,6 +32,9 @@ type FileWrapper = {
32
32
  size: number;
33
33
  lastModified: number;
34
34
  arrayBuffer(): Promise<ArrayBuffer>;
35
+ slice(start: number, end: number): {
36
+ arrayBuffer(): Promise<ArrayBuffer>;
37
+ };
35
38
  }>;
36
39
  createWritable(config?: {
37
40
  keepExistingData?: boolean;
@@ -40,6 +40,9 @@ type FileWrapper = {
40
40
  size: number;
41
41
  lastModified: number;
42
42
  arrayBuffer(): Promise<ArrayBuffer>;
43
+ // Matches Blob.slice (which the native File object provides), so the browser
44
+ // implementation works vanilla. End is exclusive, both clamped to the file size.
45
+ slice(start: number, end: number): { arrayBuffer(): Promise<ArrayBuffer> };
43
46
  }>;
44
47
  createWritable(config?: { keepExistingData?: boolean }): Promise<{
45
48
  seek(offset: number): Promise<void>;
@@ -99,13 +102,29 @@ class NodeJSFileHandleWrapper implements FileWrapper {
99
102
 
100
103
  async getFile() {
101
104
  const stats = await fs.promises.stat(this.filePath);
105
+ const filePath = this.filePath;
102
106
  return {
103
107
  size: stats.size,
104
108
  lastModified: stats.mtimeMs,
105
109
  arrayBuffer: async () => {
106
- const buffer = await fs.promises.readFile(this.filePath);
110
+ const buffer = await fs.promises.readFile(filePath);
107
111
  return buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength);
108
- }
112
+ },
113
+ slice: (start: number, end: number) => ({
114
+ arrayBuffer: async () => {
115
+ const clampedStart = Math.min(Math.max(start, 0), stats.size);
116
+ const clampedEnd = Math.min(Math.max(end, clampedStart), stats.size);
117
+ const length = clampedEnd - clampedStart;
118
+ const fileHandle = await fs.promises.open(filePath, "r");
119
+ try {
120
+ const buffer = Buffer.alloc(length);
121
+ await fileHandle.read(buffer, 0, length, clampedStart);
122
+ return buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength);
123
+ } finally {
124
+ await fileHandle.close();
125
+ }
126
+ }
127
+ })
109
128
  };
110
129
  }
111
130
 
@@ -440,6 +459,17 @@ function wrapHandleFiles(handle: DirectoryWrapper): IStorageRaw {
440
459
  }
441
460
  },
442
461
 
462
+ async getRange(key: string, config: { start: number; end: number }): Promise<Buffer | undefined> {
463
+ try {
464
+ const file = await handle.getFileHandle(key);
465
+ const fileContent = await file.getFile();
466
+ const arrayBuffer = await fileContent.slice(config.start, config.end).arrayBuffer();
467
+ return Buffer.from(arrayBuffer);
468
+ } catch (error) {
469
+ return undefined;
470
+ }
471
+ },
472
+
443
473
  async append(key: string, value: Buffer): Promise<void> {
444
474
  await appendQueue(key)(async () => {
445
475
  // NOTE: Interesting point. Chrome doesn't optimize this to be an append, and instead
@@ -27,6 +27,10 @@ export type IStorage<T> = {
27
27
  };
28
28
  export type IStorageRaw = {
29
29
  get(key: string): Promise<Buffer | undefined>;
30
+ getRange(key: string, config: {
31
+ start: number;
32
+ end: number;
33
+ }): Promise<Buffer | undefined>;
30
34
  append(key: string, value: Buffer): Promise<void>;
31
35
  set(key: string, value: Buffer): Promise<void>;
32
36
  remove(key: string): Promise<void>;
@@ -29,6 +29,9 @@ export type IStorage<T> = {
29
29
  // (/ makes a folder). And there are even more rules, such as lengths per folder, etc, etc.
30
30
  export type IStorageRaw = {
31
31
  get(key: string): Promise<Buffer | undefined>;
32
+ // Reads bytes in the range [start, end) (end is exclusive, clamped to the file size).
33
+ // Returns undefined if the file doesn't exist.
34
+ getRange(key: string, config: { start: number; end: number }): Promise<Buffer | undefined>;
32
35
  // May or may not be efficient in the underlying storage
33
36
  append(key: string, value: Buffer): Promise<void>;
34
37
  set(key: string, value: Buffer): Promise<void>;
@@ -44,6 +44,12 @@ class VirtualFileStorage implements FileStorage {
44
44
  return badBuffer;
45
45
  }
46
46
 
47
+ async getRange(key: string, config: { start: number; end: number }): Promise<Buffer | undefined> {
48
+ const fullBuffer = await this.get(key);
49
+ if (!fullBuffer) return undefined;
50
+ return fullBuffer.subarray(config.start, config.end);
51
+ }
52
+
47
53
  async append(key: string, value: Buffer): Promise<void> {
48
54
  const store = this.getStore("readwrite");
49
55
  const fullPath = this.id + key;
@@ -11,6 +11,10 @@ export declare class PrivateFileSystemStorage implements IStorageRaw {
11
11
  private getFileHandle;
12
12
  private fileExists;
13
13
  get(key: string): Promise<Buffer | undefined>;
14
+ getRange(key: string, config: {
15
+ start: number;
16
+ end: number;
17
+ }): Promise<Buffer | undefined>;
14
18
  set(key: string, value: Buffer): Promise<void>;
15
19
  append(key: string, value: Buffer): Promise<void>;
16
20
  remove(key: string): Promise<void>;
@@ -114,6 +114,17 @@ export class PrivateFileSystemStorage implements IStorageRaw {
114
114
  }
115
115
  }
116
116
 
117
+ public async getRange(key: string, config: { start: number; end: number }): Promise<Buffer | undefined> {
118
+ const fileHandle = await this.getFileHandle(key, false);
119
+ if (!fileHandle) {
120
+ return undefined;
121
+ }
122
+
123
+ const file = await fileHandle.getFile();
124
+ const arrayBuffer = await file.slice(config.start, config.end).arrayBuffer();
125
+ return Buffer.from(arrayBuffer);
126
+ }
127
+
117
128
  public async set(key: string, value: Buffer): Promise<void> {
118
129
  try {
119
130
  const fileHandle = await this.getFileHandle(key, true);