[FEAT] update new archidata

This commit is contained in:
Edouard DUPIN 2025-03-22 12:09:18 +01:00
parent a7134c01ed
commit 3e92c2b74a
40 changed files with 527 additions and 229 deletions

View File

@ -20,7 +20,7 @@
<dependency>
<groupId>kangaroo-and-rabbit</groupId>
<artifactId>archidata</artifactId>
<version>0.23.6</version>
<version>0.25.4</version>
</dependency>
<!-- Loopback of logger JDK logging API to SLF4J -->
<dependency>

View File

@ -13,6 +13,7 @@ import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
import org.glassfish.jersey.jackson.JacksonFeature;
import org.glassfish.jersey.media.multipart.MultiPartFeature;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.server.validation.ValidationFeature;
import org.kar.archidata.UpdateJwtPublicKey;
import org.kar.archidata.api.DataResource;
import org.kar.archidata.api.ProxyResource;
@ -151,6 +152,8 @@ public class WebLauncher {
// add jackson to be discover when we are ins standalone server
rc.register(JacksonFeature.class);
// enable jersey specific validations (@Valid)
rc.register(ValidationFeature.class);
// enable this to show low level request
// rc.property(LoggingFeature.LOGGING_FEATURE_LOGGER_LEVEL_SERVER, Level.WARNING.getName());

View File

@ -32,7 +32,6 @@ public class WebLauncherLocal extends WebLauncher {
if (true) {
// for local test:
ConfigBaseVariable.apiAdress = "http://0.0.0.0:19080/karusic/api/";
// ConfigBaseVariable.ssoAdress = "https://atria-soft.org/karso/api/";
ConfigBaseVariable.dbPort = "3906";
ConfigBaseVariable.testMode = "true";
}

View File

@ -6,9 +6,9 @@ import java.util.UUID;
import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
import org.glassfish.jersey.media.multipart.FormDataParam;
import org.kar.archidata.annotation.AsyncType;
import org.kar.archidata.annotation.FormDataOptional;
import org.kar.archidata.annotation.TypeScriptProgress;
import org.kar.archidata.annotation.apiGenerator.ApiAsyncType;
import org.kar.archidata.annotation.apiGenerator.ApiInputOptional;
import org.kar.archidata.annotation.apiGenerator.ApiTypeScriptProgress;
import org.kar.archidata.dataAccess.DBAccess;
import org.kar.archidata.dataAccess.DataAccess;
import org.kar.archidata.dataAccess.addOnSQL.AddOnDataJson;
@ -74,7 +74,7 @@ public class AlbumResource {
@RolesAllowed("ADMIN")
@Consumes(MediaType.APPLICATION_JSON)
@Operation(description = "Update a specific album")
public Album patch(@PathParam("id") final Long id, @AsyncType(Album.class) final String jsonRequest) throws Exception {
public Album patch(@PathParam("id") final Long id, @ApiAsyncType(Album.class) final String jsonRequest) throws Exception {
// final Query<Album> query = this.morphiaService.getDatastore().find(Album.class).filter(Filters.eq("id", id));
// final UpdateOperations<Album> ops = this.morphiaService.getDatastore().createUpdateOperations(Album.class)
// .set("name", master.getName());
@ -119,9 +119,9 @@ public class AlbumResource {
@RolesAllowed("ADMIN")
@Consumes({ MediaType.MULTIPART_FORM_DATA })
@Operation(description = "Add a cover on a specific album")
@TypeScriptProgress
public Album uploadCover(@PathParam("id") final Long id, @FormDataOptional @FormDataParam("uri") final String uri, @FormDataOptional @FormDataParam("file") final InputStream fileInputStream,
@FormDataOptional @FormDataParam("file") final FormDataContentDisposition fileMetaData) throws Exception {
@ApiTypeScriptProgress
public Album uploadCover(@PathParam("id") final Long id, @ApiInputOptional @FormDataParam("uri") final String uri, @ApiInputOptional @FormDataParam("file") final InputStream fileInputStream,
@ApiInputOptional @FormDataParam("file") final FormDataContentDisposition fileMetaData) throws Exception {
try (DBAccess db = DBAccess.createInterface()) {
if (uri != null) {
DataTools.uploadCoverFromUri(db, Album.class, id, uri);

View File

@ -6,9 +6,8 @@ import java.util.List;
import org.bson.types.ObjectId;
import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
import org.glassfish.jersey.media.multipart.FormDataParam;
import org.kar.archidata.annotation.AsyncType;
import org.kar.archidata.annotation.FormDataOptional;
import org.kar.archidata.annotation.TypeScriptProgress;
import org.kar.archidata.annotation.apiGenerator.ApiInputOptional;
import org.kar.archidata.annotation.apiGenerator.ApiTypeScriptProgress;
import org.kar.archidata.dataAccess.DBAccess;
import org.kar.archidata.dataAccess.DataAccess;
import org.kar.archidata.dataAccess.addOnSQL.AddOnDataJson;
@ -20,11 +19,12 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jakarta.annotation.security.RolesAllowed;
import jakarta.validation.Valid;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.DELETE;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.PATCH;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.PUT;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.PathParam;
import jakarta.ws.rs.Produces;
@ -56,12 +56,13 @@ public class ArtistResource {
return DataAccess.insert(data, new CheckFunction(CHECKER));
}
@PATCH
@PUT
@Path("{id}")
@RolesAllowed("ADMIN")
@Consumes(MediaType.APPLICATION_JSON)
public Artist patch(@PathParam("id") final Long id, @AsyncType(Artist.class) final String jsonRequest) throws Exception {
DataAccess.updateWithJson(Artist.class, id, jsonRequest, new CheckFunction(CHECKER));
public Artist patch(@PathParam("id") final Long id, @Valid final Artist jsonRequest) throws Exception {
// new CheckFunction(CHECKER)
DataAccess.update(id, jsonRequest);
return DataAccess.get(Artist.class, id);
}
@ -76,9 +77,9 @@ public class ArtistResource {
@Path("{id}/cover")
@RolesAllowed("ADMIN")
@Consumes({ MediaType.MULTIPART_FORM_DATA })
@TypeScriptProgress
public Artist uploadCover(@PathParam("id") final Long id, @FormDataOptional @FormDataParam("uri") final String uri, @FormDataOptional @FormDataParam("file") final InputStream fileInputStream,
@FormDataOptional @FormDataParam("file") final FormDataContentDisposition fileMetaData) throws Exception {
@ApiTypeScriptProgress
public Artist uploadCover(@PathParam("id") final Long id, @ApiInputOptional @FormDataParam("uri") final String uri, @ApiInputOptional @FormDataParam("file") final InputStream fileInputStream,
@ApiInputOptional @FormDataParam("file") final FormDataContentDisposition fileMetaData) throws Exception {
try (DBAccess db = DBAccess.createInterface()) {
if (uri != null) {
DataTools.uploadCoverFromUri(db, Artist.class, id, uri);

View File

@ -6,9 +6,9 @@ import java.util.List;
import org.bson.types.ObjectId;
import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
import org.glassfish.jersey.media.multipart.FormDataParam;
import org.kar.archidata.annotation.AsyncType;
import org.kar.archidata.annotation.FormDataOptional;
import org.kar.archidata.annotation.TypeScriptProgress;
import org.kar.archidata.annotation.apiGenerator.ApiAsyncType;
import org.kar.archidata.annotation.apiGenerator.ApiInputOptional;
import org.kar.archidata.annotation.apiGenerator.ApiTypeScriptProgress;
import org.kar.archidata.dataAccess.DBAccess;
import org.kar.archidata.dataAccess.DataAccess;
import org.kar.archidata.dataAccess.addOnSQL.AddOnDataJson;
@ -60,7 +60,7 @@ public class GenderResource {
@Path("{id}")
@RolesAllowed("ADMIN")
@Consumes(MediaType.APPLICATION_JSON)
public Gender patch(@PathParam("id") final Long id, @AsyncType(Gender.class) final String jsonRequest) throws Exception {
public Gender patch(@PathParam("id") final Long id, @ApiAsyncType(Gender.class) final String jsonRequest) throws Exception {
DataAccess.updateWithJson(Gender.class, id, jsonRequest, new CheckFunction(CHECKER));
return DataAccess.get(Gender.class, id);
}
@ -76,9 +76,9 @@ public class GenderResource {
@Path("{id}/cover")
@RolesAllowed("ADMIN")
@Consumes({ MediaType.MULTIPART_FORM_DATA })
@TypeScriptProgress
public Gender uploadCover(@PathParam("id") final Long id, @FormDataOptional @FormDataParam("uri") final String uri, @FormDataOptional @FormDataParam("file") final InputStream fileInputStream,
@FormDataOptional @FormDataParam("file") final FormDataContentDisposition fileMetaData) throws Exception {
@ApiTypeScriptProgress
public Gender uploadCover(@PathParam("id") final Long id, @ApiInputOptional @FormDataParam("uri") final String uri, @ApiInputOptional @FormDataParam("file") final InputStream fileInputStream,
@ApiInputOptional @FormDataParam("file") final FormDataContentDisposition fileMetaData) throws Exception {
try (DBAccess db = DBAccess.createInterface()) {
if (uri != null) {
DataTools.uploadCoverFromUri(db, Gender.class, id, uri);

View File

@ -6,7 +6,7 @@ import java.util.List;
import org.bson.types.ObjectId;
import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
import org.glassfish.jersey.media.multipart.FormDataParam;
import org.kar.archidata.annotation.AsyncType;
import org.kar.archidata.annotation.apiGenerator.ApiAsyncType;
import org.kar.archidata.dataAccess.DBAccess;
import org.kar.archidata.dataAccess.DataAccess;
import org.kar.archidata.dataAccess.addOnSQL.AddOnDataJson;
@ -58,7 +58,7 @@ public class PlaylistResource {
@Path("{id}")
@RolesAllowed("ADMIN")
@Consumes(MediaType.APPLICATION_JSON)
public Playlist patch(@PathParam("id") final Long id, @AsyncType(Playlist.class) final String jsonRequest) throws Exception {
public Playlist patch(@PathParam("id") final Long id, @ApiAsyncType(Playlist.class) final String jsonRequest) throws Exception {
DataAccess.updateWithJson(Playlist.class, id, jsonRequest, new CheckFunction(CHECKER));
return DataAccess.get(Playlist.class, id);
}
@ -95,7 +95,7 @@ public class PlaylistResource {
@Path("{id}/cover")
@RolesAllowed("ADMIN")
@Consumes({ MediaType.MULTIPART_FORM_DATA })
@AsyncType(Playlist.class)
@ApiAsyncType(Playlist.class)
public void uploadCover(@PathParam("id") final Long id, @FormDataParam("file") final InputStream fileInputStream, @FormDataParam("file") final FormDataContentDisposition fileMetaData)
throws Exception {
try (DBAccess db = DBAccess.createInterface()) {

View File

@ -9,9 +9,9 @@ import java.util.List;
import org.bson.types.ObjectId;
import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
import org.glassfish.jersey.media.multipart.FormDataParam;
import org.kar.archidata.annotation.AsyncType;
import org.kar.archidata.annotation.FormDataOptional;
import org.kar.archidata.annotation.TypeScriptProgress;
import org.kar.archidata.annotation.apiGenerator.ApiAsyncType;
import org.kar.archidata.annotation.apiGenerator.ApiInputOptional;
import org.kar.archidata.annotation.apiGenerator.ApiTypeScriptProgress;
import org.kar.archidata.dataAccess.DBAccess;
import org.kar.archidata.dataAccess.DataAccess;
import org.kar.archidata.dataAccess.addOnSQL.AddOnDataJson;
@ -65,7 +65,7 @@ public class TrackResource {
@Path("{id}")
@RolesAllowed("ADMIN")
@Consumes(MediaType.APPLICATION_JSON)
public Track patch(@PathParam("id") final Long id, @AsyncType(Track.class) final String jsonRequest) throws Exception {
public Track patch(@PathParam("id") final Long id, @ApiAsyncType(Track.class) final String jsonRequest) throws Exception {
DataAccess.updateWithJson(Track.class, id, jsonRequest, new CheckFunction(CHECKER));
return DataAccess.get(Track.class, id);
}
@ -102,7 +102,7 @@ public class TrackResource {
@Path("{id}/cover")
@RolesAllowed("ADMIN")
@Consumes({ MediaType.MULTIPART_FORM_DATA })
@TypeScriptProgress
@ApiTypeScriptProgress
public Track uploadCover(@PathParam("id") final Long id, @FormDataParam("uri") final String uri, @FormDataParam("file") final InputStream fileInputStream,
@FormDataParam("file") final FormDataContentDisposition fileMetaData) throws Exception {
try (DBAccess db = DBAccess.createInterface()) {
@ -129,14 +129,14 @@ public class TrackResource {
@Path("upload/")
@RolesAllowed("ADMIN")
@Consumes({ MediaType.MULTIPART_FORM_DATA })
@AsyncType(Track.class)
@TypeScriptProgress
@ApiAsyncType(Track.class)
@ApiTypeScriptProgress
public Response uploadTrack( //
@FormDataParam("title") String title, //
@FormDataOptional @AsyncType(Long.class) @FormDataParam("genderId") String genderId, //
@FormDataOptional @AsyncType(Long.class) @FormDataParam("artistId") String artistId, //
@FormDataOptional @AsyncType(Long.class) @FormDataParam("albumId") String albumId, //
@FormDataOptional @AsyncType(Long.class) @FormDataParam("trackId") String trackId, //
@ApiInputOptional @ApiAsyncType(Long.class) @FormDataParam("genderId") String genderId, //
@ApiInputOptional @ApiAsyncType(Long.class) @FormDataParam("artistId") String artistId, //
@ApiInputOptional @ApiAsyncType(Long.class) @FormDataParam("albumId") String albumId, //
@ApiInputOptional @ApiAsyncType(Long.class) @FormDataParam("trackId") String trackId, //
@FormDataParam("file") final InputStream fileInputStream, //
@FormDataParam("file") final FormDataContentDisposition fileMetaData //
) {

View File

@ -2,9 +2,6 @@ package org.kar.karusic.api.UserResourceModel;
import java.util.HashMap;
import org.kar.archidata.annotation.NoWriteSpecificMode;
@NoWriteSpecificMode
public class ModuleAuthorizations extends HashMap<String, PartRight> {
private static final long serialVersionUID = 1L;

View File

@ -2,11 +2,8 @@ package org.kar.karusic.api.UserResourceModel;
import java.util.Map;
import org.kar.archidata.annotation.NoWriteSpecificMode;
import io.swagger.v3.oas.annotations.media.Schema;
@NoWriteSpecificMode
public class UserMe {
public long id;
public String login;

View File

@ -10,6 +10,7 @@ import org.kar.archidata.externalRestApi.TsGenerateApi;
import org.kar.archidata.migration.MigrationSqlStep;
import org.kar.archidata.model.Data;
import org.kar.archidata.model.User;
import org.kar.archidata.model.token.JwtToken;
import org.kar.karusic.api.AlbumResource;
import org.kar.karusic.api.ArtistResource;
import org.kar.karusic.api.Front;
@ -43,6 +44,7 @@ public class Initialization extends MigrationSqlStep {
TrackResource.class, DataResource.class, ProxyResource.class);
final AnalyzeApi api = new AnalyzeApi();
api.addAllApi(listOfResources);
api.addModel(JwtToken.class);
TsGenerateApi.generateApi(api, "../front/src/back-api/");
LOGGER.info("Generate APIs (DONE)");
}

View File

@ -6,6 +6,7 @@ import java.util.List;
import org.bson.types.ObjectId;
import org.kar.archidata.annotation.DataIfNotExists;
import org.kar.archidata.annotation.DataJson;
import org.kar.archidata.annotation.apiGenerator.ApiGenerationMode;
import org.kar.archidata.checker.CheckJPA;
import org.kar.archidata.model.Data;
import org.kar.archidata.model.GenericDataSoftDelete;
@ -22,6 +23,7 @@ import jakarta.persistence.Table;
@Table(name = "album")
@DataIfNotExists
@JsonInclude(JsonInclude.Include.NON_NULL)
@ApiGenerationMode(create = true, update = true)
public class Album extends GenericDataSoftDelete {
public static class AlbumChecker extends CheckJPA<Album> {
public AlbumChecker() {

View File

@ -6,6 +6,7 @@ import java.util.List;
import org.bson.types.ObjectId;
import org.kar.archidata.annotation.DataIfNotExists;
import org.kar.archidata.annotation.DataJson;
import org.kar.archidata.annotation.apiGenerator.ApiGenerationMode;
import org.kar.archidata.checker.CheckJPA;
import org.kar.archidata.model.Data;
import org.kar.archidata.model.GenericDataSoftDelete;
@ -22,6 +23,7 @@ import jakarta.persistence.Table;
@Table(name = "artist")
@DataIfNotExists
@JsonInclude(JsonInclude.Include.NON_NULL)
@ApiGenerationMode(create = true, update = true)
public class Artist extends GenericDataSoftDelete {
public static class ArtistChecker extends CheckJPA<Artist> {
public ArtistChecker() {

View File

@ -17,6 +17,7 @@ import java.util.List;
import org.bson.types.ObjectId;
import org.kar.archidata.annotation.DataIfNotExists;
import org.kar.archidata.annotation.DataJson;
import org.kar.archidata.annotation.apiGenerator.ApiGenerationMode;
import org.kar.archidata.checker.CheckJPA;
import org.kar.archidata.model.Data;
import org.kar.archidata.model.GenericDataSoftDelete;
@ -33,6 +34,7 @@ import jakarta.persistence.Table;
@Table(name = "gender")
@DataIfNotExists
@JsonInclude(JsonInclude.Include.NON_NULL)
@ApiGenerationMode(create = true, update = true)
public class Gender extends GenericDataSoftDelete {
public static class GenderChecker extends CheckJPA<Gender> {
public GenderChecker() {

View File

@ -17,6 +17,7 @@ import java.util.List;
import org.bson.types.ObjectId;
import org.kar.archidata.annotation.DataIfNotExists;
import org.kar.archidata.annotation.DataJson;
import org.kar.archidata.annotation.apiGenerator.ApiGenerationMode;
import org.kar.archidata.checker.CheckJPA;
import org.kar.archidata.model.Data;
import org.kar.archidata.model.GenericDataSoftDelete;
@ -35,6 +36,7 @@ import jakarta.persistence.Table;
@Table(name = "playlist")
@DataIfNotExists
@JsonInclude(JsonInclude.Include.NON_NULL)
@ApiGenerationMode(create = true, update = true)
public class Playlist extends GenericDataSoftDelete {
public static class PlaylistChecker extends CheckJPA<Playlist> {
public PlaylistChecker() {

View File

@ -17,6 +17,7 @@ import java.util.List;
import org.bson.types.ObjectId;
import org.kar.archidata.annotation.DataIfNotExists;
import org.kar.archidata.annotation.DataJson;
import org.kar.archidata.annotation.apiGenerator.ApiGenerationMode;
import org.kar.archidata.checker.CheckJPA;
import org.kar.archidata.model.Data;
import org.kar.archidata.model.GenericDataSoftDelete;
@ -33,6 +34,7 @@ import jakarta.persistence.Table;
@Table(name = "track")
@DataIfNotExists
@JsonInclude(JsonInclude.Include.NON_NULL)
@ApiGenerationMode(create = true, update = true)
public class Track extends GenericDataSoftDelete {
public static class TrackChecker extends CheckJPA<Track> {

View File

@ -13,7 +13,8 @@ import {
import { z as zod } from "zod"
import {
Album,
AlbumWrite,
AlbumCreate,
AlbumUpdate,
Long,
UUID,
ZodAlbum,
@ -87,7 +88,7 @@ export namespace AlbumResource {
params: {
id: Long,
},
data: AlbumWrite,
data: Partial<AlbumUpdate>,
}): Promise<Album> {
return RESTRequestJson({
restModel: {
@ -109,7 +110,7 @@ export namespace AlbumResource {
data,
}: {
restConfig: RESTConfig,
data: AlbumWrite,
data: AlbumCreate,
}): Promise<Album> {
return RESTRequestJson({
restModel: {

View File

@ -13,7 +13,8 @@ import {
import { z as zod } from "zod"
import {
Artist,
ArtistWrite,
ArtistCreate,
ArtistUpdate,
Long,
ObjectId,
ZodArtist,
@ -78,12 +79,12 @@ export namespace ArtistResource {
params: {
id: Long,
},
data: ArtistWrite,
data: ArtistUpdate,
}): Promise<Artist> {
return RESTRequestJson({
restModel: {
endPoint: "/artist/{id}",
requestType: HTTPRequestModel.PATCH,
requestType: HTTPRequestModel.PUT,
contentType: HTTPMimeType.JSON,
accept: HTTPMimeType.JSON,
},
@ -97,7 +98,7 @@ export namespace ArtistResource {
data,
}: {
restConfig: RESTConfig,
data: ArtistWrite,
data: ArtistCreate,
}): Promise<Artist> {
return RESTRequestJson({
restModel: {

View File

@ -22,7 +22,7 @@ export namespace DataResource {
restConfig,
queries,
params,
data,
headers,
}: {
restConfig: RESTConfig,
queries: {
@ -32,7 +32,9 @@ export namespace DataResource {
name: string,
oid: ObjectId,
},
data: string,
headers?: {
Range?: string,
},
}): Promise<object> {
return RESTRequestJson({
restModel: {
@ -42,7 +44,7 @@ export namespace DataResource {
restConfig,
params,
queries,
data,
headers,
});
};
/**
@ -52,7 +54,7 @@ export namespace DataResource {
restConfig,
queries,
params,
data,
headers,
}: {
restConfig: RESTConfig,
queries: {
@ -61,7 +63,9 @@ export namespace DataResource {
params: {
oid: ObjectId,
},
data: string,
headers?: {
Range: string,
},
}): Promise<object> {
return RESTRequestJson({
restModel: {
@ -71,7 +75,7 @@ export namespace DataResource {
restConfig,
params,
queries,
data,
headers,
});
};
/**
@ -81,7 +85,7 @@ export namespace DataResource {
restConfig,
queries,
params,
data,
headers,
}: {
restConfig: RESTConfig,
queries: {
@ -90,7 +94,9 @@ export namespace DataResource {
params: {
oid: ObjectId,
},
data: string,
headers?: {
Range: string,
},
}): Promise<object> {
return RESTRequestJson({
restModel: {
@ -100,7 +106,7 @@ export namespace DataResource {
restConfig,
params,
queries,
data,
headers,
});
};
/**

View File

@ -13,7 +13,8 @@ import {
import { z as zod } from "zod"
import {
Gender,
GenderWrite,
GenderCreate,
GenderUpdate,
Long,
ObjectId,
ZodGender,
@ -78,7 +79,7 @@ export namespace GenderResource {
params: {
id: Long,
},
data: GenderWrite,
data: Partial<GenderUpdate>,
}): Promise<Gender> {
return RESTRequestJson({
restModel: {
@ -97,7 +98,7 @@ export namespace GenderResource {
data,
}: {
restConfig: RESTConfig,
data: GenderWrite,
data: GenderCreate,
}): Promise<Gender> {
return RESTRequestJson({
restModel: {

View File

@ -14,7 +14,8 @@ import {
Long,
ObjectId,
Playlist,
PlaylistWrite,
PlaylistCreate,
PlaylistUpdate,
ZodPlaylist,
isPlaylist,
} from "../model";
@ -98,7 +99,7 @@ export namespace PlaylistResource {
params: {
id: Long,
},
data: PlaylistWrite,
data: Partial<PlaylistUpdate>,
}): Promise<Playlist> {
return RESTRequestJson({
restModel: {
@ -117,7 +118,7 @@ export namespace PlaylistResource {
data,
}: {
restConfig: RESTConfig,
data: PlaylistWrite,
data: PlaylistCreate,
}): Promise<Playlist> {
return RESTRequestJson({
restModel: {

View File

@ -15,7 +15,8 @@ import {
Long,
ObjectId,
Track,
TrackWrite,
TrackCreate,
TrackUpdate,
ZodTrack,
isTrack,
} from "../model";
@ -99,7 +100,7 @@ export namespace TrackResource {
params: {
id: Long,
},
data: TrackWrite,
data: Partial<TrackUpdate>,
}): Promise<Track> {
return RESTRequestJson({
restModel: {
@ -118,7 +119,7 @@ export namespace TrackResource {
data,
}: {
restConfig: RESTConfig,
data: TrackWrite,
data: TrackCreate,
}): Promise<Track> {
return RESTRequestJson({
restModel: {

View File

@ -5,7 +5,7 @@ import { z as zod } from "zod";
import {ZodObjectId} from "./object-id";
import {ZodLocalDate} from "./local-date";
import {ZodGenericDataSoftDelete, ZodGenericDataSoftDeleteWrite } from "./generic-data-soft-delete";
import {ZodGenericDataSoftDelete, ZodGenericDataSoftDeleteUpdate , ZodGenericDataSoftDeleteCreate } from "./generic-data-soft-delete";
export const ZodAlbum = ZodGenericDataSoftDelete.extend({
name: zod.string().optional(),
@ -29,7 +29,7 @@ export function isAlbum(data: any): data is Album {
return false;
}
}
export const ZodAlbumWrite = ZodGenericDataSoftDeleteWrite.extend({
export const ZodAlbumUpdate = ZodGenericDataSoftDeleteUpdate.extend({
name: zod.string().nullable().optional(),
description: zod.string().nullable().optional(),
/**
@ -40,14 +40,36 @@ export const ZodAlbumWrite = ZodGenericDataSoftDeleteWrite.extend({
});
export type AlbumWrite = zod.infer<typeof ZodAlbumWrite>;
export type AlbumUpdate = zod.infer<typeof ZodAlbumUpdate>;
export function isAlbumWrite(data: any): data is AlbumWrite {
export function isAlbumUpdate(data: any): data is AlbumUpdate {
try {
ZodAlbumWrite.parse(data);
ZodAlbumUpdate.parse(data);
return true;
} catch (e: any) {
console.log(`Fail to parse data type='ZodAlbumWrite' error=${e}`);
console.log(`Fail to parse data type='ZodAlbumUpdate' error=${e}`);
return false;
}
}
export const ZodAlbumCreate = ZodGenericDataSoftDeleteCreate.extend({
name: zod.string().nullable().optional(),
description: zod.string().nullable().optional(),
/**
* List of Id of the specific covers
*/
covers: zod.array(ZodObjectId).nullable().optional(),
publication: ZodLocalDate.nullable().optional(),
});
export type AlbumCreate = zod.infer<typeof ZodAlbumCreate>;
export function isAlbumCreate(data: any): data is AlbumCreate {
try {
ZodAlbumCreate.parse(data);
return true;
} catch (e: any) {
console.log(`Fail to parse data type='ZodAlbumCreate' error=${e}`);
return false;
}
}

View File

@ -5,7 +5,7 @@ import { z as zod } from "zod";
import {ZodObjectId} from "./object-id";
import {ZodLocalDate} from "./local-date";
import {ZodGenericDataSoftDelete, ZodGenericDataSoftDeleteWrite } from "./generic-data-soft-delete";
import {ZodGenericDataSoftDelete, ZodGenericDataSoftDeleteUpdate , ZodGenericDataSoftDeleteCreate } from "./generic-data-soft-delete";
export const ZodArtist = ZodGenericDataSoftDelete.extend({
name: zod.string().optional(),
@ -32,7 +32,7 @@ export function isArtist(data: any): data is Artist {
return false;
}
}
export const ZodArtistWrite = ZodGenericDataSoftDeleteWrite.extend({
export const ZodArtistUpdate = ZodGenericDataSoftDeleteUpdate.extend({
name: zod.string().nullable().optional(),
description: zod.string().nullable().optional(),
/**
@ -46,14 +46,39 @@ export const ZodArtistWrite = ZodGenericDataSoftDeleteWrite.extend({
});
export type ArtistWrite = zod.infer<typeof ZodArtistWrite>;
export type ArtistUpdate = zod.infer<typeof ZodArtistUpdate>;
export function isArtistWrite(data: any): data is ArtistWrite {
export function isArtistUpdate(data: any): data is ArtistUpdate {
try {
ZodArtistWrite.parse(data);
ZodArtistUpdate.parse(data);
return true;
} catch (e: any) {
console.log(`Fail to parse data type='ZodArtistWrite' error=${e}`);
console.log(`Fail to parse data type='ZodArtistUpdate' error=${e}`);
return false;
}
}
export const ZodArtistCreate = ZodGenericDataSoftDeleteCreate.extend({
name: zod.string().nullable().optional(),
description: zod.string().nullable().optional(),
/**
* List of Id of the specific covers
*/
covers: zod.array(ZodObjectId).nullable().optional(),
firstName: zod.string().nullable().optional(),
surname: zod.string().nullable().optional(),
birth: ZodLocalDate.nullable().optional(),
death: ZodLocalDate.nullable().optional(),
});
export type ArtistCreate = zod.infer<typeof ZodArtistCreate>;
export function isArtistCreate(data: any): data is ArtistCreate {
try {
ZodArtistCreate.parse(data);
return true;
} catch (e: any) {
console.log(`Fail to parse data type='ZodArtistCreate' error=${e}`);
return false;
}
}

View File

@ -4,7 +4,7 @@
import { z as zod } from "zod";
import {ZodObjectId} from "./object-id";
import {ZodGenericDataSoftDelete, ZodGenericDataSoftDeleteWrite } from "./generic-data-soft-delete";
import {ZodGenericDataSoftDelete, ZodGenericDataSoftDeleteUpdate , ZodGenericDataSoftDeleteCreate } from "./generic-data-soft-delete";
export const ZodGender = ZodGenericDataSoftDelete.extend({
name: zod.string().optional(),
@ -27,7 +27,7 @@ export function isGender(data: any): data is Gender {
return false;
}
}
export const ZodGenderWrite = ZodGenericDataSoftDeleteWrite.extend({
export const ZodGenderUpdate = ZodGenericDataSoftDeleteUpdate.extend({
name: zod.string().nullable().optional(),
description: zod.string().nullable().optional(),
/**
@ -37,14 +37,35 @@ export const ZodGenderWrite = ZodGenericDataSoftDeleteWrite.extend({
});
export type GenderWrite = zod.infer<typeof ZodGenderWrite>;
export type GenderUpdate = zod.infer<typeof ZodGenderUpdate>;
export function isGenderWrite(data: any): data is GenderWrite {
export function isGenderUpdate(data: any): data is GenderUpdate {
try {
ZodGenderWrite.parse(data);
ZodGenderUpdate.parse(data);
return true;
} catch (e: any) {
console.log(`Fail to parse data type='ZodGenderWrite' error=${e}`);
console.log(`Fail to parse data type='ZodGenderUpdate' error=${e}`);
return false;
}
}
export const ZodGenderCreate = ZodGenericDataSoftDeleteCreate.extend({
name: zod.string().nullable().optional(),
description: zod.string().nullable().optional(),
/**
* List of Id of the specific covers
*/
covers: zod.array(ZodObjectId).nullable().optional(),
});
export type GenderCreate = zod.infer<typeof ZodGenderCreate>;
export function isGenderCreate(data: any): data is GenderCreate {
try {
ZodGenderCreate.parse(data);
return true;
} catch (e: any) {
console.log(`Fail to parse data type='ZodGenderCreate' error=${e}`);
return false;
}
}

View File

@ -3,7 +3,7 @@
*/
import { z as zod } from "zod";
import {ZodGenericData, ZodGenericDataWrite } from "./generic-data";
import {ZodGenericData, ZodGenericDataUpdate , ZodGenericDataCreate } from "./generic-data";
export const ZodGenericDataSoftDelete = ZodGenericData.extend({
/**
@ -24,16 +24,29 @@ export function isGenericDataSoftDelete(data: any): data is GenericDataSoftDelet
return false;
}
}
export const ZodGenericDataSoftDeleteWrite = ZodGenericDataWrite;
export const ZodGenericDataSoftDeleteUpdate = ZodGenericDataUpdate;
export type GenericDataSoftDeleteWrite = zod.infer<typeof ZodGenericDataSoftDeleteWrite>;
export type GenericDataSoftDeleteUpdate = zod.infer<typeof ZodGenericDataSoftDeleteUpdate>;
export function isGenericDataSoftDeleteWrite(data: any): data is GenericDataSoftDeleteWrite {
export function isGenericDataSoftDeleteUpdate(data: any): data is GenericDataSoftDeleteUpdate {
try {
ZodGenericDataSoftDeleteWrite.parse(data);
ZodGenericDataSoftDeleteUpdate.parse(data);
return true;
} catch (e: any) {
console.log(`Fail to parse data type='ZodGenericDataSoftDeleteWrite' error=${e}`);
console.log(`Fail to parse data type='ZodGenericDataSoftDeleteUpdate' error=${e}`);
return false;
}
}
export const ZodGenericDataSoftDeleteCreate = ZodGenericDataCreate;
export type GenericDataSoftDeleteCreate = zod.infer<typeof ZodGenericDataSoftDeleteCreate>;
export function isGenericDataSoftDeleteCreate(data: any): data is GenericDataSoftDeleteCreate {
try {
ZodGenericDataSoftDeleteCreate.parse(data);
return true;
} catch (e: any) {
console.log(`Fail to parse data type='ZodGenericDataSoftDeleteCreate' error=${e}`);
return false;
}
}

View File

@ -4,7 +4,7 @@
import { z as zod } from "zod";
import {ZodLong} from "./long";
import {ZodGenericTiming, ZodGenericTimingWrite } from "./generic-timing";
import {ZodGenericTiming, ZodGenericTimingUpdate , ZodGenericTimingCreate } from "./generic-timing";
export const ZodGenericData = ZodGenericTiming.extend({
/**
@ -25,16 +25,29 @@ export function isGenericData(data: any): data is GenericData {
return false;
}
}
export const ZodGenericDataWrite = ZodGenericTimingWrite;
export const ZodGenericDataUpdate = ZodGenericTimingUpdate;
export type GenericDataWrite = zod.infer<typeof ZodGenericDataWrite>;
export type GenericDataUpdate = zod.infer<typeof ZodGenericDataUpdate>;
export function isGenericDataWrite(data: any): data is GenericDataWrite {
export function isGenericDataUpdate(data: any): data is GenericDataUpdate {
try {
ZodGenericDataWrite.parse(data);
ZodGenericDataUpdate.parse(data);
return true;
} catch (e: any) {
console.log(`Fail to parse data type='ZodGenericDataWrite' error=${e}`);
console.log(`Fail to parse data type='ZodGenericDataUpdate' error=${e}`);
return false;
}
}
export const ZodGenericDataCreate = ZodGenericTimingCreate;
export type GenericDataCreate = zod.infer<typeof ZodGenericDataCreate>;
export function isGenericDataCreate(data: any): data is GenericDataCreate {
try {
ZodGenericDataCreate.parse(data);
return true;
} catch (e: any) {
console.log(`Fail to parse data type='ZodGenericDataCreate' error=${e}`);
return false;
}
}

View File

@ -28,18 +28,33 @@ export function isGenericTiming(data: any): data is GenericTiming {
return false;
}
}
export const ZodGenericTimingWrite = zod.object({
export const ZodGenericTimingUpdate = zod.object({
});
export type GenericTimingWrite = zod.infer<typeof ZodGenericTimingWrite>;
export type GenericTimingUpdate = zod.infer<typeof ZodGenericTimingUpdate>;
export function isGenericTimingWrite(data: any): data is GenericTimingWrite {
export function isGenericTimingUpdate(data: any): data is GenericTimingUpdate {
try {
ZodGenericTimingWrite.parse(data);
ZodGenericTimingUpdate.parse(data);
return true;
} catch (e: any) {
console.log(`Fail to parse data type='ZodGenericTimingWrite' error=${e}`);
console.log(`Fail to parse data type='ZodGenericTimingUpdate' error=${e}`);
return false;
}
}
export const ZodGenericTimingCreate = zod.object({
});
export type GenericTimingCreate = zod.infer<typeof ZodGenericTimingCreate>;
export function isGenericTimingCreate(data: any): data is GenericTimingCreate {
try {
ZodGenericTimingCreate.parse(data);
return true;
} catch (e: any) {
console.log(`Fail to parse data type='ZodGenericTimingCreate' error=${e}`);
return false;
}
}

View File

@ -19,18 +19,3 @@ export function isHealthResult(data: any): data is HealthResult {
return false;
}
}
export const ZodHealthResultWrite = zod.object({
});
export type HealthResultWrite = zod.infer<typeof ZodHealthResultWrite>;
export function isHealthResultWrite(data: any): data is HealthResultWrite {
try {
ZodHealthResultWrite.parse(data);
return true;
} catch (e: any) {
console.log(`Fail to parse data type='ZodHealthResultWrite' error=${e}`);
return false;
}
}

View File

@ -10,12 +10,16 @@ export * from "./generic-timing"
export * from "./health-result"
export * from "./integer"
export * from "./iso-date"
export * from "./jwt-header"
export * from "./jwt-payload"
export * from "./jwt-token"
export * from "./local-date"
export * from "./long"
export * from "./object-id"
export * from "./part-right"
export * from "./playlist"
export * from "./rest-error-response"
export * from "./rest-input-error"
export * from "./timestamp"
export * from "./track"
export * from "./user"

View File

@ -0,0 +1,23 @@
/**
* Interface of the server (auto-generated code)
*/
import { z as zod } from "zod";
export const ZodJwtHeader = zod.object({
typ: zod.string().max(128),
alg: zod.string().max(128),
});
export type JwtHeader = zod.infer<typeof ZodJwtHeader>;
export function isJwtHeader(data: any): data is JwtHeader {
try {
ZodJwtHeader.parse(data);
return true;
} catch (e: any) {
console.log(`Fail to parse data type='ZodJwtHeader' error=${e}`);
return false;
}
}

View File

@ -0,0 +1,29 @@
/**
* Interface of the server (auto-generated code)
*/
import { z as zod } from "zod";
import {ZodLong} from "./long";
export const ZodJwtPayload = zod.object({
sub: zod.string(),
application: zod.string(),
iss: zod.string(),
right: zod.record(zod.string(), zod.record(zod.string(), ZodLong)),
login: zod.string(),
exp: ZodLong,
iat: ZodLong,
});
export type JwtPayload = zod.infer<typeof ZodJwtPayload>;
export function isJwtPayload(data: any): data is JwtPayload {
try {
ZodJwtPayload.parse(data);
return true;
} catch (e: any) {
console.log(`Fail to parse data type='ZodJwtPayload' error=${e}`);
return false;
}
}

View File

@ -0,0 +1,26 @@
/**
* Interface of the server (auto-generated code)
*/
import { z as zod } from "zod";
import {ZodJwtHeader} from "./jwt-header";
import {ZodJwtPayload} from "./jwt-payload";
export const ZodJwtToken = zod.object({
header: ZodJwtHeader,
payload: ZodJwtPayload,
signature: zod.string(),
});
export type JwtToken = zod.infer<typeof ZodJwtToken>;
export function isJwtToken(data: any): data is JwtToken {
try {
ZodJwtToken.parse(data);
return true;
} catch (e: any) {
console.log(`Fail to parse data type='ZodJwtToken' error=${e}`);
return false;
}
}

View File

@ -4,7 +4,7 @@
import { z as zod } from "zod";
import {ZodObjectId} from "./object-id";
import {ZodGenericDataSoftDelete, ZodGenericDataSoftDeleteWrite } from "./generic-data-soft-delete";
import {ZodGenericDataSoftDelete, ZodGenericDataSoftDeleteUpdate , ZodGenericDataSoftDeleteCreate } from "./generic-data-soft-delete";
export const ZodPlaylist = ZodGenericDataSoftDelete.extend({
name: zod.string().optional(),
@ -28,25 +28,47 @@ export function isPlaylist(data: any): data is Playlist {
return false;
}
}
export const ZodPlaylistWrite = ZodGenericDataSoftDeleteWrite.extend({
export const ZodPlaylistUpdate = ZodGenericDataSoftDeleteUpdate.extend({
name: zod.string().nullable().optional(),
description: zod.string().nullable().optional(),
/**
* List of Id of the specific covers
*/
covers: zod.array(ZodObjectId).nullable().optional(),
tracks: zod.array(ZodObjectId).optional(),
tracks: zod.array(ZodObjectId),
});
export type PlaylistWrite = zod.infer<typeof ZodPlaylistWrite>;
export type PlaylistUpdate = zod.infer<typeof ZodPlaylistUpdate>;
export function isPlaylistWrite(data: any): data is PlaylistWrite {
export function isPlaylistUpdate(data: any): data is PlaylistUpdate {
try {
ZodPlaylistWrite.parse(data);
ZodPlaylistUpdate.parse(data);
return true;
} catch (e: any) {
console.log(`Fail to parse data type='ZodPlaylistWrite' error=${e}`);
console.log(`Fail to parse data type='ZodPlaylistUpdate' error=${e}`);
return false;
}
}
export const ZodPlaylistCreate = ZodGenericDataSoftDeleteCreate.extend({
name: zod.string().nullable().optional(),
description: zod.string().nullable().optional(),
/**
* List of Id of the specific covers
*/
covers: zod.array(ZodObjectId).nullable().optional(),
tracks: zod.array(ZodObjectId),
});
export type PlaylistCreate = zod.infer<typeof ZodPlaylistCreate>;
export function isPlaylistCreate(data: any): data is PlaylistCreate {
try {
ZodPlaylistCreate.parse(data);
return true;
} catch (e: any) {
console.log(`Fail to parse data type='ZodPlaylistCreate' error=${e}`);
return false;
}
}

View File

@ -5,6 +5,7 @@ import { z as zod } from "zod";
import {ZodObjectId} from "./object-id";
import {ZodInteger} from "./integer";
import {ZodRestInputError} from "./rest-input-error";
export const ZodRestErrorResponse = zod.object({
oid: ZodObjectId.optional(),
@ -13,6 +14,7 @@ export const ZodRestErrorResponse = zod.object({
time: zod.string(),
status: ZodInteger,
statusMessage: zod.string(),
inputError: zod.array(ZodRestInputError).optional(),
});

View File

@ -0,0 +1,24 @@
/**
* Interface of the server (auto-generated code)
*/
import { z as zod } from "zod";
export const ZodRestInputError = zod.object({
argument: zod.string().optional(),
path: zod.string().optional(),
message: zod.string(),
});
export type RestInputError = zod.infer<typeof ZodRestInputError>;
export function isRestInputError(data: any): data is RestInputError {
try {
ZodRestInputError.parse(data);
return true;
} catch (e: any) {
console.log(`Fail to parse data type='ZodRestInputError' error=${e}`);
return false;
}
}

View File

@ -5,7 +5,7 @@ import { z as zod } from "zod";
import {ZodObjectId} from "./object-id";
import {ZodLong} from "./long";
import {ZodGenericDataSoftDelete, ZodGenericDataSoftDeleteWrite } from "./generic-data-soft-delete";
import {ZodGenericDataSoftDelete, ZodGenericDataSoftDeleteUpdate , ZodGenericDataSoftDeleteCreate } from "./generic-data-soft-delete";
export const ZodTrack = ZodGenericDataSoftDelete.extend({
name: zod.string().optional(),
@ -33,7 +33,7 @@ export function isTrack(data: any): data is Track {
return false;
}
}
export const ZodTrackWrite = ZodGenericDataSoftDeleteWrite.extend({
export const ZodTrackUpdate = ZodGenericDataSoftDeleteUpdate.extend({
name: zod.string().nullable().optional(),
description: zod.string().nullable().optional(),
/**
@ -44,18 +44,44 @@ export const ZodTrackWrite = ZodGenericDataSoftDeleteWrite.extend({
albumId: ZodLong.nullable().optional(),
track: ZodLong.nullable().optional(),
dataId: ZodObjectId.nullable().optional(),
artists: zod.array(ZodLong).optional(),
artists: zod.array(ZodLong),
});
export type TrackWrite = zod.infer<typeof ZodTrackWrite>;
export type TrackUpdate = zod.infer<typeof ZodTrackUpdate>;
export function isTrackWrite(data: any): data is TrackWrite {
export function isTrackUpdate(data: any): data is TrackUpdate {
try {
ZodTrackWrite.parse(data);
ZodTrackUpdate.parse(data);
return true;
} catch (e: any) {
console.log(`Fail to parse data type='ZodTrackWrite' error=${e}`);
console.log(`Fail to parse data type='ZodTrackUpdate' error=${e}`);
return false;
}
}
export const ZodTrackCreate = ZodGenericDataSoftDeleteCreate.extend({
name: zod.string().nullable().optional(),
description: zod.string().nullable().optional(),
/**
* List of Id of the specific covers
*/
covers: zod.array(ZodObjectId).nullable().optional(),
genderId: ZodLong.nullable().optional(),
albumId: ZodLong.nullable().optional(),
track: ZodLong.nullable().optional(),
dataId: ZodObjectId.nullable().optional(),
artists: zod.array(ZodLong),
});
export type TrackCreate = zod.infer<typeof ZodTrackCreate>;
export function isTrackCreate(data: any): data is TrackCreate {
try {
ZodTrackCreate.parse(data);
return true;
} catch (e: any) {
console.log(`Fail to parse data type='ZodTrackCreate' error=${e}`);
return false;
}
}

View File

@ -3,7 +3,7 @@
*/
import { z as zod } from "zod";
import {ZodUser, ZodUserWrite } from "./user";
import {ZodUser, ZodUserUpdate , ZodUserCreate } from "./user";
export const ZodUserKarusic = ZodUser;
@ -18,16 +18,3 @@ export function isUserKarusic(data: any): data is UserKarusic {
return false;
}
}
export const ZodUserKarusicWrite = ZodUserWrite;
export type UserKarusicWrite = zod.infer<typeof ZodUserKarusicWrite>;
export function isUserKarusicWrite(data: any): data is UserKarusicWrite {
try {
ZodUserKarusicWrite.parse(data);
return true;
} catch (e: any) {
console.log(`Fail to parse data type='ZodUserKarusicWrite' error=${e}`);
return false;
}
}

View File

@ -5,7 +5,7 @@ import { z as zod } from "zod";
import {ZodTimestamp} from "./timestamp";
import {ZodUUID} from "./uuid";
import {ZodGenericDataSoftDelete, ZodGenericDataSoftDeleteWrite } from "./generic-data-soft-delete";
import {ZodGenericDataSoftDelete, ZodGenericDataSoftDeleteUpdate , ZodGenericDataSoftDeleteCreate } from "./generic-data-soft-delete";
export const ZodUser = ZodGenericDataSoftDelete.extend({
login: zod.string().min(3).max(128),
@ -30,8 +30,8 @@ export function isUser(data: any): data is User {
return false;
}
}
export const ZodUserWrite = ZodGenericDataSoftDeleteWrite.extend({
login: zod.string().min(3).max(128).optional(),
export const ZodUserUpdate = ZodGenericDataSoftDeleteUpdate.extend({
login: zod.string().min(3).max(128),
lastConnection: ZodTimestamp.nullable().optional(),
blocked: zod.boolean().nullable().optional(),
blockedReason: zod.string().max(512).nullable().optional(),
@ -42,14 +42,37 @@ export const ZodUserWrite = ZodGenericDataSoftDeleteWrite.extend({
});
export type UserWrite = zod.infer<typeof ZodUserWrite>;
export type UserUpdate = zod.infer<typeof ZodUserUpdate>;
export function isUserWrite(data: any): data is UserWrite {
export function isUserUpdate(data: any): data is UserUpdate {
try {
ZodUserWrite.parse(data);
ZodUserUpdate.parse(data);
return true;
} catch (e: any) {
console.log(`Fail to parse data type='ZodUserWrite' error=${e}`);
console.log(`Fail to parse data type='ZodUserUpdate' error=${e}`);
return false;
}
}
export const ZodUserCreate = ZodGenericDataSoftDeleteCreate.extend({
login: zod.string().min(3).max(128),
lastConnection: ZodTimestamp.nullable().optional(),
blocked: zod.boolean().nullable().optional(),
blockedReason: zod.string().max(512).nullable().optional(),
/**
* List of Id of the specific covers
*/
covers: zod.array(ZodUUID).nullable().optional(),
});
export type UserCreate = zod.infer<typeof ZodUserCreate>;
export function isUserCreate(data: any): data is UserCreate {
try {
ZodUserCreate.parse(data);
return true;
} catch (e: any) {
console.log(`Fail to parse data type='ZodUserCreate' error=${e}`);
return false;
}
}

View File

@ -3,30 +3,29 @@
* @copyright 2024, Edouard DUPIN, all right reserved
* @license MPL-2
*/
import { RestErrorResponse, isRestErrorResponse } from "./model";
import { RestErrorResponse, isRestErrorResponse } from './model';
export enum HTTPRequestModel {
ARCHIVE = "ARCHIVE",
DELETE = "DELETE",
HEAD = "HEAD",
GET = "GET",
OPTION = "OPTION",
PATCH = "PATCH",
POST = "POST",
PUT = "PUT",
RESTORE = "RESTORE",
ARCHIVE = 'ARCHIVE',
DELETE = 'DELETE',
HEAD = 'HEAD',
GET = 'GET',
OPTION = 'OPTION',
PATCH = 'PATCH',
POST = 'POST',
PUT = 'PUT',
RESTORE = 'RESTORE',
}
export enum HTTPMimeType {
ALL = "*/*",
CSV = "text/csv",
IMAGE = "image/*",
IMAGE_JPEG = "image/jpeg",
IMAGE_PNG = "image/png",
JSON = "application/json",
MULTIPART = "multipart/form-data",
OCTET_STREAM = "application/octet-stream",
TEXT_PLAIN = "text/plain",
ALL = '*/*',
CSV = 'text/csv',
IMAGE = 'image/*',
IMAGE_JPEG = 'image/jpeg',
IMAGE_PNG = 'image/png',
JSON = 'application/json',
MULTIPART = 'multipart/form-data',
OCTET_STREAM = 'application/octet-stream',
TEXT_PLAIN = 'text/plain',
}
export interface RESTConfig {
@ -54,6 +53,14 @@ export interface ModelResponseHttp {
data: any;
}
export type ErrorRestApiCallback = (response: Response) => void;
let errorApiGlobalCallback: ErrorRestApiCallback | undefined = undefined;
export const setErrorApiGlobalCallback = (callback: ErrorRestApiCallback) => {
errorApiGlobalCallback = callback;
};
function isNullOrUndefined(data: any): data is undefined | null {
return data === undefined || data === null;
}
@ -78,6 +85,7 @@ export interface RESTRequestType {
data?: any;
params?: object;
queries?: object;
headers?: any;
callbacks?: RESTCallbacks;
}
@ -87,15 +95,15 @@ function replaceAll(input, searchValue, replaceValue) {
function removeTrailingSlashes(input: string): string {
if (isNullOrUndefined(input)) {
return "undefined";
return 'undefined';
}
return input.replace(/\/+$/, "");
return input.replace(/\/+$/, '');
}
function removeLeadingSlashes(input: string): string {
if (isNullOrUndefined(input)) {
return "";
return '';
}
return input.replace(/^\/+/, "");
return input.replace(/^\/+/, '');
}
export function RESTUrl({
@ -133,9 +141,9 @@ export function RESTUrl({
}
}
if (restConfig.token !== undefined && restModel.tokenInUrl === true) {
searchParams.append("Authorization", `Bearer ${restConfig.token}`);
searchParams.append('Authorization', `Bearer ${restConfig.token}`);
}
return generateUrl + "?" + searchParams.toString();
return generateUrl + '?' + searchParams.toString();
}
export function fetchProgress(
@ -159,7 +167,7 @@ export function fetchProgress(
return new Promise((resolve, reject) => {
// Stream the upload progress
if (progressUpload) {
xhr.io?.upload.addEventListener("progress", (dataEvent) => {
xhr.io?.upload.addEventListener('progress', (dataEvent) => {
if (dataEvent.lengthComputable) {
progressUpload(dataEvent.loaded, dataEvent.total);
}
@ -167,7 +175,7 @@ export function fetchProgress(
}
// Stream the download progress
if (progressDownload) {
xhr.io?.addEventListener("progress", (dataEvent) => {
xhr.io?.addEventListener('progress', (dataEvent) => {
if (dataEvent.lengthComputable) {
progressDownload(dataEvent.loaded, dataEvent.total);
}
@ -187,19 +195,19 @@ export function fetchProgress(
};
}
// Check if we have an internal Fail:
xhr.io?.addEventListener("error", () => {
xhr.io?.addEventListener('error', () => {
xhr.io = undefined;
reject(new TypeError("Failed to fetch"));
reject(new TypeError('Failed to fetch'));
});
// Capture the end of the stream
xhr.io?.addEventListener("loadend", () => {
xhr.io?.addEventListener('loadend', () => {
if (xhr.io?.readyState !== XMLHttpRequest.DONE) {
return;
}
if (xhr.io?.status === 0) {
//the stream has been aborted
reject(new TypeError("Fetch has been aborted"));
reject(new TypeError('Fetch has been aborted'));
return;
}
// Stream is ended, transform in a generic response:
@ -209,17 +217,17 @@ export function fetchProgress(
});
const headersArray = replaceAll(
xhr.io.getAllResponseHeaders().trim(),
"\r\n",
"\n"
).split("\n");
'\r\n',
'\n'
).split('\n');
headersArray.forEach(function (header) {
const firstColonIndex = header.indexOf(":");
const firstColonIndex = header.indexOf(':');
if (firstColonIndex !== -1) {
const key = header.substring(0, firstColonIndex).trim();
const value = header.substring(firstColonIndex + 1).trim();
response.headers.set(key, value);
} else {
response.headers.set(header, "");
response.headers.set(header, '');
}
});
xhr.io = undefined;
@ -241,27 +249,29 @@ export function RESTRequest({
data,
params,
queries,
headers = {},
callbacks,
}: RESTRequestType): Promise<ModelResponseHttp> {
// Create the URL PATH:
let generateUrl = RESTUrl({ restModel, restConfig, data, params, queries });
let headers: any = {};
if (restConfig.token !== undefined && restModel.tokenInUrl !== true) {
headers["Authorization"] = `Bearer ${restConfig.token}`;
headers['Authorization'] = `Bearer ${restConfig.token}`;
}
if (restModel.accept !== undefined) {
headers["Accept"] = restModel.accept;
headers['Accept'] = restModel.accept;
}
if (restModel.requestType !== HTTPRequestModel.GET &&
restModel.requestType !== HTTPRequestModel.ARCHIVE &&
restModel.requestType !== HTTPRequestModel.RESTORE
if (
restModel.requestType !== HTTPRequestModel.GET &&
restModel.requestType !== HTTPRequestModel.ARCHIVE &&
restModel.requestType !== HTTPRequestModel.RESTORE
) {
// if Get we have not a content type, the body is empty
if (restModel.contentType !== HTTPMimeType.MULTIPART &&
restModel.contentType !== undefined
) {
if (
restModel.contentType !== HTTPMimeType.MULTIPART &&
restModel.contentType !== undefined
) {
// special case of multi-part ==> no content type otherwise the browser does not set the ";bundary=--****"
headers["Content-Type"] = restModel.contentType;
headers['Content-Type'] = restModel.contentType;
}
}
let body = data;
@ -302,19 +312,27 @@ export function RESTRequest({
}
action
.then((response: Response) => {
if (
errorApiGlobalCallback &&
400 <= response.status &&
response.status <= 499
) {
// Detect an error and trigger the generic error callback:
errorApiGlobalCallback(response);
}
if (response.status >= 200 && response.status <= 299) {
const contentType = response.headers.get("Content-Type");
const contentType = response.headers.get('Content-Type');
if (
!isNullOrUndefined(restModel.accept) &&
restModel.accept !== contentType
) {
reject({
name: "Model accept type incompatible",
name: 'Model accept type incompatible',
time: Date().toString(),
status: 901,
message: `REST Content type are not compatible: ${restModel.accept} != ${contentType}`,
statusMessage: "Fetch error",
error: "rest-tools.ts Wrong type in the message return type",
statusMessage: 'Fetch error',
error: 'rest-tools.ts Wrong type in the message return type',
} as RestErrorResponse);
} else if (contentType === HTTPMimeType.JSON) {
response
@ -324,12 +342,12 @@ export function RESTRequest({
})
.catch((reason: Error) => {
reject({
name: "API serialization error",
name: 'API serialization error',
time: Date().toString(),
status: 902,
message: `REST parse json fail: ${reason}`,
statusMessage: "Fetch parse error",
error: "rest-tools.ts Wrong message model to parse",
statusMessage: 'Fetch parse error',
error: 'rest-tools.ts Wrong message model to parse',
} as RestErrorResponse);
});
} else {
@ -349,22 +367,22 @@ export function RESTRequest({
.text()
.then((dataError: string) => {
reject({
name: "API serialization error",
name: 'API serialization error',
time: Date().toString(),
status: 903,
message: `REST parse error json with wrong type fail. ${dataError}`,
statusMessage: "Fetch parse error",
error: "rest-tools.ts Wrong message model to parse",
statusMessage: 'Fetch parse error',
error: 'rest-tools.ts Wrong message model to parse',
} as RestErrorResponse);
})
.catch((reason: any) => {
reject({
name: "API serialization error",
name: 'API serialization error',
time: Date().toString(),
status: response.status,
message: `unmanaged error model: ??? with error: ${reason}`,
statusMessage: "Fetch ERROR parse error",
error: "rest-tools.ts Wrong message model to parse",
statusMessage: 'Fetch ERROR parse error',
error: 'rest-tools.ts Wrong message model to parse',
} as RestErrorResponse);
});
}
@ -374,22 +392,22 @@ export function RESTRequest({
.text()
.then((dataError: string) => {
reject({
name: "API serialization error",
name: 'API serialization error',
time: Date().toString(),
status: response.status,
message: `unmanaged error model: ${dataError} with error: ${reason}`,
statusMessage: "Fetch ERROR TEXT parse error",
error: "rest-tools.ts Wrong message model to parse",
statusMessage: 'Fetch ERROR TEXT parse error',
error: 'rest-tools.ts Wrong message model to parse',
} as RestErrorResponse);
})
.catch((reason: any) => {
reject({
name: "API serialization error",
name: 'API serialization error',
time: Date().toString(),
status: response.status,
message: `unmanaged error model: ??? with error: ${reason}`,
statusMessage: "Fetch ERROR TEXT FAIL",
error: "rest-tools.ts Wrong message model to parse",
statusMessage: 'Fetch ERROR TEXT FAIL',
error: 'rest-tools.ts Wrong message model to parse',
} as RestErrorResponse);
});
});
@ -400,12 +418,12 @@ export function RESTRequest({
reject(error);
} else {
reject({
name: "Request fail",
name: 'Request fail',
time: Date(),
status: 999,
message: error,
statusMessage: "Fetch catch error",
error: "rest-tools.ts detect an error in the fetch request",
statusMessage: 'Fetch catch error',
error: 'rest-tools.ts detect an error in the fetch request',
});
}
});
@ -426,12 +444,12 @@ export function RESTRequestJson<TYPE>(
resolve(value.data);
} else {
reject({
name: "Model check fail",
name: 'Model check fail',
time: Date().toString(),
status: 950,
error: "REST Fail to verify the data",
statusMessage: "API cast ERROR",
message: "api.ts Check type as fail",
error: 'REST Fail to verify the data',
statusMessage: 'API cast ERROR',
message: 'api.ts Check type as fail',
} as RestErrorResponse);
}
})