New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

ts-auto-guard

Package Overview
Dependencies
Maintainers
2
Versions
48
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

ts-auto-guard - npm Package Compare versions

Comparing version 1.0.0-alpha.3 to 1.0.0-alpha.4

6

lib/cli.js

@@ -85,2 +85,7 @@ #!/usr/bin/env node

{
description: 'Generate checks for all exported types, even those not marked with comment',
name: 'export-all',
type: Boolean,
},
{
description: 'Path to `tsconfig.json`.',

@@ -124,2 +129,3 @@ name: 'project',

debug: options.debug,
exportAll: options['export-all'],
shortCircuitCondition: options.shortcircuit,

@@ -126,0 +132,0 @@ },

1

lib/index.d.ts
import { Project } from 'ts-morph';
export interface IProcessOptions {
exportAll?: boolean;
shortCircuitCondition?: string;

@@ -4,0 +5,0 @@ debug: boolean;

142

lib/index.js

@@ -151,4 +151,6 @@ "use strict";

}
function getTypeGuardName(jsDocs) {
function getTypeGuardName(child, options) {
var e_2, _a, e_3, _b;
var _c;
var jsDocs = child.getJsDocs();
try {

@@ -158,4 +160,4 @@ for (var jsDocs_1 = __values(jsDocs), jsDocs_1_1 = jsDocs_1.next(); !jsDocs_1_1.done; jsDocs_1_1 = jsDocs_1.next()) {

try {
for (var _c = (e_3 = void 0, __values(doc.getInnerText().split('\n'))), _d = _c.next(); !_d.done; _d = _c.next()) {
var line = _d.value;
for (var _d = (e_3 = void 0, __values(doc.getInnerText().split('\n'))), _e = _d.next(); !_e.done; _e = _d.next()) {
var line = _e.value;
var match = line

@@ -165,3 +167,3 @@ .trim()

if (match !== null) {
var _e = __read(match, 3), typeGuardName = _e[1], command = _e[2];
var _f = __read(match, 3), typeGuardName = _f[1], command = _f[2];
if (command !== 'type-guard') {

@@ -178,3 +180,3 @@ reportError("command " + command + " is not supported!");

try {
if (_d && !_d.done && (_b = _c.return)) _b.call(_c);
if (_e && !_e.done && (_b = _d.return)) _b.call(_d);
}

@@ -192,2 +194,9 @@ finally { if (e_3) throw e_3.error; }

}
if (options.exportAll) {
var t = child.getType();
var name = (_c = t.getSymbol()) === null || _c === void 0 ? void 0 : _c.getName();
if (name) {
return 'is' + name;
}
}
return null;

@@ -216,7 +225,7 @@ }

}
function typeUnionConditions(varName, types, addDependency, project, path, arrayDepth, debug) {
function typeUnionConditions(varName, types, addDependency, project, path, arrayDepth, options) {
var conditions = [];
conditions.push.apply(conditions, __spread(types
.map(function (type) {
return typeConditions(varName, type, addDependency, project, path, arrayDepth, true, debug);
return typeConditions(varName, type, addDependency, project, path, arrayDepth, true, options);
})

@@ -229,3 +238,3 @@ .filter(function (v) { return v !== null; })));

}
function arrayCondition(varName, arrayType, addDependency, project, path, arrayDepth, debug) {
function arrayCondition(varName, arrayType, addDependency, project, path, arrayDepth, options) {
if (arrayType.getText() === 'never') {

@@ -236,3 +245,3 @@ return ands("Array.isArray(" + varName + ")", eq(varName + ".length", '0'));

var elementPath = path + "[${" + indexIdentifier + "}]";
var conditions = typeConditions('e', arrayType, addDependency, project, elementPath, arrayDepth + 1, true, debug);
var conditions = typeConditions('e', arrayType, addDependency, project, elementPath, arrayDepth + 1, true, options);
if (conditions === null) {

@@ -253,3 +262,3 @@ reportError("No conditions for " + varName + ", with array type " + arrayType.getText());

}
function objectCondition(varName, type, addDependency, useGuard, project, path, arrayDepth, debug) {
function objectCondition(varName, type, addDependency, useGuard, project, path, arrayDepth, options) {
var conditions = [];

@@ -272,6 +281,11 @@ var symbol = type.getSymbol();

// case of eg. `type Foo = { x: number }`
var docNode = ts_morph_1.TypeGuards.isJSDocableNode(declaration)
? declaration
: declaration.getParentIfKind(ts_morph_1.SyntaxKind.TypeAliasDeclaration) || null;
var typeGuardName = docNode === null ? null : getTypeGuardName(docNode.getJsDocs());
var declarationResolved = ts_morph_1.Node.isTypeAliasDeclaration(declaration)
? declaration.getParentIfKind(ts_morph_1.SyntaxKind.TypeAliasDeclaration)
: declaration;
var jsDocable = ts_morph_1.Node.isJSDocableNode(declarationResolved)
? declarationResolved
: declarationResolved === null || declarationResolved === void 0 ? void 0 : declarationResolved.getParent();
var typeGuardName = ts_morph_1.Node.isJSDocableNode(jsDocable)
? getTypeGuardName(jsDocable, options)
: null;
if (useGuard && typeGuardName !== null) {

@@ -286,7 +300,7 @@ var sourcePath = declaration.getSourceFile().getFilePath();

if (!useGuard || typeGuardName === null) {
if (!ts_morph_1.TypeGuards.isInterfaceDeclaration(declaration)) {
if (!ts_morph_1.Node.isInterfaceDeclaration(declaration)) {
throw new TypeError('Extected declaration to be an interface delcaration!');
}
declaration.getBaseTypes().forEach(function (baseType) {
var condition = typeConditions(varName, baseType, addDependency, project, path, arrayDepth, true, debug);
var condition = typeConditions(varName, baseType, addDependency, project, path, arrayDepth, true, options);
if (condition !== null) {

@@ -299,3 +313,3 @@ conditions.push(condition);

}
conditions.push.apply(conditions, __spread(propertiesConditions(varName, declaration.getProperties(), addDependency, project, path, arrayDepth, debug)));
conditions.push.apply(conditions, __spread(propertiesConditions(varName, declaration.getProperties(), addDependency, project, path, arrayDepth, options)));
}

@@ -309,3 +323,3 @@ }

var propertySignatures = properties.map(function (p) { return p.getDeclarations()[0]; });
conditions.push.apply(conditions, __spread(propertiesConditions(varName, propertySignatures, addDependency, project, path, arrayDepth, debug)));
conditions.push.apply(conditions, __spread(propertiesConditions(varName, propertySignatures, addDependency, project, path, arrayDepth, options)));
}

@@ -321,6 +335,6 @@ catch (error) {

}
function tupleCondition(varName, type, addDependency, project, path, arrayDepth, debug) {
function tupleCondition(varName, type, addDependency, project, path, arrayDepth, options) {
var types = type.getTupleElements();
var conditions = types.reduce(function (acc, elementType, i) {
var condition = typeConditions(varName + "[" + i + "]", elementType, addDependency, project, path, arrayDepth, true, debug);
var condition = typeConditions(varName + "[" + i + "]", elementType, addDependency, project, path, arrayDepth, true, options);
if (condition !== null) {

@@ -352,3 +366,3 @@ acc.push(condition);

}
function typeConditions(varName, type, addDependency, project, path, arrayDepth, useGuard, debug) {
function typeConditions(varName, type, addDependency, project, path, arrayDepth, useGuard, options) {
if (type.isNull()) {

@@ -372,12 +386,12 @@ return eq(varName, 'null');

}
return typeUnionConditions(varName, type.getUnionTypes(), addDependency, project, path, arrayDepth, debug);
return typeUnionConditions(varName, type.getUnionTypes(), addDependency, project, path, arrayDepth, options);
}
if (type.isIntersection()) {
return typeUnionConditions(varName, type.getIntersectionTypes(), addDependency, project, path, arrayDepth, debug);
return typeUnionConditions(varName, type.getIntersectionTypes(), addDependency, project, path, arrayDepth, options);
}
if (type.isArray()) {
return arrayCondition(varName, type.getArrayElementType(), addDependency, project, path, arrayDepth, debug);
return arrayCondition(varName, type.getArrayElementType(), addDependency, project, path, arrayDepth, options);
}
if (isReadonlyArrayType(type)) {
return arrayCondition(varName, getReadonlyArrayType(type), addDependency, project, path, arrayDepth, debug);
return arrayCondition(varName, getReadonlyArrayType(type), addDependency, project, path, arrayDepth, options);
}

@@ -389,6 +403,6 @@ if (isClassType(type)) {

if (type.isObject()) {
return objectCondition(varName, type, addDependency, useGuard, project, path, arrayDepth, debug);
return objectCondition(varName, type, addDependency, useGuard, project, path, arrayDepth, options);
}
if (type.isTuple()) {
return tupleCondition(varName, type, addDependency, project, path, arrayDepth, debug);
return tupleCondition(varName, type, addDependency, project, path, arrayDepth, options);
}

@@ -400,3 +414,4 @@ if (type.isLiteral()) {

}
function propertyConditions(objName, property, addDependency, project, path, arrayDepth, debug) {
function propertyConditions(objName, property, addDependency, project, path, arrayDepth, options) {
var debug = options.debug;
// working around a bug in ts-simple-ast

@@ -407,3 +422,3 @@ var propertyName = property === undefined ? '(???)' : property.getName();

var expectedType = property.getType().getText();
var conditions = typeConditions(varName, property.getType(), addDependency, project, propertyPath, arrayDepth, true, debug);
var conditions = typeConditions(varName, property.getType(), addDependency, project, propertyPath, arrayDepth, true, options);
if (debug) {

@@ -415,13 +430,14 @@ return (conditions &&

}
function propertiesConditions(varName, properties, addDependency, project, path, arrayDepth, debug) {
function propertiesConditions(varName, properties, addDependency, project, path, arrayDepth, options) {
return properties
.map(function (prop) {
return propertyConditions(varName, prop, addDependency, project, path, arrayDepth, debug);
return propertyConditions(varName, prop, addDependency, project, path, arrayDepth, options);
})
.filter(function (v) { return v !== null; });
}
function generateTypeGuard(functionName, typeName, type, addDependency, project, shortCircuitCondition, debug) {
function generateTypeGuard(functionName, typeName, type, addDependency, project, options) {
var debug = options.debug, shortCircuitCondition = options.shortCircuitCondition;
var defaultArgumentName = lodash_1.lowerFirst(typeName);
var conditions = typeConditions('obj', type, addDependency, project, '${argumentName}', // tslint:disable-line:no-invalid-template-strings
0, false, debug);
0, false, options);
var secondArgument = debug

@@ -487,35 +503,39 @@ ? "argumentName: string = \"" + defaultArgumentName + "\""

project.getSourceFiles().forEach(function (sourceFile) {
var e_4, _a, e_5, _b;
var dependencies = new Map();
var addDependency = createAddDependency(dependencies);
var functions = sourceFile
.getChildAtIndex(0)
.getChildren()
.reduce(function (acc, child) {
if (!ts_morph_1.TypeGuards.isJSDocableNode(child)) {
return acc;
}
var typeGuardName = getTypeGuardName(child.getJsDocs());
if (typeGuardName === null) {
return acc;
}
if (!ts_morph_1.TypeGuards.isExportableNode(child)) {
reportError("Must be exportable:\n\n" + child.getText() + "\n");
return acc;
}
if (ts_morph_1.TypeGuards.isEnumDeclaration(child) ||
ts_morph_1.TypeGuards.isInterfaceDeclaration(child) ||
ts_morph_1.TypeGuards.isTypeAliasDeclaration(child)) {
if (!child.isExported()) {
reportError("Node must be exported:\n\n" + child.getText() + "\n");
var functions = [];
var exports = Array.from(sourceFile.getExportedDeclarations().values());
try {
for (var exports_1 = __values(exports), exports_1_1 = exports_1.next(); !exports_1_1.done; exports_1_1 = exports_1.next()) {
var exp = exports_1_1.value;
try {
for (var exp_1 = (e_5 = void 0, __values(exp)), exp_1_1 = exp_1.next(); !exp_1_1.done; exp_1_1 = exp_1.next()) {
var singleExport = exp_1_1.value;
if (ts_morph_1.Node.isTypeAliasDeclaration(singleExport) ||
ts_morph_1.Node.isInterfaceDeclaration(singleExport)) {
var typeGuardName = getTypeGuardName(singleExport, options);
if (typeGuardName !== null) {
functions.push(generateTypeGuard(typeGuardName, singleExport.getName(), singleExport.getType(), addDependency, project, options));
addDependency(sourceFile, singleExport.getName(), singleExport.isDefaultExport());
}
}
}
}
acc.push(generateTypeGuard(typeGuardName, child.getName(), child.getType(), addDependency, project, options.shortCircuitCondition, options.debug));
var exportName = child.getName();
addDependency(sourceFile, exportName, child.isDefaultExport());
catch (e_5_1) { e_5 = { error: e_5_1 }; }
finally {
try {
if (exp_1_1 && !exp_1_1.done && (_b = exp_1.return)) _b.call(exp_1);
}
finally { if (e_5) throw e_5.error; }
}
}
else {
reportError("Unsupported:\n\n" + child.getText() + "\n");
return acc;
}
catch (e_4_1) { e_4 = { error: e_4_1 }; }
finally {
try {
if (exports_1_1 && !exports_1_1.done && (_a = exports_1.return)) _a.call(exports_1);
}
return acc;
}, []);
finally { if (e_4) throw e_4.error; }
}
if (functions.length > 0) {

@@ -522,0 +542,0 @@ if (options.debug) {

{
"name": "ts-auto-guard",
"version": "1.0.0-alpha.3",
"version": "1.0.0-alpha.4",
"description": "Generate type guard functions from TypeScript interfaces",

@@ -5,0 +5,0 @@ "homepage": "https://github.com/rhys-vdw/ts-auto-guard",

@@ -27,17 +27,4 @@ # ts-auto-guard

Annotate interfaces in your project. ts-auto-guard will generate guards only for interfaces with a `@see {name} ts-auto-guard:type-guard` JSDoc tag.
Specify which types to process (see below) and run the CLI tool in the same folder as your project's `tsconfig.json` (optionally passing in paths to the files you'd like it to parse).
```ts
// my-project/Person.ts
/** @see {isPerson} ts-auto-guard:type-guard */
export interface Person {
name: string
age?: number
children: Person[]
}
```
Run the CLI tool in the same folder as your project's `tsconfig.json` (optionally passing in paths to the files you'd like it to parse).
```sh

@@ -84,2 +71,24 @@ $ ts-auto-guard ./my-project/Person.ts

## Specifying which types to process
###Specify with annotation
Annotate interfaces in your project or pass. ts-auto-guard will generate guards only for interfaces with a `@see {name} ts-auto-guard:type-guard` JSDoc tag.
```ts
// my-project/Person.ts
/** @see {isPerson} ts-auto-guard:type-guard */
export interface Person { // !do not forget to export - only exported types are processed
name: string
age?: number
children: Person[]
}
```
###Process all types
Use `--export-all` parameter to process all exported types:
```
$ ts-auto-guard --export-all
```
## Debug mode

@@ -86,0 +95,0 @@

@@ -108,2 +108,21 @@ import { each, pull } from 'lodash'

testProcessProject(
'generates type guards for empty object if exportAll is true',
{
'test.ts': `
export interface Empty {}`,
},
{
'test.guard.ts': `
import { Empty } from "./test";
export function isEmpty(obj: any, _argumentName?: string): obj is Empty {
return (
typeof obj === "object"
)
}`,
},
{ options: { exportAll: true, debug: false } }
)
testProcessProject(
'generates type guards for boolean',

@@ -110,0 +129,0 @@ {

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc