From a7b2932981efbf32058d5bba615f46a1e7e0cbeb Mon Sep 17 00:00:00 2001 From: develar Date: Thu, 2 Jun 2016 20:08:31 +0200 Subject: [PATCH] fix: Application entry can't be found Closes #371 --- docs/Options.md | 2 +- package.json | 4 +- src/globby.ts | 55 ++++++ src/metadata.ts | 9 +- src/packager.ts | 2 +- src/platformPackager.ts | 122 ++++++++++-- test/tsconfig.json | 2 +- tsconfig.json | 3 +- typings.json | 1 + typings/asar.d.ts | 14 ++ typings/electron-packager.d.ts | 19 +- typings/globby.d.ts | 9 - typings/modules/glob/index.d.ts | 302 ++++++++++++++++++++++++++++++ typings/modules/glob/typings.json | 21 +++ 14 files changed, 521 insertions(+), 44 deletions(-) create mode 100644 src/globby.ts delete mode 100644 typings/globby.d.ts create mode 100644 typings/modules/glob/index.d.ts create mode 100644 typings/modules/glob/typings.json diff --git a/docs/Options.md b/docs/Options.md index 9c20254bf54..2d13a61bf04 100644 --- a/docs/Options.md +++ b/docs/Options.md @@ -52,7 +52,7 @@ Here documented only `electron-builder` specific options: | --- | --- | app-bundle-id | *OS X-only.* The app bundle ID. See [CFBundleIdentifier](https://developer.apple.com/library/ios/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html#//apple_ref/doc/uid/20001431-102070). | app-category-type |

*OS X-only.* The application category type, as shown in the Finder via *View -> Arrange by Application Category* when viewing the Applications directory.

For example, app-category-type=public.app-category.developer-tools will set the application category to *Developer Tools*.

Valid values are listed in [Apple’s documentation](https://developer.apple.com/library/ios/documentation/General/Reference/InfoPlistKeyReference/Articles/LaunchServicesKeys.html#//apple_ref/doc/uid/TP40009250-SW8).

-| asar |

Whether to package the application’s source code into an archive, using [Electron’s archive format](https://github.com/electron/asar). Defaults to true. Reasons why you may want to disable this feature are described in [an application packaging tutorial in Electron’s documentation](http://electron.atom.io/docs/latest/tutorial/application-packaging/#limitations-on-node-api/).

+| asar |

Whether to package the application’s source code into an archive, using [Electron’s archive format](https://github.com/electron/asar). Defaults to true. Reasons why you may want to disable this feature are described in [an application packaging tutorial in Electron’s documentation](http://electron.atom.io/docs/latest/tutorial/application-packaging/#limitations-on-node-api/).

Or you can pass object of any asar options.

| productName | See [AppMetadata.productName](#AppMetadata-productName). | extraResources |

A [glob expression](https://www.npmjs.com/package/glob#glob-primer), when specified, copy the file or directory with matching names directly into the app’s resources directory (Contents/Resources for OS X, resources for Linux/Windows).

You can use ${os} (expanded to osx, linux or win according to current platform) and ${arch} in the pattern.

If directory matched, all contents are copied. So, you can just specify foo to copy <project_dir>/foo directory.

May be specified in the platform options (i.e. in the build.osx).

| extraFiles | The same as [extraResources](#BuildMetadata-extraResources) but copy into the app's content directory (`Contents` for OS X, `` for Linux/Windows). diff --git a/package.json b/package.json index 2cc77c2a07a..0fb45902c8f 100644 --- a/package.json +++ b/package.json @@ -66,9 +66,9 @@ "deep-assign": "^2.0.0", "electron-osx-sign-tf": "0.6.0", "electron-packager-tf": "~7.3.0", - "electron-winstaller-fixed": "~2.9.4", + "electron-winstaller-fixed": "~2.9.5", "fs-extra-p": "^1.0.1", - "globby": "^4.1.0", + "glob": "^7.0.3", "hosted-git-info": "^2.1.5", "image-size": "^0.5.0", "lodash.template": "^4.2.5", diff --git a/src/globby.ts b/src/globby.ts new file mode 100644 index 00000000000..aa0025796b0 --- /dev/null +++ b/src/globby.ts @@ -0,0 +1,55 @@ +import { Promise as BluebirdPromise } from "bluebird" +import { Glob, Options } from "glob" + +//noinspection JSUnusedLocalSymbols +const __awaiter = require("./awaiter") + +function isNegative(pattern: string): boolean { + return pattern[0] === "!" +} + +function generateGlobTasks(patterns: Array, opts: Options): Array { + opts = Object.assign({ignore: []}, opts) + + const globTasks: Array = [] + patterns.forEach(function (pattern, i) { + if (isNegative(pattern)) { + return + } + + const ignore = patterns.slice(i).filter(isNegative).map(it => it.slice(1)) + globTasks.push({ + pattern: pattern, + opts: Object.assign({}, opts, { + ignore: (>opts.ignore).concat(ignore) + }) + }) + }) + return globTasks +} + +export function globby(patterns: Array, opts: Options): Promise> { + let firstGlob: Glob | null = null + return BluebirdPromise + .map(generateGlobTasks(patterns, opts), task => new BluebirdPromise((resolve, reject) => { + let glob = new Glob(task.pattern, task.opts, (error, matches) => { + if (error == null) { + resolve(matches) + } + else { + reject(error) + } + }) + + if (firstGlob == null) { + firstGlob = glob + } + else { + glob.statCache = firstGlob.statCache + glob.symlinks = firstGlob.symlinks + glob.realpathCache = firstGlob.realpathCache + glob.cache = firstGlob.cache + } + })) + .then(it => new Set([].concat(...it))) +} \ No newline at end of file diff --git a/src/metadata.ts b/src/metadata.ts index 12b74061135..f530e944572 100755 --- a/src/metadata.ts +++ b/src/metadata.ts @@ -1,4 +1,5 @@ import { ElectronPackagerOptions } from "electron-packager-tf" +import { AsarOptions } from "asar" export interface Metadata { readonly repository?: string | RepositoryInfo | null @@ -92,9 +93,11 @@ export interface BuildMetadata { /* Whether to package the application's source code into an archive, using [Electron's archive format](https://github.com/electron/asar). Defaults to `true`. - Reasons why you may want to disable this feature are described in [an application packaging tutorial in Electron's documentation](http://electron.atom.io/docs/latest/tutorial/application-packaging/#limitations-on-node-api/). + Reasons why you may want to disable this feature are described in [an application packaging tutorial in Electron's documentation](http://electron.atom.io/docs/latest/tutorial/application-packaging/#limitations-on-node-api/). + + Or you can pass object of any asar options. */ - readonly asar?: boolean + readonly asar?: AsarOptions | boolean | null // deprecated readonly iconUrl?: string | null @@ -345,6 +348,8 @@ export interface PlatformSpecificBuildOptions { readonly extraFiles?: Array | null readonly extraResources?: Array | null + readonly asar?: AsarOptions | boolean + readonly target?: Array | null } diff --git a/src/packager.ts b/src/packager.ts index 8a065800a4d..05b8b5c5d51 100644 --- a/src/packager.ts +++ b/src/packager.ts @@ -30,7 +30,7 @@ export class Packager implements BuildInfo { metadata: AppMetadata devMetadata: DevMetadata - private isTwoPackageJsonProjectLayoutUsed = true + isTwoPackageJsonProjectLayoutUsed = true electronVersion: string diff --git a/src/platformPackager.ts b/src/platformPackager.ts index 8ff694fa038..9d77df22dd0 100644 --- a/src/platformPackager.ts +++ b/src/platformPackager.ts @@ -4,13 +4,14 @@ import EventEmitter = NodeJS.EventEmitter import { Promise as BluebirdPromise } from "bluebird" import * as path from "path" import { pack, ElectronPackagerOptions } from "electron-packager-tf" -import globby = require("globby") -import { readdir, copy, unlink } from "fs-extra-p" -import { statOrNull, use, spawn, debug7zArgs, debug } from "./util" +import { globby } from "./globby" +import { readdir, copy, unlink, lstat, remove } from "fs-extra-p" +import { statOrNull, use, spawn, debug7zArgs, debug, warn } from "./util" import { Packager } from "./packager" -import deepAssign = require("deep-assign") -import { listPackage, statFile } from "asar" +import { listPackage, statFile, AsarFileMetadata, createPackageFromFiles, AsarOptions } from "asar" import { path7za } from "7zip-bin" +import deepAssign = require("deep-assign") +import { Glob } from "glob" //noinspection JSUnusedLocalSymbols const __awaiter = require("./awaiter") @@ -64,6 +65,8 @@ export interface BuildInfo extends ProjectMetadataProvider { repositoryInfo: InfoRetriever | n eventEmitter: EventEmitter + + isTwoPackageJsonProjectLayoutUsed: boolean } export abstract class PlatformPackager implements ProjectMetadataProvider { @@ -149,7 +152,16 @@ export abstract class PlatformPackager abstract pack(outDir: string, arch: Arch, targets: Array, postAsyncTasks: Array>): Promise protected async doPack(options: ElectronPackagerOptions, outDir: string, appOutDir: string, arch: Arch, customBuildOptions: DC) { + const asar = options.asar + options.asar = false await pack(options) + options.asar = asar + + const asarOptions = this.computeAsarOptions(customBuildOptions) + if (asarOptions != null) { + await this.createAsarArchive(appOutDir, asarOptions) + } + await this.copyExtraFiles(appOutDir, arch, customBuildOptions) const afterPack = this.devMetadata.build.afterPack @@ -160,7 +172,7 @@ export abstract class PlatformPackager }) } - await this.sanityCheckPackage(appOutDir, options.asar) + await this.sanityCheckPackage(appOutDir, asarOptions != null) } protected computePackOptions(outDir: string, appOutDir: string, arch: Arch): ElectronPackagerOptions { @@ -171,7 +183,8 @@ export abstract class PlatformPackager buildVersion += "." + buildNumber } - const options = deepAssign({ + //noinspection JSUnusedGlobalSymbols + const options: any = deepAssign({ dir: this.info.appDir, out: outDir, name: this.appName, @@ -180,7 +193,6 @@ export abstract class PlatformPackager arch: Arch[arch], version: this.info.electronVersion, icon: path.join(this.buildResourcesDir, "icon"), - asar: true, overwrite: true, "app-version": version, "app-copyright": `Copyright © ${new Date().getFullYear()} ${this.metadata.author.name || this.appName}`, @@ -195,6 +207,14 @@ export abstract class PlatformPackager } }, this.devMetadata.build) + if (!this.info.isTwoPackageJsonProjectLayoutUsed && typeof options.ignore !== "function") { + const defaultIgnores = ["/node_modules/electron-builder($|/)", path.relative(this.projectDir, this.buildResourcesDir) + "($|/)"] + if (options.ignore != null && !Array.isArray(options.ignore)) { + options.ignore = [options.ignore] + } + options.ignore = options.ignore == null ? defaultIgnores : options.ignore.concat(defaultIgnores) + } + delete options.osx delete options.win delete options.linux @@ -203,23 +223,89 @@ export abstract class PlatformPackager return options } - private getExtraResources(isResources: boolean, arch: Arch, customBuildOptions: DC): Promise> { - const buildMetadata: any = this.devMetadata.build - let extra: Array | n = buildMetadata == null ? null : buildMetadata[isResources ? "extraResources" : "extraFiles"] + private getExtraResources(isResources: boolean, arch: Arch, customBuildOptions: DC): Promise> { + let patterns: Array | n = (this.devMetadata.build)[isResources ? "extraResources" : "extraFiles"] + const platformSpecificPatterns = isResources ? customBuildOptions.extraResources : customBuildOptions.extraFiles + if (platformSpecificPatterns != null) { + patterns = patterns == null ? platformSpecificPatterns : patterns.concat(platformSpecificPatterns) + } + return patterns == null ? BluebirdPromise.resolve(new Set()) : globby(this.expandPatterns(patterns, arch), {cwd: this.projectDir}); + } + + private computeAsarOptions(customBuildOptions: DC): AsarOptions | null { + let result = this.devMetadata.build.asar + let platformSpecific = customBuildOptions.asar + if (platformSpecific != null) { + result = platformSpecific + } - const platformSpecificExtra = isResources ? customBuildOptions.extraResources : customBuildOptions.extraFiles - if (platformSpecificExtra != null) { - extra = extra == null ? platformSpecificExtra : extra.concat(platformSpecificExtra) + if (result === false) { + return null } - if (extra == null) { - return BluebirdPromise.resolve([]) + const buildMetadata = this.devMetadata.build + if (buildMetadata["asar-unpack"] != null) { + warn("asar-unpack is deprecated, please set as asar.unpack") + } + if (buildMetadata["asar-unpack-dir"] != null) { + warn("asar-unpack-dir is deprecated, please set as asar.unpackDir") } - const expandedPatterns = extra.map(it => it + if (result == null || result === true) { + return { + unpack: buildMetadata["asar-unpack"], + unpackDir: buildMetadata["asar-unpack-dir"] + } + } + else { + return result + } + } + + private async createAsarArchive(appOutDir: string, options: AsarOptions): Promise { + const src = path.join(this.getResourcesDir(appOutDir), "app") + + let glob: Glob | null = null + const files = (await new BluebirdPromise>((resolve, reject) => { + glob = new Glob("**/*", { + cwd: src, + // dot: true as in the asar by default + dot: true, + ignore: "**/.DS_Store", + }, (error, matches) => { + if (error == null) { + resolve(matches) + } + else { + reject(error) + } + }) + })).map(it => path.join(src, it)) + + const stats = await BluebirdPromise.map(files, it => { + // const stat = glob!.statCache[it] + // return stat == null ? lstat(it) : stat + // todo check is it safe to reuse glob stat + return lstat(it) + }) + + const metadata: { [key: string]: AsarFileMetadata; } = {} + for (let i = 0, n = files.length; i < n; i++) { + const stat = stats[i] + metadata[files[i]] = { + type: stat.isFile() ? "file" : (stat.isDirectory() ? "directory" : "link"), + stat: stat, + } + } + + await BluebirdPromise.promisify(createPackageFromFiles)(src, path.join(this.getResourcesDir(appOutDir), "app.asar"), files, metadata, options) + await remove(src) + } + + private expandPatterns(list: Array, arch: Arch): Array { + return list.map(it => it .replace(/\$\{arch}/g, Arch[arch]) .replace(/\$\{os}/g, this.platform.buildConfigurationKey)) - return globby(expandedPatterns, {cwd: this.projectDir}) } protected async copyExtraFiles(appOutDir: string, arch: Arch, customBuildOptions: DC): Promise { diff --git a/test/tsconfig.json b/test/tsconfig.json index f0380c64e98..452b403d0b4 100755 --- a/test/tsconfig.json +++ b/test/tsconfig.json @@ -34,7 +34,6 @@ "../typings/deep-assign.d.ts", "../typings/electron-packager.d.ts", "../typings/gh-api.d.ts", - "../typings/globby.d.ts", "../typings/hosted-git-info.d.ts", "../typings/lib.es2016.array.include.d.ts", "../typings/main/ambient/mime/mime.d.ts", @@ -42,6 +41,7 @@ "../typings/main/definitions/chalk/index.d.ts", "../typings/main/definitions/debug/index.d.ts", "../typings/main/definitions/source-map-support/source-map-support.d.ts", + "../typings/modules/glob/index.d.ts", "../typings/node.d.ts", "../typings/progress-stream.d.ts", "../typings/read-package-json.d.ts", diff --git a/tsconfig.json b/tsconfig.json index a6fdccdbd77..acb8a3b8b6a 100755 --- a/tsconfig.json +++ b/tsconfig.json @@ -38,7 +38,6 @@ "typings/deep-assign.d.ts", "typings/electron-packager.d.ts", "typings/gh-api.d.ts", - "typings/globby.d.ts", "typings/hosted-git-info.d.ts", "typings/lib.es2016.array.include.d.ts", "typings/main/ambient/mime/mime.d.ts", @@ -46,6 +45,7 @@ "typings/main/definitions/chalk/index.d.ts", "typings/main/definitions/debug/index.d.ts", "typings/main/definitions/source-map-support/source-map-support.d.ts", + "typings/modules/glob/index.d.ts", "typings/node.d.ts", "typings/progress-stream.d.ts", "typings/read-package-json.d.ts", @@ -65,6 +65,7 @@ "src/fpmDownload.ts", "src/gitHubPublisher.ts", "src/gitHubRequest.ts", + "src/globby.ts", "src/httpRequest.ts", "src/index.ts", "src/install-app-deps.ts", diff --git a/typings.json b/typings.json index 8afa16b4457..ee848027787 100755 --- a/typings.json +++ b/typings.json @@ -4,6 +4,7 @@ "progress": "github:DefinitelyTyped/DefinitelyTyped/progress/progress.d.ts#d54b18e0ac3277376700b6026ef9e9e3f380df50" }, "dependencies": { + "glob": "registry:npm/glob#6.0.0+20160211003958", "source-map-support": "github:typed-typings/npm-source-map-support#900ed4180a22285bce4bbabc0760427e71a59eca" } } diff --git a/typings/asar.d.ts b/typings/asar.d.ts index 81dd3b932a1..41ab7a713e4 100644 --- a/typings/asar.d.ts +++ b/typings/asar.d.ts @@ -1,11 +1,25 @@ declare module "asar" { + import { Stats } from "fs" + interface Info { offset: number size: number } + interface AsarFileMetadata { + type: "file" | "directory" | "link" + stat: Stats + } + + interface AsarOptions { + unpack?: string + unpackDir?: string + } + export function listPackage(archive: string): Array // followLinks defaults to true export function statFile(archive: string, filename: string, followLinks?: boolean): Info | null + + export function createPackageFromFiles(src: string, dest: string, filenames: Array, metadata: { [key: string]: AsarFileMetadata;}, options: AsarOptions, callback: (error?: Error) => void): void } \ No newline at end of file diff --git a/typings/electron-packager.d.ts b/typings/electron-packager.d.ts index fb00f7b2909..fd87b0609fb 100644 --- a/typings/electron-packager.d.ts +++ b/typings/electron-packager.d.ts @@ -2,9 +2,9 @@ declare module "electron-packager-tf" { /** Electron-packager Options. */ export interface ElectronPackagerOptions { /** The source directory. */ - dir: string; + dir?: string; /** The application name. */ - name: string; + name?: string; /** * Allowed values: linux, win32, darwin, all. Not required if `all` is used. * Arbitrary combinations of individual platforms are also supported via a comma-delimited string or array of strings. @@ -13,7 +13,7 @@ declare module "electron-packager-tf" { /** Allowed values: ia32, x64, all Not required if `all` is used. */ arch?: string; /** Electron version (without the "v"). See https://github.com/atom/electron/releases. */ - version: string; + version?: string; /** Shortcut for `--arch=all --platform=all`. */ all?: boolean; @@ -33,20 +33,20 @@ declare module "electron-packager-tf" { icon?: string; /** The bundle identifier to use in the app plist. */ - "app-bundle-id"?: string; + "app-bundle-id"?: string | null; /** The release version to set for the app. */ "app-version"?: string; /** The build version to set for the app (OS X only). */ - "build-version"?: string; + "build-version"?: string | null; /** The bundle identifier to use in the app helper plist. */ - "helper-bundle-id"?: string; + "helper-bundle-id"?: string | null; /** Object hash of application metadata to embed into the executable (Windows only). */ "version-string"?: VersionString; /** The directory of cached electron downloads. Defaults to "$HOME/.electron". */ cache?: string; /** Do not copy files into App whose filenames regex .match this string. */ - ignore?: RegExp; + ignore?: RegExp | Array; /** Runs `npm prune --production` on the app. */ prune?: boolean; /** If output directory for a platform already exists, replaces it rather than skipping it. */ @@ -54,7 +54,8 @@ declare module "electron-packager-tf" { /** Packages the source code within your app into an archive. */ asar?: boolean; /** Unpacks the files to app.asar.unpacked directory whose filenames regex .match this string. */ - "asar-unpack"?: string; + "asar-unpack"?: string; + "asar-unpack-dir"?: string; /** Should contain the identity to be used when running `codesign` (OS X only). */ sign?: string; @@ -74,6 +75,6 @@ declare module "electron-packager-tf" { ProductName?: string; InternalName?: string; } - + export function pack(opts: ElectronPackagerOptions): Promise } \ No newline at end of file diff --git a/typings/globby.d.ts b/typings/globby.d.ts deleted file mode 100644 index 758708d920d..00000000000 --- a/typings/globby.d.ts +++ /dev/null @@ -1,9 +0,0 @@ -declare module "globby" { - interface GlobOptions { - cwd?: string - } - - function globby(patterns: Array, options?: GlobOptions): Promise> - - export = globby -} \ No newline at end of file diff --git a/typings/modules/glob/index.d.ts b/typings/modules/glob/index.d.ts new file mode 100644 index 00000000000..a4de7636d7c --- /dev/null +++ b/typings/modules/glob/index.d.ts @@ -0,0 +1,302 @@ +// Generated by typings +// Source: https://raw.githubusercontent.com/typed-typings/npm-minimatch/74f47de8acb42d668491987fc6bc144e7d9aa891/minimatch.d.ts +declare module '~glob~minimatch/minimatch' { +function minimatch (target: string, pattern: string, options?: minimatch.Options): boolean; + +namespace minimatch { + export function match (list: string[], pattern: string, options?: Options): string[]; + export function filter (pattern: string, options?: Options): (element: string, indexed: number, array: string[]) => boolean; + export function makeRe (pattern: string, options?: Options): RegExp; + + /** + * All options are `false` by default. + */ + export interface Options { + /** + * Dump a ton of stuff to stderr. + */ + debug?: boolean; + /** + * Do not expand `{a,b}` and `{1..3}` brace sets. + */ + nobrace?: boolean; + /** + * Disable `**` matching against multiple folder names. + */ + noglobstar?: boolean; + /** + * Allow patterns to match filenames starting with a period, even if the pattern does not explicitly have a period in that spot. + * + * Note that by default, `a\/**\/b` will not match `a/.d/b`, unless `dot` is set. + */ + dot?: boolean; + /** + * Disable "extglob" style patterns like `+(a|b)`. + */ + noext?: boolean; + /** + * Perform a case-insensitive match. + */ + nocase?: boolean; + /** + * When a match is not found by `minimatch.match`, return a list containing the pattern itself if this option is set. When not set, an empty list is returned if there are no matches. + */ + nonull?: boolean; + /** + * If set, then patterns without slashes will be matched against the basename of the path if it contains slashes. For example, `a?b` would match the path `/xyz/123/acb`, but not `/xyz/acb/123`. + */ + matchBase?: boolean; + /** + * Suppress the behavior of treating `#` at the start of a pattern as a comment. + */ + nocomment?: boolean; + /** + * Suppress the behavior of treating a leading `!` character as negation. + */ + nonegate?: boolean; + /** + * Returns from negate expressions the same as if they were not negated. (Ie, true on a hit, false on a miss.) + */ + flipNegate?: boolean; + } + + export class Minimatch { + constructor (pattern: string, options?: Options); + + /** + * The original pattern the minimatch object represents. + */ + pattern: string; + /** + * The options supplied to the constructor. + */ + options: Options; + + /** + * Created by the `makeRe` method. A single regular expression expressing the entire pattern. This is useful in cases where you wish to use the pattern somewhat like `fnmatch(3)` with `FNM_PATH` enabled. + */ + regexp: RegExp; + /** + * True if the pattern is negated. + */ + negate: boolean; + /** + * True if the pattern is a comment. + */ + comment: boolean; + /** + * True if the pattern is `""`. + */ + empty: boolean; + + /** + * Generate the regexp member if necessary, and return it. Will return false if the pattern is invalid. + */ + makeRe (): RegExp | boolean; + /** + * Return true if the filename matches the pattern, or false otherwise. + */ + match (fname: string): boolean; + /** + * Take a `/-`split filename, and match it against a single row in the `regExpSet`. This method is mainly for internal use, but is exposed so that it can be used by a glob-walker that needs to avoid excessive filesystem calls. + */ + matchOne (fileArray: string[], patternArray: string[], partial: boolean): boolean; + } +} + +export = minimatch; +} +declare module '~glob~minimatch' { +import alias = require('~glob~minimatch/minimatch'); +export = alias; +} + +// Generated by typings +// Source: https://raw.githubusercontent.com/typed-typings/npm-glob/59ca0f5d4696a8d4da27858035316c1014133fcb/glob.d.ts +declare module '~glob/glob' { +import events = require('events'); +import fs = require('fs'); +import minimatch = require('~glob~minimatch'); + +function glob (pattern: string, cb: (err: Error, matches: string[]) => void): void; +function glob (pattern: string, options: glob.Options, cb: (err: Error, matches: string[]) => void): void; + +namespace glob { + export function sync (pattern: string, options?: Options): string[]; + export function hasMagic (pattern: string, options?: Options): boolean; + + export interface Cache { + [path: string]: boolean | string | string[]; + } + + export interface StatCache { + [path: string]: fs.Stats; + } + + export interface Symlinks { + [path: string]: boolean; + } + + export interface Options extends minimatch.Options { + /** + * The current working directory in which to search. Defaults to `process.cwd()`. + */ + cwd?: string; + /** + * The place where patterns starting with `/` will be mounted onto. Defaults to `path.resolve(options.cwd, "/")` (`/` on Unix systems, and `C:\` or some such on Windows.) + */ + root?: string; + /** + * Include `.dot` files in normal matches and `globstar` matches. Note that an explicit dot in a portion of the pattern will always match dot files. + */ + dot?: boolean; + /** + * By default, a pattern starting with a forward-slash will be "mounted" onto the root setting, so that a valid filesystem path is returned. Set this flag to disable that behavior. + */ + nomount?: boolean; + /** + * Add a `/` character to directory matches. Note that this requires additional stat calls. + */ + mark?: boolean; + /** + * Don't sort the results. + */ + nosort?: boolean; + /** + * Set to true to stat all results. This reduces performance somewhat, and is completely unnecessary, unless `readdir` is presumed to be an untrustworthy indicator of file existence. + */ + stat?: boolean; + /** + * When an unusual error is encountered when attempting to read a directory, a warning will be printed to stderr. Set the `silent` option to true to suppress these warnings. + */ + silent?: boolean; + /** + * When an unusual error is encountered when attempting to read a directory, the process will just continue on in search of other matches. Set the `strict` option to raise an error in these cases. + */ + strict?: boolean; + /** + * See `cache` property above. Pass in a previously generated cache object to save some fs calls. + */ + cache?: Cache; + /** + * A cache of results of filesystem information, to prevent unnecessary stat calls. While it should not normally be necessary to set this, you may pass the statCache from one glob() call to the options object of another, if you know that the filesystem will not change between calls. (See https://github.com/isaacs/node-glob#race-conditions) + */ + statCache?: StatCache; + /** + * A cache of known symbolic links. You may pass in a previously generated `symlinks` object to save lstat calls when resolving `**` matches. + */ + symlinks?: Symlinks; + /** + * DEPRECATED: use `glob.sync(pattern, opts)` instead. + */ + sync?: boolean; + /** + * In some cases, brace-expanded patterns can result in the same file showing up multiple times in the result set. By default, this implementation prevents duplicates in the result set. Set this flag to disable that behavior. + */ + nounique?: boolean; + /** + * Set to never return an empty set, instead returning a set containing the pattern itself. This is the default in glob(3). + */ + nonull?: boolean; + /** + * Set to enable debug logging in minimatch and glob. + */ + debug?: boolean; + /** + * Do not expand `{a,b}` and `{1..3}` brace sets. + */ + nobrace?: boolean; + /** + * Do not match `**` against multiple filenames. (Ie, treat it as a normal `*` instead.) + */ + noglobstar?: boolean; + /** + * Do not match `+(a|b)` "extglob" patterns. + */ + noext?: boolean; + /** + * Perform a case-insensitive match. Note: on case-insensitive filesystems, non-magic patterns will match by default, since `stat` and `readdir` will not raise errors. + */ + nocase?: boolean; + /** + * Perform a basename-only match if the pattern does not contain any slash characters. That is, `*.js` would be treated as equivalent to `**\/*.js`, matching all js files in all directories. + */ + matchBase?: any; + /** + * Do not match directories, only files. (Note: to match only directories, simply put a `/` at the end of the pattern.) + */ + nodir?: boolean; + /** + * Add a pattern or an array of glob patterns to exclude matches. Note: `ignore` patterns are always in `dot:true` mode, regardless of any other settings. + */ + ignore?: string | string[]; + /** + * Follow symlinked directories when expanding `**` patterns. Note that this can result in a lot of duplicate references in the presence of cyclic links. + */ + follow?: boolean; + /** + * Set to true to call `fs.realpath` on all of the results. In the case of a symlink that cannot be resolved, the full absolute path to the matched entry is returned (though it will usually be a broken symlink) + */ + realpath?: boolean; + } + + export class Glob extends events.EventEmitter { + constructor (pattern: string, cb?: (err: Error, matches: string[]) => void); + constructor (pattern: string, options: Options, cb?: (err: Error, matches: string[]) => void); + + /** + * The minimatch object that the glob uses. + */ + minimatch: minimatch.Minimatch; + /** + * The options object passed in. + */ + options: Options; + /** + * Boolean which is set to true when calling `abort()`. There is no way at this time to continue a glob search after aborting, but you can re-use the statCache to avoid having to duplicate syscalls. + * @type {boolean} + */ + aborted: boolean; + /** + * Convenience object. + */ + cache: Cache; + /** + * Cache of `fs.stat` results, to prevent statting the same path multiple times. + */ + statCache: StatCache; + /** + * A record of which paths are symbolic links, which is relevant in resolving `**` patterns. + */ + symlinks: Symlinks; + /** + * An optional object which is passed to `fs.realpath` to minimize unnecessary syscalls. It is stored on the instantiated Glob object, and may be re-used. + */ + realpathCache: { [path: string]: string }; + found: string[]; + + /** + * Temporarily stop the search. + */ + pause(): void; + /** + * Resume the search. + */ + resume(): void; + /** + * Stop the search forever. + */ + abort(): void; + } +} + +export = glob; +} +declare module 'glob/glob' { +import alias = require('~glob/glob'); +export = alias; +} +declare module 'glob' { +import alias = require('~glob/glob'); +export = alias; +} diff --git a/typings/modules/glob/typings.json b/typings/modules/glob/typings.json new file mode 100644 index 00000000000..f75da64049b --- /dev/null +++ b/typings/modules/glob/typings.json @@ -0,0 +1,21 @@ +{ + "resolution": "main", + "tree": { + "src": "https://raw.githubusercontent.com/typed-typings/npm-glob/59ca0f5d4696a8d4da27858035316c1014133fcb/typings.json", + "raw": "registry:npm/glob#6.0.0+20160211003958", + "main": "glob.d.ts", + "global": false, + "dependencies": { + "minimatch": { + "src": "https://raw.githubusercontent.com/typed-typings/npm-minimatch/74f47de8acb42d668491987fc6bc144e7d9aa891/typings.json", + "raw": "github:typed-typings/npm-minimatch#74f47de8acb42d668491987fc6bc144e7d9aa891", + "main": "minimatch.d.ts", + "global": false, + "name": "minimatch", + "type": "typings" + } + }, + "name": "glob", + "type": "typings" + } +}