firstly 0.1.2 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +25 -0
- package/esm/auth/Entities.js +2 -2
- package/esm/auth/server/helperRole.js +5 -2
- package/esm/auth/static/assets/Page-C1pM-UDt.js +2 -2
- package/esm/bin/cmd.js +1 -1
- package/esm/carbone/CarboneController.d.ts +35 -0
- package/esm/carbone/CarboneController.js +155 -0
- package/esm/carbone/Roles_Carbon.d.ts +8 -0
- package/esm/carbone/Roles_Carbon.js +8 -0
- package/esm/carbone/carboneEntities.d.ts +21 -0
- package/esm/carbone/carboneEntities.js +83 -0
- package/esm/carbone/index.d.ts +29 -0
- package/esm/carbone/index.js +68 -0
- package/esm/carbone/server/CarboneServer.d.ts +19 -0
- package/esm/carbone/server/CarboneServer.js +38 -0
- package/esm/carbone/server/index.d.ts +7 -0
- package/esm/carbone/server/index.js +23 -0
- package/esm/changeLog/changeLogEntities.js +1 -1
- package/esm/changeLog/index.d.ts +37 -1
- package/esm/changeLog/index.js +28 -0
- package/esm/changeLog/server/index.d.ts +17 -28
- package/esm/changeLog/server/index.js +17 -28
- package/esm/cron/Cron.js +1 -1
- package/esm/index.d.ts +5 -3
- package/esm/index.js +5 -3
- package/esm/internals/FF_Entity.js +4 -27
- package/esm/internals/FF_Fields.d.ts +3 -2
- package/esm/internals/FF_Fields.js +13 -9
- package/esm/internals/index.d.ts +1 -1
- package/esm/mail/Mail.js +1 -1
- package/esm/svelte/FF_Cell.svelte +1 -0
- package/esm/svelte/FF_Cell.svelte.d.ts +10 -3
- package/esm/svelte/FF_Cell_Caption.svelte.d.ts +10 -3
- package/esm/svelte/FF_Cell_Display.svelte.d.ts +10 -3
- package/esm/svelte/FF_Cell_Edit.svelte.d.ts +11 -4
- package/esm/svelte/FF_Cell_Error.svelte.d.ts +10 -3
- package/esm/svelte/FF_Cell_Hint.svelte.d.ts +10 -3
- package/esm/svelte/FF_Display.svelte.d.ts +10 -3
- package/esm/svelte/FF_Edit.svelte.d.ts +11 -4
- package/esm/svelte/FF_Error.svelte.d.ts +10 -3
- package/esm/svelte/FF_Field.svelte.d.ts +10 -3
- package/esm/svelte/FF_Form.svelte.d.ts +10 -3
- package/esm/svelte/FF_Grid.svelte +1 -1
- package/esm/svelte/FF_Grid.svelte.d.ts +10 -4
- package/esm/svelte/FF_Hint.svelte.d.ts +10 -3
- package/esm/svelte/FF_Label.svelte.d.ts +10 -3
- package/esm/svelte/FF_Layout.svelte.d.ts +10 -3
- package/esm/ui/Button.svelte +0 -1
- package/esm/ui/Field.svelte +19 -2
- package/esm/ui/LibIcon.d.ts +2 -0
- package/esm/ui/LibIcon.js +3 -1
- package/esm/ui/dialog/DialogPrimitive.svelte +1 -1
- package/esm/ui/internals/select/SelectMelt.svelte +22 -25
- package/esm/virtual/Customer.js +1 -1
- package/esm/virtual/UIEntity.js +1 -1
- package/package.json +11 -3
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var CarbonLogAction_1;
|
|
8
|
+
import { Entity, Field, Fields, remult, ValueListFieldType } from 'remult';
|
|
9
|
+
import { Roles_Carbon } from './Roles_Carbon';
|
|
10
|
+
let CarbonLogAction = class CarbonLogAction {
|
|
11
|
+
static { CarbonLogAction_1 = this; }
|
|
12
|
+
id;
|
|
13
|
+
static template_upload = new CarbonLogAction_1('TEMPLATE_UPLOAD');
|
|
14
|
+
static template_download = new CarbonLogAction_1('TEMPLATE_DOWNLOAD');
|
|
15
|
+
static template_delete = new CarbonLogAction_1('TEMPLATE_DELETE');
|
|
16
|
+
static render = new CarbonLogAction_1('RENDER');
|
|
17
|
+
constructor(id) {
|
|
18
|
+
this.id = id;
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
CarbonLogAction = CarbonLogAction_1 = __decorate([
|
|
22
|
+
ValueListFieldType()
|
|
23
|
+
], CarbonLogAction);
|
|
24
|
+
export { CarbonLogAction };
|
|
25
|
+
let CarboneTemplate = class CarboneTemplate {
|
|
26
|
+
id;
|
|
27
|
+
updatedAt = new Date();
|
|
28
|
+
name;
|
|
29
|
+
extension = '';
|
|
30
|
+
};
|
|
31
|
+
__decorate([
|
|
32
|
+
Fields.string({ required: true })
|
|
33
|
+
], CarboneTemplate.prototype, "id", void 0);
|
|
34
|
+
__decorate([
|
|
35
|
+
Fields.updatedAt()
|
|
36
|
+
], CarboneTemplate.prototype, "updatedAt", void 0);
|
|
37
|
+
__decorate([
|
|
38
|
+
Fields.string({ required: true })
|
|
39
|
+
], CarboneTemplate.prototype, "name", void 0);
|
|
40
|
+
__decorate([
|
|
41
|
+
Fields.string({ required: true })
|
|
42
|
+
], CarboneTemplate.prototype, "extension", void 0);
|
|
43
|
+
CarboneTemplate = __decorate([
|
|
44
|
+
Entity('carboneTemplates', {
|
|
45
|
+
allowApiCrud: Roles_Carbon.Carbon_Admin,
|
|
46
|
+
allowApiRead: Roles_Carbon.Carbon_ViewTemplate,
|
|
47
|
+
defaultOrderBy: { updatedAt: 'desc' },
|
|
48
|
+
})
|
|
49
|
+
], CarboneTemplate);
|
|
50
|
+
export { CarboneTemplate };
|
|
51
|
+
let CarboneLog = class CarboneLog {
|
|
52
|
+
id;
|
|
53
|
+
updatedAt = new Date();
|
|
54
|
+
userId = '';
|
|
55
|
+
action = CarbonLogAction.template_upload;
|
|
56
|
+
templateId = '';
|
|
57
|
+
};
|
|
58
|
+
__decorate([
|
|
59
|
+
Fields.id()
|
|
60
|
+
], CarboneLog.prototype, "id", void 0);
|
|
61
|
+
__decorate([
|
|
62
|
+
Fields.updatedAt()
|
|
63
|
+
], CarboneLog.prototype, "updatedAt", void 0);
|
|
64
|
+
__decorate([
|
|
65
|
+
Fields.string({
|
|
66
|
+
saving: (item) => {
|
|
67
|
+
item.userId = remult.user?.id ?? '';
|
|
68
|
+
},
|
|
69
|
+
})
|
|
70
|
+
], CarboneLog.prototype, "userId", void 0);
|
|
71
|
+
__decorate([
|
|
72
|
+
Field(() => CarbonLogAction)
|
|
73
|
+
], CarboneLog.prototype, "action", void 0);
|
|
74
|
+
__decorate([
|
|
75
|
+
Fields.string({ required: true })
|
|
76
|
+
], CarboneLog.prototype, "templateId", void 0);
|
|
77
|
+
CarboneLog = __decorate([
|
|
78
|
+
Entity('carboneLogs', {
|
|
79
|
+
allowApiCrud: Roles_Carbon.Carbon_Admin,
|
|
80
|
+
defaultOrderBy: { updatedAt: 'desc' },
|
|
81
|
+
})
|
|
82
|
+
], CarboneLog);
|
|
83
|
+
export { CarboneLog };
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Log } from '@kitql/helpers';
|
|
2
|
+
import { CarboneLog, CarboneTemplate } from './carboneEntities';
|
|
3
|
+
export { Roles_Carbon as Roles_Mail } from './Roles_Carbon';
|
|
4
|
+
export declare const key = "carbone";
|
|
5
|
+
export declare const log: Log;
|
|
6
|
+
export declare const carbonEntities: {
|
|
7
|
+
CarboneTemplate: typeof CarboneTemplate;
|
|
8
|
+
CarboneLog: typeof CarboneLog;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Converts a File object to base64 string (without data URL prefix)
|
|
12
|
+
* @param file - The File object to convert
|
|
13
|
+
* @returns Promise<string> - Base64 string without data URL prefix
|
|
14
|
+
*/
|
|
15
|
+
export declare const fileToBase64: (file: File) => Promise<string>;
|
|
16
|
+
/**
|
|
17
|
+
* Downloads a file from base64 data
|
|
18
|
+
* @param base64Data - The base64 encoded file data
|
|
19
|
+
* @param filename - The filename for the download
|
|
20
|
+
* @param contentType - The MIME type of the file
|
|
21
|
+
*/
|
|
22
|
+
export declare const downloadFile: (base64Data: string, filename: string, contentType: string) => void;
|
|
23
|
+
/**
|
|
24
|
+
* File processing utilities for Carbone templates
|
|
25
|
+
*/
|
|
26
|
+
export declare const carboneFileUtils: {
|
|
27
|
+
fileToBase64: (file: File) => Promise<string>;
|
|
28
|
+
downloadFile: (base64Data: string, filename: string, contentType: string) => void;
|
|
29
|
+
};
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { Log } from '@kitql/helpers';
|
|
2
|
+
import { CarboneLog, CarboneTemplate } from './carboneEntities';
|
|
3
|
+
export { Roles_Carbon as Roles_Mail } from './Roles_Carbon';
|
|
4
|
+
export const key = 'carbone';
|
|
5
|
+
export const log = new Log(key);
|
|
6
|
+
export const carbonEntities = {
|
|
7
|
+
CarboneTemplate,
|
|
8
|
+
CarboneLog,
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Converts a File object to base64 string (without data URL prefix)
|
|
12
|
+
* @param file - The File object to convert
|
|
13
|
+
* @returns Promise<string> - Base64 string without data URL prefix
|
|
14
|
+
*/
|
|
15
|
+
export const fileToBase64 = (file) => {
|
|
16
|
+
return new Promise((resolve, reject) => {
|
|
17
|
+
const reader = new FileReader();
|
|
18
|
+
reader.onload = () => {
|
|
19
|
+
const result = reader.result;
|
|
20
|
+
// Remove data URL prefix to get just the base64 content
|
|
21
|
+
const base64Content = result.split(',')[1];
|
|
22
|
+
resolve(base64Content);
|
|
23
|
+
};
|
|
24
|
+
reader.onerror = reject;
|
|
25
|
+
reader.readAsDataURL(file);
|
|
26
|
+
});
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Downloads a file from base64 data
|
|
30
|
+
* @param base64Data - The base64 encoded file data
|
|
31
|
+
* @param filename - The filename for the download
|
|
32
|
+
* @param contentType - The MIME type of the file
|
|
33
|
+
*/
|
|
34
|
+
export const downloadFile = (base64Data, filename, contentType) => {
|
|
35
|
+
try {
|
|
36
|
+
// Convert base64 to blob
|
|
37
|
+
const byteCharacters = atob(base64Data);
|
|
38
|
+
const byteNumbers = new Array(byteCharacters.length);
|
|
39
|
+
for (let i = 0; i < byteCharacters.length; i++) {
|
|
40
|
+
byteNumbers[i] = byteCharacters.charCodeAt(i);
|
|
41
|
+
}
|
|
42
|
+
const byteArray = new Uint8Array(byteNumbers);
|
|
43
|
+
const blob = new Blob([byteArray], { type: contentType });
|
|
44
|
+
// Create download link
|
|
45
|
+
const url = URL.createObjectURL(blob);
|
|
46
|
+
const link = document.createElement('a');
|
|
47
|
+
link.href = url;
|
|
48
|
+
link.download = filename;
|
|
49
|
+
link.style.display = 'none';
|
|
50
|
+
// Trigger download
|
|
51
|
+
document.body.appendChild(link);
|
|
52
|
+
link.click();
|
|
53
|
+
document.body.removeChild(link);
|
|
54
|
+
// Clean up
|
|
55
|
+
URL.revokeObjectURL(url);
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
console.error('Download failed:', error);
|
|
59
|
+
throw error;
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
/**
|
|
63
|
+
* File processing utilities for Carbone templates
|
|
64
|
+
*/
|
|
65
|
+
export const carboneFileUtils = {
|
|
66
|
+
fileToBase64,
|
|
67
|
+
downloadFile,
|
|
68
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export declare class CarboneServer {
|
|
2
|
+
api_key: string;
|
|
3
|
+
api_url: string;
|
|
4
|
+
api_version: '5';
|
|
5
|
+
test: boolean;
|
|
6
|
+
constructor(options: {
|
|
7
|
+
CARBONE_API_KEY?: string;
|
|
8
|
+
api_url?: string;
|
|
9
|
+
api_version?: '5';
|
|
10
|
+
test?: boolean;
|
|
11
|
+
});
|
|
12
|
+
private getHeaders;
|
|
13
|
+
fetch: (o: {
|
|
14
|
+
api: string;
|
|
15
|
+
body?: string;
|
|
16
|
+
method?: "POST" | "GET" | "DELETE";
|
|
17
|
+
headers?: HeadersInit;
|
|
18
|
+
}) => Promise<Response>;
|
|
19
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { log } from '..';
|
|
2
|
+
export class CarboneServer {
|
|
3
|
+
api_key;
|
|
4
|
+
api_url;
|
|
5
|
+
api_version;
|
|
6
|
+
test;
|
|
7
|
+
constructor(options) {
|
|
8
|
+
this.api_key = options.CARBONE_API_KEY ?? '';
|
|
9
|
+
this.api_url = options.api_url ?? 'https://api.carbone.io';
|
|
10
|
+
this.api_version = options.api_version ?? '5';
|
|
11
|
+
this.test = options.test ?? false;
|
|
12
|
+
}
|
|
13
|
+
getHeaders = (headersInit) => {
|
|
14
|
+
if (this.api_key === undefined || this.api_key === '') {
|
|
15
|
+
log.error('Token CARBONE_API_TOKEN not defined!');
|
|
16
|
+
throw new Error('Configuration error');
|
|
17
|
+
}
|
|
18
|
+
const headers = new Headers(headersInit);
|
|
19
|
+
headers.append('Authorization', 'Bearer ' + this.api_key);
|
|
20
|
+
headers.append('Carbone-version', this.api_version);
|
|
21
|
+
// headers.append('Carbone-version', 'staging')
|
|
22
|
+
headers.append('Content-type', 'application/json');
|
|
23
|
+
return headers;
|
|
24
|
+
};
|
|
25
|
+
fetch = async (o) => {
|
|
26
|
+
const response = await fetch(`${this.api_url}${o.api}`, {
|
|
27
|
+
method: o.method ?? 'POST',
|
|
28
|
+
headers: this.getHeaders(o.headers),
|
|
29
|
+
body: o.body,
|
|
30
|
+
});
|
|
31
|
+
if (!response.ok) {
|
|
32
|
+
const err = await response.json();
|
|
33
|
+
log.error(`Carbone render failed`, err);
|
|
34
|
+
throw new Error(err.error);
|
|
35
|
+
}
|
|
36
|
+
return response;
|
|
37
|
+
};
|
|
38
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Module } from 'remult/server';
|
|
2
|
+
import { carbonEntities, key, log } from '..';
|
|
3
|
+
import { CarboneController } from '../CarboneController';
|
|
4
|
+
import { CarboneServer } from './CarboneServer';
|
|
5
|
+
export const carbone = (config) => {
|
|
6
|
+
return new Module({
|
|
7
|
+
key,
|
|
8
|
+
entities: Object.values(carbonEntities),
|
|
9
|
+
controllers: [CarboneController],
|
|
10
|
+
initApi: async () => {
|
|
11
|
+
if (config.CARBONE_API_KEY === undefined) {
|
|
12
|
+
log.error('CARBONE_API_KEY is required');
|
|
13
|
+
}
|
|
14
|
+
else {
|
|
15
|
+
CarboneController.server = new CarboneServer({
|
|
16
|
+
...config,
|
|
17
|
+
test: config.test === undefined ? config.CARBONE_API_KEY.startsWith('test') : config.test,
|
|
18
|
+
});
|
|
19
|
+
log.success('initialized');
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
});
|
|
23
|
+
};
|
package/esm/changeLog/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type FieldRef, type FieldsRef, type LifecycleEvent } from 'remult';
|
|
1
|
+
import { type EntityOptions, type FieldRef, type FieldsRef, type LifecycleEvent } from 'remult';
|
|
2
2
|
import { Roles_ChangeLog, type change } from './changeLogEntities';
|
|
3
3
|
export { Roles_ChangeLog };
|
|
4
4
|
export type { change };
|
|
@@ -21,3 +21,39 @@ export declare class FieldDecider<entityType> {
|
|
|
21
21
|
excludedValues: FieldRef<entityType>[];
|
|
22
22
|
constructor(entity: entityType, options?: ColumnDeciderArgs<entityType>);
|
|
23
23
|
}
|
|
24
|
+
export declare const withChangeLog: <entityType>(options?: EntityOptions<entityType>) => {
|
|
25
|
+
saved: (entity: entityType, e: LifecycleEvent<entityType>) => Promise<void>;
|
|
26
|
+
deleted: (entity: entityType, e: LifecycleEvent<entityType>) => Promise<void>;
|
|
27
|
+
caption?: string;
|
|
28
|
+
label?: string;
|
|
29
|
+
allowApiRead?: import("remult").Allowed;
|
|
30
|
+
allowApiUpdate?: import("remult").AllowedForInstance<entityType> | undefined;
|
|
31
|
+
allowApiDelete?: import("remult").AllowedForInstance<entityType> | undefined;
|
|
32
|
+
allowApiInsert?: import("remult").AllowedForInstance<entityType> | undefined;
|
|
33
|
+
allowApiCrud?: import("remult").Allowed;
|
|
34
|
+
apiPrefilter?: import("remult").EntityFilter<entityType> | (() => import("remult").EntityFilter<entityType> | Promise<import("remult").EntityFilter<entityType>>) | undefined;
|
|
35
|
+
apiPreprocessFilter?: ((filter: import("remult").EntityFilter<entityType>, event: import("remult").PreprocessFilterEvent<entityType>) => import("remult").EntityFilter<entityType> | Promise<import("remult").EntityFilter<entityType>>) | undefined;
|
|
36
|
+
backendPreprocessFilter?: ((filter: import("remult").EntityFilter<entityType>, event: import("remult").PreprocessFilterEvent<entityType>) => import("remult").EntityFilter<entityType> | Promise<import("remult").EntityFilter<entityType>>) | undefined;
|
|
37
|
+
backendPrefilter?: import("remult").EntityFilter<entityType> | (() => import("remult").EntityFilter<entityType> | Promise<import("remult").EntityFilter<entityType>>) | undefined;
|
|
38
|
+
defaultOrderBy?: import("remult").EntityOrderBy<entityType> | undefined;
|
|
39
|
+
saving?: ((entity: entityType, event: LifecycleEvent<entityType>) => Promise<any> | any) | undefined;
|
|
40
|
+
deleting?: ((entity: entityType, e: LifecycleEvent<entityType>) => Promise<any> | any) | undefined;
|
|
41
|
+
validation?: ((entity: entityType, ref: LifecycleEvent<entityType>) => Promise<any> | any) | undefined;
|
|
42
|
+
dbName?: string;
|
|
43
|
+
sqlExpression?: string | ((entity: import("remult").EntityMetadata<entityType>) => string | Promise<string>) | undefined;
|
|
44
|
+
id?: keyof import("remult").MembersOnly<entityType> | (keyof import("remult").MembersOnly<entityType>)[] | import("remult").EntityIdFields<entityType> | ((entity: import("remult").FieldsMetadata<entityType>) => import("remult").FieldMetadata | import("remult").FieldMetadata[]) | undefined;
|
|
45
|
+
entityRefInit?: ((ref: import("remult").EntityRef<entityType>, row: entityType) => void) | undefined;
|
|
46
|
+
apiRequireId?: import("remult").Allowed;
|
|
47
|
+
dataProvider?: ((defaultDataProvider: import("remult").DataProvider) => import("remult").DataProvider | Promise<import("remult").DataProvider> | undefined | null) | undefined;
|
|
48
|
+
ui?: {
|
|
49
|
+
getLayout?: import("../svelte/customField").getLayout<entityType> | undefined;
|
|
50
|
+
} | undefined;
|
|
51
|
+
searchableFind?: ((str: string) => import("remult").FindOptionsBase<entityType>) | undefined;
|
|
52
|
+
displayValue?: ((item: entityType) => import("../internals").BaseItem) | undefined;
|
|
53
|
+
permissionApiCrud?: import("../internals").BaseEnum[] | import("../internals").BaseEnum;
|
|
54
|
+
permissionApiDelete?: import("../internals").BaseEnum[] | import("../internals").BaseEnum;
|
|
55
|
+
permissionApiInsert?: import("../internals").BaseEnum[] | import("../internals").BaseEnum;
|
|
56
|
+
permissionApiRead?: import("../internals").BaseEnum[] | import("../internals").BaseEnum;
|
|
57
|
+
permissionApiUpdate?: import("../internals").BaseEnum[] | import("../internals").BaseEnum;
|
|
58
|
+
changeLog?: false | ColumnDeciderArgs<entityType> | undefined;
|
|
59
|
+
};
|
package/esm/changeLog/index.js
CHANGED
|
@@ -95,3 +95,31 @@ export class FieldDecider {
|
|
|
95
95
|
this.fields = meta.fields.toArray().filter((f) => !this.excludedFields.includes(f));
|
|
96
96
|
}
|
|
97
97
|
}
|
|
98
|
+
export const withChangeLog = (options) => {
|
|
99
|
+
return {
|
|
100
|
+
...options,
|
|
101
|
+
// changesLogs
|
|
102
|
+
saved: async (entity, e) => {
|
|
103
|
+
await options?.saved?.(entity, e);
|
|
104
|
+
if (options?.changeLog === false) {
|
|
105
|
+
// Don't log changes
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
if (isBackend()) {
|
|
109
|
+
await recordSaved(entity, e, options?.changeLog);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
},
|
|
113
|
+
deleted: async (entity, e) => {
|
|
114
|
+
await options?.deleted?.(entity, e);
|
|
115
|
+
if (options?.changeLog === false) {
|
|
116
|
+
// Don't log changes
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
if (isBackend()) {
|
|
120
|
+
await recordDeleted(entity, e, options?.changeLog);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
};
|
|
125
|
+
};
|
|
@@ -6,15 +6,28 @@ declare module 'remult' {
|
|
|
6
6
|
}
|
|
7
7
|
}
|
|
8
8
|
/**
|
|
9
|
-
*
|
|
10
|
-
*
|
|
9
|
+
* ## Option 1
|
|
10
|
+
* Use the `withChangeLog` function to wrap your entity options.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```ts
|
|
14
|
+
* import { withChangeLog } from '..'
|
|
15
|
+
*
|
|
16
|
+
* \@Entity('users', withChangeLog({
|
|
17
|
+
* // ...
|
|
18
|
+
* }))
|
|
19
|
+
* class User { }
|
|
20
|
+
* ```
|
|
21
|
+
* ## Option 2
|
|
22
|
+
* Create your own `@APP_Entity` decorator and use it instead of `@Entity`.
|
|
23
|
+
* Inside, it uses the `withChangeLog` function to wrap your entity options.
|
|
11
24
|
*
|
|
12
25
|
* @example
|
|
13
26
|
* ```ts
|
|
14
27
|
* // APP_Entity.ts example
|
|
15
28
|
* import { Entity, isBackend, type EntityOptions } from 'remult'
|
|
16
29
|
*
|
|
17
|
-
* import {
|
|
30
|
+
* import { withChangeLog } from '..'
|
|
18
31
|
*
|
|
19
32
|
* export function APP_Entity<entityType>(
|
|
20
33
|
* key: string,
|
|
@@ -22,31 +35,7 @@ declare module 'remult' {
|
|
|
22
35
|
* entityType extends new (...args: any) => any ? InstanceType<entityType> : entityType
|
|
23
36
|
* >,
|
|
24
37
|
* ) {
|
|
25
|
-
* return Entity(key,
|
|
26
|
-
* ...options,
|
|
27
|
-
*
|
|
28
|
-
* // changesLogs
|
|
29
|
-
* saved: async (entity, e) => {
|
|
30
|
-
* await options?.saved?.(entity, e)
|
|
31
|
-
* if (options?.changeLog === false) {
|
|
32
|
-
* // Don't log changes
|
|
33
|
-
* } else {
|
|
34
|
-
* if (isBackend()) {
|
|
35
|
-
* await recordSaved(entity, e, options?.changeLog)
|
|
36
|
-
* }
|
|
37
|
-
* }
|
|
38
|
-
* },
|
|
39
|
-
* deleted: async (entity, e) => {
|
|
40
|
-
* await options?.deleted?.(entity, e)
|
|
41
|
-
* if (options?.changeLog === false) {
|
|
42
|
-
* // Don't log changes
|
|
43
|
-
* } else {
|
|
44
|
-
* if (isBackend()) {
|
|
45
|
-
* await recordDeleted(entity, e, options?.changeLog)
|
|
46
|
-
* }
|
|
47
|
-
* }
|
|
48
|
-
* },
|
|
49
|
-
* })
|
|
38
|
+
* return Entity(key, withChangeLog(options))
|
|
50
39
|
* }
|
|
51
40
|
* ```
|
|
52
41
|
*/
|
|
@@ -1,15 +1,28 @@
|
|
|
1
1
|
import { Module } from 'remult/server';
|
|
2
2
|
import { ChangeLog } from '../changeLogEntities';
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* ## Option 1
|
|
5
|
+
* Use the `withChangeLog` function to wrap your entity options.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```ts
|
|
9
|
+
* import { withChangeLog } from '..'
|
|
10
|
+
*
|
|
11
|
+
* \@Entity('users', withChangeLog({
|
|
12
|
+
* // ...
|
|
13
|
+
* }))
|
|
14
|
+
* class User { }
|
|
15
|
+
* ```
|
|
16
|
+
* ## Option 2
|
|
17
|
+
* Create your own `@APP_Entity` decorator and use it instead of `@Entity`.
|
|
18
|
+
* Inside, it uses the `withChangeLog` function to wrap your entity options.
|
|
6
19
|
*
|
|
7
20
|
* @example
|
|
8
21
|
* ```ts
|
|
9
22
|
* // APP_Entity.ts example
|
|
10
23
|
* import { Entity, isBackend, type EntityOptions } from 'remult'
|
|
11
24
|
*
|
|
12
|
-
* import {
|
|
25
|
+
* import { withChangeLog } from '..'
|
|
13
26
|
*
|
|
14
27
|
* export function APP_Entity<entityType>(
|
|
15
28
|
* key: string,
|
|
@@ -17,31 +30,7 @@ import { ChangeLog } from '../changeLogEntities';
|
|
|
17
30
|
* entityType extends new (...args: any) => any ? InstanceType<entityType> : entityType
|
|
18
31
|
* >,
|
|
19
32
|
* ) {
|
|
20
|
-
* return Entity(key,
|
|
21
|
-
* ...options,
|
|
22
|
-
*
|
|
23
|
-
* // changesLogs
|
|
24
|
-
* saved: async (entity, e) => {
|
|
25
|
-
* await options?.saved?.(entity, e)
|
|
26
|
-
* if (options?.changeLog === false) {
|
|
27
|
-
* // Don't log changes
|
|
28
|
-
* } else {
|
|
29
|
-
* if (isBackend()) {
|
|
30
|
-
* await recordSaved(entity, e, options?.changeLog)
|
|
31
|
-
* }
|
|
32
|
-
* }
|
|
33
|
-
* },
|
|
34
|
-
* deleted: async (entity, e) => {
|
|
35
|
-
* await options?.deleted?.(entity, e)
|
|
36
|
-
* if (options?.changeLog === false) {
|
|
37
|
-
* // Don't log changes
|
|
38
|
-
* } else {
|
|
39
|
-
* if (isBackend()) {
|
|
40
|
-
* await recordDeleted(entity, e, options?.changeLog)
|
|
41
|
-
* }
|
|
42
|
-
* }
|
|
43
|
-
* },
|
|
44
|
-
* })
|
|
33
|
+
* return Entity(key, withChangeLog(options))
|
|
45
34
|
* }
|
|
46
35
|
* ```
|
|
47
36
|
*/
|
package/esm/cron/Cron.js
CHANGED
package/esm/index.d.ts
CHANGED
package/esm/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Entity
|
|
2
|
-
import {
|
|
1
|
+
import { Entity } from 'remult';
|
|
2
|
+
import { withChangeLog } from '../changeLog';
|
|
3
3
|
const toAllow = (permission) => {
|
|
4
4
|
if (permission) {
|
|
5
5
|
if (Array.isArray(permission)) {
|
|
@@ -10,35 +10,12 @@ const toAllow = (permission) => {
|
|
|
10
10
|
return undefined;
|
|
11
11
|
};
|
|
12
12
|
export function FF_Entity(key, options) {
|
|
13
|
-
return Entity(key, {
|
|
13
|
+
return Entity(key, withChangeLog({
|
|
14
14
|
...options,
|
|
15
15
|
allowApiCrud: options?.allowApiCrud ?? toAllow(options?.permissionApiCrud),
|
|
16
16
|
allowApiDelete: options?.allowApiDelete ?? toAllow(options?.permissionApiDelete),
|
|
17
17
|
allowApiInsert: options?.allowApiInsert ?? toAllow(options?.permissionApiInsert),
|
|
18
18
|
allowApiRead: options?.allowApiRead ?? toAllow(options?.permissionApiRead),
|
|
19
19
|
allowApiUpdate: options?.allowApiUpdate ?? toAllow(options?.permissionApiUpdate),
|
|
20
|
-
|
|
21
|
-
saved: async (entity, e) => {
|
|
22
|
-
await options?.saved?.(entity, e);
|
|
23
|
-
if (options?.changeLog === false) {
|
|
24
|
-
// Don't log changes
|
|
25
|
-
}
|
|
26
|
-
else {
|
|
27
|
-
if (isBackend()) {
|
|
28
|
-
await recordSaved(entity, e, options?.changeLog);
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
},
|
|
32
|
-
deleted: async (entity, e) => {
|
|
33
|
-
await options?.deleted?.(entity, e);
|
|
34
|
-
if (options?.changeLog === false) {
|
|
35
|
-
// Don't log changes
|
|
36
|
-
}
|
|
37
|
-
else {
|
|
38
|
-
if (isBackend()) {
|
|
39
|
-
await recordDeleted(entity, e, options?.changeLog);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
},
|
|
43
|
-
});
|
|
20
|
+
}));
|
|
44
21
|
}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { type FieldOptions, type StringFieldOptions } from 'remult';
|
|
1
|
+
import { type ClassType, type FieldOptions, type StringFieldOptions } from 'remult';
|
|
2
|
+
import type { BaseEnum } from './BaseEnum';
|
|
2
3
|
export declare class FF_Fields {
|
|
3
4
|
static string<entityType = unknown, valueType = string>(o?: StringFieldOptions<entityType, valueType>): import("remult").ClassFieldDecorator<entityType, valueType | undefined>;
|
|
4
5
|
static currency<entityType = unknown>(o?: FieldOptions<entityType, number>): import("remult").ClassFieldDecorator<entityType, number | undefined>;
|
|
5
6
|
static dateOnly<entityType = any>(o?: FieldOptions<entityType, Date>): import("remult").ClassFieldDecorator<entityType, Date | undefined>;
|
|
6
7
|
static arrayEnum<enumType = any, entityType = any>(enumClass: enumType, o?: FieldOptions<entityType, any[]>): import("remult").ClassFieldDecorator<entityType, any[] | undefined>;
|
|
7
8
|
static arrayEnumToGql<enumType = any, entityType = any>(enumClass: enumType, o?: FieldOptions<entityType, any[]>): import("remult").ClassFieldDecorator<entityType, any[] | undefined>;
|
|
8
|
-
static arrayValueList<enumType = any, entityType = any>(enumClass:
|
|
9
|
+
static arrayValueList<enumType = any, entityType = any>(enumClass: ClassType<BaseEnum<any>>, o?: FieldOptions<entityType, any[]>): import("remult").ClassFieldDecorator<entityType, any[] | undefined>;
|
|
9
10
|
}
|
|
@@ -155,18 +155,22 @@ export class FF_Fields {
|
|
|
155
155
|
fromDb: (v) => {
|
|
156
156
|
if (!v)
|
|
157
157
|
return [];
|
|
158
|
-
const
|
|
159
|
-
|
|
160
|
-
.
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
.
|
|
165
|
-
|
|
158
|
+
const arr = Array.isArray(v)
|
|
159
|
+
? v
|
|
160
|
+
: v?.split(',').flatMap((c) => c.replaceAll('{', '').replaceAll('}', ''));
|
|
161
|
+
const list = getEnums(enumClass);
|
|
162
|
+
const toRet = [];
|
|
163
|
+
for (const s of arr) {
|
|
164
|
+
const found = list.find((c) => c.id === s);
|
|
165
|
+
if (found) {
|
|
166
|
+
toRet.push(found);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
return toRet;
|
|
166
170
|
},
|
|
167
171
|
toDb: (v) => {
|
|
168
172
|
const arr = Array.isArray(v) ? v : [v];
|
|
169
|
-
return `{${[...new Set((arr ?? []).map((c) => c.id))].join(',')}}`;
|
|
173
|
+
return `{${[...new Set((arr.filter((c) => c !== undefined) ?? []).map((c) => c.id))].join(',')}}`;
|
|
170
174
|
},
|
|
171
175
|
displayValue: (v) => {
|
|
172
176
|
// Nice to have a oneLiner, but if you want custom style, just take the array and do what you want
|
package/esm/internals/index.d.ts
CHANGED
|
@@ -57,7 +57,7 @@ declare module 'remult' {
|
|
|
57
57
|
suffixEdit?: string;
|
|
58
58
|
suffixEditWithS?: boolean;
|
|
59
59
|
styleRadioUntil?: number;
|
|
60
|
-
step?: '1' | '0.1' | '0.01';
|
|
60
|
+
step?: '1' | '0.1' | '0.01' | '0.5';
|
|
61
61
|
href?: (item: entityType) => string;
|
|
62
62
|
findOptionsForEdit?: ((entity: entityType) => FindOptionsBase<valueType>) | FindOptionsBase<valueType>;
|
|
63
63
|
findOptionsLimit?: number;
|
package/esm/mail/Mail.js
CHANGED