Skip to content

Commit

Permalink
readRaw(original = false)
Browse files Browse the repository at this point in the history
  • Loading branch information
3vorp committed May 3, 2024
1 parent 2cde398 commit dd17eda
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 49 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added

- Exposed `Collection.collectionName` as a readonly property for TypeScript usage.
- TypeScript overview to README.md.
- TypeScript overview to the README.
- Optional replacement argument for `array-splice` edit fields.
- `array-contains-none` option for array fields.
- Optional constructor for the `JSONDatabase` PHP class to reduce repetitive code.
- "Advanced" section to the README for previously undocumented features.
- `original` option for `readRaw` to not insert ID fields, for easier non-relational collection usage.

### Changed

Expand Down
42 changes: 21 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,16 +74,16 @@ johnDoe.hello(); // "John Doe says hello!"

## Read operations

| Name | Parameters | Description |
| ------------------------- | ----------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ |
| sha1() | none | Get the sha1 hash of the file. Can be used to compare file content without downloading the JSON. |
| readRaw() | none | Read the entire collection. ID values are injected for easier iteration, so this may be different from sha1. |
| get(key) | key: `string \| number` | Get an element from the collection by its key. |
| searchKeys(keys) | keys: `string[] \| number[]` | Get multiple elements from the collection by their keys. |
| search(options, random) | options: `SearchOption[]` random?:`boolean \| number` | Search through the collection. You can randomize the output order with random as true or a given seed. |
| select(option) | option: `SelectOption` | Get only selected fields from the collection. Essentially an upgraded version of readRaw. |
| values(option) | option: `ValueOption` | Get all distinct non-null values for a given key across a collection. |
| random(max, seed, offset) | max?: `number >= -1` seed?: `number` offset?: `number >= 0` | Read random elements of the collection. |
| Name | Parameters | Description |
| ------------------------- | ----------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ |
| sha1() | none | Get the sha1 hash of the file. Can be used to compare file content without downloading the JSON. |
| readRaw(original) | original?: `boolean` | Read the entire collection. `original` disables ID field injection, for non-relational collections. |
| get(key) | key: `string \| number` | Get an element from the collection by its key. |
| searchKeys(keys) | keys: `string[] \| number[]` | Get multiple elements from the collection by their keys. |
| search(options, random) | options: `SearchOption[]` random?:`boolean \| number` | Search through the collection. You can randomize the output order with random as true or a given seed. |
| select(option) | option: `SelectOption` | Get only selected fields from the collection. Essentially an upgraded version of readRaw. |
| values(option) | option: `ValueOption` | Get all distinct non-null values for a given key across a collection. |
| random(max, seed, offset) | max?: `number >= -1` seed?: `number` offset?: `number >= 0` | Read random elements of the collection. |

## Search options

Expand Down Expand Up @@ -131,17 +131,17 @@ The search method can take one or more options to filter entries in a collection

Edit objects have an `id` of the element, a `field` to edit, an `operation` with what to do to this field, and a possible `value`. Here is a list of operations:

| Operation | Needs value | Allowed value types | Description |
| -------------- | ----------- | ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| `set` | Yes | `any` | Sets a value to a given field. |
| `remove` | No | *N/A* | Removes a field from the element. |
| `append` | Yes | `string` | Appends a string to the end of a string field. |
| `invert` | No | *N/A* | Inverts the state of a boolean field. |
| `increment` | No | `number` | Adds a number to the field (default: 1). |
| `decrement` | No | `number` | Removes a number from the field (default: 1). |
| `array-push ` | Yes | `any` | Pushes an element to the end of an array field. |
| `array-delete` | Yes | `number` | Removes an array element by index. |
| `array-splice` | Yes | `[number, number, any?]` | Last argument is optional. Check the PHP [array_splice](https://www.php.net/manual/function.array-splice) documentation for more info. |
| Operation | Needs value | Allowed value types | Description |
| -------------- | ----------- | ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------|
| `set` | Yes | `any` | Sets a value to a given field. |
| `remove` | No | *N/A* | Removes a field from the element. |
| `append` | Yes | `string` | Appends a string to the end of a string field. |
| `invert` | No | *N/A* | Inverts the state of a boolean field. |
| `increment` | No | `number` | Adds a number to the field (default: 1). |
| `decrement` | No | `number` | Removes a number from the field (default: 1). |
| `array-push ` | Yes | `any` | Pushes an element to the end of an array field. |
| `array-delete` | Yes | `number` | Removes an array element by index. |
| `array-splice` | Yes | `[number, number, any?]` | Last argument is optional. Check the PHP [array_splice](https://www.php.net/manual/function.array-splice) documentation for more info. |

Various other methods and constants exist in the JavaScript client, which will make more sense once you learn what's actually happening behind the scenes.

Expand Down
55 changes: 32 additions & 23 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,9 @@ class Collection {
* @param {Function} [addMethods] - Additional methods and data to add to the objects
*/
constructor(name, addMethods = (el) => el) {
if (name === undefined) throw new SyntaxError("Collection must have a name");
if (!name) throw new SyntaxError("Collection must have a name");
if (typeof addMethods !== "function")
throw new TypeError("Collection must have an addMethods of type Function");
throw new TypeError("Collection add methods must be a function");
this.addMethods = addMethods;
this.collectionName = name;
}
Expand All @@ -106,19 +106,24 @@ class Collection {
* Add user methods to returned data
* @private
* @ignore
* @param {AxiosPromise} req - Incoming request
* @returns {Promise<any>}
* @param {any} el - Value to add methods to
* @param {boolean} [nested] - Nest the methods inside an object
* @returns {any}
*/
__add_methods(req) {
if (!(req instanceof Promise)) req = Promise.resolve(req);
return req.then((el) => {
if (Array.isArray(el)) return el.map((el) => this.addMethods(el));
el[Object.keys(el)[0]][ID_FIELD_NAME] = Object.keys(el)[0];
el = el[Object.keys(el)[0]];

// else on the object itself
return this.addMethods(el);
});
__add_methods(el, nested = true) {
// can't add properties on falsy values
if (!el) return el;
if (Array.isArray(el)) return el.map((el) => this.addMethods(el));
// nested objects
if (nested && typeof el === "object") {
Object.keys(el).forEach((k) => {
el[k] = this.addMethods(el[k]);
});
return el;
}

// add directly to single object
return this.addMethods(el);
}

/**
Expand Down Expand Up @@ -217,7 +222,12 @@ class Collection {
get(key) {
return this.__get_request("get", {
id: key,
}).then((res) => this.__add_methods(res));
}).then((res) => {
const firstKey = Object.keys(res)[0];
res[firstKey][ID_FIELD_NAME] = firstKey;
res = res[firstKey];
return this.__add_methods(res, false);
});
}

/**
Expand Down Expand Up @@ -294,18 +304,19 @@ class Collection {

/**
* Read the entire collection
* - ID values are injected for easier iteration, so this may be different from {@link sha1}
* @param {boolean} [original] - Disable ID field injection for easier iteration (default false)
* @returns {Promise<Record<string, T>>} The entire collection
*/
readRaw() {
readRaw(original = false) {
return this.__get_request("read_raw").then((data) => {
if (original) return this.__add_methods(data);

// preserve as object
Object.keys(data).forEach((key) => {
data[key][ID_FIELD_NAME] = key;
this.addMethods(data[key]);
});

return data;
return this.__add_methods(data);
});
}

Expand All @@ -332,9 +343,8 @@ class Collection {
}).then((data) => {
Object.keys(data).forEach((key) => {
data[key][ID_FIELD_NAME] = key;
this.addMethods(data[key]);
});
return data;
return this.__add_methods(data);
});
}

Expand Down Expand Up @@ -395,10 +405,9 @@ class Collection {
}).then((data) => {
Object.keys(data).forEach((key) => {
data[key][ID_FIELD_NAME] = key;
this.addMethods(data[key]);
});

return data;
return this.__add_methods(data);
});
}

Expand Down
19 changes: 17 additions & 2 deletions tests/js-test.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -200,17 +200,32 @@ describe("GET operations", () => {
});
});

it("returns the exact content of the file", (done) => {
it("returns the exact contents of the file", (done) => {
base
.readRaw(true)
.then((res) => {
expect(res).deep.equals(content, "Content different");
done();
})
.catch(done);
});

it("injects ID values into every item", (done) => {
base
.readRaw()
.then((res) => {
Object.entries(res).forEach(([k, v]) =>
expect(v).to.have.property(firestorm.ID_FIELD, k, "Missing ID field"),
);
Object.keys(res).forEach((key) => delete res[key][firestorm.ID_FIELD]);
expect(res).deep.equals(content, "Content different");
done();
})
.catch(done);
});
});

describe("sha1()", () => {
it("sha1 content hash is the same", (done) => {
base
.sha1()
Expand Down Expand Up @@ -348,7 +363,7 @@ describe("GET operations", () => {
];

testArray.forEach(([criteria, field, value, idsFound, ignoreCase]) => {
ignoreCase = !!ignoreCase
ignoreCase = !!ignoreCase;
it(`${criteria} criteria${idsFound.length == 0 ? " (empty result)" : ""}${
ignoreCase ? " (case insensitive)" : ""
}`, (done) => {
Expand Down
4 changes: 2 additions & 2 deletions typings/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -228,10 +228,10 @@ declare class Collection<T> {

/**
* Read the entire collection
* - ID values are injected for easier iteration, so this may be different from {@link sha1}
* @param original - Disable ID field injection for easier iteration (default false)
* @returns The entire collection
*/
public readRaw(): Promise<Record<string, T>>;
public readRaw(original?: boolean): Promise<Record<string, T>>;

/**
* Read the entire collection
Expand Down

0 comments on commit dd17eda

Please sign in to comment.