@gjsify/cli 0.0.4 → 0.1.1

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/README.md ADDED
@@ -0,0 +1,30 @@
1
+ # @gjsify/cli
2
+
3
+ CLI tool for building and running GJS applications. Bundles TypeScript/JavaScript using esbuild with automatic Node.js to GJS module aliasing.
4
+
5
+ Part of the [gjsify](https://github.com/gjsify/gjsify) project — Node.js and Web APIs for GJS (GNOME JavaScript).
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ npm install @gjsify/cli
11
+ # or
12
+ yarn add @gjsify/cli
13
+ ```
14
+
15
+ ## Usage
16
+
17
+ ```bash
18
+ # Build a GJS application
19
+ npx @gjsify/cli build src/index.ts
20
+
21
+ # Run a built GJS application (sets up LD_LIBRARY_PATH, GI_TYPELIB_PATH, etc.)
22
+ npx @gjsify/cli run dist/index.js
23
+
24
+ # Show environment info for a bundle
25
+ npx @gjsify/cli info dist/index.js
26
+ ```
27
+
28
+ ## License
29
+
30
+ MIT
@@ -9,86 +9,87 @@ export declare class BuildAction {
9
9
  buildLibrary(): Promise<BuildResult<BuildOptions>[]>;
10
10
  /** Application mode */
11
11
  buildApp(app?: App): Promise<BuildResult<{
12
- format: "cjs" | "esm";
12
+ format: "esm" | "cjs";
13
13
  plugins: import("esbuild").Plugin[];
14
- bundle?: boolean | undefined;
15
- splitting?: boolean | undefined;
16
- preserveSymlinks?: boolean | undefined;
17
- outfile?: string | undefined;
18
- metafile?: boolean | undefined;
19
- outdir?: string | undefined;
20
- outbase?: string | undefined;
21
- external?: string[] | undefined;
22
- packages?: "external" | undefined;
23
- alias?: Record<string, string> | undefined;
14
+ bundle?: boolean;
15
+ splitting?: boolean;
16
+ preserveSymlinks?: boolean;
17
+ outfile?: string;
18
+ metafile?: boolean;
19
+ outdir?: string;
20
+ outbase?: string;
21
+ external?: string[];
22
+ packages?: "bundle" | "external";
23
+ alias?: Record<string, string>;
24
24
  loader?: {
25
25
  [ext: string]: import("esbuild").Loader;
26
- } | undefined;
27
- resolveExtensions?: string[] | undefined;
28
- mainFields?: string[] | undefined;
29
- conditions?: string[] | undefined;
30
- write?: boolean | undefined;
31
- allowOverwrite?: boolean | undefined;
32
- tsconfig?: string | undefined;
26
+ };
27
+ resolveExtensions?: string[];
28
+ mainFields?: string[];
29
+ conditions?: string[];
30
+ write?: boolean;
31
+ allowOverwrite?: boolean;
32
+ tsconfig?: string;
33
33
  outExtension?: {
34
34
  [ext: string]: string;
35
- } | undefined;
36
- publicPath?: string | undefined;
37
- entryNames?: string | undefined;
38
- chunkNames?: string | undefined;
39
- assetNames?: string | undefined;
40
- inject?: string[] | undefined;
35
+ };
36
+ publicPath?: string;
37
+ entryNames?: string;
38
+ chunkNames?: string;
39
+ assetNames?: string;
40
+ inject?: string[];
41
41
  banner?: {
42
42
  [type: string]: string;
43
- } | undefined;
43
+ };
44
44
  footer?: {
45
45
  [type: string]: string;
46
- } | undefined;
47
- entryPoints?: string[] | Record<string, string> | {
46
+ };
47
+ entryPoints?: (string | {
48
48
  in: string;
49
49
  out: string;
50
- }[] | undefined;
51
- stdin?: import("esbuild").StdinOptions | undefined;
52
- absWorkingDir?: string | undefined;
53
- nodePaths?: string[] | undefined;
54
- sourcemap?: boolean | "inline" | "both" | "external" | "linked" | undefined;
55
- legalComments?: "inline" | "none" | "external" | "linked" | "eof" | undefined;
56
- sourceRoot?: string | undefined;
57
- sourcesContent?: boolean | undefined;
58
- globalName?: string | undefined;
59
- target?: string | string[] | undefined;
60
- supported?: Record<string, boolean> | undefined;
61
- platform?: import("esbuild").Platform | undefined;
62
- mangleProps?: RegExp | undefined;
63
- reserveProps?: RegExp | undefined;
64
- mangleQuoted?: boolean | undefined;
65
- mangleCache?: Record<string, string | false> | undefined;
66
- drop?: import("esbuild").Drop[] | undefined;
67
- dropLabels?: string[] | undefined;
68
- minify?: boolean | undefined;
69
- minifyWhitespace?: boolean | undefined;
70
- minifyIdentifiers?: boolean | undefined;
71
- minifySyntax?: boolean | undefined;
72
- lineLimit?: number | undefined;
73
- charset?: import("esbuild").Charset | undefined;
74
- treeShaking?: boolean | undefined;
75
- ignoreAnnotations?: boolean | undefined;
76
- jsx?: "transform" | "preserve" | "automatic" | undefined;
77
- jsxFactory?: string | undefined;
78
- jsxFragment?: string | undefined;
79
- jsxImportSource?: string | undefined;
80
- jsxDev?: boolean | undefined;
81
- jsxSideEffects?: boolean | undefined;
50
+ })[] | Record<string, string>;
51
+ stdin?: import("esbuild").StdinOptions;
52
+ absWorkingDir?: string;
53
+ nodePaths?: string[];
54
+ sourcemap?: boolean | "linked" | "inline" | "external" | "both";
55
+ legalComments?: "none" | "inline" | "eof" | "linked" | "external";
56
+ sourceRoot?: string;
57
+ sourcesContent?: boolean;
58
+ globalName?: string;
59
+ target?: string | string[];
60
+ supported?: Record<string, boolean>;
61
+ platform?: import("esbuild").Platform;
62
+ mangleProps?: RegExp;
63
+ reserveProps?: RegExp;
64
+ mangleQuoted?: boolean;
65
+ mangleCache?: Record<string, string | false>;
66
+ drop?: import("esbuild").Drop[];
67
+ dropLabels?: string[];
68
+ minify?: boolean;
69
+ minifyWhitespace?: boolean;
70
+ minifyIdentifiers?: boolean;
71
+ minifySyntax?: boolean;
72
+ lineLimit?: number;
73
+ charset?: import("esbuild").Charset;
74
+ treeShaking?: boolean;
75
+ ignoreAnnotations?: boolean;
76
+ jsx?: "transform" | "preserve" | "automatic";
77
+ jsxFactory?: string;
78
+ jsxFragment?: string;
79
+ jsxImportSource?: string;
80
+ jsxDev?: boolean;
81
+ jsxSideEffects?: boolean;
82
82
  define?: {
83
83
  [key: string]: string;
84
- } | undefined;
85
- pure?: string[] | undefined;
86
- keepNames?: boolean | undefined;
87
- color?: boolean | undefined;
88
- logLevel?: import("esbuild").LogLevel | undefined;
89
- logLimit?: number | undefined;
90
- logOverride?: Record<string, import("esbuild").LogLevel> | undefined;
91
- tsconfigRaw?: string | import("esbuild").TsconfigRaw | undefined;
84
+ };
85
+ pure?: string[];
86
+ keepNames?: boolean;
87
+ absPaths?: import("esbuild").AbsPaths[];
88
+ color?: boolean;
89
+ logLevel?: import("esbuild").LogLevel;
90
+ logLimit?: number;
91
+ logOverride?: Record<string, import("esbuild").LogLevel>;
92
+ tsconfigRaw?: string | import("esbuild").TsconfigRaw;
92
93
  }>[]>;
93
94
  start(buildType?: {
94
95
  library?: boolean;
@@ -50,7 +50,7 @@ export class BuildAction {
50
50
  const outfilePath = esbuild?.outfile || library?.module || library?.main;
51
51
  const outExt = outfilePath ? extname(outfilePath) : '.js';
52
52
  const outdir = esbuild?.outdir || (outfilePath ? dirname(outfilePath) : undefined);
53
- const format = esbuild?.format || outdir?.includes('/cjs') || outExt === '.cjs' ? 'cjs' : 'esm';
53
+ const format = esbuild?.format ?? (outdir?.includes('/cjs') || outExt === '.cjs' ? 'cjs' : 'esm');
54
54
  results.push(await build({
55
55
  ...this.getEsBuildDefaults(),
56
56
  ...esbuild,
@@ -66,17 +66,18 @@ export class BuildAction {
66
66
  /** Application mode */
67
67
  async buildApp(app = 'gjs') {
68
68
  const { verbose, esbuild, typescript, exclude, library: pgk } = this.configData;
69
- const format = esbuild?.format || esbuild?.outfile?.endsWith('.cjs') ? 'cjs' : 'esm';
69
+ const format = esbuild?.format ?? (esbuild?.outfile?.endsWith('.cjs') ? 'cjs' : 'esm');
70
70
  // Set default outfile if no outdir is set
71
71
  if (esbuild && !esbuild?.outfile && !esbuild?.outdir && (pgk?.main || pgk?.module)) {
72
72
  esbuild.outfile = esbuild?.format === 'cjs' ? pgk.main || pgk.module : pgk.module || pgk.main;
73
73
  }
74
+ const { consoleShim } = this.configData;
74
75
  const result = await build({
75
76
  ...this.getEsBuildDefaults(),
76
77
  ...esbuild,
77
78
  format,
78
79
  plugins: [
79
- gjsifyPlugin({ debug: verbose, app, format, exclude, reflection: typescript?.reflection }),
80
+ gjsifyPlugin({ debug: verbose, app, format, exclude, reflection: typescript?.reflection, consoleShim }),
80
81
  ]
81
82
  });
82
83
  // See https://esbuild.github.io/api/#metafile
@@ -30,9 +30,9 @@ export const buildCommand = {
30
30
  default: false
31
31
  })
32
32
  .option('app', {
33
- description: "Use this if you want to build a application, the application platforms node and deno are usually only used for tests",
33
+ description: "Use this if you want to build an application, the platform node is usually only used for tests",
34
34
  type: 'string',
35
- choices: ['gjs', 'node', 'deno', 'browser'],
35
+ choices: ['gjs', 'node', 'browser'],
36
36
  normalize: true,
37
37
  default: 'gjs'
38
38
  })
@@ -79,6 +79,12 @@ export const buildCommand = {
79
79
  choices: ['silent', 'error', 'warning', 'info', 'debug', 'verbose'],
80
80
  normalize: true,
81
81
  default: 'warning'
82
+ })
83
+ .option('console-shim', {
84
+ description: "Inject a console shim into GJS builds for clean output without the GLib prefix and with working ANSI colors. Use --no-console-shim to disable. Only applies to GJS app builds.",
85
+ type: 'boolean',
86
+ normalize: true,
87
+ default: true
82
88
  });
83
89
  },
84
90
  handler: async (args) => {
@@ -1 +1,3 @@
1
1
  export * from './build.js';
2
+ export * from './run.js';
3
+ export * from './info.js';
@@ -1 +1,3 @@
1
1
  export * from './build.js';
2
+ export * from './run.js';
3
+ export * from './info.js';
@@ -0,0 +1,7 @@
1
+ import type { Command } from '../types/index.js';
2
+ interface InfoOptions {
3
+ export: boolean;
4
+ file?: string;
5
+ }
6
+ export declare const infoCommand: Command<any, InfoOptions>;
7
+ export {};
@@ -0,0 +1,59 @@
1
+ import { resolve } from 'node:path';
2
+ import { detectNativePackages, buildNativeEnv } from '../utils/detect-native-packages.js';
3
+ export const infoCommand = {
4
+ command: 'info [file]',
5
+ description: 'Show native gjsify packages detected in node_modules and the env vars needed to run a GJS bundle directly with gjs.',
6
+ builder: (yargs) => {
7
+ return yargs
8
+ .positional('file', {
9
+ description: 'Optional: the GJS bundle path to include in the example command (e.g. dist/gjs.js)',
10
+ type: 'string',
11
+ normalize: true,
12
+ })
13
+ .option('export', {
14
+ description: 'Output only shell export statements suitable for eval (eval $(gjsify info --export))',
15
+ type: 'boolean',
16
+ default: false,
17
+ });
18
+ },
19
+ handler: async (args) => {
20
+ const cwd = process.cwd();
21
+ const file = args.file ? resolve(args.file) : null;
22
+ const nativePackages = detectNativePackages(cwd);
23
+ const { LD_LIBRARY_PATH, GI_TYPELIB_PATH } = buildNativeEnv(nativePackages);
24
+ if (args.export) {
25
+ // Machine-readable output for eval
26
+ console.log(`export LD_LIBRARY_PATH="${LD_LIBRARY_PATH}"`);
27
+ console.log(`export GI_TYPELIB_PATH="${GI_TYPELIB_PATH}"`);
28
+ return;
29
+ }
30
+ // Human-readable output
31
+ if (nativePackages.length === 0) {
32
+ console.log('No native gjsify packages detected in node_modules.');
33
+ console.log('Native packages declare "gjsify": { "prebuilds": "<dir>" } in their package.json.');
34
+ return;
35
+ }
36
+ console.log('Native packages detected:');
37
+ for (const pkg of nativePackages) {
38
+ console.log(` ${pkg.name} → ${pkg.prebuildsDir}`);
39
+ }
40
+ console.log('');
41
+ console.log('To run your app directly with gjs, set:');
42
+ console.log(` export LD_LIBRARY_PATH="${LD_LIBRARY_PATH}"`);
43
+ console.log(` export GI_TYPELIB_PATH="${GI_TYPELIB_PATH}"`);
44
+ if (file) {
45
+ console.log(` gjs -m ${file}`);
46
+ }
47
+ else {
48
+ console.log(' gjs -m <your-bundle.js>');
49
+ }
50
+ console.log('');
51
+ console.log('Or use gjsify run to handle this automatically:');
52
+ if (file) {
53
+ console.log(` gjsify run ${args.file}`);
54
+ }
55
+ else {
56
+ console.log(' gjsify run <your-bundle.js>');
57
+ }
58
+ },
59
+ };
@@ -0,0 +1,7 @@
1
+ import type { Command } from '../types/index.js';
2
+ interface RunOptions {
3
+ file: string;
4
+ args: string[];
5
+ }
6
+ export declare const runCommand: Command<any, RunOptions>;
7
+ export {};
@@ -0,0 +1,49 @@
1
+ import { spawn } from 'node:child_process';
2
+ import { resolve } from 'node:path';
3
+ import { detectNativePackages, buildNativeEnv } from '../utils/detect-native-packages.js';
4
+ export const runCommand = {
5
+ command: 'run <file> [args..]',
6
+ description: 'Run a GJS bundle, automatically setting LD_LIBRARY_PATH and GI_TYPELIB_PATH for any installed native gjsify packages (e.g. @gjsify/webgl).',
7
+ builder: (yargs) => {
8
+ return yargs
9
+ .positional('file', {
10
+ description: 'The GJS bundle to run (e.g. dist/gjs.js)',
11
+ type: 'string',
12
+ normalize: true,
13
+ demandOption: true,
14
+ })
15
+ .positional('args', {
16
+ description: 'Extra arguments passed through to gjs',
17
+ type: 'string',
18
+ array: true,
19
+ default: [],
20
+ });
21
+ },
22
+ handler: async (args) => {
23
+ const file = resolve(args.file);
24
+ const extraArgs = args.args ?? [];
25
+ const cwd = process.cwd();
26
+ const nativePackages = detectNativePackages(cwd);
27
+ const nativeEnv = buildNativeEnv(nativePackages);
28
+ const env = {
29
+ ...process.env,
30
+ ...nativeEnv,
31
+ };
32
+ const gjsArgs = ['-m', file, ...extraArgs];
33
+ const child = spawn('gjs', gjsArgs, { env, stdio: 'inherit' });
34
+ await new Promise((resolvePromise, reject) => {
35
+ child.on('close', (code) => {
36
+ if (code !== 0) {
37
+ reject(new Error(`gjs exited with code ${code}`));
38
+ }
39
+ else {
40
+ resolvePromise();
41
+ }
42
+ });
43
+ child.on('error', reject);
44
+ }).catch((err) => {
45
+ console.error(err.message);
46
+ process.exit(1);
47
+ });
48
+ },
49
+ };
package/lib/config.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Options as LoadOptions } from 'cosmiconfig';
1
+ import { type Options as LoadOptions } from 'cosmiconfig';
2
2
  import type { CliBuildOptions, ConfigData } from './types/index.js';
3
3
  import type { ArgumentsCamelCase } from 'yargs';
4
4
  export declare class Config {
package/lib/config.js CHANGED
@@ -2,8 +2,29 @@ import { APP_NAME } from './constants.js';
2
2
  import { cosmiconfig } from 'cosmiconfig';
3
3
  import { readPackageJSON, resolvePackageJSON } from 'pkg-types';
4
4
  import { getTsconfig } from 'get-tsconfig';
5
- import lodash from "lodash";
6
- const { merge } = lodash;
5
+ /** Deep merge objects (replaces lodash.merge) */
6
+ function merge(target, ...sources) {
7
+ for (const source of sources) {
8
+ if (!source)
9
+ continue;
10
+ for (const key of Object.keys(source)) {
11
+ const targetVal = target[key];
12
+ const sourceVal = source[key];
13
+ if (sourceVal !== undefined) {
14
+ if (isPlainObject(targetVal) && isPlainObject(sourceVal)) {
15
+ merge(targetVal, sourceVal);
16
+ }
17
+ else {
18
+ target[key] = sourceVal;
19
+ }
20
+ }
21
+ }
22
+ }
23
+ return target;
24
+ }
25
+ function isPlainObject(val) {
26
+ return typeof val === 'object' && val !== null && !Array.isArray(val) && Object.getPrototypeOf(val) === Object.prototype;
27
+ }
7
28
  export class Config {
8
29
  loadOptions = {};
9
30
  constructor(loadOptions = {}) {
@@ -46,9 +67,11 @@ export class Config {
46
67
  // TODO replace with `cliArgs.logLevel`
47
68
  configData.verbose = cliArgs.verbose || false;
48
69
  configData.exclude = cliArgs.exclude || [];
49
- merge(configData.library, pkg, configData.library);
50
- merge(configData.typescript, tsConfig, configData.typescript);
51
- merge(configData.esbuild, {
70
+ if (cliArgs.consoleShim !== undefined)
71
+ configData.consoleShim = cliArgs.consoleShim;
72
+ merge(configData.library ??= {}, pkg, configData.library);
73
+ merge(configData.typescript ??= {}, tsConfig, configData.typescript);
74
+ merge(configData.esbuild ??= {}, {
52
75
  format: cliArgs.format,
53
76
  minify: cliArgs.minify,
54
77
  entryPoints: cliArgs.entryPoints,
package/lib/index.js CHANGED
@@ -1,12 +1,14 @@
1
1
  #!/usr/bin/env node
2
2
  import yargs from 'yargs';
3
3
  import { hideBin } from 'yargs/helpers';
4
- import { buildCommand as build } from './commands/index.js';
4
+ import { buildCommand as build, runCommand as run, infoCommand as info } from './commands/index.js';
5
5
  import { APP_NAME } from './constants.js';
6
6
  void yargs(hideBin(process.argv))
7
7
  .scriptName(APP_NAME)
8
8
  .strict()
9
9
  // .usage(Config.usage)
10
10
  .command(build.command, build.description, build.builder, build.handler)
11
+ .command(run.command, run.description, run.builder, run.handler)
12
+ .command(info.command, info.description, info.builder, info.handler)
11
13
  .demandCommand(1)
12
14
  .help().argv;
@@ -17,7 +17,7 @@ export interface CliBuildOptions {
17
17
  * @see https://esbuild.github.io/api/#format
18
18
  */
19
19
  format?: 'iife' | 'esm' | 'cjs';
20
- /** Use this if you want to build a application or test, the platforms node and deno are usually only used internally to build the tests for Gjsify */
20
+ /** Use this if you want to build an application or test, the platform node is usually only used internally to build the tests for Gjsify */
21
21
  app?: App;
22
22
  /** Use this if you want to build a library for Gjsify */
23
23
  library?: boolean;
@@ -42,4 +42,9 @@ export interface CliBuildOptions {
42
42
  logLevel: 'silent' | 'error' | 'warning' | 'info' | 'debug' | 'verbose';
43
43
  /** An array of glob patterns to exclude matches and aliases */
44
44
  exclude?: string[];
45
+ /**
46
+ * Inject a console shim into GJS builds for clean output (no GLib prefix, ANSI colors work).
47
+ * Use --no-console-shim to disable. Only applies to GJS app builds. Default: true.
48
+ */
49
+ consoleShim?: boolean;
45
50
  }
@@ -8,4 +8,9 @@ export interface ConfigData {
8
8
  typescript?: ConfigDataTypescript;
9
9
  /** An array of glob patterns to exclude matches and aliases */
10
10
  exclude?: string[];
11
+ /**
12
+ * Inject a console shim into GJS builds for clean output (no GLib prefix, ANSI colors work).
13
+ * Only applies to GJS app builds. Default: true.
14
+ */
15
+ consoleShim?: boolean;
11
16
  }
@@ -0,0 +1,22 @@
1
+ export interface NativePackage {
2
+ /** npm package name, e.g. "@gjsify/webgl" */
3
+ name: string;
4
+ /** Absolute path to the arch-specific prebuilds dir, e.g. "/…/@gjsify/webgl/prebuilds/linux-x86_64" */
5
+ prebuildsDir: string;
6
+ }
7
+ /**
8
+ * Walk up the directory tree from `startDir` looking for a node_modules directory.
9
+ * Returns all native packages found in the first node_modules encountered.
10
+ *
11
+ * Note: This intentionally stops at the first node_modules to match how Node.js
12
+ * resolves packages from the perspective of the calling project.
13
+ */
14
+ export declare function detectNativePackages(startDir: string): NativePackage[];
15
+ /**
16
+ * Build the LD_LIBRARY_PATH and GI_TYPELIB_PATH env var values for the detected native packages.
17
+ * Prepends the new paths to any existing values from the environment.
18
+ */
19
+ export declare function buildNativeEnv(packages: NativePackage[]): {
20
+ LD_LIBRARY_PATH: string;
21
+ GI_TYPELIB_PATH: string;
22
+ };
@@ -0,0 +1,119 @@
1
+ // Utility to find npm packages with gjsify native prebuilds.
2
+ // Packages declare: "gjsify": { "prebuilds": "<dir>" } in their package.json.
3
+ // The CLI uses this to auto-set LD_LIBRARY_PATH / GI_TYPELIB_PATH before running gjs.
4
+ import { readdirSync, existsSync, readFileSync } from 'node:fs';
5
+ import { join, resolve } from 'node:path';
6
+ /** Map Node.js process.arch values to the convention used in prebuilds/ directories. */
7
+ function nodeArchToLinuxArch(arch) {
8
+ const map = {
9
+ x64: 'x86_64',
10
+ arm64: 'aarch64',
11
+ arm: 'armv7',
12
+ ia32: 'i686',
13
+ };
14
+ return map[arch] ?? arch;
15
+ }
16
+ /** Read a package.json file and return its parsed content, or null on error. */
17
+ function readPackageJson(pkgJsonPath) {
18
+ try {
19
+ return JSON.parse(readFileSync(pkgJsonPath, 'utf-8'));
20
+ }
21
+ catch {
22
+ return null;
23
+ }
24
+ }
25
+ /**
26
+ * Scan all packages in a node_modules directory for gjsify native prebuilds.
27
+ * Handles scoped packages (@scope/name) as well as flat packages.
28
+ */
29
+ function scanNodeModules(nodeModulesDir, arch) {
30
+ const results = [];
31
+ if (!existsSync(nodeModulesDir))
32
+ return results;
33
+ let entries;
34
+ try {
35
+ entries = readdirSync(nodeModulesDir);
36
+ }
37
+ catch {
38
+ return results;
39
+ }
40
+ for (const entry of entries) {
41
+ if (entry.startsWith('.'))
42
+ continue;
43
+ if (entry.startsWith('@')) {
44
+ // Scoped packages — one more level deep
45
+ const scopeDir = join(nodeModulesDir, entry);
46
+ let scopeEntries;
47
+ try {
48
+ scopeEntries = readdirSync(scopeDir);
49
+ }
50
+ catch {
51
+ continue;
52
+ }
53
+ for (const scopedPkg of scopeEntries) {
54
+ const pkgDir = join(scopeDir, scopedPkg);
55
+ const native = checkPackage(pkgDir, `${entry}/${scopedPkg}`, arch);
56
+ if (native)
57
+ results.push(native);
58
+ }
59
+ }
60
+ else {
61
+ const pkgDir = join(nodeModulesDir, entry);
62
+ const native = checkPackage(pkgDir, entry, arch);
63
+ if (native)
64
+ results.push(native);
65
+ }
66
+ }
67
+ return results;
68
+ }
69
+ /** Check a single package directory for gjsify prebuilds metadata. */
70
+ function checkPackage(pkgDir, name, arch) {
71
+ const pkgJson = readPackageJson(join(pkgDir, 'package.json'));
72
+ if (!pkgJson)
73
+ return null;
74
+ const gjsifyMeta = pkgJson['gjsify'];
75
+ if (!gjsifyMeta || typeof gjsifyMeta !== 'object')
76
+ return null;
77
+ const prebuildsField = gjsifyMeta['prebuilds'];
78
+ if (typeof prebuildsField !== 'string')
79
+ return null;
80
+ const prebuildsDir = join(pkgDir, prebuildsField, `linux-${arch}`);
81
+ if (!existsSync(prebuildsDir))
82
+ return null;
83
+ return { name, prebuildsDir };
84
+ }
85
+ /**
86
+ * Walk up the directory tree from `startDir` looking for a node_modules directory.
87
+ * Returns all native packages found in the first node_modules encountered.
88
+ *
89
+ * Note: This intentionally stops at the first node_modules to match how Node.js
90
+ * resolves packages from the perspective of the calling project.
91
+ */
92
+ export function detectNativePackages(startDir) {
93
+ const arch = nodeArchToLinuxArch(process.arch);
94
+ let dir = resolve(startDir);
95
+ // Walk up to filesystem root
96
+ while (true) {
97
+ const nodeModulesDir = join(dir, 'node_modules');
98
+ if (existsSync(nodeModulesDir)) {
99
+ return scanNodeModules(nodeModulesDir, arch);
100
+ }
101
+ const parent = resolve(dir, '..');
102
+ if (parent === dir)
103
+ break; // reached filesystem root
104
+ dir = parent;
105
+ }
106
+ return [];
107
+ }
108
+ /**
109
+ * Build the LD_LIBRARY_PATH and GI_TYPELIB_PATH env var values for the detected native packages.
110
+ * Prepends the new paths to any existing values from the environment.
111
+ */
112
+ export function buildNativeEnv(packages) {
113
+ const dirs = packages.map(p => p.prebuildsDir);
114
+ const existing_ld = process.env['LD_LIBRARY_PATH'] ?? '';
115
+ const existing_gi = process.env['GI_TYPELIB_PATH'] ?? '';
116
+ const LD_LIBRARY_PATH = [...dirs, ...(existing_ld ? [existing_ld] : [])].join(':');
117
+ const GI_TYPELIB_PATH = [...dirs, ...(existing_gi ? [existing_gi] : [])].join(':');
118
+ return { LD_LIBRARY_PATH, GI_TYPELIB_PATH };
119
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gjsify/cli",
3
- "version": "0.0.4",
3
+ "version": "0.1.1",
4
4
  "description": "CLI for Gjsify",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",
@@ -10,10 +10,10 @@
10
10
  "gjsify": "./lib/index.js"
11
11
  },
12
12
  "scripts": {
13
- "clear": "rm -rf lib tsconfig.tsbuildinfo tsconfig.types.tsbuildinfo || exit 0",
14
- "print:name": "echo '@gjsify/cli'",
13
+ "clear": "rm -rf lib tsconfig.tsbuildinfo || exit 0",
14
+ "check": "tsc --noEmit",
15
15
  "start": "node lib/index.js",
16
- "build": "yarn print:name && tsc && yarn chmod",
16
+ "build": "tsc && yarn chmod",
17
17
  "chmod": "chmod +x ./lib/index.js"
18
18
  },
19
19
  "keywords": [
@@ -23,17 +23,15 @@
23
23
  "cli"
24
24
  ],
25
25
  "dependencies": {
26
- "@gjsify/esbuild-plugin-deepkit": "^0.0.4",
27
- "@gjsify/esbuild-plugin-gjsify": "^0.0.4",
28
- "cosmiconfig": "^9.0.0",
29
- "esbuild": "^0.19.10",
30
- "get-tsconfig": "^4.7.2",
31
- "lodash": "^4.17.21",
32
- "pkg-types": "^1.0.3",
33
- "yargs": "^17.7.2"
26
+ "@gjsify/esbuild-plugin-gjsify": "^0.1.1",
27
+ "cosmiconfig": "^9.0.1",
28
+ "esbuild": "^0.27.4",
29
+ "get-tsconfig": "^4.13.7",
30
+ "pkg-types": "^2.3.0",
31
+ "yargs": "^18.0.0"
34
32
  },
35
33
  "devDependencies": {
36
- "@types/yargs": "^17.0.32",
37
- "typescript": "^5.3.3"
34
+ "@types/yargs": "^17.0.35",
35
+ "typescript": "^6.0.2"
38
36
  }
39
37
  }
@@ -60,7 +60,7 @@ export class BuildAction {
60
60
  const outfilePath = esbuild?.outfile || library?.module || library?.main;
61
61
  const outExt = outfilePath ? extname(outfilePath) : '.js';
62
62
  const outdir = esbuild?.outdir || (outfilePath ? dirname(outfilePath) : undefined);
63
- const format = esbuild?.format || outdir?.includes('/cjs') || outExt === '.cjs' ? 'cjs' : 'esm';
63
+ const format: 'esm' | 'cjs' = (esbuild?.format as 'esm' | 'cjs') ?? (outdir?.includes('/cjs') || outExt === '.cjs' ? 'cjs' : 'esm');
64
64
  results.push(await build({
65
65
  ...this.getEsBuildDefaults(),
66
66
  ...esbuild,
@@ -79,19 +79,20 @@ export class BuildAction {
79
79
 
80
80
  const { verbose, esbuild, typescript, exclude, library: pgk } = this.configData;
81
81
 
82
- const format: 'cjs' | 'esm' = esbuild?.format || esbuild?.outfile?.endsWith('.cjs') ? 'cjs' : 'esm';
82
+ const format: 'esm' | 'cjs' = (esbuild?.format as 'esm' | 'cjs') ?? (esbuild?.outfile?.endsWith('.cjs') ? 'cjs' : 'esm');
83
83
 
84
84
  // Set default outfile if no outdir is set
85
85
  if(esbuild && !esbuild?.outfile && !esbuild?.outdir && (pgk?.main || pgk?.module)) {
86
86
  esbuild.outfile = esbuild?.format === 'cjs' ? pgk.main || pgk.module : pgk.module || pgk.main;
87
87
  }
88
88
 
89
+ const { consoleShim } = this.configData;
89
90
  const result = await build({
90
91
  ...this.getEsBuildDefaults(),
91
92
  ...esbuild,
92
93
  format,
93
94
  plugins: [
94
- gjsifyPlugin({debug: verbose, app, format, exclude, reflection: typescript?.reflection}),
95
+ gjsifyPlugin({debug: verbose, app, format, exclude, reflection: typescript?.reflection, consoleShim}),
95
96
  ]
96
97
  });
97
98
 
@@ -32,9 +32,9 @@ export const buildCommand: Command<any, CliBuildOptions> = {
32
32
  default: false
33
33
  })
34
34
  .option('app', {
35
- description: "Use this if you want to build a application, the application platforms node and deno are usually only used for tests",
35
+ description: "Use this if you want to build an application, the platform node is usually only used for tests",
36
36
  type: 'string',
37
- choices: ['gjs', 'node', 'deno', 'browser'],
37
+ choices: ['gjs', 'node', 'browser'],
38
38
  normalize: true,
39
39
  default: 'gjs'
40
40
  })
@@ -82,6 +82,12 @@ export const buildCommand: Command<any, CliBuildOptions> = {
82
82
  normalize: true,
83
83
  default: 'warning'
84
84
  })
85
+ .option('console-shim', {
86
+ description: "Inject a console shim into GJS builds for clean output without the GLib prefix and with working ANSI colors. Use --no-console-shim to disable. Only applies to GJS app builds.",
87
+ type: 'boolean',
88
+ normalize: true,
89
+ default: true
90
+ })
85
91
  },
86
92
  handler: async (args) => {
87
93
  const config = new Config();
@@ -1 +1,3 @@
1
- export * from './build.js';
1
+ export * from './build.js';
2
+ export * from './run.js';
3
+ export * from './info.js';
@@ -0,0 +1,70 @@
1
+ import { resolve } from 'node:path';
2
+ import type { Command } from '../types/index.js';
3
+ import { detectNativePackages, buildNativeEnv } from '../utils/detect-native-packages.js';
4
+
5
+ interface InfoOptions {
6
+ export: boolean;
7
+ file?: string;
8
+ }
9
+
10
+ export const infoCommand: Command<any, InfoOptions> = {
11
+ command: 'info [file]',
12
+ description: 'Show native gjsify packages detected in node_modules and the env vars needed to run a GJS bundle directly with gjs.',
13
+ builder: (yargs) => {
14
+ return yargs
15
+ .positional('file', {
16
+ description: 'Optional: the GJS bundle path to include in the example command (e.g. dist/gjs.js)',
17
+ type: 'string',
18
+ normalize: true,
19
+ })
20
+ .option('export', {
21
+ description: 'Output only shell export statements suitable for eval (eval $(gjsify info --export))',
22
+ type: 'boolean',
23
+ default: false,
24
+ });
25
+ },
26
+ handler: async (args) => {
27
+ const cwd = process.cwd();
28
+ const file = args.file ? resolve(args.file as string) : null;
29
+ const nativePackages = detectNativePackages(cwd);
30
+ const { LD_LIBRARY_PATH, GI_TYPELIB_PATH } = buildNativeEnv(nativePackages);
31
+
32
+ if (args.export) {
33
+ // Machine-readable output for eval
34
+ console.log(`export LD_LIBRARY_PATH="${LD_LIBRARY_PATH}"`);
35
+ console.log(`export GI_TYPELIB_PATH="${GI_TYPELIB_PATH}"`);
36
+ return;
37
+ }
38
+
39
+ // Human-readable output
40
+ if (nativePackages.length === 0) {
41
+ console.log('No native gjsify packages detected in node_modules.');
42
+ console.log('Native packages declare "gjsify": { "prebuilds": "<dir>" } in their package.json.');
43
+ return;
44
+ }
45
+
46
+ console.log('Native packages detected:');
47
+ for (const pkg of nativePackages) {
48
+ console.log(` ${pkg.name} → ${pkg.prebuildsDir}`);
49
+ }
50
+
51
+ console.log('');
52
+ console.log('To run your app directly with gjs, set:');
53
+ console.log(` export LD_LIBRARY_PATH="${LD_LIBRARY_PATH}"`);
54
+ console.log(` export GI_TYPELIB_PATH="${GI_TYPELIB_PATH}"`);
55
+
56
+ if (file) {
57
+ console.log(` gjs -m ${file}`);
58
+ } else {
59
+ console.log(' gjs -m <your-bundle.js>');
60
+ }
61
+
62
+ console.log('');
63
+ console.log('Or use gjsify run to handle this automatically:');
64
+ if (file) {
65
+ console.log(` gjsify run ${args.file}`);
66
+ } else {
67
+ console.log(' gjsify run <your-bundle.js>');
68
+ }
69
+ },
70
+ };
@@ -0,0 +1,59 @@
1
+ import { spawn } from 'node:child_process';
2
+ import { resolve } from 'node:path';
3
+ import type { Command } from '../types/index.js';
4
+ import { detectNativePackages, buildNativeEnv } from '../utils/detect-native-packages.js';
5
+
6
+ interface RunOptions {
7
+ file: string;
8
+ args: string[];
9
+ }
10
+
11
+ export const runCommand: Command<any, RunOptions> = {
12
+ command: 'run <file> [args..]',
13
+ description: 'Run a GJS bundle, automatically setting LD_LIBRARY_PATH and GI_TYPELIB_PATH for any installed native gjsify packages (e.g. @gjsify/webgl).',
14
+ builder: (yargs) => {
15
+ return yargs
16
+ .positional('file', {
17
+ description: 'The GJS bundle to run (e.g. dist/gjs.js)',
18
+ type: 'string',
19
+ normalize: true,
20
+ demandOption: true,
21
+ })
22
+ .positional('args', {
23
+ description: 'Extra arguments passed through to gjs',
24
+ type: 'string',
25
+ array: true,
26
+ default: [],
27
+ });
28
+ },
29
+ handler: async (args) => {
30
+ const file = resolve(args.file as string);
31
+ const extraArgs = (args.args as string[]) ?? [];
32
+ const cwd = process.cwd();
33
+
34
+ const nativePackages = detectNativePackages(cwd);
35
+ const nativeEnv = buildNativeEnv(nativePackages);
36
+
37
+ const env = {
38
+ ...process.env,
39
+ ...nativeEnv,
40
+ };
41
+
42
+ const gjsArgs = ['-m', file, ...extraArgs];
43
+ const child = spawn('gjs', gjsArgs, { env, stdio: 'inherit' });
44
+
45
+ await new Promise<void>((resolvePromise, reject) => {
46
+ child.on('close', (code) => {
47
+ if (code !== 0) {
48
+ reject(new Error(`gjs exited with code ${code}`));
49
+ } else {
50
+ resolvePromise();
51
+ }
52
+ });
53
+ child.on('error', reject);
54
+ }).catch((err) => {
55
+ console.error(err.message);
56
+ process.exit(1);
57
+ });
58
+ },
59
+ };
package/src/config.ts CHANGED
@@ -1,9 +1,30 @@
1
1
  import { APP_NAME } from './constants.js';
2
- import { cosmiconfig, Options as LoadOptions } from 'cosmiconfig';
2
+ import { cosmiconfig, type Options as LoadOptions } from 'cosmiconfig';
3
3
  import { readPackageJSON, resolvePackageJSON } from 'pkg-types';
4
4
  import { getTsconfig } from 'get-tsconfig';
5
- import lodash from "lodash";
6
- const { merge } = lodash;
5
+
6
+ /** Deep merge objects (replaces lodash.merge) */
7
+ function merge<T extends Record<string, any>>(target: T, ...sources: Record<string, any>[]): T {
8
+ for (const source of sources) {
9
+ if (!source) continue;
10
+ for (const key of Object.keys(source)) {
11
+ const targetVal = (target as any)[key];
12
+ const sourceVal = source[key];
13
+ if (sourceVal !== undefined) {
14
+ if (isPlainObject(targetVal) && isPlainObject(sourceVal)) {
15
+ merge(targetVal, sourceVal);
16
+ } else {
17
+ (target as any)[key] = sourceVal;
18
+ }
19
+ }
20
+ }
21
+ }
22
+ return target;
23
+ }
24
+
25
+ function isPlainObject(val: unknown): val is Record<string, any> {
26
+ return typeof val === 'object' && val !== null && !Array.isArray(val) && Object.getPrototypeOf(val) === Object.prototype;
27
+ }
7
28
 
8
29
  import type { CliBuildOptions, ConfigData, CosmiconfigResult, ConfigDataTypescript, ConfigDataLibrary} from './types/index.js';
9
30
  import type { ArgumentsCamelCase } from 'yargs';
@@ -60,10 +81,11 @@ export class Config {
60
81
  // TODO replace with `cliArgs.logLevel`
61
82
  configData.verbose = cliArgs.verbose || false;
62
83
  configData.exclude = cliArgs.exclude || [];
84
+ if (cliArgs.consoleShim !== undefined) configData.consoleShim = cliArgs.consoleShim;
63
85
 
64
- merge(configData.library, pkg, configData.library);
65
- merge(configData.typescript, tsConfig, configData.typescript);
66
- merge(configData.esbuild, {
86
+ merge(configData.library ??= {}, pkg, configData.library);
87
+ merge(configData.typescript ??= {}, tsConfig, configData.typescript);
88
+ merge(configData.esbuild ??= {}, {
67
89
  format: cliArgs.format,
68
90
  minify: cliArgs.minify,
69
91
  entryPoints: cliArgs.entryPoints,
package/src/index.ts CHANGED
@@ -2,7 +2,7 @@
2
2
  import yargs from 'yargs'
3
3
  import { hideBin } from 'yargs/helpers'
4
4
 
5
- import { buildCommand as build } from './commands/index.js'
5
+ import { buildCommand as build, runCommand as run, infoCommand as info } from './commands/index.js'
6
6
  import { APP_NAME } from './constants.js'
7
7
 
8
8
  void yargs(hideBin(process.argv))
@@ -10,5 +10,7 @@ void yargs(hideBin(process.argv))
10
10
  .strict()
11
11
  // .usage(Config.usage)
12
12
  .command(build.command, build.description, build.builder, build.handler)
13
+ .command(run.command, run.description, run.builder, run.handler)
14
+ .command(info.command, info.description, info.builder, info.handler)
13
15
  .demandCommand(1)
14
16
  .help().argv
@@ -18,7 +18,7 @@ export interface CliBuildOptions {
18
18
  * @see https://esbuild.github.io/api/#format
19
19
  */
20
20
  format?: 'iife' | 'esm' | 'cjs';
21
- /** Use this if you want to build a application or test, the platforms node and deno are usually only used internally to build the tests for Gjsify */
21
+ /** Use this if you want to build an application or test, the platform node is usually only used internally to build the tests for Gjsify */
22
22
  app?: App;
23
23
  /** Use this if you want to build a library for Gjsify */
24
24
  library?: boolean;
@@ -43,4 +43,9 @@ export interface CliBuildOptions {
43
43
  logLevel: 'silent' | 'error' | 'warning' | 'info' | 'debug' | 'verbose';
44
44
  /** An array of glob patterns to exclude matches and aliases */
45
45
  exclude?: string[];
46
+ /**
47
+ * Inject a console shim into GJS builds for clean output (no GLib prefix, ANSI colors work).
48
+ * Use --no-console-shim to disable. Only applies to GJS app builds. Default: true.
49
+ */
50
+ consoleShim?: boolean;
46
51
  }
@@ -9,4 +9,9 @@ export interface ConfigData {
9
9
  typescript?: ConfigDataTypescript;
10
10
  /** An array of glob patterns to exclude matches and aliases */
11
11
  exclude?: string[];
12
+ /**
13
+ * Inject a console shim into GJS builds for clean output (no GLib prefix, ANSI colors work).
14
+ * Only applies to GJS app builds. Default: true.
15
+ */
16
+ consoleShim?: boolean;
12
17
  }
@@ -0,0 +1,133 @@
1
+ // Utility to find npm packages with gjsify native prebuilds.
2
+ // Packages declare: "gjsify": { "prebuilds": "<dir>" } in their package.json.
3
+ // The CLI uses this to auto-set LD_LIBRARY_PATH / GI_TYPELIB_PATH before running gjs.
4
+
5
+ import { readdirSync, existsSync, readFileSync } from 'node:fs';
6
+ import { join, resolve } from 'node:path';
7
+
8
+ export interface NativePackage {
9
+ /** npm package name, e.g. "@gjsify/webgl" */
10
+ name: string;
11
+ /** Absolute path to the arch-specific prebuilds dir, e.g. "/…/@gjsify/webgl/prebuilds/linux-x86_64" */
12
+ prebuildsDir: string;
13
+ }
14
+
15
+ /** Map Node.js process.arch values to the convention used in prebuilds/ directories. */
16
+ function nodeArchToLinuxArch(arch: string): string {
17
+ const map: Record<string, string> = {
18
+ x64: 'x86_64',
19
+ arm64: 'aarch64',
20
+ arm: 'armv7',
21
+ ia32: 'i686',
22
+ };
23
+ return map[arch] ?? arch;
24
+ }
25
+
26
+ /** Read a package.json file and return its parsed content, or null on error. */
27
+ function readPackageJson(pkgJsonPath: string): Record<string, unknown> | null {
28
+ try {
29
+ return JSON.parse(readFileSync(pkgJsonPath, 'utf-8'));
30
+ } catch {
31
+ return null;
32
+ }
33
+ }
34
+
35
+ /**
36
+ * Scan all packages in a node_modules directory for gjsify native prebuilds.
37
+ * Handles scoped packages (@scope/name) as well as flat packages.
38
+ */
39
+ function scanNodeModules(nodeModulesDir: string, arch: string): NativePackage[] {
40
+ const results: NativePackage[] = [];
41
+ if (!existsSync(nodeModulesDir)) return results;
42
+
43
+ let entries: string[];
44
+ try {
45
+ entries = readdirSync(nodeModulesDir);
46
+ } catch {
47
+ return results;
48
+ }
49
+
50
+ for (const entry of entries) {
51
+ if (entry.startsWith('.')) continue;
52
+
53
+ if (entry.startsWith('@')) {
54
+ // Scoped packages — one more level deep
55
+ const scopeDir = join(nodeModulesDir, entry);
56
+ let scopeEntries: string[];
57
+ try {
58
+ scopeEntries = readdirSync(scopeDir);
59
+ } catch {
60
+ continue;
61
+ }
62
+ for (const scopedPkg of scopeEntries) {
63
+ const pkgDir = join(scopeDir, scopedPkg);
64
+ const native = checkPackage(pkgDir, `${entry}/${scopedPkg}`, arch);
65
+ if (native) results.push(native);
66
+ }
67
+ } else {
68
+ const pkgDir = join(nodeModulesDir, entry);
69
+ const native = checkPackage(pkgDir, entry, arch);
70
+ if (native) results.push(native);
71
+ }
72
+ }
73
+
74
+ return results;
75
+ }
76
+
77
+ /** Check a single package directory for gjsify prebuilds metadata. */
78
+ function checkPackage(pkgDir: string, name: string, arch: string): NativePackage | null {
79
+ const pkgJson = readPackageJson(join(pkgDir, 'package.json'));
80
+ if (!pkgJson) return null;
81
+
82
+ const gjsifyMeta = pkgJson['gjsify'];
83
+ if (!gjsifyMeta || typeof gjsifyMeta !== 'object') return null;
84
+
85
+ const prebuildsField = (gjsifyMeta as Record<string, unknown>)['prebuilds'];
86
+ if (typeof prebuildsField !== 'string') return null;
87
+
88
+ const prebuildsDir = join(pkgDir, prebuildsField, `linux-${arch}`);
89
+ if (!existsSync(prebuildsDir)) return null;
90
+
91
+ return { name, prebuildsDir };
92
+ }
93
+
94
+ /**
95
+ * Walk up the directory tree from `startDir` looking for a node_modules directory.
96
+ * Returns all native packages found in the first node_modules encountered.
97
+ *
98
+ * Note: This intentionally stops at the first node_modules to match how Node.js
99
+ * resolves packages from the perspective of the calling project.
100
+ */
101
+ export function detectNativePackages(startDir: string): NativePackage[] {
102
+ const arch = nodeArchToLinuxArch(process.arch);
103
+ let dir = resolve(startDir);
104
+
105
+ // Walk up to filesystem root
106
+ while (true) {
107
+ const nodeModulesDir = join(dir, 'node_modules');
108
+ if (existsSync(nodeModulesDir)) {
109
+ return scanNodeModules(nodeModulesDir, arch);
110
+ }
111
+ const parent = resolve(dir, '..');
112
+ if (parent === dir) break; // reached filesystem root
113
+ dir = parent;
114
+ }
115
+
116
+ return [];
117
+ }
118
+
119
+ /**
120
+ * Build the LD_LIBRARY_PATH and GI_TYPELIB_PATH env var values for the detected native packages.
121
+ * Prepends the new paths to any existing values from the environment.
122
+ */
123
+ export function buildNativeEnv(packages: NativePackage[]): { LD_LIBRARY_PATH: string; GI_TYPELIB_PATH: string } {
124
+ const dirs = packages.map(p => p.prebuildsDir);
125
+
126
+ const existing_ld = process.env['LD_LIBRARY_PATH'] ?? '';
127
+ const existing_gi = process.env['GI_TYPELIB_PATH'] ?? '';
128
+
129
+ const LD_LIBRARY_PATH = [...dirs, ...(existing_ld ? [existing_ld] : [])].join(':');
130
+ const GI_TYPELIB_PATH = [...dirs, ...(existing_gi ? [existing_gi] : [])].join(':');
131
+
132
+ return { LD_LIBRARY_PATH, GI_TYPELIB_PATH };
133
+ }
package/tsconfig.json CHANGED
@@ -1,13 +1,16 @@
1
1
  {
2
2
  "compilerOptions": {
3
+ "rootDir": "src",
3
4
  "outDir": "lib",
4
5
  "declarationDir": "lib",
5
6
  "declaration": true,
6
7
  "target": "ESNext",
7
- "moduleResolution":"Node",
8
- "allowSyntheticDefaultImports": true,
9
- "strict": true
8
+ "module": "NodeNext",
9
+ "moduleResolution": "NodeNext",
10
+ "types": ["node"],
11
+ "esModuleInterop": true,
12
+ "strict": true,
13
+ "skipLibCheck": true
10
14
  },
11
- "include": ["src/lodash.d.ts"],
12
15
  "files": ["src/index.ts"]
13
- }
16
+ }
package/src/lodash.d.ts DELETED
@@ -1,46 +0,0 @@
1
- declare module 'lodash' {
2
- /**
3
- * Recursively merges own and inherited enumerable properties of source
4
- * objects into the destination object, skipping source properties that resolve
5
- * to `undefined`. Array and plain object properties are merged recursively.
6
- * Other objects and value types are overridden by assignment. Source objects
7
- * are applied from left to right. Subsequent sources overwrite property
8
- * assignments of previous sources.
9
- *
10
- * **Note:** This method mutates `object`.
11
- *
12
- * @category Object
13
- * @param object The destination object.
14
- * @param [sources] The source objects.
15
- * @returns Returns `object`.
16
- * @example
17
- *
18
- * var users = {
19
- * 'data': [{ 'user': 'barney' }, { 'user': 'fred' }]
20
- * };
21
- *
22
- * var ages = {
23
- * 'data': [{ 'age': 36 }, { 'age': 40 }]
24
- * };
25
- *
26
- * _.merge(users, ages);
27
- * // => { 'data': [{ 'user': 'barney', 'age': 36 }, { 'user': 'fred', 'age': 40 }] }
28
- */
29
- function merge<TObject, TSource>(object: TObject, source: TSource): TObject & TSource;
30
- /**
31
- * @see _.merge
32
- */
33
- function merge<TObject, TSource1, TSource2>(object: TObject, source1: TSource1, source2: TSource2): TObject & TSource1 & TSource2;
34
- /**
35
- * @see _.merge
36
- */
37
- function merge<TObject, TSource1, TSource2, TSource3>(object: TObject, source1: TSource1, source2: TSource2, source3: TSource3): TObject & TSource1 & TSource2 & TSource3;
38
- /**
39
- * @see _.merge
40
- */
41
- function merge<TObject, TSource1, TSource2, TSource3, TSource4>(object: TObject, source1: TSource1, source2: TSource2, source3: TSource3, source4: TSource4): TObject & TSource1 & TSource2 & TSource3 & TSource4;
42
- /**
43
- * @see _.merge
44
- */
45
- function merge(object: any, ...otherArgs: any[]): any;
46
- }