Skip to content

Commit 1bd326b

Browse files
committed
Merge branch 'release/0.x' into feat/various
2 parents ac87b4c + 8828051 commit 1bd326b

File tree

15 files changed

+379
-408
lines changed

15 files changed

+379
-408
lines changed

.github/workflows/deploy-api-docs.yml

+1-2
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,7 @@ jobs:
2424
git add -f assets
2525
git add -f classes
2626
git add -f interfaces
27-
touch .nojekyll
28-
git add -f .nojekyll
27+
git add -f '.nojekyll'
2928
git add -f index.html
3029
git add -f modules.html
3130
git commit -m "Updates from ${{ github.ref }}" --no-verify

docs/calliope/readme.md

+1-13
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ Bundlers/minifier options examples:
170170
#### create
171171
<Badge text="static" type="warning"/>
172172

173-
The `create` method instantiates your model while setting up attributes and relations. This will mass assign attributes to the model while respecting the [guarding](./attributes#guarding) settings.
173+
The `create` method instantiates your model while setting up attributes and relations.
174174

175175
```ts
176176
import User from '@Models/User';
@@ -181,18 +181,6 @@ const user = User.create({ name: 'User Name' }); // User
181181
Constructing a new class like `new User({...})` is **not** acceptable. This will not overwrite your class fields with default values if the same key has been passed in due to how JavaScript first constructs the parent class and only then the subclasses. However, you can still use it to call instance methods. Furthermore, it will not cause unexpected results if using it with the [setAttribute](./attributes.md#setattribute) method or call methods that under the hood uses the [setAttribute](./attributes.md#setattribute).
182182
:::
183183

184-
::: tip
185-
When creating an instance and passing in another instance of the model:
186-
```js
187-
import User from '@Models/User';
188-
import Shift from '@Models/Shift';
189-
190-
const user = User.create({ name: 'John Doe' });
191-
const newUser = User.create(user);
192-
```
193-
It will clone the [raw attributes](./attributes#getrawattributes) and the [relationships](./relationships.md#getrelations) of the model.
194-
:::
195-
196184
#### replicate
197185

198186
The `replicate` method copies the instance into a non-existent instance. Meaning primary key and the timestamps won't be copied.

docs/testing.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ import type { Attributes } from '@upfrontjs/framework';
105105
import type User from './src/Models/User';
106106

107107
export default UserFactory extends Factory<User> {
108-
public definition(model: T, index: number): Attributes<User> {
108+
definition(model: T, index: number): Attributes<User> {
109109
return {
110110
name: 'user name',
111111
someUuid: String.uuid()

package-lock.json

+338-335
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@upfrontjs/framework",
3-
"version": "0.9.0",
3+
"version": "0.8.2",
44
"description": "Data handling framework complementary to backend model systems.",
55
"main": "index.min.js",
66
"module": "index.es.min.js",

src/Calliope/Concerns/CallsApi.ts

+4-6
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ export default class CallsApi extends BuildsQuery {
204204
* @return
205205
*/
206206
// @ts-expect-error - despite TS2526, it still infers correctly
207-
public async post<T extends Model = this>(data: FormData | SimpleAttributes | SimpleAttributes<this>): Promise<T> {
207+
public async post<T extends Model = this>(data: Attributes | FormData): Promise<T> {
208208
return this.call('POST', data)
209209
.then(responseData => this.getResponseModel<T>(this.getDataFromResponse(responseData)));
210210
}
@@ -217,7 +217,7 @@ export default class CallsApi extends BuildsQuery {
217217
* @return
218218
*/
219219
// @ts-expect-error - despite TS2526, it still infers correctly
220-
public async put<T extends Model = this>(data: FormData | SimpleAttributes | SimpleAttributes<this>): Promise<T> {
220+
public async put<T extends Model = this>(data: Attributes | FormData): Promise<T> {
221221
return this.call('PUT', data)
222222
.then(responseData => this.getResponseModel<T>(this.getDataFromResponse(responseData)));
223223
}
@@ -230,7 +230,7 @@ export default class CallsApi extends BuildsQuery {
230230
* @return
231231
*/
232232
// @ts-expect-error - despite TS2526, it still infers correctly
233-
public async patch<T extends Model = this>(data: FormData | SimpleAttributes | SimpleAttributes<this>): Promise<T> {
233+
public async patch<T extends Model = this>(data: Attributes | FormData): Promise<T> {
234234
return this.call('PATCH', data)
235235
.then(responseData => this.getResponseModel<T>(this.getDataFromResponse(responseData)));
236236
}
@@ -244,9 +244,7 @@ export default class CallsApi extends BuildsQuery {
244244
* @return {Promise<boolean>}
245245
*/
246246
// @ts-expect-error - despite TS2526, it still infers correctly
247-
public async delete<T extends Model = this>(
248-
data?: FormData | SimpleAttributes | SimpleAttributes<this>
249-
): Promise<T> {
247+
public async delete<T extends Model = this>(data?: Attributes | FormData): Promise<T> {
250248
return this.call('DELETE', data)
251249
.then(responseData => this.getResponseModel<T>(this.getDataFromResponse(responseData)));
252250
}

src/Calliope/Concerns/HasAttributes.ts

+20-20
Original file line numberDiff line numberDiff line change
@@ -448,8 +448,8 @@ export default class HasAttributes extends GuardsAttributes implements Jsonable,
448448
*
449449
* @return {any}
450450
*/
451-
public getOriginal<K extends SimpleAttributeKeys<this> | string, T extends this[K]>(key: K, defaultValue?: T): T;
452-
public getOriginal(): SimpleAttributes<this>;
451+
public getOriginal<K extends AttributeKeys<this> | string, T extends this[K]>(key: K, defaultValue?: T): T;
452+
public getOriginal(): Attributes<this>;
453453
public getOriginal(key?: string, defaultValue?: unknown): unknown {
454454
const getOriginalValue = (attributeKey: string) => {
455455
if (this.hasGetAccessor(attributeKey)) {
@@ -480,8 +480,8 @@ export default class HasAttributes extends GuardsAttributes implements Jsonable,
480480
*
481481
* @return {any}
482482
*/
483-
public getRawOriginal<K extends SimpleAttributeKeys<this> | string, T extends this[K]>(key: K, defaultValue?: T): T;
484-
public getRawOriginal(): SimpleAttributes<this>;
483+
public getRawOriginal<K extends AttributeKeys<this> | string, T extends this[K]>(key: K, defaultValue?: T): T;
484+
public getRawOriginal(): Attributes<this>;
485485
public getRawOriginal(key?: string, defaultValue?: unknown): unknown {
486486
if (key) {
487487
return this.original.hasOwnProperty(key) ? cloneDeep(this.original[key]) : defaultValue;
@@ -497,9 +497,9 @@ export default class HasAttributes extends GuardsAttributes implements Jsonable,
497497
*
498498
* @return {object}
499499
*/
500-
public getChanges<K extends SimpleAttributeKeys<this>>(key: K): Record<K, this[K] | undefined>;
501-
public getChanges(key?: string): Partial<SimpleAttributes<this>>;
502-
public getChanges(key?: string): SimpleAttributes {
500+
public getChanges<K extends AttributeKeys<this>>(key: K): Record<K, this[K] | undefined>;
501+
public getChanges(key?: string): Partial<Attributes<this>>;
502+
public getChanges(key?: string): Attributes {
503503
if (key) {
504504
if (isEqual(this.getRawOriginal(key), this.attributes[key])) {
505505
return {};
@@ -528,9 +528,9 @@ export default class HasAttributes extends GuardsAttributes implements Jsonable,
528528
*
529529
* @return {object}
530530
*/
531-
public getDeletedAttributes<K extends SimpleAttributeKeys<this>>(key: K): Record<K, this[K] | undefined>;
532-
public getDeletedAttributes(key?: string): Partial<SimpleAttributes<this>>;
533-
public getDeletedAttributes(key?: string): SimpleAttributes {
531+
public getDeletedAttributes<K extends AttributeKeys<this>>(key: K): Record<K, this[K] | undefined>;
532+
public getDeletedAttributes(key?: string): Partial<Attributes<this>>;
533+
public getDeletedAttributes(key?: string): Attributes {
534534
if (key) {
535535
if (key in this.original) {
536536
if (key in this.attributes) {
@@ -564,9 +564,9 @@ export default class HasAttributes extends GuardsAttributes implements Jsonable,
564564
*
565565
* @return {object}
566566
*/
567-
public getNewAttributes<K extends SimpleAttributeKeys<this>>(key: K): Record<K, this[K] | undefined>;
568-
public getNewAttributes(key?: string): Partial<SimpleAttributes<this>>;
569-
public getNewAttributes(key?: string): SimpleAttributes {
567+
public getNewAttributes<K extends AttributeKeys<this>>(key: K): Record<K, this[K] | undefined>;
568+
public getNewAttributes(key?: string): Partial<Attributes<this>>;
569+
public getNewAttributes(key?: string): Attributes {
570570
if (key) {
571571
if (key in this.attributes) {
572572
if (key in this.original) {
@@ -640,11 +640,11 @@ export default class HasAttributes extends GuardsAttributes implements Jsonable,
640640
* @return {object}
641641
*/
642642
public only<
643-
K extends SimpleAttributeKeys<this>[],
644-
R = { [P in K[number]]?: SimpleAttributes<this>[P] }
643+
K extends AttributeKeys<this>[],
644+
R = { [P in K[number]]?: Attributes<this>[P] }
645645
>(attributes: K): R;
646-
public only<K extends SimpleAttributeKeys<this>, R = Record<K, this[K]>>(attributes: K): R;
647-
public only(attributes: MaybeArray<string>): SimpleAttributes {
646+
public only<K extends AttributeKeys<this>, R = Record<K, this[K]>>(attributes: K): R;
647+
public only(attributes: MaybeArray<string>): Attributes {
648648
attributes = Array.isArray(attributes) ? attributes : [attributes];
649649
const result: Attributes = {};
650650

@@ -664,9 +664,9 @@ export default class HasAttributes extends GuardsAttributes implements Jsonable,
664664
*
665665
* @return {object}
666666
*/
667-
public except<K extends SimpleAttributeKeys<this>[], R = Omit<SimpleAttributes<this>, K[number]>>(attributes: K): R;
668-
public except<K extends SimpleAttributeKeys<this> | string, R = Omit<SimpleAttributes<this>, K>>(attributes: K): R;
669-
public except(attributes: MaybeArray<string>): SimpleAttributes {
667+
public except<K extends AttributeKeys<this>[], R = Omit<Attributes<this>, K[number]>>(attributes: K): R;
668+
public except<K extends AttributeKeys<this> | string, R = Omit<Attributes<this>, K>>(attributes: K): R;
669+
public except(attributes: MaybeArray<string>): Attributes {
670670
const result: Attributes = {};
671671

672672
attributes = Array.isArray(attributes) ? attributes : [attributes];

src/Calliope/Model.ts

+5-5
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import type HasFactory from '../Contracts/HasFactory';
44
import type { Attributes, AttributeKeys, SimpleAttributes } from './Concerns/HasAttributes';
55
import ModelCollection from './ModelCollection';
66
import LogicException from '../Exceptions/LogicException';
7-
import { finish } from '../Support/string';
7+
import { finish, isUuid } from '../Support/string';
88
import type { MaybeArray, StaticToThis } from '../Support/type';
99
import { cloneDeep } from 'lodash';
1010
import { isObjectLiteral } from '../Support/function';
@@ -79,7 +79,7 @@ export default class Model extends SoftDeletes implements HasFactory {
7979
*
8080
* @return {this}
8181
*/
82-
public new(attributes?: Attributes<this> | this): this {
82+
public new(attributes?: Attributes<this> | Model): this {
8383
return (this.constructor as typeof Model).create(attributes) as this;
8484
}
8585

@@ -100,10 +100,10 @@ export default class Model extends SoftDeletes implements HasFactory {
100100
if (attributes instanceof Model) {
101101
// if creating by passing a model, we'll take the attributes
102102
// in their current state, not the original.
103-
const allProperties = attributes.getRawAttributes() as Attributes<T>;
103+
const allProperties = (attributes as T).getRawAttributes();
104104

105-
if (isObjectLiteral(attributes.relations)) {
106-
Object.assign(allProperties, attributes.getRelations());
105+
if (isObjectLiteral((attributes as T).relations)) {
106+
Object.assign(allProperties, cloneDeep((attributes as T).relations));
107107
}
108108

109109
attributes = allProperties;

src/Calliope/ModelCollection.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -419,7 +419,7 @@ export default class ModelCollection<T extends Model> extends Collection<T> {
419419
/**
420420
* @inheritDoc
421421
*/
422-
public override toJSON<R extends ReturnType<typeof JSON.parse> = RawAttributes<T>>(): { elements: R[] } {
422+
public override toJSON(): { elements: ReturnType<T['toJSON']>[] } {
423423
// eslint-disable-next-line max-len
424424
// https://security.stackexchange.com/questions/7001/how-should-web-app-developers-defend-against-json-hijacking/7003#7003
425425
return { elements: this.toArray().map(model => model.toJSON()) };

src/Services/API.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ export default class API implements ApiCaller {
4242
url: string,
4343
method: 'HEAD' | 'head',
4444
data?: FormData | Record<string, unknown>,
45-
customHeaders?: CustomHeaders,
45+
customHeaders?: Record<string, MaybeArray<string>>,
4646
queryParameters?: Record<string, unknown>
4747
): Promise<ApiResponse & { request: { method: 'HEAD' } }>;
4848
public async call<T>(
@@ -56,7 +56,7 @@ export default class API implements ApiCaller {
5656
url: string,
5757
method: Method,
5858
data?: FormData | Record<string, unknown>,
59-
customHeaders?: CustomHeaders,
59+
customHeaders?: Record<string, MaybeArray<string>>,
6060
queryParameters?: Record<string, unknown>
6161
): Promise<ApiResponse> {
6262
const config = await this.initConfig(url, method, data, customHeaders, queryParameters);

src/index.ts

+2-8
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,7 @@ import type { QueryParams } from './Calliope/Concerns/BuildsQuery';
3737
import type FormatsQueryParameters from './Contracts/FormatsQueryParameters';
3838
import type { ApiResponse } from './Contracts/HandlesApiResponse';
3939
import type { Events, Listener } from './Support/EventEmitter';
40-
import type { Method, CustomHeaders } from './Calliope/Concerns/CallsApi';
41-
import type { ResolvableAttributes } from './Calliope/Factory/FactoryBuilder';
40+
import type { Method } from './Calliope/Concerns/CallsApi';
4241

4342
export type {
4443
AttributeCaster,
@@ -54,12 +53,7 @@ export type {
5453
Events,
5554
Listener,
5655
AttributeKeys,
57-
Method,
58-
SimpleAttributes,
59-
SimpleAttributeKeys,
60-
CustomHeaders,
61-
RawAttributes,
62-
ResolvableAttributes
56+
Method
6357
};
6458

6559
export * from './Support/type';

tests/Calliope/Concerns/CallsApi.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ describe('CallsApi', () => {
218218
});
219219

220220
it('should send all the given data', async () => {
221-
mockUserModelResponse(User.factory().makeOne());
221+
fetchMock.mockResponseOnce(async () => Promise.resolve(buildResponse(User.factory().raw())));
222222
await caller.call('POST', {
223223
falsyKey1: null,
224224
falsyKey2: undefined,

tests/Calliope/Concerns/HasAttributes.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,7 @@ describe('HasAttributes', () => {
318318

319319
it('should overwrite existing descriptors', () => {
320320
class ModelWithProperties extends User {
321-
public attribute1?: string;
321+
public attribute1?: string;
322322

323323
public attribute2 = 1;
324324

tests/Calliope/Factory/FactoryBuilder.test.ts

-11
Original file line numberDiff line numberDiff line change
@@ -60,11 +60,6 @@ describe('FactoryBuilder', () => {
6060
});
6161

6262
it('should throw an error if the given state is not a function', () => {
63-
class FakeFactory extends Factory<User> {
64-
// @ts-expect-error
65-
public scopeAsProperty = 0;
66-
}
67-
6863
// @ts-expect-error
6964
User.prototype.factory = () => new FakeFactory();
7065

@@ -80,12 +75,6 @@ describe('FactoryBuilder', () => {
8075
});
8176

8277
it('should throw an error if the given state is not a returning an object', () => {
83-
class FakeFactory extends Factory<User> {
84-
public invalidScope() {
85-
return null;
86-
}
87-
}
88-
8978
// @ts-expect-error
9079
User.prototype.factory = () => new FakeFactory();
9180

tests/Services/API.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import API from '../../src/Services/API';
22
import { config as globalConfig } from '../setupTests';
3-
import type { CustomHeaders, Method } from '../../src/Calliope/Concerns/CallsApi';
3+
import type { Method } from '../../src/Calliope/Concerns/CallsApi';
44
import { finish } from '../../src/Support/string';
55
import InvalidArgumentException from '../../src/Exceptions/InvalidArgumentException';
66

0 commit comments

Comments
 (0)