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.4 to 1.0.0-alpha.5

2

lib/index.d.ts

@@ -5,3 +5,3 @@ import { Project } from 'ts-morph';

shortCircuitCondition?: string;
debug: boolean;
debug?: boolean;
}

@@ -8,0 +8,0 @@ export interface IGenerateOptions {

@@ -88,3 +88,3 @@ "use strict";

return (lodash_1.flatMap(symbol.getDeclarations(), function (d) { return __spread([d], d.getAncestors()); })
.filter(ts_morph_1.TypeGuards.isExportableNode)
.filter(ts_morph_1.Node.isExportableNode)
.find(function (n) { return n.isExported(); }) || null);

@@ -121,6 +121,6 @@ }

var declaration = _c.value;
if (ts_morph_1.TypeGuards.isClassDeclaration(declaration)) {
if (ts_morph_1.Node.isClassDeclaration(declaration)) {
return true;
}
if (ts_morph_1.TypeGuards.isVariableDeclaration(declaration) &&
if (ts_morph_1.Node.isVariableDeclaration(declaration) &&
declaration.getType().getConstructSignatures().length > 0) {

@@ -155,3 +155,2 @@ return true;

var e_2, _a, e_3, _b;
var _c;
var jsDocs = child.getJsDocs();

@@ -162,4 +161,4 @@ try {

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

@@ -169,3 +168,3 @@ .trim()

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

@@ -182,3 +181,3 @@ reportError("command " + command + " is not supported!");

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

@@ -198,3 +197,4 @@ finally { if (e_3) throw e_3.error; }

var t = child.getType();
var name = (_c = t.getSymbol()) === null || _c === void 0 ? void 0 : _c.getName();
var symbol = t.getSymbol() || t.getAliasSymbol();
var name = symbol === null || symbol === void 0 ? void 0 : symbol.getName();
if (name) {

@@ -227,7 +227,7 @@ return 'is' + name;

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

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

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

@@ -247,3 +247,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, options);
var conditions = typeConditions('e', arrayType, addDependency, project, elementPath, arrayDepth + 1, true, records, options);
if (conditions === null) {

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

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

@@ -281,36 +282,18 @@ var symbol = type.getSymbol();

}
// JSDoc is attached to the type alias rather than the object literal in the
// case of eg. `type Foo = { x: number }`
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) {
var sourcePath = declaration.getSourceFile().getFilePath();
addDependency(findOrCreate(project, outFilePath(sourcePath)), typeGuardName, false);
// NOTE: Cast to boolean to stop type guard property and prevent compile
// errors.
return typeGuardName + "(" + varName + ") as boolean";
}
if (type.isInterface()) {
if (!useGuard || typeGuardName === null) {
if (!ts_morph_1.Node.isInterfaceDeclaration(declaration)) {
throw new TypeError('Extected declaration to be an interface delcaration!');
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, records, options);
if (condition !== null) {
conditions.push(condition);
}
declaration.getBaseTypes().forEach(function (baseType) {
var condition = typeConditions(varName, baseType, addDependency, project, path, arrayDepth, true, options);
if (condition !== null) {
conditions.push(condition);
}
});
if (conditions.length === 0) {
conditions.push(objectTypeCondition(varName, type));
}
conditions.push.apply(conditions, __spread(propertiesConditions(varName, declaration.getProperties(), addDependency, project, path, arrayDepth, options)));
});
if (conditions.length === 0) {
conditions.push(objectTypeCondition(varName, type));
}
conditions.push.apply(conditions, __spread(propertiesConditions(varName, declaration
.getProperties()
.map(function (p) { return ({ name: p.getName(), type: p.getType() }); }), addDependency, project, path, arrayDepth, records, options)));
}

@@ -322,4 +305,14 @@ else {

var properties = type.getProperties();
var propertySignatures = properties.map(function (p) { return p.getDeclarations()[0]; });
conditions.push.apply(conditions, __spread(propertiesConditions(varName, propertySignatures, addDependency, project, path, arrayDepth, options)));
var typeDeclarations_1 = (_a = type.getSymbol()) === null || _a === void 0 ? void 0 : _a.getDeclarations();
var propertySignatures = properties.map(function (p) {
var propertyDeclarations = p.getDeclarations();
var typeAtLocation = propertyDeclarations.length !== 0
? p.getTypeAtLocation(propertyDeclarations[0])
: p.getTypeAtLocation((typeDeclarations_1 || [])[0]);
return {
name: p.getName(),
type: typeAtLocation,
};
});
conditions.push.apply(conditions, __spread(propertiesConditions(varName, propertySignatures, addDependency, project, path, arrayDepth, records, options)));
}

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

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

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

.getDeclarations()
.find(ts_morph_1.TypeGuards.isEnumMember)
.find(ts_morph_1.Node.isEnumMember)
.getParent();

@@ -359,3 +352,3 @@ if (node === undefined) {

}
if (!ts_morph_1.TypeGuards.isEnumDeclaration(node)) {
if (!ts_morph_1.Node.isEnumDeclaration(node)) {
reportError('Enum literal parent was not an enum declaration');

@@ -365,6 +358,19 @@ return null;

typeToDependency(type, addDependency);
// type.getText() returns incorrect module name for some reason
return eq(varName, node.getSymbol().getName() + "." + type.getSymbol().getName());
}
return eq(varName, type.getText());
}
function typeConditions(varName, type, addDependency, project, path, arrayDepth, useGuard, options) {
function reusedCondition(type, records, varName) {
var record = records.find(function (x) { return x.typeDeclaration.getType() === type; });
if (record) {
return record.guardName + "(" + varName + ") as boolean";
}
return null;
}
function typeConditions(varName, type, addDependency, project, path, arrayDepth, useGuard, records, options) {
var reused = reusedCondition(type, records, varName);
if (useGuard && reused) {
return reused;
}
if (type.isNull()) {

@@ -388,12 +394,12 @@ return eq(varName, 'null');

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

@@ -405,6 +411,6 @@ if (isClassType(type)) {

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

@@ -416,10 +422,9 @@ if (type.isLiteral()) {

}
function propertyConditions(objName, property, addDependency, project, path, arrayDepth, options) {
function propertyConditions(objName, property, addDependency, project, path, arrayDepth, records, options) {
var debug = options.debug;
// working around a bug in ts-simple-ast
var propertyName = property === undefined ? '(???)' : property.getName();
var propertyName = property.name;
var varName = objName + "." + propertyName;
var propertyPath = path + "." + propertyName;
var expectedType = property.getType().getText();
var conditions = typeConditions(varName, property.getType(), addDependency, project, propertyPath, arrayDepth, true, options);
var expectedType = property.type.getText();
var conditions = typeConditions(varName, property.type, addDependency, project, propertyPath, arrayDepth, true, records, options);
if (debug) {

@@ -431,14 +436,15 @@ return (conditions &&

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

@@ -453,10 +459,2 @@ ? "argumentName: string = \"" + defaultArgumentName + "\""

}
// -- Process project --
function findOrCreate(project, path) {
var outFile = project.getSourceFile(path);
if (outFile === undefined) {
outFile = project.createSourceFile(path);
}
return outFile;
}
function createAddDependency(dependencies) {

@@ -505,3 +503,3 @@ return function addDependency(sourceFile, name, isDefault) {

project.getSourceFiles().forEach(function (sourceFile) {
var e_4, _a, e_5, _b;
var e_4, _a, e_5, _b, e_6, _c, e_7, _d;
var dependencies = new Map();

@@ -511,2 +509,3 @@ var addDependency = createAddDependency(dependencies);

var exports = Array.from(sourceFile.getExportedDeclarations().values());
var allTypesDeclarations = [];
try {

@@ -519,8 +518,5 @@ for (var exports_1 = __values(exports), exports_1_1 = exports_1.next(); !exports_1_1.done; exports_1_1 = exports_1.next()) {

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());
}
ts_morph_1.Node.isInterfaceDeclaration(singleExport) ||
ts_morph_1.Node.isEnumDeclaration(singleExport)) {
allTypesDeclarations.push(singleExport);
}

@@ -545,2 +541,36 @@ }

}
var records = [];
try {
for (var allTypesDeclarations_1 = __values(allTypesDeclarations), allTypesDeclarations_1_1 = allTypesDeclarations_1.next(); !allTypesDeclarations_1_1.done; allTypesDeclarations_1_1 = allTypesDeclarations_1.next()) {
var typeDeclaration = allTypesDeclarations_1_1.value;
var typeGuardName = getTypeGuardName(typeDeclaration, options);
if (typeGuardName !== null) {
records.push({ guardName: typeGuardName, typeDeclaration: typeDeclaration });
}
}
}
catch (e_6_1) { e_6 = { error: e_6_1 }; }
finally {
try {
if (allTypesDeclarations_1_1 && !allTypesDeclarations_1_1.done && (_c = allTypesDeclarations_1.return)) _c.call(allTypesDeclarations_1);
}
finally { if (e_6) throw e_6.error; }
}
try {
for (var allTypesDeclarations_2 = __values(allTypesDeclarations), allTypesDeclarations_2_1 = allTypesDeclarations_2.next(); !allTypesDeclarations_2_1.done; allTypesDeclarations_2_1 = allTypesDeclarations_2.next()) {
var typeDeclaration = allTypesDeclarations_2_1.value;
var typeGuardName = getTypeGuardName(typeDeclaration, options);
if (typeGuardName !== null) {
functions.push(generateTypeGuard(typeGuardName, typeDeclaration, addDependency, project, records, options));
addDependency(sourceFile, typeDeclaration.getName(), typeDeclaration.isDefaultExport());
}
}
}
catch (e_7_1) { e_7 = { error: e_7_1 }; }
finally {
try {
if (allTypesDeclarations_2_1 && !allTypesDeclarations_2_1.done && (_d = allTypesDeclarations_2.return)) _d.call(allTypesDeclarations_2);
}
finally { if (e_7) throw e_7.error; }
}
if (functions.length > 0) {

@@ -547,0 +577,0 @@ if (options.debug) {

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

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

@@ -71,3 +71,4 @@ import { each, pull } from 'lodash'

t.equal(sourceText, expectedFile.getText(), filePath)
const expectedText = expectedFile.getText()
t.equal(sourceText, expectedText, filePath)
}

@@ -483,1 +484,164 @@ }

)
testProcessProject(
'generates type guards for mapped types',
{
'test.ts': `
/** @see {isPropertyValueType} ts-auto-guard:type-guard */
export type PropertyValueType = {value: string};
/** @see {isPropertyName} ts-auto-guard:type-guard */
export type PropertyName = 'name' | 'value';
/** @see {isFoo} ts-auto-guard:type-guard */
export type Foo = {
[key in PropertyName]: PropertyValueType
}`,
},
{
'test.guard.ts': `
import { PropertyValueType, PropertyName, Foo } from "./test";
export function isPropertyValueType(obj: any, _argumentName?: string): obj is PropertyValueType {
return (
typeof obj === "object" &&
typeof obj.value === "string"
)
}
export function isPropertyName(obj: any, _argumentName?: string): obj is PropertyName {
return (
(
obj === "name" ||
obj === "value"
)
)
}
export function isFoo(obj: any, _argumentName?: string): obj is Foo {
return (
typeof obj === "object" &&
isPropertyValueType(obj.name) as boolean &&
isPropertyValueType(obj.value) as boolean
)
}
`,
}
)
testProcessProject(
'generates type guards for recursive types',
{
'test.ts': `
/** @see {isBranch1} ts-auto-guard:type-guard */
export type Branch1 = Branch1[] | string;
/** @see {isBranch2} ts-auto-guard:type-guard */
export type Branch2 = { branches: Branch2[] } | string;
/** @see {isBranch3} ts-auto-guard:type-guard */
export type Branch3 = { branches: Branch3[] } | {branches: Branch3 }[] | string;
`,
},
{
'test.guard.ts': `
import { Branch1, Branch2, Branch3 } from "./test";
export function isBranch1(obj: any, _argumentName?: string): obj is Branch1 {
return (
(
typeof obj === "string" ||
Array.isArray(obj) &&
obj.every((e: any) =>
isBranch1(e) as boolean
)
)
)
}
export function isBranch2(obj: any, _argumentName?: string): obj is Branch2 {
return (
(
typeof obj === "string" ||
typeof obj === "object" &&
Array.isArray(obj.branches) &&
obj.branches.every((e: any) =>
isBranch2(e) as boolean
)
)
)
}
export function isBranch3(obj: any, _argumentName?: string): obj is Branch3 {
return (
(
typeof obj === "string" ||
typeof obj === "object" &&
Array.isArray(obj.branches) &&
obj.branches.every((e: any) =>
isBranch3(e) as boolean
) ||
Array.isArray(obj) &&
obj.every((e: any) =>
typeof e === "object" &&
isBranch3(e.branches) as boolean
)
)
)
}`,
}
)
testProcessProject(
'generated type guards for discriminated unions',
{
'test.ts': `
export type X = { type: 'a', value: number } | { type: 'b', value: string }
`,
},
{
'test.guard.ts': `
import { X } from "./test";
export function isX(obj: any, _argumentName?: string): obj is X {
return (
(
typeof obj === "object" &&
obj.type === "a" &&
typeof obj.value === "number" ||
typeof obj === "object" &&
obj.type === "b" &&
typeof obj.value === "string"
)
)
}`,
},
{ options: { exportAll: true } }
)
testProcessProject(
'generated type guards for enums',
{
'test.ts': `
export enum Types{
TheGood,
TheBad,
TheTypeSafe
}`,
},
{
'test.guard.ts': `
import { Types } from "./test";
export function isTypes(obj: any, _argumentName?: string): obj is Types {
return (
(
obj === Types.TheGood ||
obj === Types.TheBad ||
obj === Types.TheTypeSafe
)
)
}`,
},
{ options: { exportAll: true } }
)

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