Skip to content

Commit

Permalink
fix: fix singleton update path issue
Browse files Browse the repository at this point in the history
  • Loading branch information
pviti committed Dec 12, 2024
1 parent c3afd1a commit 439dc3b
Show file tree
Hide file tree
Showing 10 changed files with 806 additions and 634 deletions.
4 changes: 3 additions & 1 deletion gen/fixer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,11 +96,13 @@ const fixHeadingEmptyLines = (lines: string[]): string[] => {

const fixResourcesType = (schema: ApiSchema): ApiSchema => {

const skippedKeys = ['user']

const resources = {}

for (const key in schema.resources) {
const type = Inflector.pluralize(key)
if (type === key) resources[key] = schema.resources[key]
if ((type === key) || skippedKeys.includes(key)) resources[key] = schema.resources[key]
else resources[type] = schema.resources[key]
}

Expand Down
4 changes: 2 additions & 2 deletions gen/templates/singleton_update.tpl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
async update(resource: ##__RESOURCE_REQUEST_CLASS__##, params?: QueryParamsRetrieve<##__RESOURCE_RESPONSE_CLASS__##>, options?: ResourcesConfig): Promise<##__RESOURCE_RESPONSE_CLASS__##> {
const res = await this.retrieve(params, options) // JsonAPI requires id in the request body
return this.resources.update<##__RESOURCE_REQUEST_CLASS__##, ##__RESOURCE_RESPONSE_CLASS__##>({ ...resource, id: res.id, type: ##__RESOURCE_CLASS__##.TYPE }, params, options)
const id = resource.id || (await this.retrieve()).id // JsonAPI requires id in the request body
return this.resources.update<##__RESOURCE_REQUEST_CLASS__##, ##__RESOURCE_RESPONSE_CLASS__##>({ ...resource, id, type: ##__RESOURCE_CLASS__##.TYPE }, params, options)
}
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@
"@semantic-release/git": "^10.0.1",
"@types/debug": "^4.1.12",
"@types/jest": "^29.5.14",
"@types/node": "^22.9.1",
"dotenv": "^16.4.5",
"@types/node": "^22.10.2",
"dotenv": "^16.4.7",
"eslint": "^8.57.1",
"jest": "^29.7.0",
"json-typescript": "^1.1.2",
Expand All @@ -52,7 +52,7 @@
"semantic-release": "^24.2.0",
"tsup": "^8.3.5",
"tsx": "^4.19.2",
"typescript": "^5.6.3"
"typescript": "^5.7.2"
},
"repository": "github:commercelayer/provisioning-sdk",
"bugs": "https://github.com/commercelayer/provisioning-sdk/issues",
Expand Down
1,374 changes: 772 additions & 602 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ beforeAll(async () => { clp = await getClient() })

describe('Users resource', () => {

const resourceType = 'users'
const resourceType = 'user'
const resourcePath = 'user'


Expand Down
14 changes: 7 additions & 7 deletions src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export { default as Memberships } from './resources/memberships'
export { default as Organizations } from './resources/organizations'
export { default as Permissions } from './resources/permissions'
export { default as Roles } from './resources/roles'
export { default as Users } from './resources/users'
export { default as Users } from './resources/user'
export { default as Versions } from './resources/versions'
// ##__API_RESOURCES_STOP__##

Expand All @@ -26,7 +26,7 @@ export type ResourceTypeLock =
| 'organizations'
| 'permissions'
| 'roles'
| 'users'
| 'user'
| 'versions'
// ##__API_RESOURCE_TYPES_STOP__##

Expand All @@ -39,15 +39,15 @@ export const resourceList: ResourceTypeLock[] = [
'organizations',
'permissions',
'roles',
'users',
'user',
'versions'
// ##__API_RESOURCE_LIST_STOP__##
] as const


export const singletonList: ResourceTypeLock[] = [
// ##__API_RESOURCE_SINGLETON_START__##
'users'
'user'
// ##__API_RESOURCE_SINGLETON_STOP__##
] as const

Expand All @@ -63,7 +63,7 @@ export type RetrievableResource = Resource & {
// Listable resources
export type ListableResourceType = Exclude<ResourceTypeLock,
// ##__API_RESOURCE_NOT_LISTABLE_START__##
'users'
'user'
// ##__API_RESOURCE_NOT_LISTABLE_STOP__##
>

Expand Down Expand Up @@ -140,7 +140,7 @@ export type ResourceFields = {
organizations: models.Organization,
permissions: models.Permission,
roles: models.Role,
users: models.User,
user: models.User,
versions: models.Version
// ##__API_RESOURCE_FIELDS_STOP__##
}
Expand All @@ -154,7 +154,7 @@ export type ResourceSortFields = {
organizations: models.OrganizationSort,
permissions: models.PermissionSort,
roles: models.RoleSort,
users: models.UserSort,
user: models.UserSort,
versions: models.VersionSort
// ##__API_RESOURCE_SORTABLE_FIELDS_STOP__##
}
2 changes: 1 addition & 1 deletion src/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@ export type { Membership, MembershipCreate, MembershipUpdate, MembershipSort } f
export type { Organization, OrganizationCreate, OrganizationUpdate, OrganizationSort } from './resources/organizations'
export type { Permission, PermissionCreate, PermissionUpdate, PermissionSort } from './resources/permissions'
export type { Role, RoleCreate, RoleUpdate, RoleSort } from './resources/roles'
export type { User, UserUpdate, UserSort } from './resources/users'
export type { User, UserUpdate, UserSort } from './resources/user'
export type { Version, VersionSort } from './resources/versions'
// ##__MODEL_TYPES_STOP__##
20 changes: 10 additions & 10 deletions src/resource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,12 +152,12 @@ class ResourceAdapter {

const singleton = !('id' in resource) || CommerceLayerProvisioningStatic.isSingleton(resource.type)

debug('retrieve:%s %o, %O, %O', (singleton? ' singleton,' : ''), resource, params || {}, options || {})
debug('retrieve:%s %o, %O, %O', (singleton ? ' singleton,' : ''), resource, params || {}, options || {})

const queryParams = generateQueryStringParams(params, resource)
if (options?.params) Object.assign(queryParams, options?.params)

const retrievePath = `${path || resource.type}${singleton? '' : `/${resource.id}`}`
const retrievePath = `${path || resource.type}${singleton ? '' : `/${resource.id}`}`

const res: DocWithData = await this.#client.request('GET', retrievePath, undefined, { ...options, params: queryParams })
const r = denormalize<R>(res) as R
Expand Down Expand Up @@ -205,19 +205,19 @@ class ResourceAdapter {
}


async update<U extends ResourceUpdate, R extends Resource>(resource: U & ResourceId, params?: QueryParamsRetrieve<R>, options?: ResourcesConfig): Promise<R> {
async update<U extends ResourceUpdate, R extends Resource>(resource: U & ResourceId, params?: QueryParamsRetrieve<R>, options?: ResourcesConfig, path?: string): Promise<R> {

const singleton = !('id' in resource) || CommerceLayerProvisioningStatic.isSingleton(resource.type)

debug('update:%s %o, %O, %O', (singleton? ' singleton,' : ''), resource, params || {}, options || {})
debug('update:%s %o, %O, %O', (singleton ? ' singleton,' : ''), resource, params || {}, options || {})

const queryParams = generateQueryStringParams(params, resource)
if (options?.params) Object.assign(queryParams, options?.params)

const path = `${resource.type}${singleton? '' : `/${resource.id}`}`
const updatePath = `${path || resource.type}${singleton ? '' : `/${resource.id}`}`

const data = normalize(resource)
const res = await this.#client.request('PATCH', path, data, { ...options, params: queryParams })
const res = await this.#client.request('PATCH', updatePath, data, { ...options, params: queryParams })
const r = denormalize<R>(res as DocWithData) as R

return r
Expand Down Expand Up @@ -263,7 +263,7 @@ class ResourceAdapter {
const queryParams = {}
if (options?.params) Object.assign(queryParams, options?.params)

const data = (payload && isResourceId(payload))? normalize(payload) : payload
const data = (payload && isResourceId(payload)) ? normalize(payload) : payload

await this.#client.request(cmd, path, data, { ...options, params: queryParams })

Expand All @@ -290,15 +290,15 @@ abstract class ApiResourceBase<R extends Resource> {
}

protected relationshipOneToMany<RR extends ResourceRel>(...ids: string[]): RR[] {
return (((ids === null) || (ids.length === 0) || (ids[0] === null))? [ { id: null, type: this.type() } ] : ids.map(id => { return { id, type: this.type() } })) as RR[]
return (((ids === null) || (ids.length === 0) || (ids[0] === null)) ? [{ id: null, type: this.type() }] : ids.map(id => { return { id, type: this.type() } })) as RR[]
}

abstract type(): ResourceTypeLock

protected path(): string {
return this.type()
}


parse(resource: string): R | R[] {
try {
Expand All @@ -314,7 +314,7 @@ abstract class ApiResourceBase<R extends Resource> {

// reference, reference_origin and metadata attributes are always updatable
async update(resource: ResourceUpdate, params?: QueryParamsRetrieve<R>, options?: ResourcesConfig): Promise<R> {
return this.resources.update<ResourceUpdate, R>({ ...resource, type: this.type() }, params, options)
return this.resources.update<ResourceUpdate, R>({ ...resource, type: this.type() }, params, options, this.path())
}

}
Expand Down
8 changes: 4 additions & 4 deletions src/resources/users.ts → src/resources/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import type { QueryParamsRetrieve } from '../query'



type UserType = 'users'
type UserType = 'user'
type UserRel = ResourceRel & { type: UserType }


Expand Down Expand Up @@ -73,11 +73,11 @@ interface UserUpdate extends ResourceUpdate {

class Users extends ApiSingleton<User> {

static readonly TYPE: UserType = 'users' as const
static readonly TYPE: UserType = 'user' as const

async update(resource: UserUpdate, params?: QueryParamsRetrieve<User>, options?: ResourcesConfig): Promise<User> {
const res = await this.retrieve(params, options) // JsonAPI requires id in the request body
return this.resources.update<UserUpdate, User>({ ...resource, id: res.id, type: Users.TYPE }, params, options)
const id = resource.id || (await this.retrieve()).id // JsonAPI requires id in the request body
return this.resources.update<UserUpdate, User>({ ...resource, id, type: Users.TYPE }, params, options)
}


Expand Down
6 changes: 3 additions & 3 deletions test/spot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ async function refreshToken(old: string): Promise<string> {

try {

const membership = (await clp.memberships.list()).first()
if (membership) await clp.memberships.resend(membership)
else console.log('No membership')
let user = await clp.user.retrieve()
console.log(user)
user = await clp.user.update(user)

} catch (error: any) {
console.log(inspect(error, false, null, true))
Expand Down

0 comments on commit 439dc3b

Please sign in to comment.