Merge pull request #4 from MarciiTheDev/feature/GenericCollections
Added Generic Types - Version 2.0.0
This commit is contained in:
commit
4ff41ebfec
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,4 +1,5 @@
|
|||||||
package-lock.json
|
package-lock.json
|
||||||
|
pnpm-lock.yaml
|
||||||
node_modules
|
node_modules
|
||||||
dist
|
dist
|
||||||
test
|
test
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "marcsync",
|
"name": "marcsync",
|
||||||
"version": "1.1.4-dev",
|
"version": "1.2.0",
|
||||||
"description": "A NodeJS MarcSync Client to communicate with MarcSync's API",
|
"description": "A NodeJS MarcSync Client to communicate with MarcSync's API",
|
||||||
"main": "dist/marcsync.js",
|
"main": "dist/marcsync.js",
|
||||||
"types": "dist/index.d.ts",
|
"types": "dist/index.d.ts",
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { Entry, EntryData, EntryNotFound } from "./Entry";
|
import { Entry, EntryData, EntryNotFound } from "./Entry";
|
||||||
import { Unauthorized } from "./marcsync";
|
import { Unauthorized } from "./marcsync";
|
||||||
|
|
||||||
export class Collection {
|
export class Collection<T extends EntryData> {
|
||||||
|
|
||||||
private _accessToken: string;
|
private _accessToken: string;
|
||||||
private _collectionName: string;
|
private _collectionName: string;
|
||||||
@ -149,7 +149,7 @@ export class Collection {
|
|||||||
* });
|
* });
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
async createEntry(data: EntryData): Promise<Entry> {
|
async createEntry(data: T): Promise<Entry<T>> {
|
||||||
try {
|
try {
|
||||||
const result = await fetch(`https://api.marcsync.dev/v0/entries/${this._collectionName}`, {
|
const result = await fetch(`https://api.marcsync.dev/v0/entries/${this._collectionName}`, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
@ -185,7 +185,7 @@ export class Collection {
|
|||||||
*
|
*
|
||||||
* const entry = await collection.getEntryById("my-entry-id");
|
* const entry = await collection.getEntryById("my-entry-id");
|
||||||
*/
|
*/
|
||||||
async getEntryById(id: string): Promise<Entry> {
|
async getEntryById(id: string): Promise<Entry<T>> {
|
||||||
try {
|
try {
|
||||||
const result = await fetch(`https://api.marcsync.dev/v1/entries/${this._collectionName}?methodOverwrite=GET`, {
|
const result = await fetch(`https://api.marcsync.dev/v1/entries/${this._collectionName}?methodOverwrite=GET`, {
|
||||||
method: "PATCH",
|
method: "PATCH",
|
||||||
@ -203,7 +203,7 @@ export class Collection {
|
|||||||
const json = await result.json();
|
const json = await result.json();
|
||||||
if (!json.success) throw new Error();
|
if (!json.success) throw new Error();
|
||||||
if(json.entries.length === 0) throw new EntryNotFound();
|
if(json.entries.length === 0) throw new EntryNotFound();
|
||||||
return new Entry(this._accessToken, this._collectionName, json.entries[0]);
|
return new Entry<T>(this._accessToken, this._collectionName, json.entries[0]);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if(e instanceof Unauthorized) throw new Unauthorized();
|
if(e instanceof Unauthorized) throw new Unauthorized();
|
||||||
if(e instanceof EntryNotFound) throw new EntryNotFound();
|
if(e instanceof EntryNotFound) throw new EntryNotFound();
|
||||||
@ -236,7 +236,7 @@ export class Collection {
|
|||||||
* @see {@link EntryData} for more information about entry data.
|
* @see {@link EntryData} for more information about entry data.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
async getEntries(filter: EntryData={}): Promise<Entry[]> {
|
async getEntries(filter?: Partial<{ [K in keyof T]: T[K] }>): Promise<Entry<T>[]> {
|
||||||
try {
|
try {
|
||||||
const result = await fetch(`https://api.marcsync.dev/v1/entries/${this._collectionName}?methodOverwrite=GET`, {
|
const result = await fetch(`https://api.marcsync.dev/v1/entries/${this._collectionName}?methodOverwrite=GET`, {
|
||||||
method: "PATCH",
|
method: "PATCH",
|
||||||
@ -245,7 +245,7 @@ export class Collection {
|
|||||||
"content-type": "application/json"
|
"content-type": "application/json"
|
||||||
},
|
},
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
filters: filter
|
filters: filter || {}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
if (result.status === 401) throw new Unauthorized();
|
if (result.status === 401) throw new Unauthorized();
|
||||||
@ -297,7 +297,7 @@ export class Collection {
|
|||||||
* **__warning: Will delete the entries from the collection. This action cannot be undone.__**
|
* **__warning: Will delete the entries from the collection. This action cannot be undone.__**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
async deleteEntries(filter: EntryData): Promise<number> {
|
async deleteEntries(filter?: Partial<{ [K in keyof T]: T[K] }>): Promise<number> {
|
||||||
try {
|
try {
|
||||||
const result = await fetch(`https://api.marcsync.dev/v1/entries/${this._collectionName}`, {
|
const result = await fetch(`https://api.marcsync.dev/v1/entries/${this._collectionName}`, {
|
||||||
method: "DELETE",
|
method: "DELETE",
|
||||||
@ -324,7 +324,7 @@ export class Collection {
|
|||||||
* @returns The Id of the updated entry
|
* @returns The Id of the updated entry
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
async updateEntryById(id: string, data: EntryData): Promise<string> {
|
async updateEntryById(id: string, data: Partial<{ [K in keyof T]: T[K] }>): Promise<string> {
|
||||||
try {
|
try {
|
||||||
const result = await fetch(`https://api.marcsync.dev/v1/entries/${this._collectionName}`, {
|
const result = await fetch(`https://api.marcsync.dev/v1/entries/${this._collectionName}`, {
|
||||||
method: "PUT",
|
method: "PUT",
|
||||||
@ -355,7 +355,7 @@ export class Collection {
|
|||||||
* @returns The amount of updated entries
|
* @returns The amount of updated entries
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
async updateEntries(filter: EntryData, data: EntryData): Promise<number> {
|
async updateEntries(filter: Partial<{ [K in keyof T]: T[K] }>, data: Partial<{ [K in keyof T]: T[K] }>): Promise<number> {
|
||||||
try {
|
try {
|
||||||
const result = await fetch(`https://api.marcsync.dev/v1/entries/${this._collectionName}`, {
|
const result = await fetch(`https://api.marcsync.dev/v1/entries/${this._collectionName}`, {
|
||||||
method: "PUT",
|
method: "PUT",
|
||||||
|
61
src/Entry.ts
61
src/Entry.ts
@ -1,9 +1,13 @@
|
|||||||
export class BaseEntry {
|
type WithDefaultId<T extends EntryData> = T['_id'] extends string
|
||||||
|
? T
|
||||||
|
: T & { _id: string };
|
||||||
|
|
||||||
private _data: EntryData;
|
export class BaseEntry<T extends EntryData> {
|
||||||
|
|
||||||
|
private _data: T;
|
||||||
private _collectionName: string;
|
private _collectionName: string;
|
||||||
|
|
||||||
constructor(private data: EntryData, private collectionName: string) {
|
constructor(private data: T, private collectionName: string) {
|
||||||
this._data = data;
|
this._data = data;
|
||||||
this._collectionName = collectionName;
|
this._collectionName = collectionName;
|
||||||
}
|
}
|
||||||
@ -31,36 +35,8 @@ export class BaseEntry {
|
|||||||
* @see {@link EntryData} for more information about entry data.
|
* @see {@link EntryData} for more information about entry data.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
getValues(): EntryData {
|
getValues(): WithDefaultId<T> {
|
||||||
return this._data;
|
return this._data as WithDefaultId<T>;
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param key - The key of the value to get
|
|
||||||
* @returns The value of the specified key
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
*
|
|
||||||
* import { Client } from "marcsync";
|
|
||||||
*
|
|
||||||
* const client = new Client("<my access token>");
|
|
||||||
* const collection = client.getCollection("my-collection");
|
|
||||||
*
|
|
||||||
* const entry = await collection.getEntryById("my-entry-id");
|
|
||||||
*
|
|
||||||
* const name = entry.getValueAs<string>("name");
|
|
||||||
*
|
|
||||||
* console.log(name);
|
|
||||||
*
|
|
||||||
* @remarks
|
|
||||||
* This method is useful if you want to get the value of a specific key as a specific type.
|
|
||||||
*
|
|
||||||
* @see {@link EntryData} for more information about entry data.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
getValueAs<T>(key: string): T {
|
|
||||||
return this._data[key];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -87,8 +63,8 @@ export class BaseEntry {
|
|||||||
* @see {@link EntryData} for more information about entry data.
|
* @see {@link EntryData} for more information about entry data.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
getValue(key: string): any {
|
getValue<K extends keyof WithDefaultId<T>>(key: K): WithDefaultId<T>[K] {
|
||||||
return this._data[key];
|
return (this._data as WithDefaultId<T>)[key];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -100,20 +76,20 @@ export class BaseEntry {
|
|||||||
return this._collectionName;
|
return this._collectionName;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected _setData(data: EntryData) {
|
protected _setData(data: T) {
|
||||||
this._data = data;
|
this._data = data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Entry extends BaseEntry {
|
export class Entry<T extends EntryData> extends BaseEntry<T> {
|
||||||
|
|
||||||
private _accessToken: string;
|
private _accessToken: string;
|
||||||
private _entryId: string;
|
private _entryId: string;
|
||||||
|
|
||||||
constructor(accessToken: string, collectionName: string, data: EntryData) {
|
constructor(accessToken: string, collectionName: string, data: T) {
|
||||||
super(data, collectionName);
|
super(data, collectionName);
|
||||||
this._accessToken = accessToken;
|
this._accessToken = accessToken;
|
||||||
this._entryId = data._id;
|
this._entryId = data._id!;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -139,7 +115,7 @@ export class Entry extends BaseEntry {
|
|||||||
* This method is useful if you want to update the value of a specific key.
|
* This method is useful if you want to update the value of a specific key.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
async updateValue(key: string, value: any): Promise<EntryData> {
|
async updateValue<K extends keyof WithDefaultId<T>>(key: K, value: WithDefaultId<T>[K]): Promise<WithDefaultId<T>> {
|
||||||
try {
|
try {
|
||||||
const result = await fetch(`https://api.marcsync.dev/v1/entries/${this.getCollectionName()}`, {
|
const result = await fetch(`https://api.marcsync.dev/v1/entries/${this.getCollectionName()}`, {
|
||||||
method: "PUT",
|
method: "PUT",
|
||||||
@ -193,7 +169,7 @@ export class Entry extends BaseEntry {
|
|||||||
* @see {@link updateValue} for more information about updating a single value.
|
* @see {@link updateValue} for more information about updating a single value.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
async updateValues(values: EntryData): Promise<EntryData> {
|
async updateValues(values: Partial<{ [K in keyof WithDefaultId<T>]: WithDefaultId<T>[K] }>): Promise<WithDefaultId<T>> {
|
||||||
try {
|
try {
|
||||||
const result = await fetch(`https://api.marcsync.dev/v1/entries/${this.getCollectionName()}`, {
|
const result = await fetch(`https://api.marcsync.dev/v1/entries/${this.getCollectionName()}`, {
|
||||||
method: "PUT",
|
method: "PUT",
|
||||||
@ -215,7 +191,7 @@ export class Entry extends BaseEntry {
|
|||||||
}
|
}
|
||||||
const data = this.getValues();
|
const data = this.getValues();
|
||||||
for (const key in values) {
|
for (const key in values) {
|
||||||
data[key] = values[key];
|
data[key] = values[key]!;
|
||||||
}
|
}
|
||||||
this._setData(data);
|
this._setData(data);
|
||||||
return data;
|
return data;
|
||||||
@ -249,6 +225,7 @@ export class Entry extends BaseEntry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface EntryData {
|
export interface EntryData {
|
||||||
|
_id?: string
|
||||||
[key: string]: any;
|
[key: string]: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { Collection, CollectionAlreadyExists, CollectionNotFound } from "./Collection";
|
import { Collection, CollectionAlreadyExists, CollectionNotFound } from "./Collection";
|
||||||
import { BaseEntry, Entry } from "./Entry";
|
import { BaseEntry, Entry, EntryData } from "./Entry";
|
||||||
import { SubscriptionManager } from "./SubscriptionManager";
|
import { SubscriptionManager } from "./SubscriptionManager";
|
||||||
|
|
||||||
export class Client {
|
export class Client {
|
||||||
@ -31,8 +31,8 @@ export class Client {
|
|||||||
* const collection = client.getCollection("my-collection");
|
* const collection = client.getCollection("my-collection");
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
getCollection(collectionName: string) {
|
getCollection<T extends EntryData = EntryData>(collectionName: string): Collection<T> {
|
||||||
return new Collection(this._accessToken, collectionName);
|
return new Collection<T>(this._accessToken, collectionName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -51,7 +51,7 @@ export class Client {
|
|||||||
* This method is useful if you want to fetch the collection from the server to check if it exists before using it.
|
* This method is useful if you want to fetch the collection from the server to check if it exists before using it.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
async fetchCollection(collectionName: string): Promise<Collection> {
|
async fetchCollection<T extends EntryData = EntryData>(collectionName: string): Promise<Collection<T>> {
|
||||||
try {
|
try {
|
||||||
const result = await fetch(`https://api.marcsync.dev/v0/collection/${collectionName}`, {
|
const result = await fetch(`https://api.marcsync.dev/v0/collection/${collectionName}`, {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
@ -66,7 +66,7 @@ export class Client {
|
|||||||
if (e instanceof Unauthorized) throw new Unauthorized();
|
if (e instanceof Unauthorized) throw new Unauthorized();
|
||||||
throw new CollectionNotFound();
|
throw new CollectionNotFound();
|
||||||
}
|
}
|
||||||
return new Collection(this._accessToken, collectionName);
|
return new Collection<T>(this._accessToken, collectionName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -83,7 +83,7 @@ export class Client {
|
|||||||
*
|
*
|
||||||
* @remarks
|
* @remarks
|
||||||
*/
|
*/
|
||||||
async createCollection(collectionName: string): Promise<Collection> {
|
async createCollection<T extends EntryData = EntryData>(collectionName: string): Promise<Collection<T>> {
|
||||||
try {
|
try {
|
||||||
const result = await fetch(`https://api.marcsync.dev/v0/collection/${collectionName}`, {
|
const result = await fetch(`https://api.marcsync.dev/v0/collection/${collectionName}`, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
@ -121,7 +121,7 @@ export class Unauthorized extends Error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface ClientEvents {
|
export interface ClientEvents {
|
||||||
entryCreated: [entry: Entry, databaseId: string, timestamp: number];
|
entryCreated: [entry: Entry<EntryData>, databaseId: string, timestamp: number];
|
||||||
entryUpdated: [oldEntry: BaseEntry, newEntry: Entry, databaseId: string, timestamp: number];
|
entryUpdated: [oldEntry: BaseEntry<EntryData>, newEntry: Entry<EntryData>, databaseId: string, timestamp: number];
|
||||||
entryDeleted: [entry: BaseEntry, databaseId: string, timestamp: number];
|
entryDeleted: [entry: BaseEntry<EntryData>, databaseId: string, timestamp: number];
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user