Skip to content

Commit ec92676

Browse files
authored
Rolling changes (#122) (#135)
## Fix * fix: added the expected type key to `isObjectLiteral` method * fix: added type argument to `Arrayable` interface * fix(model-collection): added missing toArray call * Issue stemming from not adding the call in the refactor commit bb8817c * fix(internal): fix `_relationType` type * fix: fixed typing issue from MaybeArray update * commit: 8369c5e ## Refactor * refactor: updated `_allAreObjects` method to use existing helper * refactor(deps-dev): use jest timers * removed jest-date-mock and use the jest built in fake timers * refactor(deps-dev): use jest timers * committing missing logic from previous commit * refactor(deps-dev): use jest timers * committing missing logic from previous commit * refactor(model-collection)!: made internal methods more predictable * These methods are protected so should not be breaking but marking it as such just in case * refactor(model): simplify replicate method ## Feature * feat(services): made API accept a promise from initRequest method * feat(model): improved return typing of `replicate` and `find` * feat(api-calls): added requestMiddleware * This allows for transforming the requests before being passed to the ApiCaller * feat(relations): `for` method now accepts model constructors * feat: added utility types * feat: exported utility types * feat: added ExtractArguments and DeepPartial type utility types * feat(events): added event emitter * Resolves #23 * feat(collection): added overrides for more exact type inference * feat(relations): updated argument option of `addRelation` method * Added model array as possible argument * feat(relations): add argument type to `addRelation` method * Added Collection of models as a possible argument type ## Documentation * docs: correct some inaccuracies * docs: fixed toc * docs: removed duplication * docs: fixed small documentation issues * docs: added teaser code example * docs: added link to releases page as change-log ## Test * test(internal): simplified test helper * test(model-collection): use types for testing `isModelCollection` * test: added more test types to the helper array ## Style * style: small inconsequential changes * spacing * property description * removed debugging log * style: fixed eslint issues * style: ignored eslint issues ## Chore * chore(deps-dev): updated dependencies * @commitlint/config-conventional * @commitlint/prompt-cli * @commitlint/types * @semantic-release/git * @types/lodash * @types/semantic-release * @typescript-eslint/eslint-plugin * @typescript-eslint/parser * commitlint * eslint-plugin-jest * rollup * semantic-release * typedoc * chore: incremented version * chore(deps-dev): updated dependencies * @commitlint/prompt-cli * @rollup/plugin-typescript * @types/lodash * @typescript-eslint/eslint-plugin * @typescript-eslint/parser * commitlint * eslint-plugin-import * eslint-plugin-jest * husky * lint-staged * typedoc * typescript * chore: updated bug issue template * chore(deps-dev): updated dependencies * lint-staged * rollup * typedoc ## Refactor * refactor: updated arguments to use MaybeArray utility type
1 parent e5a3427 commit ec92676

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+3282
-3136
lines changed

.commitlintrc.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ module.exports = {
1212
'attributes', // guarding and casting can also go under attributes
1313
'global-config',
1414
'exception',
15+
'events',
1516
'services',
1617
'helpers',
1718
'collection',

.eslintrc.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ module.exports = {
3939
"comma-dangle": ["warn", "never"],
4040
"max-len": ["warn", 120],
4141
"eqeqeq": "error",
42+
"no-restricted-imports": "off",
4243

4344
// https://github.com/typescript-eslint/typescript-eslint/tree/master/packages/eslint-plugin#supported-rules
4445
'@typescript-eslint/object-curly-spacing': ['warn', 'always'],
@@ -85,6 +86,7 @@ module.exports = {
8586
"@typescript-eslint/no-loop-func": "off",
8687
"@typescript-eslint/no-confusing-void-expression": "off",
8788
"@typescript-eslint/array-type": "warn",
88-
"@typescript-eslint/prefer-for-of": "off"
89+
"@typescript-eslint/prefer-for-of": "off",
90+
"@typescript-eslint/no-restricted-imports": "off"
8991
}
9092
}

.github/ISSUE_TEMPLATE/bug_report.md

Lines changed: 0 additions & 44 deletions
This file was deleted.

.github/ISSUE_TEMPLATE/bug_report.yml

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
name: 🐞 Bug Report
2+
description: File a bug/issue
3+
labels: [ bug ]
4+
body:
5+
- type: markdown
6+
attributes:
7+
value: |
8+
Please read the contribution docs before creating a bug report
9+
👉 https://upfrontjs.com/prologue/contributing.html#issues-and-prs
10+
- type: checkboxes
11+
id: has-searched-issues
12+
attributes:
13+
label: Is there an existing issue for this?
14+
description: Please search to see if an issue already exists for the bug you encountered.
15+
options:
16+
- label: I have searched the existing issues
17+
required: true
18+
- type: textarea
19+
id: current-behaviour
20+
attributes:
21+
label: Current Behavior
22+
description: A concise description of what you're experiencing.
23+
validations:
24+
required: false
25+
- type: textarea
26+
id: expected behaviour
27+
attributes:
28+
label: Expected Behavior
29+
description: A concise description of what you expected to happen.
30+
validations:
31+
required: false
32+
- type: textarea
33+
id: environment
34+
attributes:
35+
label: Environment
36+
description: |
37+
examples:
38+
- **OS**: Ubuntu 20.04
39+
- **Node**: 13.14.0
40+
- **npm**: 7.6.3
41+
value: |
42+
- OS:
43+
- Node:
44+
- npm:
45+
render: markdown
46+
validations:
47+
required: false
48+
- type: textarea
49+
id: context
50+
attributes:
51+
label: Anything else?
52+
description: |
53+
Links? References? Anything that will give more context about the issue you are encountering!
54+
55+
Tip: You can attach images or log files by clicking this area to highlight it and then dragging files in.
56+
validations:
57+
required: false
58+
required: false
59+
- type: textarea
60+
id: reproduction
61+
attributes:
62+
label: Reproduction
63+
description: Please provide a link to a repo that can reproduce the problem you ran into, unless the issue is obvious and easy to understand without more context. This will make sure your problem can be addressed faster. If a report is vague (e.g. just a generic error message) and has no reproduction, it will receive a "need reproduction" label. If no reproduction is provided it might get closed.
64+
placeholder: Reproduction
65+
validations:
66+
required: false

docs/calliope/model-collection.md

Lines changed: 47 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,47 @@
1-
# Model Collection
2-
3-
ModelCollection is a sub class of the [Collection](../helpers/collection.md), therefore all methods are inherited. The following methods have been updated to use either the model's [is](./readme.md#is) method, or the [primary key](./readme.md#getkey) of the model for comparison between models. `unique`, `hasDuplicates`, `duplicates`, `diff`, `only`, `except`, `intersect`, `delete`, `union`, `includes`. The signature of the before mentioned methods has not changed. In addition, the ModelCollection ensures that only [Models](./readme.md) are included in the collection. On top of the collection's methods couple of others has been added that are only relevant to model values.
4-
5-
## Methods
6-
7-
#### modelKeys
8-
9-
The `modelKeys` method returns the [primary key](./readme.md#getkey) of the models on a Collection.
10-
```js
11-
import User from '@Models/User';
12-
13-
const modelCollection = await User.get();
14-
modelCollection.modelKeys(); // Collection[1, 2, 3, ...ids]
15-
```
16-
17-
#### findByKey
18-
19-
The `findByKey` method returns the Model or ModelCollection depending on the argument. The method can take the ids as a single argument or as an array or collection. Optionally you may give it a second argument which will be returned is the id is not found in the model collection.
20-
```js
21-
import User from '@Models/User';
22-
import { Model } from '@upfrontjs/framework';
23-
24-
const defaultModel = new Model;
25-
const modelCollection = await User.get();
26-
modelCollection.findByKey(1); // User1
27-
modelCollection.findByKey([1, 2]); // ModelCollection[User1, User2]
28-
modelCollection.findByKey(43, defaultModel); // Model
29-
```
30-
31-
#### isModelCollection
32-
33-
The `isModelCollection` static method same as the [isCollection](../helpers/collection.md#iscollection) method on the collection, is used to evaluate that the given value is a ModelCollection.
34-
```js
35-
import { ModelCollection, Collection } from '@upfrontjs/framework';
36-
37-
const modelCollection = await User.get();
38-
ModelCollection.isModelCollection(modelCollection); // true
39-
ModelCollection.isModelCollection([Model1, Model2]); // false
40-
Collection.isCollection(modelCollection); // true
41-
```
42-
43-
---
44-
45-
::: tip
46-
The `map` method returns a ModelCollection if the return of the given callback is a [Model](./readme.md), otherwise it returns a [Collection](../helpers/collection.md).
47-
:::
1+
# Model Collection
2+
3+
ModelCollection is a sub class of the [Collection](../helpers/collection.md), therefore all methods are inherited. The following methods have been updated to use either the model's [is](./readme.md#is) method, or the [primary key](./readme.md#getkey) of the model for comparison between models. `unique`, `hasDuplicates`, `duplicates`, `diff`, `only`, `except`, `intersect`, `delete`, `union`, `includes`. The signature of the before mentioned methods has not changed. In addition, the ModelCollection ensures that only [Models](./readme.md) are included in the collection. On top of the collection's methods couple of others has been added that are only relevant to model values.
4+
5+
## Methods
6+
7+
#### modelKeys
8+
9+
The `modelKeys` method returns the [primary key](./readme.md#getkey) of the models on a Collection.
10+
```js
11+
import User from '@Models/User';
12+
13+
const modelCollection = await User.get();
14+
modelCollection.modelKeys(); // Collection[1, 2, 3, ...ids]
15+
```
16+
17+
#### findByKey
18+
19+
The `findByKey` method returns the Model or ModelCollection depending on the argument. The method can take the ids as a single argument or as an array or collection. Optionally you may give it a second argument which will be returned if the id is not found in the model collection.
20+
```js
21+
import User from '@Models/User';
22+
import { Model } from '@upfrontjs/framework';
23+
24+
const defaultModel = new Model;
25+
const modelCollection = await User.get();
26+
modelCollection.findByKey(1); // User1
27+
modelCollection.findByKey([1, 2]); // ModelCollection[User1, User2]
28+
modelCollection.findByKey(43, defaultModel); // Model
29+
```
30+
31+
#### isModelCollection
32+
33+
The `isModelCollection` static method same as the [isCollection](../helpers/collection.md#iscollection) method on the collection, is used to evaluate that the given value is a ModelCollection.
34+
```js
35+
import { ModelCollection, Collection } from '@upfrontjs/framework';
36+
37+
const modelCollection = await User.get();
38+
ModelCollection.isModelCollection(modelCollection); // true
39+
ModelCollection.isModelCollection([Model1, Model2]); // false
40+
Collection.isCollection(modelCollection); // true
41+
```
42+
43+
---
44+
45+
::: tip
46+
The `map` method returns a ModelCollection if the return of the given callback is a [Model](./readme.md), otherwise it returns a [Collection](../helpers/collection.md).
47+
:::

docs/calliope/query-building.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ const morningWorkers = await User
1414

1515
Which will generate request url similar to the described [Shape of the request](../services/api.md#shape-of-the-request) the [API](../services/api.md) service class generates.
1616

17-
### Customising the generated query string
17+
## Customising the generated query string
1818

1919
Given the above may not follow the desired namings for the parameters, you could customise the result by implementing the provided `FormatsQueryParameters` interface.
2020

docs/calliope/readme.md

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,6 @@ export default class User extends Model {
5050

5151
The `exists` property is a getter on the model that returns a boolean which can be used to assert that the model has been persisted. It takes the [primary key](#getkey), [timestamps](./timestamps.md#timestamps) and [soft deletes](./timestamps.md#soft-deletes) into account.
5252

53-
#### primaryKey
54-
55-
The `primaryKey` is property is a getter that defines what is the primary identifier's key from the model attributes. The default value is `'id'`.
56-
5753
## Additional methods
5854

5955
#### is

docs/calliope/relationships.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ Then you may query as:
3333
import User from '@Models/User';
3434

3535
const user = new User({ id: 1 });
36-
const shiftsWithColleagues = user.$shifts().with('colleagues').get(); // ModelCollection
36+
const shiftsWithColleagues = await user.$shifts().with('colleagues').get(); // ModelCollection
3737

3838
await user.load('contract');
3939
user.contract; // Contract
@@ -304,6 +304,7 @@ import User from '@Models/User';
304304
user.for(new Team({ id: 1 })); // 'teams/1/users'
305305
user.for([new Team({ id: 1 }), new Contract({ id: 1 })]); // 'teams/1/contracts/1/users'
306306
user.for([new Team, new Contract({ id: 1 })]); // 'teams/contracts/1/users'
307+
user.for([Team, Contract]); // teams/contracts/users
307308
```
308309

309310
### Overwrites

docs/cookbook.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -115,11 +115,11 @@ const experiencedSafeDrivers = await User
115115
With the default [ApiCaller](./services#apicaller) and [HandlesApiRequest](./services#handlesapiresponse) implementations, you can interact with your api without the need for the models or any of their methods.
116116

117117
```js
118-
import { GlobalConfig } from '@upfrontjs/framework';
118+
import { GlobalConfig, API, ApiResponseHandler } from '@upfrontjs/framework';
119119

120120
const config = new GlobalConfig;
121-
const handler = config.get('apiResponseHandler');
122-
const api = config.get('api');
121+
const handler = new ApiResponseHandler;
122+
const api = new API;
123123

124124
const form = new FormData;
125125
// ... collect the form entries
@@ -137,7 +137,7 @@ const response = await handler.handle(
137137

138138
#### Alias methods
139139

140-
There may be some logic you frequently use, but it might not be apparent at the first glance what's happening or can be simpler to comprehend.
140+
There may be some logic you frequently use, but it might not be apparent at the first glance what's happening or can be made simpler to comprehend.
141141

142142
For example, you may express that you want the first model like so:
143143

docs/getting-started/readme.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,16 @@
33
## What is it?
44
It's a model centric data handling solution. With it, you can write expressive, readable, concise syntax that you already know and love from back-end MVC frameworks. It provides an elegant structure to complex data with a plethora of features to manage the data, and additional helpers for common tasks like handling lists, pagination, string manipulation etc.
55

6+
```ts
7+
import User from '@models/User';
8+
9+
const students = await User.where('is_student', true).with('grades').get();
10+
11+
const excellentStudentNames = students
12+
.filter(student => student.grades.average('value') > 4)
13+
.pluck('name');
14+
```
15+
616
## What does it solve?
717
There are number of solutions out there for fetching data and working with the response. However not all of these might be as scalable as one would hope. With state management, you might have a getter for users, but those users include all users, meaning for a custom collection you would need a new getter method. An on-demand ajax request written specifically to solve a single issue, while it is simple to do, it quickly gets repetitive and hard to maintain. [Upfront](./installation.md) solves the above by creating abstraction over the data in a unified api. Just like the above examples it can be used to fetch data on demand or be complimentary to state management libraries.
818

0 commit comments

Comments
 (0)