fix(core): update
This commit is contained in:
parent
1c417e15cc
commit
9f1c880c6a
@ -123,7 +123,7 @@ pages:
|
|||||||
stage: metadata
|
stage: metadata
|
||||||
script:
|
script:
|
||||||
- npmci node install lts
|
- npmci node install lts
|
||||||
- npmci command npm install -g @gitzone/tsdoc
|
- npmci command npm install -g @git.zone/tsdoc
|
||||||
- npmci npm prepare
|
- npmci npm prepare
|
||||||
- npmci npm install
|
- npmci npm install
|
||||||
- npmci command tsdoc
|
- npmci command tsdoc
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
"githost": "code.foss.global",
|
"githost": "code.foss.global",
|
||||||
"gitscope": "push.rocks",
|
"gitscope": "push.rocks",
|
||||||
"gitrepo": "smartguard",
|
"gitrepo": "smartguard",
|
||||||
"description": "A library for creating and managing validation guards.",
|
"description": "A TypeScript library for creating and managing validation guards, aiding in data validation and security checks.",
|
||||||
"npmPackagename": "@push.rocks/smartguard",
|
"npmPackagename": "@push.rocks/smartguard",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"projectDomain": "push.rocks",
|
"projectDomain": "push.rocks",
|
||||||
@ -16,7 +16,13 @@
|
|||||||
"async",
|
"async",
|
||||||
"nodejs",
|
"nodejs",
|
||||||
"express",
|
"express",
|
||||||
"middleware"
|
"middleware",
|
||||||
|
"data validation",
|
||||||
|
"security",
|
||||||
|
"input validation",
|
||||||
|
"API",
|
||||||
|
"custom validation",
|
||||||
|
"composite validation"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
954
package-lock.json
generated
954
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
27
package.json
27
package.json
@ -2,7 +2,7 @@
|
|||||||
"name": "@push.rocks/smartguard",
|
"name": "@push.rocks/smartguard",
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"private": false,
|
"private": false,
|
||||||
"description": "A library for creating and managing validation guards.",
|
"description": "A TypeScript library for creating and managing validation guards, aiding in data validation and security checks.",
|
||||||
"main": "dist_ts/index.js",
|
"main": "dist_ts/index.js",
|
||||||
"typings": "dist_ts/index.d.ts",
|
"typings": "dist_ts/index.d.ts",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
@ -14,17 +14,16 @@
|
|||||||
"format": "(gitzone format)"
|
"format": "(gitzone format)"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@gitzone/tsbuild": "^2.1.60",
|
"@api.global/typedserver": "^3.0.50",
|
||||||
"@gitzone/tstest": "^1.0.69",
|
"@git.zone/tsbuild": "^2.1.66",
|
||||||
"@pushrocks/smartexpress": "^3.0.110",
|
"@git.zone/tsrun": "^1.2.46",
|
||||||
"@pushrocks/tapbundle": "^5.0.2",
|
"@git.zone/tstest": "^1.0.77",
|
||||||
"@types/node": "^17.0.22",
|
"@push.rocks/tapbundle": "^5.0.8",
|
||||||
"tslint": "^6.1.3",
|
"@types/node": "^20.12.13"
|
||||||
"tslint-config-prettier": "^1.15.0"
|
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@pushrocks/smartpromise": "^3.0.2",
|
"@push.rocks/smartpromise": "^4.0.2",
|
||||||
"@pushrocks/smartrequest": "^1.1.56"
|
"@push.rocks/smartrequest": "^2.0.15"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"ts/**/*",
|
"ts/**/*",
|
||||||
@ -48,7 +47,13 @@
|
|||||||
"async",
|
"async",
|
||||||
"nodejs",
|
"nodejs",
|
||||||
"express",
|
"express",
|
||||||
"middleware"
|
"middleware",
|
||||||
|
"data validation",
|
||||||
|
"security",
|
||||||
|
"input validation",
|
||||||
|
"API",
|
||||||
|
"custom validation",
|
||||||
|
"composite validation"
|
||||||
],
|
],
|
||||||
"homepage": "https://code.foss.global/push.rocks/smartguard",
|
"homepage": "https://code.foss.global/push.rocks/smartguard",
|
||||||
"repository": {
|
"repository": {
|
||||||
|
8360
pnpm-lock.yaml
generated
8360
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
161
readme.md
161
readme.md
@ -1,5 +1,5 @@
|
|||||||
# @push.rocks/smartguard
|
# @push.rocks/smartguard
|
||||||
smart guards for validations
|
A library for creating and managing validation guards.
|
||||||
|
|
||||||
## Install
|
## Install
|
||||||
|
|
||||||
@ -13,7 +13,7 @@ This will add `@push.rocks/smartguard` to your project's dependencies.
|
|||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
`@push.rocks/smartguard` provides a sturdy and easy way to validate data by using guards. Guards are functions that return a Boolean value indicating whether the data meets certain criteria. This package is highly beneficial for input validation, security checks, or any scenario where data needs to conform to specific rules or patterns.
|
`@push.rocks/smartguard` provides a robust and easy way to validate data by using guards. Guards are functions that return a boolean value indicating whether the data meets certain criteria. This package is highly beneficial for input validation, security checks, or any scenario where data needs to conform to specific rules or patterns.
|
||||||
|
|
||||||
### Basics
|
### Basics
|
||||||
|
|
||||||
@ -21,7 +21,7 @@ At the core of `@push.rocks/smartguard` are two main classes: `Guard` and `Guard
|
|||||||
|
|
||||||
### Creating a Guard
|
### Creating a Guard
|
||||||
|
|
||||||
A `Guard` is an object that encapsulates a validation rule. You define a guard by providing a function that takes an input and returns a Promise, resolving to a Boolean value indicating if the input meets the criteria.
|
A `Guard` is an object that encapsulates a validation rule. You define a guard by providing a function that takes an input and returns a Promise, resolving to a boolean value indicating if the input meets the criteria.
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { Guard } from '@push.rocks/smartguard';
|
import { Guard } from '@push.rocks/smartguard';
|
||||||
@ -95,7 +95,7 @@ const isAuthorizedUserGuard = new Guard<express.Request>(async (req) => {
|
|||||||
|
|
||||||
app.use(async (req, res, next) => {
|
app.use(async (req, res, next) => {
|
||||||
const isAuthorized = await isAuthorizedUserGuard.executeGuardWithData(req);
|
const isAuthorized = await isAuthorizedUserGuard.executeGuardWithData(req);
|
||||||
if(!isAuthorized) {
|
if (!isAuthorized) {
|
||||||
res.status(403).send('Unauthorized');
|
res.status(403).send('Unauthorized');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -107,10 +107,159 @@ app.listen(3000, () => console.log('Server running on port 3000'));
|
|||||||
|
|
||||||
In the example above, we use a guard to check if a request has a valid authorization header. This demonstrates how `@push.rocks/smartguard` can be seamlessly integrated into existing server applications to enforce security or input validations.
|
In the example above, we use a guard to check if a request has a valid authorization header. This demonstrates how `@push.rocks/smartguard` can be seamlessly integrated into existing server applications to enforce security or input validations.
|
||||||
|
|
||||||
### Conclusion
|
### Combining Guards with `GuardSet`
|
||||||
|
|
||||||
`@push.rocks/smartguard` offers a robust, flexible way to perform validations across your application. Whether you're validating simple data types, complex objects, or making asynchronous validation calls, smartguard simplifies the process and makes your code cleaner and more maintainable.
|
One of the strengths of `@push.rocks/smartguard` is its ability to combine multiple guards into a `GuardSet`. This is particularly useful when you need to validate data against several criteria. For example, to validate a string that must be non-empty and start with a specific prefix:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { Guard, GuardSet } from '@push.rocks/smartguard';
|
||||||
|
|
||||||
|
const isStringGuard = new Guard<string>(async (data) => {
|
||||||
|
return typeof data === 'string';
|
||||||
|
});
|
||||||
|
|
||||||
|
const isNotEmptyGuard = new Guard<string>(async (data) => {
|
||||||
|
return data.length > 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
const startsWithPrefixGuard = new Guard<string>(async (data) => {
|
||||||
|
return data.startsWith('prefix');
|
||||||
|
});
|
||||||
|
|
||||||
|
const combinedValidationSet = new GuardSet<string>([isStringGuard, isNotEmptyGuard, startsWithPrefixGuard]);
|
||||||
|
|
||||||
|
const validationResults = await combinedValidationSet.executeGuardsWithData('prefix: Valid String');
|
||||||
|
console.log(validationResults.every(result => result)); // true if all validations passed
|
||||||
|
```
|
||||||
|
|
||||||
|
### Integration with Other Libraries
|
||||||
|
|
||||||
|
To demonstrate the versatility and integration capabilities of `@push.rocks/smartguard`, let's integrate it with another popular library, `@push.rocks/smartrequest`, for validating API response data.
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { Guard } from '@push.rocks/smartguard';
|
||||||
|
import { smartrequest } from '@push.rocks/smartrequest';
|
||||||
|
|
||||||
|
const validApiResponseGuard = new Guard(async (url: string) => {
|
||||||
|
const response = await smartrequest.request(url, { method: 'GET' });
|
||||||
|
return response.status === 200;
|
||||||
|
});
|
||||||
|
|
||||||
|
const isValidResponse = await validApiResponseGuard.executeGuardWithData('https://example.com/api/data');
|
||||||
|
console.log(isValidResponse); // true if the API response status is 200
|
||||||
|
```
|
||||||
|
|
||||||
|
### Real-World Example: Form Validation
|
||||||
|
|
||||||
|
Let's create a real-world example where we use `@push.rocks/smartguard` to validate form data in a Node.js application. Suppose we have a user registration form with fields for `username`, `email`, and `password`.
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { Guard, GuardSet } from '@push.rocks/smartguard';
|
||||||
|
|
||||||
|
// Guards for individual fields
|
||||||
|
const isUsernameValid = new Guard<string>(async (username) => {
|
||||||
|
return typeof username === 'string' && username.length >= 3;
|
||||||
|
});
|
||||||
|
|
||||||
|
const isEmailValid = new Guard<string>(async (email) => {
|
||||||
|
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||||
|
return typeof email === 'string' && emailRegex.test(email);
|
||||||
|
});
|
||||||
|
|
||||||
|
const isPasswordStrong = new Guard<string>(async (password) => {
|
||||||
|
return typeof password === 'string' && password.length >= 8;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Combining guards using GuardSet
|
||||||
|
const registrationValidationSet = new GuardSet<{ username: string, email: string, password: string }>([
|
||||||
|
new Guard(async (data) => isUsernameValid.executeGuardWithData(data.username)),
|
||||||
|
new Guard(async (data) => isEmailValid.executeGuardWithData(data.email)),
|
||||||
|
new Guard(async (data) => isPasswordStrong.executeGuardWithData(data.password))
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Form data to validate
|
||||||
|
const formData = {
|
||||||
|
username: 'exampleUser',
|
||||||
|
email: 'user@example.com',
|
||||||
|
password: 'strongpassword123'
|
||||||
|
};
|
||||||
|
|
||||||
|
const formValidationResults = await registrationValidationSet.executeGuardsWithData(formData);
|
||||||
|
console.log(formValidationResults.every(result => result)); // true if all fields are valid
|
||||||
|
```
|
||||||
|
|
||||||
|
In this example, we used guards to validate each form field. We then combined these guards into a `GuardSet` to validate the entire form data object.
|
||||||
|
|
||||||
|
### Validating Nested Objects
|
||||||
|
|
||||||
|
`@push.rocks/smartguard` can also handle validation of nested objects. Suppose you need to validate a user profile that includes nested address information.
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
interface UserProfile {
|
||||||
|
username: string;
|
||||||
|
email: string;
|
||||||
|
address: {
|
||||||
|
street: string;
|
||||||
|
city: string;
|
||||||
|
postalCode: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const isStreetValid = new Guard<string>(async (street) => {
|
||||||
|
return typeof street === 'string' && street.length > 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
const isCityValid = new Guard<string>(async (city) => {
|
||||||
|
return typeof city === 'string' && city.length > 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
const isPostalCodeValid = new Guard<string>(async (postalCode) => {
|
||||||
|
return typeof postalCode === 'string' && /^[0-9]{5}$/.test(postalCode);
|
||||||
|
});
|
||||||
|
|
||||||
|
const isAddressValid = new Guard<UserProfile['address']>(async (address) => {
|
||||||
|
const streetValid = await isStreetValid.executeGuardWithData(address.street);
|
||||||
|
const cityValid = await isCityValid.executeGuardWithData(address.city);
|
||||||
|
const postalCodeValid = await isPostalCodeValid.executeGuardWithData(address.postalCode);
|
||||||
|
return streetValid && cityValid && postalCodeValid;
|
||||||
|
});
|
||||||
|
|
||||||
|
const isUsernameValid = new Guard<string>(async (username) => {
|
||||||
|
return typeof username === 'string' && username.length >= 3;
|
||||||
|
});
|
||||||
|
|
||||||
|
const isEmailValid = new Guard<string>(async (email) => {
|
||||||
|
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||||
|
return typeof email === 'string' && emailRegex.test(email);
|
||||||
|
});
|
||||||
|
|
||||||
|
const userProfileValidationSet = new GuardSet<UserProfile>([
|
||||||
|
new Guard(async (data) => isUsernameValid.executeGuardWithData(data.username)),
|
||||||
|
new Guard(async (data) => isEmailValid.executeGuardWithData(data.email)),
|
||||||
|
new Guard(async (data) => isAddressValid.executeGuardWithData(data.address))
|
||||||
|
]);
|
||||||
|
|
||||||
|
const userProfile = {
|
||||||
|
username: 'exampleUser',
|
||||||
|
email: 'user@example.com',
|
||||||
|
address: {
|
||||||
|
street: '123 Main St',
|
||||||
|
city: 'Anytown',
|
||||||
|
postalCode: '12345'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const userProfileValidationResults = await userProfileValidationSet.executeGuardsWithData(userProfile);
|
||||||
|
console.log(userProfileValidationResults.every(result => result)); // true if user profile is valid
|
||||||
|
```
|
||||||
|
|
||||||
|
In this example, we created a nested guard structure to validate a user profile object that includes address information. Each nested object is validated individually using its specific guards.
|
||||||
|
|
||||||
|
### Summary
|
||||||
|
|
||||||
|
`@push.rocks/smartguard` provides a powerful framework for creating and managing validation guards in JavaScript and TypeScript applications. The library's flexibility allows it to handle simple boolean checks, asynchronous operations, integration with external APIs, and complex composite validations. Its use of `Guard` and `GuardSet` classes ensures that validations are both modular and reusable.
|
||||||
|
|
||||||
|
Whether you are validating form inputs, securing APIs, or ensuring data integrity in your backend services, `@push.rocks/smartguard` simplifies the process and makes your code cleaner and more maintainable.
|
||||||
|
|
||||||
## License and Legal Information
|
## License and Legal Information
|
||||||
|
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
import { expect, expectAsync, tap } from '@pushrocks/tapbundle';
|
import { expect, expectAsync, tap } from '@push.rocks/tapbundle';
|
||||||
import * as smartguard from '../ts/index.js';
|
import * as smartguard from '../ts/index.js';
|
||||||
import * as smartexpress from '@pushrocks/smartexpress';
|
import * as typedserver from '@api.global/typedserver';
|
||||||
import * as smartrequest from '@pushrocks/smartrequest';
|
import * as smartrequest from '@push.rocks/smartrequest';
|
||||||
|
|
||||||
let smartexpressInstance: smartexpress.Server;
|
let smartexpressInstance: typedserver.servertools.Server;
|
||||||
|
|
||||||
tap.test('should create a demo smartexpress instance', async () => {
|
tap.test('should create a demo smartexpress instance', async () => {
|
||||||
smartexpressInstance = new smartexpress.Server({
|
smartexpressInstance = new typedserver.servertools.Server({
|
||||||
cors: true,
|
cors: true,
|
||||||
forceSsl: false,
|
forceSsl: false,
|
||||||
defaultAnswer: async () => 'hi there',
|
defaultAnswer: async () => 'hi there',
|
||||||
@ -16,8 +16,8 @@ tap.test('should create a demo smartexpress instance', async () => {
|
|||||||
|
|
||||||
tap.test('should be able to create smartguards for a request', async () => {
|
tap.test('should be able to create smartguards for a request', async () => {
|
||||||
interface IRequestGuardData {
|
interface IRequestGuardData {
|
||||||
req: smartexpress.Request;
|
req: typedserver.Request;
|
||||||
res: smartexpress.Response;
|
res: typedserver.Response;
|
||||||
}
|
}
|
||||||
const ipGuard = new smartguard.Guard<IRequestGuardData>(async (dataArg) => {
|
const ipGuard = new smartguard.Guard<IRequestGuardData>(async (dataArg) => {
|
||||||
console.log('executing ip guard');
|
console.log('executing ip guard');
|
||||||
@ -32,7 +32,7 @@ tap.test('should be able to create smartguards for a request', async () => {
|
|||||||
|
|
||||||
smartexpressInstance.addRoute(
|
smartexpressInstance.addRoute(
|
||||||
'/testroute',
|
'/testroute',
|
||||||
new smartexpress.Handler('ALL', async (req, res) => {
|
new typedserver.servertools.Handler('ALL', async (req, res) => {
|
||||||
await smartguard.passGuards(
|
await smartguard.passGuards(
|
||||||
{
|
{
|
||||||
req,
|
req,
|
||||||
|
8
ts/00_commitinfo_data.ts
Normal file
8
ts/00_commitinfo_data.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
/**
|
||||||
|
* autocreated commitinfo by @pushrocks/commitinfo
|
||||||
|
*/
|
||||||
|
export const commitinfo = {
|
||||||
|
name: '@push.rocks/smartguard',
|
||||||
|
version: '2.0.2',
|
||||||
|
description: 'A TypeScript library for creating and managing validation guards, aiding in data validation and security checks.'
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
import * as smartpromise from '@pushrocks/smartpromise';
|
import * as smartpromise from '@push.rocks/smartpromise';
|
||||||
|
|
||||||
// pushrocks scope
|
// pushrocks scope
|
||||||
export { smartpromise };
|
export { smartpromise };
|
||||||
|
Loading…
Reference in New Issue
Block a user