Skip to content

Commit

Permalink
feat: support for constructors and validations (#1)
Browse files Browse the repository at this point in the history
  • Loading branch information
shubhodeep9 authored Dec 20, 2022
1 parent 046cd3e commit b7824c9
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 19 deletions.
28 changes: 23 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,19 @@ npm install @shubhodeep9/localstorm
import { Model, Schema } from '@shubhodeep9/localstorm';

const UserSchema = new Schema({
id: "number",
name: "string",
phone: "string"
id: {
required: true, // validates the field as mandatory
type: Number
},
name: {
required: true,
type: String
},
phone: {
required: true,
type: String
},
hobbies: Array // will assume field as optional
});

const UserStore = Model('user', UserSchema);
Expand All @@ -26,9 +36,18 @@ const UserStore = Model('user', UserSchema);
UserStore.save({
id: 123,
name: "Shubho",
phone: "91xxxxx934"
phone: "91xxxxx934",
hobbies: ['sleeping']
});

// if you want to bypass validations
UserStore.save({
id: 123,
name: "Shubho",
phone: "91xxxxx934",
hobbies: ['sleeping']
}, true) // pass skipValidation as true

// to retrieve
const response = UserStore.get();

Expand All @@ -37,7 +56,6 @@ UserStore.flush();
```

## To-Do
- Add more type support
- Global Store fetch and flush
- Dynamic Schema
- Triggers
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@shubhodeep9/localstorm",
"version": "0.0.3",
"version": "0.0.4",
"description": "An ORM for localstorage",
"main": "dist/index.js",
"types": "dist/index.d.ts",
Expand All @@ -18,7 +18,7 @@
},
"author": "Shubhodeep Mukherjee",
"license": "MIT",
"dependencies": {
"devDependencies": {
"typescript": "^4.9.3"
},
"bugs": {
Expand Down
34 changes: 27 additions & 7 deletions src/entity/entry.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Schema } from "./schema";
import { isDefinedType, Schema, SchemaPropGenericTypes } from "./schema";

/**
* Entry is layer over localstorage with structuring support,
Expand All @@ -14,19 +14,39 @@ export class Entry {
}

validate(saveObj: any) {
// validate required fields
const requiredProps = this.schema.getRequiredProps();
for (let requiredProp of requiredProps) {
if (saveObj[requiredProp] === undefined) {
throw Error(`Missing required field "${requiredProp}"`);
}
}
for (let x in saveObj) {
const propType = this.schema.get(x);

if (propType != typeof saveObj[x]) {
throw Error(`Schema mismatch for ${x}`);
let intendedType: SchemaPropGenericTypes;
if (isDefinedType(propType)) {
intendedType = propType.type;
} else {
intendedType = propType;
}

if (saveObj[x].constructor != intendedType) {
throw Error(`Schema mismatch for ${x}, expected ${intendedType.name} got ${saveObj[x].constructor.name}`);
}
}
}

save(saveObj: Object) {
this.validate(saveObj);
/**
*
* @param saveObj pass the object to be saved in localstorage, it will be validated and stringified
* @param skipValidation if you want to skip schema validations, pass this param as true
*/
save(saveObj: Object, skipValidation?: boolean) {
if (!skipValidation) {
this.validate(saveObj);
}

window.localStorage.setItem(this.key, JSON.stringify(saveObj));
// window.localStorage.setItem(this.key, JSON.stringify(saveObj));
}

get() {
Expand Down
2 changes: 2 additions & 0 deletions src/entity/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import { Entry } from "./entry";
/**
* Model function takes in key-pair's key, and structure in Schema
* returns Entry with functionalities.
* @param key name for localstorage `K`
* @param schema an object of Schema class with required structured for validations
*/
export function Model(key: string, schema: Schema) {
return new Entry(key, schema);
Expand Down
31 changes: 26 additions & 5 deletions src/entity/schema.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,19 @@
/**
* PropTypes currently supports number and string
* @TODO: support more structures, or build support for constructors
* @TODO: support more structures
*/

export type SchemaPropGenericTypes = NumberConstructor | StringConstructor | ArrayConstructor
export type SchemaPropDefinedType = {
required: boolean,
type: SchemaPropGenericTypes
}
interface PropTypes {
[key: string]: "number" | "string"
[key: string]: SchemaPropDefinedType | SchemaPropGenericTypes;
}

export function isDefinedType(propType: SchemaPropDefinedType | SchemaPropGenericTypes): propType is SchemaPropDefinedType {
return (<SchemaPropDefinedType>propType).type != undefined;
}

/**
Expand All @@ -19,6 +29,17 @@ export class Schema {
return this.properties[key];
}

}


getRequiredProps(): Array<string> {
let requiredProps = [] as Array<string>;
for (let x in this.properties) {
const prop = this.properties[x];
if (isDefinedType(prop)) {
const isRequired = prop.required;
if (isRequired) {
requiredProps.push(x);
}
}
}
return requiredProps;
}
}

0 comments on commit b7824c9

Please sign in to comment.