npm package for scwrypts

This commit is contained in:
Wryn (yage) Wagner 2024-02-20 21:48:30 -07:00
parent bdb7851064
commit 113445ca43
17 changed files with 12751 additions and 12 deletions

25
run
View File

@ -327,6 +327,10 @@ source "${0:a:h}/zsh/lib/import.driver.zsh" || exit 42
|| LOGFILE='/dev/null' \
;
local RUN_MODE=normal
[[ $LOGFILE =~ ^/dev/null$ ]] && RUN_MODE=no-logfile
[[ $SCWRYPT_NAME =~ interactive ]] && RUN_MODE=interactive
local HEADER FOOTER
[[ $SCWRYPTS_LOG_LEVEL -ge 2 ]] && {
@ -358,13 +362,20 @@ source "${0:a:h}/zsh/lib/import.driver.zsh" || exit 42
set -o pipefail
{
[ $HEADER ] && echo $HEADER
[[ $LOGFILE =~ ^/dev/null$ ]] && {
eval "$RUN_STRING $(printf "%q " "$@")" </dev/tty >/dev/tty 2>&1
EXIT_CODE=$?
} || {
(eval "$RUN_STRING $(printf "%q " "$@")")
EXIT_CODE=$?
}
case $RUN_MODE in
normal )
(eval "$RUN_STRING $(printf "%q " "$@")")
EXIT_CODE=$?
;;
no-logfile )
eval "$RUN_STRING $(printf "%q " "$@")"
EXIT_CODE=$?
;;
interactive )
eval "$RUN_STRING $(printf "%q " "$@")" </dev/tty >/dev/tty 2>&1
EXIT_CODE=$?
;;
esac
[ $FOOTER ] && echo $FOOTER
[[ $EXIT_CODE -eq 0 ]] && EXIT_COLOR='32m' || EXIT_COLOR='31m'

View File

@ -9,7 +9,7 @@ FZF() {
FZF_ARGS+=(--height=50%)
FZF_ARGS+=(--layout=reverse)
local SELECTION=$(fzf ${FZF_ARGS[@]} --prompt "$1 : " ${@:2})
local SELECTION=$(fzf ${FZF_ARGS[@]} --prompt "$1 : " ${@:2} 2>/dev/tty)
PROMPT "$1"
[ $BE_QUIET ] || {

2
zx/lib/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
dist/
node_modules/

2
zx/lib/.prettierignore Normal file
View File

@ -0,0 +1,2 @@
dist
node_modules

99
zx/lib/package.json Normal file
View File

@ -0,0 +1,99 @@
{
"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 .",
"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",
"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"
}
}

3163
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
View File

@ -0,0 +1,5 @@
export * from './scwrypts/scwrypts.js';
export { ScwryptsLogLevel } from './scwrypts/types.js';
export type { ScwryptsOptions } from './scwrypts/types.js';

View 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);
}
});

View 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,
};
};

View 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);
});
});

View 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;
}
};

View File

@ -0,0 +1,158 @@
/* 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', () => {
let output;
beforeEach(async () => {
sample.spy.getScwryptsLookup.mockReturnValue(sample.lookup.exact);
output = 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,
]);
});

View 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),
]);
};

View 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
View 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

File diff suppressed because it is too large Load Diff

View File

@ -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"
}
}