diff --git a/src/model.ts b/src/model.ts index 8a71eda..4ec6459 100644 --- a/src/model.ts +++ b/src/model.ts @@ -41,6 +41,7 @@ import { JsonapiResourceIdentifier } from "./jsonapi-spec" +import { singularize } from "inflected" import { cloneDeep } from "./util/clonedeep" import { nonenumerable } from "./util/decorators" import { IncludeScopeHash } from "./util/include-directive" @@ -65,6 +66,7 @@ export interface ModelConfiguration { keyCase: KeyCase strictAttributes: boolean logger: ILogger + singularResource: boolean } export type ModelConfigurationOptions = Partial @@ -167,6 +169,7 @@ export class SpraypaintBase { static keyCase: KeyCase = { server: "snake", client: "camel" } static strictAttributes: boolean = false static logger: ILogger = defaultLogger + static singularResource: boolean = false static sync: boolean = false static credentials: "same-origin" | "omit" | "include" | undefined static clientApplication: string | null = null @@ -774,10 +777,14 @@ export class SpraypaintBase { } static url(id?: string | number): string { - const endpoint = this.endpoint || `/${this.jsonapiType}` + const endpoint = + this.endpoint || + (this.singularResource + ? `/${singularize(this.jsonapiType!)}` + : `/${this.jsonapiType}`) let base = `${this.fullBasePath()}${endpoint}` - if (id) { + if (id && !this.singularResource) { base = `${base}/${id}` } diff --git a/src/scope.ts b/src/scope.ts index dbf5a31..7d59772 100644 --- a/src/scope.ts +++ b/src/scope.ts @@ -71,6 +71,12 @@ export class Scope { return this._buildRecordResult(json) } + async findSingle(): Promise> { + const json = (await this._fetch(this.model.url())) as JsonapiResourceDoc + + return this._buildRecordResult(json) + } + async first(): Promise | NullProxy> { const newScope = this.per(1) let rawResult diff --git a/src/util/parameterize.ts b/src/util/parameterize.ts index 9bb0954..2c1913b 100644 --- a/src/util/parameterize.ts +++ b/src/util/parameterize.ts @@ -36,7 +36,7 @@ const parameterize = (obj: any, prefix?: string): string => { // IE does not encode by default like other browsers const maybeEncode = (value: string): string => { - const isBrowser = typeof document !== "undefined" + const isBrowser = typeof window !== "undefined" const isIE = isBrowser && window.navigator.userAgent.match(/(MSIE|Trident)/) const isEncoded = typeof value === "string" && value.indexOf("%") !== -1 const shouldEncode = isBrowser && isIE && !isEncoded