{"id":17561685,"url":"https://github.com/swanx1/patchdb","last_synced_at":"2026-04-17T15:32:23.688Z","repository":{"id":57156414,"uuid":"410989324","full_name":"SwanX1/patchdb","owner":"SwanX1","description":"Patch is an implementation of an in-memory structured database with persistent file storage.","archived":false,"fork":false,"pushed_at":"2023-04-22T23:06:54.000Z","size":142,"stargazers_count":0,"open_issues_count":2,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-02-04T10:57:49.357Z","etag":null,"topics":["database","hacktoberfest","javascript","node","storage","typescript"],"latest_commit_sha":null,"homepage":"https://cernavskis.dev/docs/patch","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"cc0-1.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/SwanX1.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-09-27T17:57:35.000Z","updated_at":"2021-10-17T12:50:16.000Z","dependencies_parsed_at":"2024-12-09T15:46:52.259Z","dependency_job_id":"a7969ce8-7601-44ed-81cf-f68c824f0ffe","html_url":"https://github.com/SwanX1/patchdb","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SwanX1%2Fpatchdb","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SwanX1%2Fpatchdb/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SwanX1%2Fpatchdb/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SwanX1%2Fpatchdb/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/SwanX1","download_url":"https://codeload.github.com/SwanX1/patchdb/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246177591,"owners_count":20735997,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["database","hacktoberfest","javascript","node","storage","typescript"],"created_at":"2024-10-21T12:07:25.533Z","updated_at":"2026-04-17T15:32:23.438Z","avatar_url":"https://github.com/SwanX1.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Patch\n### ...is a bad implementation of an in-memory structured database with persistent JSON file storage.\n\n## Guide\n\nPatch is meant for typescript use, with types.\n\n### Basic usage\n```typescript\n// This is Typescript!!\nimport { Database, Table } from \"patchdb\";\n```\n\nLet's create a database!\n```typescript\nconst db = new Database({\n  path: \"./\" // We need to give the database a path to save to\n  autosave: 5000 // This tells the database to check for changes,\n                 // and if there are any, autosave every 5 seconds\n});\n```\n\nLet's also create a table!\u003cbr\u003e\nCreating a table requires a schema (aka class or something).\n```typescript\nclass User {\n  constructor(id: number, username: string, password: string) {\n    this.id = id;\n    this.username = username;\n    this.password = password; // NOTE: THIS IS NOT HOW YOU STORE PASSWORDS!\n  }\n}\n```\n\nIf we want to store table entries in key-value storage, and not in an array,\nwe should set a key parameter.\u003cbr\u003e\nYou can derive this from an ID or such by using getters and setters,\notherwise you can set a plain-old unrelated key parameter.\n```typescript\nclass User {\n  id: number;\n  username: string;\n  password: string;\n\n  constructor(id: number, username: string, password: string) {\n    this.id = id;\n    this.username = username;\n    this.password = password;\n  }\n\n\n  get key(): string {\n    return this.id.toString();\n  }\n\n  set key(value: string) {\n    this.id = parseInt(value);\n  }\n}\n```\n\nWe, of course need to create the table itself!\n```typescript\nconst userTable = new Table\u003cUser\u003e(\n  // This indicates if we use a primary key or not.\n  true,\n  // This is the function that converts saved JSON data to your schema.\n  json =\u003e new User(json.id, json.username, json.password),\n  // This is the function that converts your schema to JSON data that's saved.\n  user =\u003e ({ id: user.id, username: user.username, password: user.password })\n);\n```\n\nWe can add users to the user table.\u003cbr\u003e\nThe table gets the key from the actual user object, so there's no need to provide it!\n```typescript\nuserTable.add(new User(422, \"john.coolguy\", \"super.strong.password\"));\n```\n\nThe following methods for tables also exist:\n```typescript\nTable.get(objKey)\nTable.set(objKey, obj)\n```\n\nWe can later get the same user from the table.\u003cbr\u003e\nRemember to use the keys you've set!\n```typescript\nconsole.log(userTable.get(\"422\"));\n// expected output: User { id: 422, username: 'john.coolguy', password: 'super.strong.password' }\n```\n\nWe also need to add the table to the database, duh!!\u003cbr\u003e\nThis table's name is `users`:\n```typescript\ndb.addTable(\"users\", userTable);\n```\n\nThe following methods for databases also exist:\n```typescript\nDatabase.hasTable(tableName) // Returns a boolean value - if the table exists in the database.\nDatabase.getTable(tableName) // Returns the table or undefined, if the table doesn't exist.\nDatabase.deleteTable(tableName) // Deletes the table and returns it if it existed in the first place.\n```\n\nAfter you've created your tables and added them to the database, you can start the database.\n```typescript\ndb.start(); // Returns: Promise\u003cvoid\u003e\n```\nThis method will make sure the file you've provided in the database options actually exists and can be read from and written to.\u003cbr\u003e\nIt will create a file for you if it doesn't exist.\u003cbr\u003e\nThe method will also apply any existing data from the file to your added tables, which is why we needed the conversion functions when creating the tables.\n\n### Advanced usage\n\n#### Make sure to read [basic usage](#basic-usage)!\n\nThis is a very simple implementation of a database and a table class, which means you can extend it!\u003cbr\u003e\nYou can make custom methods for tables by implementing BasicTable.\u003cbr\u003e\nThe database just needs to know **from what** and **to what** convert the table data, and how to modify the table's data, it's accomplished with the BasicTable interface.\u003cbr\u003e\nIf there's a `toJson` function on any object when parsing JSON to store, the database will use it.\u003cbr\u003e\nWhen implementing the BasicTable interface, you also need to extend the event emitter. The database depends on that for tables to notify the database that data has changed.\u003cbr\u003e\nThe only event the database is listening to from tables is `\"stateChange\"`. If any data has changed, emit that event so that the database can autosave if required.\u003cbr\u003e\nTables don't actually look for changes in their entries, the entries have to emit the table event themselves with `table.emit(\"stateChange\")`\u003cbr\u003e\n\nExample table implementation:\n```typescript\nclass UserTable extends EventEmitter implements BasicTable\u003cUser\u003e {\n  contents: User[];\n  \n  constructor() {\n    super();\n    this.contents = [];\n  }\n\n  fromJson(obj: JSONParsable): User[] {\n    return obj.map(userData =\u003e new User(userData));\n  }\n\n  toJson(): JSONParsable {\n    return this.contents.map(user =\u003e user.toJson());\n  }\n\n  add(user: User): void {\n    this.contents.push(user);\n    this.emit(\"stateChange\");\n  }\n\n  get(index: number): User {\n    return this.contents[index];\n  }\n\n  set(index: number, user: User): void {\n    this.contents[index] = user;\n    this.emit(\"stateChange\");\n  }\n}\n```\n\nYou can extend the tables to your needs. There really isn't a limit!","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fswanx1%2Fpatchdb","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fswanx1%2Fpatchdb","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fswanx1%2Fpatchdb/lists"}