Skip to content
This repository was archived by the owner on May 23, 2021. It is now read-only.

Commit 391ef91

Browse files
committedDec 18, 2019
Make nbin implemented types work
Previously if you made changes to the typings file there would be no errors telling you the implementation was now incorrect.
1 parent 2436ee5 commit 391ef91

File tree

7 files changed

+180
-161
lines changed

7 files changed

+180
-161
lines changed
 

‎package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
"patch:generate": "cd ./lib/node && git diff HEAD > ../../scripts/node.patch",
1616
"patch:apply": "cd ./lib/node && git apply ../../scripts/node.patch"
1717
},
18-
"typings": "typings/nbin/index.d.ts",
18+
"typings": "typings/nbin.d.ts",
1919
"author": "Coder",
2020
"license": "MIT",
2121
"devDependencies": {

‎src/patches/nbin.ts

Lines changed: 59 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import * as fs from "fs"
2-
import { Stat } from "nbin"
2+
import * as nbin from "nbin"
33
import * as path from "path"
44
import { readString } from "../common/buffer"
55
import { createNotFound } from "../common/error"
@@ -11,17 +11,17 @@ const execPath = process.execPath
1111
const execPathStat = fs.statSync(execPath)
1212
const nbinFd = fs.openSync(execPath, "r")
1313

14-
// Footer is located at the end of the file
14+
// Footer is located at the end of the file.
1515
const footer = readFooter(nbinFd, execPathStat.size)
1616

17-
// Contains the version, mainFile and the filesystem
17+
// Contains the version, mainFile and the filesystem.
1818
const headerBuffer = Buffer.allocUnsafe(footer.headerLength)
1919
fs.readSync(nbinFd, headerBuffer, 0, footer.headerLength, footer.headerOffset)
2020
const version = readString(headerBuffer, 0)
2121
const mainFile = readString(headerBuffer, version.offset)
2222

2323
/**
24-
* Maximize read perf by storing before any overrides
24+
* Maximize read perf by storing before any overrides.
2525
*/
2626
const originalRead = fs.read
2727
const originalReadSync = fs.readSync
@@ -47,21 +47,19 @@ const readableFs = ReadableFilesystem.fromBuffer(fsBuffer, {
4747
},
4848
})
4949

50+
interface ParsedFs {
51+
readonly fs: ReadableFilesystem
52+
readonly name: string
53+
}
54+
5055
/**
5156
* Parses an entry from a readable FS.
5257
* Will split the inputted path and attempt to
5358
* nest down the tree.
5459
*/
55-
const parse = (
56-
fullPath: string
57-
):
58-
| {
59-
readonly fs: ReadableFilesystem
60-
readonly name: string
61-
}
62-
| undefined => {
60+
const parse = (fullPath: fs.PathLike): ParsedFs | undefined => {
6361
const parts = path
64-
.normalize(fullPath)
62+
.normalize(fullPath.toString())
6563
.split(path.sep)
6664
.filter((i) => i.length)
6765
let filesystem = readableFs
@@ -86,16 +84,56 @@ const parse = (
8684
return undefined
8785
}
8886

89-
const exported: typeof import("nbin") = {
87+
// It doesn't appear possible to overload object properties so these are
88+
// implemented separately.
89+
async function readFile(pathName: fs.PathLike, encoding?: "buffer", offset?: number, length?: number): Promise<Buffer>
90+
async function readFile(pathName: fs.PathLike, encoding?: "utf8", offset?: number, length?: number): Promise<string>
91+
async function readFile(
92+
pathName: fs.PathLike,
93+
encoding?: "utf8" | "buffer",
94+
offset?: number,
95+
length?: number
96+
): Promise<Buffer | string> {
97+
const res = parse(pathName)
98+
if (!res) {
99+
throw createNotFound()
100+
}
101+
const b = await res.fs.read(res.name, offset, length)
102+
if (encoding && encoding === "utf8") {
103+
return b.toString()
104+
}
105+
return b
106+
}
107+
108+
function readFileSync(pathName: fs.PathLike, encoding?: "buffer", offset?: number, length?: number): Buffer
109+
function readFileSync(pathName: fs.PathLike, encoding?: "utf8", offset?: number, length?: number): string
110+
function readFileSync(
111+
pathName: fs.PathLike,
112+
encoding?: "utf8" | "buffer",
113+
offset?: number,
114+
length?: number
115+
): Buffer | string {
116+
const res = parse(pathName)
117+
if (!res) {
118+
throw createNotFound()
119+
}
120+
const b = res.fs.readSync(res.name, offset, length)
121+
if (encoding && encoding === "utf8") {
122+
return b.toString()
123+
}
124+
return b
125+
}
126+
127+
const exported: typeof nbin = {
90128
version: version.value,
91129
mainFile: mainFile.value,
92130

93-
existsSync: (pathName: string): boolean => {
131+
existsSync: (pathName: fs.PathLike): boolean => {
94132
const stat = exported.statSync(pathName)
95133
return stat.isFile || stat.isDirectory
96134
},
97135

98-
readdirSync: (pathName: string): ReadonlyArray<string> => {
136+
readdirSync: (pathName: fs.PathLike): ReadonlyArray<string> => {
99137
const res = parse(pathName)
100138
if (!res) {
101139
throw createNotFound()
@@ -107,31 +145,7 @@ const exported: typeof import("nbin") = {
107145
return filesystem.ls()
108146
},
109147

110-
readFile: async (pathName: string, encoding?: "utf8", offset?: number, length?: number): Promise<Buffer | string> => {
111-
const res = parse(pathName)
112-
if (!res) {
113-
throw createNotFound()
114-
}
115-
const b = await res.fs.read(res.name, offset, length)
116-
if (encoding && encoding === "utf8") {
117-
return b.toString()
118-
}
119-
return b
120-
},
121-
122-
readFileSync: (pathName: string, encoding?: "utf8", offset?: number, length?: number): Buffer | string => {
123-
const res = parse(pathName)
124-
if (!res) {
125-
throw createNotFound()
126-
}
127-
const b = res.fs.readSync(res.name, offset, length)
128-
if (encoding && encoding === "utf8") {
129-
return b.toString()
130-
}
131-
return b
132-
},
133-
134-
statSync: (pathName: string): Stat => {
148+
statSync: (pathName: fs.PathLike): nbin.Stat => {
135149
const res = parse(pathName)
136150
if (!res) {
137151
return {
@@ -143,9 +157,12 @@ const exported: typeof import("nbin") = {
143157
return res.fs.stat(res.name)
144158
},
145159

160+
readFile,
161+
readFileSync,
162+
146163
shimNativeFs: (pathName: string): void => {
147164
fillFs(pathName)
148165
},
149-
} as typeof import("nbin")
166+
}
150167

151168
export = exported

‎tsconfig.json

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,10 @@
99
"outDir": "out",
1010
"declaration": true,
1111
"sourceMap": true,
12-
"typeRoots": ["./node_modules/@types", "./typings"],
1312
"baseUrl": ".",
1413
"paths": {
15-
"nbin": ["./typings/nbin/index.d.ts"],
16-
"@coder/nbin": ["./typings/nbin/index.d.ts"]
14+
"nbin": ["./typings/internal.d.ts"],
15+
"@coder/nbin": ["./typings/external.d.ts"]
1716
}
1817
},
1918
"include": [

‎typings/external.d.ts

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/**
2+
* External nbin module (the API).
3+
*/
4+
declare module "@coder/nbin" {
5+
export interface BinaryOptions {
6+
/**
7+
* Path of the node binary to bundle.
8+
* *Must* be a patched binary.
9+
*/
10+
readonly nodePath?: string
11+
12+
/**
13+
* Main file for your application.
14+
* Will be called as the entrypoint.
15+
*/
16+
readonly mainFile: string
17+
18+
/**
19+
* OS target
20+
*/
21+
readonly target?: "darwin" | "alpine" | "linux"
22+
}
23+
24+
/**
25+
* Create a new binary.
26+
*/
27+
export class Binary {
28+
public constructor(options: BinaryOptions)
29+
30+
/**
31+
* Write a file to the bundle at a path.
32+
*/
33+
public writeFile(pathName: string, content: Buffer): void
34+
35+
/**
36+
* Writes files from an FS glob.
37+
* Calls back as files are written.
38+
* @example
39+
* writeFiles(path.join(__dirname, "dog/**"));
40+
* @returns number of files written
41+
*/
42+
public writeFiles(glob: string, callback?: (fileWritten: string) => void): number
43+
44+
/**
45+
* Will bundle a module based on path and name.
46+
* Allows you to do `writeModule("/test/bananas/node_modules/frog")` and
47+
* embed the `frog` module within the binary.
48+
*
49+
* All modules by default will be placed in `/node_modules`
50+
*/
51+
public writeModule(modulePath: string): void
52+
53+
/**
54+
* Bundles the binary.
55+
* @returns the content of the executable file.
56+
*/
57+
public build(): Promise<Buffer>
58+
}
59+
}

‎typings/internal.d.ts

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import * as fs from "fs"
2+
3+
/**
4+
* Internal nbin module. Only available inside the binary.
5+
*/
6+
declare module "nbin" {
7+
/**
8+
* Returns the stat for a path.
9+
*/
10+
export interface Stat {
11+
readonly isDirectory: boolean
12+
readonly isFile: boolean
13+
readonly size: number
14+
}
15+
16+
/**
17+
* Checks if a file exists within the binary.
18+
*/
19+
export const existsSync: (path: fs.PathLike) => boolean
20+
21+
/**
22+
* Performs a stat on paths within the binary.
23+
*/
24+
export const statSync: (path: fs.PathLike) => Stat
25+
26+
/**
27+
* Reads a directory within the binary.
28+
*/
29+
export const readdirSync: (path: fs.PathLike) => ReadonlyArray<string>
30+
31+
/**
32+
* Reads a file asynchronously from the binary.
33+
*/
34+
function readFile(path: fs.PathLike, encoding?: "buffer", offset?: number, length?: number): Promise<Buffer>
35+
function readFile(path: fs.PathLike, encoding?: "utf8", offset?: number, length?: number): Promise<string>
36+
37+
/**
38+
* Reads a file synchronously from the binary.
39+
*/
40+
function readFileSync(path: fs.PathLike, encoding?: "buffer", offset?: number, length?: number): Buffer
41+
function readFileSync(path: fs.PathLike, encoding?: "utf8", offset?: number, length?: number): string
42+
43+
/**
44+
* nbin version.
45+
*/
46+
export const version: string
47+
48+
/**
49+
* Returns the entrypoint of the application.
50+
*/
51+
export const mainFile: string
52+
53+
/**
54+
* Shims the native `fs` module for the path
55+
*/
56+
export const shimNativeFs: (path: string) => void
57+
}

‎typings/nbin.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
import "./internal"
2+
import "./external"

‎typings/nbin/index.d.ts

Lines changed: 0 additions & 115 deletions
This file was deleted.

0 commit comments

Comments
 (0)
This repository has been archived.