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.
Files changed (56) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/esm/auth/Entities.js +2 -2
  3. package/esm/auth/server/helperRole.js +5 -2
  4. package/esm/auth/static/assets/Page-C1pM-UDt.js +2 -2
  5. package/esm/bin/cmd.js +1 -1
  6. package/esm/carbone/CarboneController.d.ts +35 -0
  7. package/esm/carbone/CarboneController.js +155 -0
  8. package/esm/carbone/Roles_Carbon.d.ts +8 -0
  9. package/esm/carbone/Roles_Carbon.js +8 -0
  10. package/esm/carbone/carboneEntities.d.ts +21 -0
  11. package/esm/carbone/carboneEntities.js +83 -0
  12. package/esm/carbone/index.d.ts +29 -0
  13. package/esm/carbone/index.js +68 -0
  14. package/esm/carbone/server/CarboneServer.d.ts +19 -0
  15. package/esm/carbone/server/CarboneServer.js +38 -0
  16. package/esm/carbone/server/index.d.ts +7 -0
  17. package/esm/carbone/server/index.js +23 -0
  18. package/esm/changeLog/changeLogEntities.js +1 -1
  19. package/esm/changeLog/index.d.ts +37 -1
  20. package/esm/changeLog/index.js +28 -0
  21. package/esm/changeLog/server/index.d.ts +17 -28
  22. package/esm/changeLog/server/index.js +17 -28
  23. package/esm/cron/Cron.js +1 -1
  24. package/esm/index.d.ts +5 -3
  25. package/esm/index.js +5 -3
  26. package/esm/internals/FF_Entity.js +4 -27
  27. package/esm/internals/FF_Fields.d.ts +3 -2
  28. package/esm/internals/FF_Fields.js +13 -9
  29. package/esm/internals/index.d.ts +1 -1
  30. package/esm/mail/Mail.js +1 -1
  31. package/esm/svelte/FF_Cell.svelte +1 -0
  32. package/esm/svelte/FF_Cell.svelte.d.ts +10 -3
  33. package/esm/svelte/FF_Cell_Caption.svelte.d.ts +10 -3
  34. package/esm/svelte/FF_Cell_Display.svelte.d.ts +10 -3
  35. package/esm/svelte/FF_Cell_Edit.svelte.d.ts +11 -4
  36. package/esm/svelte/FF_Cell_Error.svelte.d.ts +10 -3
  37. package/esm/svelte/FF_Cell_Hint.svelte.d.ts +10 -3
  38. package/esm/svelte/FF_Display.svelte.d.ts +10 -3
  39. package/esm/svelte/FF_Edit.svelte.d.ts +11 -4
  40. package/esm/svelte/FF_Error.svelte.d.ts +10 -3
  41. package/esm/svelte/FF_Field.svelte.d.ts +10 -3
  42. package/esm/svelte/FF_Form.svelte.d.ts +10 -3
  43. package/esm/svelte/FF_Grid.svelte +1 -1
  44. package/esm/svelte/FF_Grid.svelte.d.ts +10 -4
  45. package/esm/svelte/FF_Hint.svelte.d.ts +10 -3
  46. package/esm/svelte/FF_Label.svelte.d.ts +10 -3
  47. package/esm/svelte/FF_Layout.svelte.d.ts +10 -3
  48. package/esm/ui/Button.svelte +0 -1
  49. package/esm/ui/Field.svelte +19 -2
  50. package/esm/ui/LibIcon.d.ts +2 -0
  51. package/esm/ui/LibIcon.js +3 -1
  52. package/esm/ui/dialog/DialogPrimitive.svelte +1 -1
  53. package/esm/ui/internals/select/SelectMelt.svelte +22 -25
  54. package/esm/virtual/Customer.js +1 -1
  55. package/esm/virtual/UIEntity.js +1 -1
  56. 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,7 @@
1
+ import { Module } from 'remult/server';
2
+ export declare const carbone: (config: {
3
+ CARBONE_API_KEY?: string;
4
+ api_url?: string;
5
+ api_version?: "5";
6
+ test?: boolean;
7
+ }) => Module<unknown>;
@@ -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
+ };
@@ -19,7 +19,7 @@ let ChangeLog = class ChangeLog {
19
19
  deleted = false;
20
20
  };
21
21
  __decorate([
22
- Fields.cuid()
22
+ Fields.id()
23
23
  ], ChangeLog.prototype, "id", void 0);
24
24
  __decorate([
25
25
  Fields.string()
@@ -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
+ };
@@ -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
- * We suggest you to create your own `@APP_Entity` decorator and use it instead of `@Entity`.
10
- * Like this you opt-in to the change log feature Entity by Entity.
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 { recordDeleted, recordSaved } from '..'
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
- * We suggest you to create your own `@APP_Entity` decorator and use it instead of `@Entity`.
5
- * Like this you opt-in to the change log feature Entity by Entity.
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 { recordDeleted, recordSaved } from '..'
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
@@ -16,7 +16,7 @@ let Cron = class Cron {
16
16
  status = 'starting';
17
17
  };
18
18
  __decorate([
19
- Fields.cuid()
19
+ Fields.id()
20
20
  ], Cron.prototype, "id", void 0);
21
21
  __decorate([
22
22
  Fields.string({ required: true })
package/esm/index.d.ts CHANGED
@@ -1,3 +1,5 @@
1
- import * as log from '@kitql/helpers';
2
- export { log };
3
- export declare const ff_Log: log.Log;
1
+ import * as h from '@kitql/helpers';
2
+ export {
3
+ /** alias for @kitql/helpers */
4
+ h, };
5
+ export declare const ff_Log: h.Log;
package/esm/index.js CHANGED
@@ -1,3 +1,5 @@
1
- import * as log from '@kitql/helpers';
2
- export { log };
3
- export const ff_Log = new log.Log('firstly');
1
+ import * as h from '@kitql/helpers';
2
+ export {
3
+ /** alias for @kitql/helpers */
4
+ h, };
5
+ export const ff_Log = new h.Log('firstly');
@@ -1,5 +1,5 @@
1
- import { Entity, isBackend } from 'remult';
2
- import { recordDeleted, recordSaved } from '../changeLog';
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
- // changesLogs
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: enumType, o?: FieldOptions<entityType, any[]>): import("remult").ClassFieldDecorator<entityType, any[] | undefined>;
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 keys = v
159
- // @ts-ignore
160
- .map((s) => {
161
- // @ts-ignore
162
- return enumClass[s];
163
- })
164
- .filter((p) => p !== undefined);
165
- return keys;
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
@@ -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
@@ -18,7 +18,7 @@ let Mail = class Mail {
18
18
  errorInfo = '';
19
19
  };
20
20
  __decorate([
21
- Fields.cuid()
21
+ Fields.id()
22
22
  ], Mail.prototype, "id", void 0);
23
23
  __decorate([
24
24
  Fields.createdAt()
@@ -15,6 +15,7 @@
15
15
  class?: string
16
16
  }
17
17
 
18
+ // eslint-disable-next-line svelte/no-unused-props
18
19
  let props: Props<valueType, entityType> = $props()
19
20
 
20
21
  // let classes = $derived(getClasses('field', props.classes))