Skip to content

Commit

Permalink
feat: saveRecord builders (#8740)
Browse files Browse the repository at this point in the history
* feat: saveRecord builders

* fix type sources

* add some docs

* fix

* fix

* improve docs

* revert pnpm file

* fix tests
  • Loading branch information
runspired authored Jul 28, 2023
1 parent f163993 commit 8ad83d7
Show file tree
Hide file tree
Showing 28 changed files with 566 additions and 119 deletions.
3 changes: 3 additions & 0 deletions docs-generator/yuidoc.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
"../packages/adapter/src",
"../packages/model/src",
"../packages/serializer/src",
"../packages/rest/src",
"../packages/active-record/src",
"../packages/request-utils/src",
"../packages/store/src",
"../packages/json-api/src",
"../packages/graph/src",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { QueryParamsSerializationOptions } from '@ember-data/request-utils';
import type { ResourceIdentifierObject } from '@ember-data/types/q/ember-data-json-api';
import { StableRecordIdentifier } from '@ember-data/types/q/identifier';

export type CacheOptions = {
key?: string;
Expand All @@ -23,6 +24,36 @@ export type QueryRequestOptions = {
op: 'query';
};

export type DeleteRequestOptions = {
url: string;
method: 'DELETE';
headers: Headers;
op: 'deleteRecord';
data: {
record: StableRecordIdentifier;
};
};

export type UpdateRequestOptions = {
url: string;
method: 'PATCH' | 'PUT';
headers: Headers;
op: 'updateRecord';
data: {
record: StableRecordIdentifier;
};
};

export type CreateRequestOptions = {
url: string;
method: 'POST';
headers: Headers;
op: 'createRecord';
data: {
record: StableRecordIdentifier;
};
};

export type RemotelyAccessibleIdentifier = {
id: string;
type: string;
Expand All @@ -37,3 +68,7 @@ export type ConstrainedRequestOptions = {
resourcePath?: string;
urlParamsSettings?: QueryParamsSerializationOptions;
};

export type FindRecordOptions = ConstrainedRequestOptions & {
include?: string | string[];
};
3 changes: 2 additions & 1 deletion packages/active-record/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@
"ember-cli-babel": "^7.26.11"
},
"peerDependencies": {
"ember-inflector": "^4.0.2"
"ember-inflector": "^4.0.2",
"@ember-data/store": "^4.12.0 || ^5.0.0"
},
"files": [
"addon-main.js",
Expand Down
3 changes: 1 addition & 2 deletions packages/active-record/src/-private/builders/-utils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { type UrlOptions } from '@ember-data/request-utils';

import type { CacheOptions, ConstrainedRequestOptions } from './-types';
import type { CacheOptions, ConstrainedRequestOptions } from '@ember-data/types/request';

export function copyForwardUrlOptions(urlOptions: UrlOptions, options: ConstrainedRequestOptions): void {
if ('host' in options) {
Expand Down
6 changes: 5 additions & 1 deletion packages/active-record/src/-private/builders/find-record.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,12 @@ import { underscore } from '@ember/string';
import { pluralize } from 'ember-inflector';

import { buildBaseURL, buildQueryParams, type FindRecordUrlOptions } from '@ember-data/request-utils';
import type {
ConstrainedRequestOptions,
FindRecordRequestOptions,
RemotelyAccessibleIdentifier,
} from '@ember-data/types/request';

import type { ConstrainedRequestOptions, FindRecordRequestOptions, RemotelyAccessibleIdentifier } from './-types';
import { copyForwardUrlOptions, extractCacheOptions } from './-utils';

type FindRecordOptions = ConstrainedRequestOptions & {
Expand Down
2 changes: 1 addition & 1 deletion packages/active-record/src/-private/builders/query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import { underscore } from '@ember/string';
import { pluralize } from 'ember-inflector';

import { buildBaseURL, buildQueryParams, QueryParamsSource, type QueryUrlOptions } from '@ember-data/request-utils';
import type { ConstrainedRequestOptions, QueryRequestOptions } from '@ember-data/types/request';

import type { ConstrainedRequestOptions, QueryRequestOptions } from './-types';
import { copyForwardUrlOptions, extractCacheOptions } from './-utils';

export function query(
Expand Down
112 changes: 112 additions & 0 deletions packages/active-record/src/-private/builders/save-record.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import { assert } from '@ember/debug';
import { underscore } from '@ember/string';

import { pluralize } from 'ember-inflector';

import {
buildBaseURL,
type CreateRecordUrlOptions,
type DeleteRecordUrlOptions,
type UpdateRecordUrlOptions,
} from '@ember-data/request-utils';
import { recordIdentifierFor } from '@ember-data/store';
import type { StableExistingRecordIdentifier, StableRecordIdentifier } from '@ember-data/types/q/identifier';
import {
ConstrainedRequestOptions,
CreateRequestOptions,
DeleteRequestOptions,
UpdateRequestOptions,
} from '@ember-data/types/request';

import { copyForwardUrlOptions } from './-utils';

function isExisting(identifier: StableRecordIdentifier): identifier is StableExistingRecordIdentifier {
return 'id' in identifier && identifier.id !== null && 'type' in identifier && identifier.type !== null;
}

export function deleteRecord(record: unknown, options: ConstrainedRequestOptions = {}): DeleteRequestOptions {
const identifier = recordIdentifierFor(record);
assert(`Expected to be given a record instance`, identifier);
assert(`Cannot delete a record that does not have an associated type and id.`, isExisting(identifier));

const urlOptions: DeleteRecordUrlOptions = {
identifier: identifier,
op: 'deleteRecord',
resourcePath: pluralize(underscore(identifier.type)),
};

copyForwardUrlOptions(urlOptions, options);

const url = buildBaseURL(urlOptions);
const headers = new Headers();
headers.append('Content-Type', 'application/json; charset=utf-8');

return {
url,
method: 'DELETE',
headers,
op: 'deleteRecord',
data: {
record: identifier,
},
};
}

export function createRecord(record: unknown, options: ConstrainedRequestOptions = {}): CreateRequestOptions {
const identifier = recordIdentifierFor(record);
assert(`Expected to be given a record instance`, identifier);
assert(`Cannot delete a record that does not have an associated type and id.`, isExisting(identifier));

const urlOptions: CreateRecordUrlOptions = {
identifier: identifier,
op: 'createRecord',
resourcePath: pluralize(underscore(identifier.type)),
};

copyForwardUrlOptions(urlOptions, options);

const url = buildBaseURL(urlOptions);
const headers = new Headers();
headers.append('Content-Type', 'application/json; charset=utf-8');

return {
url,
method: 'POST',
headers,
op: 'createRecord',
data: {
record: identifier,
},
};
}

export function updateRecord(
record: unknown,
options: ConstrainedRequestOptions & { patch?: boolean } = {}
): UpdateRequestOptions {
const identifier = recordIdentifierFor(record);
assert(`Expected to be given a record instance`, identifier);
assert(`Cannot delete a record that does not have an associated type and id.`, isExisting(identifier));

const urlOptions: UpdateRecordUrlOptions = {
identifier: identifier,
op: 'updateRecord',
resourcePath: pluralize(underscore(identifier.type)),
};

copyForwardUrlOptions(urlOptions, options);

const url = buildBaseURL(urlOptions);
const headers = new Headers();
headers.append('Content-Type', 'application/json; charset=utf-8');

return {
url,
method: options.patch ? 'PATCH' : 'PUT',
headers,
op: 'updateRecord',
data: {
record: identifier,
},
};
}
1 change: 1 addition & 0 deletions packages/active-record/src/request.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export { findRecord } from './-private/builders/find-record';
export { query } from './-private/builders/query';
export { deleteRecord, createRecord, updateRecord } from './-private/builders/save-record';
39 changes: 0 additions & 39 deletions packages/json-api/src/-private/builders/-types.ts

This file was deleted.

3 changes: 1 addition & 2 deletions packages/json-api/src/-private/builders/-utils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { type UrlOptions } from '@ember-data/request-utils';

import type { CacheOptions, ConstrainedRequestOptions } from './-types';
import type { CacheOptions, ConstrainedRequestOptions } from '@ember-data/types/request';

export function copyForwardUrlOptions(urlOptions: UrlOptions, options: ConstrainedRequestOptions): void {
if ('host' in options) {
Expand Down
10 changes: 5 additions & 5 deletions packages/json-api/src/-private/builders/find-record.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { pluralize } from 'ember-inflector';

import { buildBaseURL, buildQueryParams, type FindRecordUrlOptions } from '@ember-data/request-utils';
import type {
FindRecordOptions,
FindRecordRequestOptions,
RemotelyAccessibleIdentifier,
} from '@ember-data/types/request';

import type { ConstrainedRequestOptions, FindRecordRequestOptions, RemotelyAccessibleIdentifier } from './-types';
import { copyForwardUrlOptions, extractCacheOptions } from './-utils';

type FindRecordOptions = ConstrainedRequestOptions & {
include?: string | string[];
};

export function findRecord(
identifier: RemotelyAccessibleIdentifier,
options?: FindRecordOptions
Expand Down
2 changes: 1 addition & 1 deletion packages/json-api/src/-private/builders/query.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { pluralize } from 'ember-inflector';

import { buildBaseURL, buildQueryParams, QueryParamsSource, type QueryUrlOptions } from '@ember-data/request-utils';
import type { ConstrainedRequestOptions, QueryRequestOptions } from '@ember-data/types/request';

import type { ConstrainedRequestOptions, QueryRequestOptions } from './-types';
import { copyForwardUrlOptions, extractCacheOptions } from './-utils';

export function query(
Expand Down
Loading

0 comments on commit 8ad83d7

Please sign in to comment.