Used libraries
core, jsonapi, jsonapi-angular, utils
Library version(s)
"@datx/core": "^3.0.0", "@datx/jsonapi": "^3.0.0", "@datx/jsonapi-angular": "^3.0.0", "@datx/jsonapi-types": "^3.0.0", "@datx/network": "^3.0.0", "@datx/utils": "^3.0.0",
Issue description
When retrieving the model via a custom url the data is not being set inside the object.
Whereas I retrieve all the users after, the data is getting filled properly.
Response from api
{
"jsonapi":{
"version":"1.0"
},
"links":{
"self":"http:\/\/localhost\/api\/v1\/users\/1"
},
"data":{
"type":"users",
"id":"1",
"attributes":{
"name":"Stefan Willems",
"email":"",
"given_name":"Stefan",
"family_name":"Willems",
"created_at":"2023-09-25T10:04:06.000000Z",
"updated_at":"2023-09-25T10:04:06.000000Z"
},
"relationships":{
"roles":{
"links":{
"related":"http:\/\/localhost\/api\/v1\/users\/1\/roles",
"self":"http:\/\/localhost\/api\/v1\/users\/1\/relationships\/roles"
},
"data":[
{
"type":"roles",
"id":"2"
}
]
},
"revisions":{
"links":{
"related":"http:\/\/localhost\/api\/v1\/users\/1\/revisions",
"self":"http:\/\/localhost\/api\/v1\/users\/1\/relationships\/revisions"
},
"data":[
]
}
},
"links":{
"self":"http:\/\/localhost\/api\/v1\/users\/1"
}
},
"included":[
{
"type":"roles",
"id":"2",
"attributes":{
"name":"user"
},
"relationships":{
"permissions":{
"links":{
"related":"http:\/\/localhost\/api\/v1\/roles\/2\/permissions",
"self":"http:\/\/localhost\/api\/v1\/roles\/2\/relationships\/permissions"
},
"data":[
{
"type":"permissions",
"id":"1"
},
{
"type":"permissions",
"id":"10"
},
{
"type":"permissions",
"id":"11"
},
{
"type":"permissions",
"id":"12"
},
{
"type":"permissions",
"id":"13"
},
{
"type":"permissions",
"id":"14"
}
]
}
},
"links":{
"self":"http:\/\/localhost\/api\/v1\/roles\/2"
}
},
{
"type":"permissions",
"id":"1",
"attributes":{
"name":"login-permission"
},
"links":{
"self":"http:\/\/localhost\/api\/v1\/permissions\/1"
}
},
{
"type":"permissions",
"id":"10",
"attributes":{
"name":"file-read"
},
"links":{
"self":"http:\/\/localhost\/api\/v1\/permissions\/10"
}
},
{
"type":"permissions",
"id":"11",
"attributes":{
"name":"file-create"
},
"links":{
"self":"http:\/\/localhost\/api\/v1\/permissions\/11"
}
},
{
"type":"permissions",
"id":"12",
"attributes":{
"name":"file-delete"
},
"links":{
"self":"http:\/\/localhost\/api\/v1\/permissions\/12"
}
},
{
"type":"permissions",
"id":"13",
"attributes":{
"name":"file-upload"
},
"links":{
"self":"http:\/\/localhost\/api\/v1\/permissions\/13"
}
},
{
"type":"permissions",
"id":"14",
"attributes":{
"name":"file-update"
},
"links":{
"self":"http:\/\/localhost\/api\/v1\/permissions\/14"
}
}
]
}
Object inside Angular
{
"__META__": {
"type": "users",
"id": "1",
"fields": {
"name": {
"referenceDef": false
},
"email": {
"referenceDef": false
},
"given_name": {
"referenceDef": false
},
"family_name": {
"referenceDef": false
},
"company": {
"referenceDef": {
"type": 0,
"model": "companies"
}
},
"roles": {
"referenceDef": {
"type": 1,
"model": "roles"
}
},
"revisions": {
"referenceDef": {
"type": 1,
"model": "revisions"
}
},
"created_at": {
"referenceDef": false
},
"updated_at": {
"referenceDef": false
}
},
"jsonapiLinks": {
"self": "http://localhost/api/v1/users/1"
},
"networkPersisted": true,
"jsonapiRefLinks": {
"roles": {
"related": "http://localhost/api/v1/users/1/roles",
"self": "http://localhost/api/v1/users/1/relationships/roles"
},
"revisions": {
"related": "http://localhost/api/v1/users/1/revisions",
"self": "http://localhost/api/v1/users/1/relationships/revisions"
}
},
"jsonapiRefMeta": {}
},
"company": null,
"roles": [
{
"id": "2",
"type": "roles"
}
],
"revisions": [],
"created_at": "2023-09-25T10:04:06.000000Z",
"updated_at": "2023-09-25T10:04:06.000000Z"
}
Request being send from client
public me(include?: string): Observable<User> {
const options: IRequestOptions = {} as IRequestOptions;
options.queryParams = {};
if (include) {
options.queryParams.include = include;
}
return this.collection.request('users/me', HttpMethod.Get, null, options).pipe(map((response: Response) => {
console.log(response.data);
return response.data;
}));
}
App module
import {BrowserModule} from '@angular/platform-browser';
import {APP_INITIALIZER, ErrorHandler, NgModule} from '@angular/core';
import {AppRoutingModule} from './app-routing.module';
import {AppComponent} from './app.component';
import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
import {HTTP_INTERCEPTORS, HttpClient, HttpClientModule} from '@angular/common/http';
import {VersionMismatchInterceptor} from './interceptors/version-mismatch.interceptor';
import {NoConnectionInterceptor} from './interceptors/no-connection.interceptor';
import {DashboardModule} from './dashboard/dashboard.module';
import {MainModule} from './main/main.module';
import {MaterialModule} from './material/material.module';
import * as Sentry from '@sentry/angular-ivy';
import {APP_COLLECTION, DATX_CONFIG, setupDatx} from '@datx/jsonapi-angular';
import {AppCollection} from './collections/app.collection';
import {AuthenticationModule} from './authentication/authentication.module';
import {UnauthorizedInterceptor} from './interceptors/unauthorized.interceptor';
import {CustomFetchService} from './services/custom-fetch.service';
import {CachingStrategy} from '@datx/network';
import {config} from '@datx/jsonapi';
function initDatx(customFetch: CustomFetchService): () => Promise<void> {
return async () => {
config.baseFetch = customFetch.fetch.bind(customFetch);
config.defaultFetchOptions = {
credentials: 'same-origin',
headers: {
'Content-Type': 'application/vnd.api+json',
},
};
// Use cache if not older than 10 seconds
config.maxCacheAge = 10;
config.cache = CachingStrategy.CacheFirst;
};
}
@NgModule({
declarations: [
AppComponent,
],
imports: [
BrowserModule,
AuthenticationModule,
AppRoutingModule,
BrowserAnimationsModule,
DashboardModule,
MainModule,
MaterialModule,
HttpClientModule,
],
providers: [
{provide: HTTP_INTERCEPTORS, useClass: NoConnectionInterceptor, multi: true},
{provide: HTTP_INTERCEPTORS, useClass: VersionMismatchInterceptor, multi: true},
{provide: HTTP_INTERCEPTORS, useClass: UnauthorizedInterceptor, multi: true},
{
provide: ErrorHandler,
useValue: Sentry.createErrorHandler({
showDialog: false,
}),
},
{provide: APP_COLLECTION, useValue: new AppCollection()},
{
provide: DATX_CONFIG,
useFactory: (httpClient: HttpClient) => {
return setupDatx(httpClient, {
baseUrl: '/api/v1/',
});
},
deps: [HttpClient],
},
{
provide: APP_INITIALIZER,
useFactory: initDatx,
multi: true,
deps: [CustomFetchService],
},
],
bootstrap: [AppComponent]
})
export class AppModule {
}
Custom Fetch Service
import {HttpClient} from '@angular/common/http';
import {Injectable} from '@angular/core';
import {config, IResponseObject} from '@datx/jsonapi';
import {lastValueFrom, Observable} from 'rxjs';
import {map, takeUntil} from 'rxjs/operators';
import {IResponseHeaders} from '@datx/utils';
@Injectable({providedIn: 'root'})
export class CustomFetchService {
constructor(private httpClient: HttpClient) {
}
public async fetch(
method: string,
url: string,
body?: unknown,
headers: Record<string, string> = {},
fetchOptions?: { takeUntil$?: Observable<void> },
): Promise<IResponseObject> {
const takeUntil$: Observable<void> | undefined = fetchOptions?.takeUntil$;
const requestHeaders = {
...config.defaultFetchOptions.headers,
...headers,
};
let request$ = this.httpClient
.request(method, url, {
observe: 'response',
responseType: 'json',
headers: requestHeaders,
body,
})
.pipe(
map((response) => {
return {
data: response.body,
headers: response.headers as unknown as IResponseHeaders, // The interface actually matches
requestHeaders,
status: response.status,
};
}),
);
if (takeUntil$) {
request$ = request$.pipe(takeUntil(takeUntil$));
}
try {
const d = await lastValueFrom(request$);
if (d === undefined) {
return {status: -1}; // Signal to DatX that it shouldn't fail, but shouldn't cache either
}
return d;
} catch (e) {
console.error(e);
throw e;
}
}
}
Used libraries
core, jsonapi, jsonapi-angular, utils
Library version(s)
Issue description
When retrieving the model via a custom url the data is not being set inside the object.
Whereas I retrieve all the users after, the data is getting filled properly.
Response from api
{ "jsonapi":{ "version":"1.0" }, "links":{ "self":"http:\/\/localhost\/api\/v1\/users\/1" }, "data":{ "type":"users", "id":"1", "attributes":{ "name":"Stefan Willems", "email":"", "given_name":"Stefan", "family_name":"Willems", "created_at":"2023-09-25T10:04:06.000000Z", "updated_at":"2023-09-25T10:04:06.000000Z" }, "relationships":{ "roles":{ "links":{ "related":"http:\/\/localhost\/api\/v1\/users\/1\/roles", "self":"http:\/\/localhost\/api\/v1\/users\/1\/relationships\/roles" }, "data":[ { "type":"roles", "id":"2" } ] }, "revisions":{ "links":{ "related":"http:\/\/localhost\/api\/v1\/users\/1\/revisions", "self":"http:\/\/localhost\/api\/v1\/users\/1\/relationships\/revisions" }, "data":[ ] } }, "links":{ "self":"http:\/\/localhost\/api\/v1\/users\/1" } }, "included":[ { "type":"roles", "id":"2", "attributes":{ "name":"user" }, "relationships":{ "permissions":{ "links":{ "related":"http:\/\/localhost\/api\/v1\/roles\/2\/permissions", "self":"http:\/\/localhost\/api\/v1\/roles\/2\/relationships\/permissions" }, "data":[ { "type":"permissions", "id":"1" }, { "type":"permissions", "id":"10" }, { "type":"permissions", "id":"11" }, { "type":"permissions", "id":"12" }, { "type":"permissions", "id":"13" }, { "type":"permissions", "id":"14" } ] } }, "links":{ "self":"http:\/\/localhost\/api\/v1\/roles\/2" } }, { "type":"permissions", "id":"1", "attributes":{ "name":"login-permission" }, "links":{ "self":"http:\/\/localhost\/api\/v1\/permissions\/1" } }, { "type":"permissions", "id":"10", "attributes":{ "name":"file-read" }, "links":{ "self":"http:\/\/localhost\/api\/v1\/permissions\/10" } }, { "type":"permissions", "id":"11", "attributes":{ "name":"file-create" }, "links":{ "self":"http:\/\/localhost\/api\/v1\/permissions\/11" } }, { "type":"permissions", "id":"12", "attributes":{ "name":"file-delete" }, "links":{ "self":"http:\/\/localhost\/api\/v1\/permissions\/12" } }, { "type":"permissions", "id":"13", "attributes":{ "name":"file-upload" }, "links":{ "self":"http:\/\/localhost\/api\/v1\/permissions\/13" } }, { "type":"permissions", "id":"14", "attributes":{ "name":"file-update" }, "links":{ "self":"http:\/\/localhost\/api\/v1\/permissions\/14" } } ] }Object inside Angular
{ "__META__": { "type": "users", "id": "1", "fields": { "name": { "referenceDef": false }, "email": { "referenceDef": false }, "given_name": { "referenceDef": false }, "family_name": { "referenceDef": false }, "company": { "referenceDef": { "type": 0, "model": "companies" } }, "roles": { "referenceDef": { "type": 1, "model": "roles" } }, "revisions": { "referenceDef": { "type": 1, "model": "revisions" } }, "created_at": { "referenceDef": false }, "updated_at": { "referenceDef": false } }, "jsonapiLinks": { "self": "http://localhost/api/v1/users/1" }, "networkPersisted": true, "jsonapiRefLinks": { "roles": { "related": "http://localhost/api/v1/users/1/roles", "self": "http://localhost/api/v1/users/1/relationships/roles" }, "revisions": { "related": "http://localhost/api/v1/users/1/revisions", "self": "http://localhost/api/v1/users/1/relationships/revisions" } }, "jsonapiRefMeta": {} }, "company": null, "roles": [ { "id": "2", "type": "roles" } ], "revisions": [], "created_at": "2023-09-25T10:04:06.000000Z", "updated_at": "2023-09-25T10:04:06.000000Z" }Request being send from client
App module
Custom Fetch Service