v4.0.0
===================================================================== Big day! V4 is finally live. This INCLUDES some BREAKING CHANGES to ZSH TYPE scwrypts! Please refer to the readme for upgrade details (more specifically docs/upgrade/v3-to-v4.md) Upgrade is SUPER EASY, so please take the time to do so. --- New Features ---------------------------------------------------- - zsh type scwrypts have an upgraded runstring to improve context setup and simplicity to the scwrypt-writer - scwrypts now publishes the package (scwrypts) to PyPi; this provides a simple way to invoke scwrypts from python-based environments as well as the entire scwrypts python library suite pip install scwrypts - scwrypts now publishes the package (scwrypts) to npm; this provides a simple way to invoke scwrypts from nodesjs environments npm install scwrypts --- Bug Fixes ------------------------------------------------------- - scwrypts runner prompts which use the zshbuiltin "read" now appropriately read input from tty, pipe, files, and user input - virtualenv refresh now loads and prepares the scwrypts virtual environments correctly --- Changes --------------------------------------------------------- - created the (-v, --log-level) scwrypts arguments as improvements of and replacements to the --verbose and --no-log flags - (-n) is now an alias for (--log-level 0) - (--no-log) is the same as (-n) for compatibility, but will be removed in 4.2 - zsh/lib/utils/io print functions now *interact with log-level* various log levels will now only display the appropriate console prints for the specified log level - zsh/lib/utils/io:INFO has been renamed to DEBUG to align with log-level output; please use DEBUG for debug messages and REMINDER for important user messages - created zsh/lib/utils/io:FZF_USER_INPUT as a *drop-in replacement* for the confusing FZF_HEAD and FZF_TAIL commands. Update by literally changing any instances of FZF_HEAD or FZF_TAIL with FZF_USER_INPUT - FZF_HEAD and FZF_TAIL will be removed in 4.2 - zsh/lib/utils/io:READ (and other zshbuiltin/read-based prompts) now accept a --force-user-input flag in case important checks should require an admin's approval. This flag will ensure that piped input and the `scwrypts -y` flag are ignored for the single prompt. - zsh/lib/utils/color has been updated to use color names which match the ANSI color names - zsh/hello-world has been reduced to a minimal example; this is to emphasize ease-of-use with v4 - zsh/sanity-check is a scwrypts/run testing helper and detailed starting reference (helpful since hello-world is now minimal) - various refactor, updates, and improvements to the scwrypts runner - migrated all zsh scwrypts and plugins to use v4 runner syntax - zsh - plugins/kubectl - plugins/ci - refactored py/lib into py/lib/scwrypts (PyPi)
This commit is contained in:
2
zx/lib/.gitignore
vendored
Normal file
2
zx/lib/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
dist/
|
||||
node_modules/
|
2
zx/lib/.prettierignore
Normal file
2
zx/lib/.prettierignore
Normal file
@ -0,0 +1,2 @@
|
||||
dist
|
||||
node_modules
|
100
zx/lib/package.json
Normal file
100
zx/lib/package.json
Normal file
@ -0,0 +1,100 @@
|
||||
{
|
||||
"name": "scwrypts",
|
||||
"main": "dist/index.js",
|
||||
"type": "module",
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"description": "scwrypts integration for typescript",
|
||||
"scripts": {
|
||||
"build": "rm -rf ./dist && tsc",
|
||||
"test": "jest",
|
||||
"lint": "eslint . && prettier --check src/",
|
||||
"format": "prettier --write src/"
|
||||
},
|
||||
"author": "Wryn (yage) Wagner",
|
||||
"license": "GPL-3.0",
|
||||
"devDependencies": {
|
||||
"@jest/globals": "^29.7.0",
|
||||
"@types/jest": "^29.5.12",
|
||||
"@types/node": "^20.11.19",
|
||||
"@types/uuid": "^9.0.8",
|
||||
"@typescript-eslint/eslint-plugin": "^7.0.2",
|
||||
"@typescript-eslint/parser": "^7.0.2",
|
||||
"eslint": "^8.56.0",
|
||||
"jest": "^29.7.0",
|
||||
"prettier": "^3.2.5",
|
||||
"ts-jest": "^29.1.2",
|
||||
"ts-node": "^10.9.2",
|
||||
"typescript": "^5.3.3",
|
||||
"uuid": "^9.0.1"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"ignorePatterns": [
|
||||
"dist",
|
||||
"node_modules"
|
||||
],
|
||||
"env": {
|
||||
"node": true,
|
||||
"es2021": true
|
||||
},
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"plugin:@typescript-eslint/recommended"
|
||||
],
|
||||
"overrides": [
|
||||
{
|
||||
"env": {
|
||||
"node": true
|
||||
},
|
||||
"files": [
|
||||
".eslintrc.{js,cjs}"
|
||||
],
|
||||
"parserOptions": {
|
||||
"sourceType": "script"
|
||||
}
|
||||
}
|
||||
],
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"parserOptions": {
|
||||
"ecmaVersion": "latest",
|
||||
"sourceType": "module"
|
||||
},
|
||||
"plugins": [
|
||||
"@typescript-eslint"
|
||||
],
|
||||
"rules": {
|
||||
"linebreak-style": [
|
||||
"error",
|
||||
"unix"
|
||||
],
|
||||
"quotes": [
|
||||
"error",
|
||||
"single"
|
||||
],
|
||||
"semi": [
|
||||
"error",
|
||||
"always"
|
||||
],
|
||||
"comma-dangle": [
|
||||
"error",
|
||||
"always-multiline"
|
||||
]
|
||||
}
|
||||
},
|
||||
"prettier": {
|
||||
"printWidth": 120,
|
||||
"singleQuote": true,
|
||||
"trailingComma": "all"
|
||||
},
|
||||
"jest": {
|
||||
"preset": "ts-jest",
|
||||
"clearMocks": true,
|
||||
"moduleNameMapper": {
|
||||
"^(\\.{1,2}/.*)\\.js$": "$1"
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"execa": "^8.0.1"
|
||||
}
|
||||
}
|
3166
zx/lib/pnpm-lock.yaml
generated
Normal file
3166
zx/lib/pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load Diff
5
zx/lib/src/index.ts
Normal file
5
zx/lib/src/index.ts
Normal file
@ -0,0 +1,5 @@
|
||||
export * from './scwrypts/scwrypts.js';
|
||||
|
||||
export { ScwryptsLogLevel } from './scwrypts/types.js';
|
||||
|
||||
export type { ScwryptsOptions } from './scwrypts/types.js';
|
116
zx/lib/src/scwrypts/get-scwrypts-lookup.test.ts
Normal file
116
zx/lib/src/scwrypts/get-scwrypts-lookup.test.ts
Normal file
@ -0,0 +1,116 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import { describe, expect, test, beforeEach, jest } from '@jest/globals';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
|
||||
import * as parseCLIArgs from './parse-cli-args.js';
|
||||
|
||||
import { getScwryptsLookup, Errors } from './get-scwrypts-lookup.js';
|
||||
|
||||
import type { ScwryptsOptions } from './types.js';
|
||||
|
||||
let sample: any;
|
||||
beforeEach(() => {
|
||||
sample = {
|
||||
parsedCLIArgs: [uuid(), uuid(), uuid()],
|
||||
spy: {},
|
||||
};
|
||||
|
||||
sample.spy.parseCLIArgs = jest.spyOn(parseCLIArgs, 'parseCLIArgs');
|
||||
sample.spy.parseCLIArgs.mockReturnValue(sample.parsedCLIArgs);
|
||||
});
|
||||
|
||||
describe('exact', () => {
|
||||
beforeEach(() => {
|
||||
sample.exact = {
|
||||
name: uuid(),
|
||||
group: uuid(),
|
||||
type: uuid(),
|
||||
};
|
||||
});
|
||||
|
||||
test('provides correct lookup', () => {
|
||||
const lookup = getScwryptsLookup(sample.exact as ScwryptsOptions);
|
||||
|
||||
expect(lookup).toEqual({
|
||||
method: 'exact',
|
||||
...sample.exact,
|
||||
});
|
||||
});
|
||||
|
||||
describe('throws error', () => {
|
||||
test('when missing group', () => {
|
||||
delete sample.exact.group;
|
||||
try {
|
||||
getScwryptsLookup(sample.exact as ScwryptsOptions);
|
||||
expect(true).toBeFalsy();
|
||||
} catch (error) {
|
||||
expect(error).toEqual(Errors.MissingScwryptsExactLookupParametersError);
|
||||
}
|
||||
});
|
||||
|
||||
test('when missing type', () => {
|
||||
delete sample.exact.type;
|
||||
try {
|
||||
getScwryptsLookup(sample.exact as ScwryptsOptions);
|
||||
expect(true).toBeFalsy();
|
||||
} catch (error) {
|
||||
expect(error).toEqual(Errors.MissingScwryptsExactLookupParametersError);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('patterns', () => {
|
||||
describe('list', () => {
|
||||
let lookup: any;
|
||||
beforeEach(() => {
|
||||
sample.patterns = {
|
||||
patterns: [uuid(), uuid(), uuid()],
|
||||
};
|
||||
|
||||
lookup = getScwryptsLookup(sample.patterns as ScwryptsOptions);
|
||||
});
|
||||
|
||||
test('provides correct lookup', () => {
|
||||
expect(lookup).toEqual({
|
||||
method: 'patterns',
|
||||
patterns: sample.parsedCLIArgs,
|
||||
});
|
||||
});
|
||||
|
||||
test('parses patterns', () => {
|
||||
expect(sample.spy.parseCLIArgs).toHaveBeenCalledWith(sample.patterns.patterns);
|
||||
});
|
||||
});
|
||||
|
||||
describe('string', () => {
|
||||
let lookup: any;
|
||||
beforeEach(() => {
|
||||
sample.patterns = {
|
||||
patterns: uuid(),
|
||||
};
|
||||
|
||||
lookup = getScwryptsLookup(sample.patterns as ScwryptsOptions);
|
||||
});
|
||||
|
||||
test('provides correct lookup', () => {
|
||||
expect(lookup).toEqual({
|
||||
method: 'patterns',
|
||||
patterns: sample.parsedCLIArgs,
|
||||
});
|
||||
});
|
||||
|
||||
test('parses patterns', () => {
|
||||
expect(sample.spy.parseCLIArgs).toHaveBeenCalledWith(sample.patterns.patterns);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('throws error when missing name and patterns', () => {
|
||||
try {
|
||||
getScwryptsLookup({} as ScwryptsOptions);
|
||||
expect(true).toBeFalsy();
|
||||
} catch (error) {
|
||||
expect(error).toEqual(Errors.NoScwryptsLookupError);
|
||||
}
|
||||
});
|
49
zx/lib/src/scwrypts/get-scwrypts-lookup.ts
Normal file
49
zx/lib/src/scwrypts/get-scwrypts-lookup.ts
Normal file
@ -0,0 +1,49 @@
|
||||
import { parseCLIArgs } from './parse-cli-args.js';
|
||||
|
||||
import type { ScwryptsOptions } from './types.js';
|
||||
|
||||
export type ScwryptsLookupOptions =
|
||||
| {
|
||||
method: 'exact';
|
||||
name: string;
|
||||
group: string;
|
||||
type: string;
|
||||
}
|
||||
| {
|
||||
method: 'patterns';
|
||||
patterns: string[];
|
||||
};
|
||||
|
||||
export const Errors = {
|
||||
NoScwryptsLookupError: {
|
||||
name: 'NoScwryptsLookupError',
|
||||
message: 'no scwrypts lookup parameters provided',
|
||||
},
|
||||
MissingScwryptsExactLookupParametersError: {
|
||||
name: 'MissingScwryptsExactLookupParametersError',
|
||||
message: '"name" option requires "group" and "type" options',
|
||||
},
|
||||
};
|
||||
|
||||
export const getScwryptsLookup = (options: ScwryptsOptions): ScwryptsLookupOptions => {
|
||||
if (options.name === undefined) {
|
||||
if (options.patterns === undefined || options.patterns.length === 0) {
|
||||
throw Errors.NoScwryptsLookupError;
|
||||
}
|
||||
return {
|
||||
method: 'patterns',
|
||||
patterns: parseCLIArgs(options.patterns),
|
||||
};
|
||||
}
|
||||
|
||||
if (options.group === undefined || options.type === undefined) {
|
||||
throw Errors.MissingScwryptsExactLookupParametersError;
|
||||
}
|
||||
|
||||
return {
|
||||
method: 'exact',
|
||||
name: options.name,
|
||||
group: options.group,
|
||||
type: options.type,
|
||||
};
|
||||
};
|
32
zx/lib/src/scwrypts/parse-cli-args.test.ts
Normal file
32
zx/lib/src/scwrypts/parse-cli-args.test.ts
Normal file
@ -0,0 +1,32 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import { describe, expect, test, beforeEach } from '@jest/globals';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
|
||||
import { parseCLIArgs } from './parse-cli-args.js';
|
||||
|
||||
let sample: any;
|
||||
beforeEach(() => {
|
||||
sample = {
|
||||
args: [uuid(), uuid(), uuid()],
|
||||
};
|
||||
|
||||
sample.argstring = sample.args.join(' ');
|
||||
});
|
||||
|
||||
describe('undefined input', () => {
|
||||
test('produces a string[]', () => {
|
||||
expect(parseCLIArgs(undefined)).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('string input', () => {
|
||||
test('produces a string[]', () => {
|
||||
expect(parseCLIArgs(sample.argstring)).toEqual(sample.args);
|
||||
});
|
||||
});
|
||||
|
||||
describe('string[] input', () => {
|
||||
test('produces a string[]', () => {
|
||||
expect(parseCLIArgs(sample.args)).toEqual(sample.args);
|
||||
});
|
||||
});
|
12
zx/lib/src/scwrypts/parse-cli-args.ts
Normal file
12
zx/lib/src/scwrypts/parse-cli-args.ts
Normal file
@ -0,0 +1,12 @@
|
||||
export type CLIArgs = string | string[] | undefined;
|
||||
|
||||
export const parseCLIArgs = (args: CLIArgs): string[] => {
|
||||
switch (typeof args) {
|
||||
case 'undefined':
|
||||
return [];
|
||||
case 'string':
|
||||
return args.split(' ');
|
||||
default:
|
||||
return args;
|
||||
}
|
||||
};
|
155
zx/lib/src/scwrypts/scwrypts.test.ts
Normal file
155
zx/lib/src/scwrypts/scwrypts.test.ts
Normal file
@ -0,0 +1,155 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import { describe, expect, test, beforeEach, jest } from '@jest/globals';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
|
||||
import { execa } from 'execa';
|
||||
import * as Module_getScwryptsLookup from './get-scwrypts-lookup.js';
|
||||
import * as Module_parseCLIArgs from './parse-cli-args.js';
|
||||
import { ScwryptsLogLevel } from './types.js';
|
||||
|
||||
import { scwrypts } from './scwrypts.js';
|
||||
|
||||
jest.mock('execa', () => ({
|
||||
execa: jest.fn(() => Promise.resolve()),
|
||||
}));
|
||||
|
||||
const env = process.env;
|
||||
beforeEach(() => {});
|
||||
|
||||
let sample: any;
|
||||
beforeEach(() => {
|
||||
sample = {
|
||||
options: {
|
||||
name: uuid(),
|
||||
group: uuid(),
|
||||
type: uuid(),
|
||||
patterns: [uuid(), uuid(), uuid()],
|
||||
log_level: Math.floor(Math.random() * Object.keys(ScwryptsLogLevel).length),
|
||||
args: uuid(),
|
||||
},
|
||||
lookup: {
|
||||
exact: {
|
||||
method: 'exact',
|
||||
name: uuid(),
|
||||
group: uuid(),
|
||||
type: uuid(),
|
||||
},
|
||||
patterns: {
|
||||
method: 'patterns',
|
||||
patterns: [uuid(), uuid(), uuid()],
|
||||
},
|
||||
},
|
||||
env: {
|
||||
SCWRYPTS_EXECUTABLE: uuid(),
|
||||
},
|
||||
parsedCLIArgs: [uuid(), uuid(), uuid()],
|
||||
spy: {},
|
||||
};
|
||||
|
||||
sample.spy.getScwryptsLookup = jest.spyOn(Module_getScwryptsLookup, 'getScwryptsLookup');
|
||||
sample.spy.getScwryptsLookup.mockReturnValue(sample.lookup.exact);
|
||||
|
||||
sample.spy.parseCLIArgs = jest.spyOn(Module_parseCLIArgs, 'parseCLIArgs');
|
||||
sample.spy.parseCLIArgs.mockReturnValue(sample.parsedCLIArgs);
|
||||
|
||||
jest.resetModules();
|
||||
process.env = {
|
||||
...env,
|
||||
...sample.env,
|
||||
};
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
process.env = { ...env };
|
||||
});
|
||||
|
||||
describe('exact lookup', () => {
|
||||
beforeEach(async () => {
|
||||
sample.spy.getScwryptsLookup.mockReturnValue(sample.lookup.exact);
|
||||
await scwrypts(sample.options);
|
||||
});
|
||||
|
||||
test('gets the correct lookup', () => {
|
||||
expect(sample.spy.getScwryptsLookup).toHaveBeenCalledWith(sample.options);
|
||||
});
|
||||
|
||||
test('parses arguments correctly', () => {
|
||||
expect(sample.spy.parseCLIArgs).toHaveBeenCalledWith(sample.options.args);
|
||||
});
|
||||
|
||||
test('calls the correct scwrypt', () => {
|
||||
expect(execa).toHaveBeenCalledWith(sample.env.SCWRYPTS_EXECUTABLE, [
|
||||
'--name',
|
||||
sample.lookup.exact.name,
|
||||
'--group',
|
||||
sample.lookup.exact.group,
|
||||
'--type',
|
||||
sample.lookup.exact.type,
|
||||
'--log-level',
|
||||
sample.options.log_level.toString(),
|
||||
'--',
|
||||
...sample.parsedCLIArgs,
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('patterns lookup', () => {
|
||||
beforeEach(async () => {
|
||||
sample.spy.getScwryptsLookup.mockReturnValue(sample.lookup.patterns);
|
||||
await scwrypts(sample.options);
|
||||
});
|
||||
|
||||
test('gets the correct lookup', () => {
|
||||
expect(sample.spy.getScwryptsLookup).toHaveBeenCalledWith(sample.options);
|
||||
});
|
||||
|
||||
test('parses arguments correctly', () => {
|
||||
expect(sample.spy.parseCLIArgs).toHaveBeenCalledWith(sample.options.args);
|
||||
});
|
||||
|
||||
test('calls the correct scwrypt', () => {
|
||||
expect(execa).toHaveBeenCalledWith(sample.env.SCWRYPTS_EXECUTABLE, [
|
||||
...sample.lookup.patterns.patterns,
|
||||
'--log-level',
|
||||
sample.options.log_level.toString(),
|
||||
'--',
|
||||
...sample.parsedCLIArgs,
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
test('omits --log-level arguments if not provided', async () => {
|
||||
delete sample.options.log_level;
|
||||
|
||||
await scwrypts(sample.options);
|
||||
|
||||
expect(execa).toHaveBeenCalledWith(sample.env.SCWRYPTS_EXECUTABLE, [
|
||||
'--name',
|
||||
sample.lookup.exact.name,
|
||||
'--group',
|
||||
sample.lookup.exact.group,
|
||||
'--type',
|
||||
sample.lookup.exact.type,
|
||||
'--',
|
||||
...sample.parsedCLIArgs,
|
||||
]);
|
||||
});
|
||||
|
||||
test('uses default scwrypts executable SCWRYPTS_EXECUTABLE is not provided', async () => {
|
||||
delete process.env.SCWRYPTS_EXECUTABLE;
|
||||
|
||||
await scwrypts(sample.options);
|
||||
|
||||
expect(execa).toHaveBeenCalledWith('scwrypts', [
|
||||
'--name',
|
||||
sample.lookup.exact.name,
|
||||
'--group',
|
||||
sample.lookup.exact.group,
|
||||
'--type',
|
||||
sample.lookup.exact.type,
|
||||
'--log-level',
|
||||
sample.options.log_level.toString(),
|
||||
'--',
|
||||
...sample.parsedCLIArgs,
|
||||
]);
|
||||
});
|
31
zx/lib/src/scwrypts/scwrypts.ts
Normal file
31
zx/lib/src/scwrypts/scwrypts.ts
Normal file
@ -0,0 +1,31 @@
|
||||
import { execa } from 'execa';
|
||||
|
||||
import { getScwryptsLookup } from './get-scwrypts-lookup.js';
|
||||
import { parseCLIArgs } from './parse-cli-args.js';
|
||||
|
||||
import type { ScwryptsOptions } from './types.js';
|
||||
|
||||
export const scwrypts = async (options: ScwryptsOptions) => {
|
||||
const lookup = getScwryptsLookup(options);
|
||||
|
||||
const scwryptsExecutableArgs: string[] = [];
|
||||
|
||||
switch (lookup.method) {
|
||||
case 'exact':
|
||||
scwryptsExecutableArgs.push('--name', lookup.name, '--group', lookup.group, '--type', lookup.type);
|
||||
break;
|
||||
case 'patterns':
|
||||
scwryptsExecutableArgs.push(...lookup.patterns);
|
||||
break;
|
||||
}
|
||||
|
||||
if (options.log_level !== undefined) {
|
||||
scwryptsExecutableArgs.push('--log-level', options.log_level.toString());
|
||||
}
|
||||
|
||||
return await execa(process.env.SCWRYPTS_EXECUTABLE || 'scwrypts', [
|
||||
...scwryptsExecutableArgs,
|
||||
'--',
|
||||
...parseCLIArgs(options.args),
|
||||
]);
|
||||
};
|
16
zx/lib/src/scwrypts/types.ts
Normal file
16
zx/lib/src/scwrypts/types.ts
Normal file
@ -0,0 +1,16 @@
|
||||
export type ScwryptsOptions = {
|
||||
name: string | undefined;
|
||||
group: string | undefined;
|
||||
type: string | undefined;
|
||||
patterns: string[] | undefined;
|
||||
log_level: ScwryptsLogLevel | undefined;
|
||||
args: string | string[] | undefined;
|
||||
};
|
||||
|
||||
export enum ScwryptsLogLevel {
|
||||
SILENT = 0,
|
||||
QUIET = 1,
|
||||
NORMAL = 2,
|
||||
WARNING = 3,
|
||||
DEBUG = 4,
|
||||
}
|
18
zx/lib/tsconfig.json
Normal file
18
zx/lib/tsconfig.json
Normal file
@ -0,0 +1,18 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "ES2022",
|
||||
"moduleResolution": "node",
|
||||
"target": "ES2022",
|
||||
"lib": ["ES2022"],
|
||||
"checkJs": true,
|
||||
"declaration": true,
|
||||
"esModuleInterop": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"outDir": "dist",
|
||||
"resolveJsonModule": true,
|
||||
"skipLibCheck": true,
|
||||
"strict": true
|
||||
},
|
||||
"include": ["src"],
|
||||
"exclude": ["node_modules", "dist", "extensions", "**/*.test.ts"]
|
||||
}
|
9024
zx/package-lock.json
generated
9024
zx/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -3,11 +3,14 @@
|
||||
"version": "1.0.0",
|
||||
"description": "zx scripts for scwrypts",
|
||||
"main": "index.js",
|
||||
"type": "module",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"test": "",
|
||||
"preinstall": "npm i -g zx"
|
||||
"preinstall": "npm i -g zx"
|
||||
},
|
||||
"author": "yage",
|
||||
"license": "GPL-3.0-or-later"
|
||||
"license": "GPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
"scwrypts": "file:lib"
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user