firstly 0.0.1 → 0.0.2

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 (156) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/LICENSE +18 -0
  3. package/README.md +12 -0
  4. package/esm/KitBaseEnum.d.ts +35 -0
  5. package/esm/KitBaseEnum.js +32 -0
  6. package/esm/KitEntity.d.ts +2 -0
  7. package/esm/KitEntity.js +24 -0
  8. package/esm/KitFields.d.ts +10 -0
  9. package/esm/KitFields.js +196 -0
  10. package/esm/ROUTES.d.ts +88 -0
  11. package/esm/ROUTES.js +98 -0
  12. package/esm/SqlDatabase/LogToConsoleCustom.d.ts +1 -0
  13. package/esm/SqlDatabase/LogToConsoleCustom.js +102 -0
  14. package/esm/api/index.d.ts +42 -0
  15. package/esm/api/index.js +97 -0
  16. package/esm/auth/Adapter.d.ts +10 -0
  17. package/esm/auth/Adapter.js +54 -0
  18. package/esm/auth/AuthController.d.ts +59 -0
  19. package/esm/auth/AuthController.js +434 -0
  20. package/esm/auth/Entities.d.ts +39 -0
  21. package/esm/auth/Entities.js +154 -0
  22. package/esm/auth/RoleController.d.ts +14 -0
  23. package/esm/auth/RoleController.js +57 -0
  24. package/esm/auth/helper.d.ts +1 -0
  25. package/esm/auth/helper.js +7 -0
  26. package/esm/auth/index.d.ts +153 -0
  27. package/esm/auth/index.js +279 -0
  28. package/esm/auth/providers/github.d.ts +25 -0
  29. package/esm/auth/providers/github.js +51 -0
  30. package/esm/auth/providers/index.d.ts +3 -0
  31. package/esm/auth/providers/index.js +26 -0
  32. package/esm/auth/providers/strava.d.ts +25 -0
  33. package/esm/auth/providers/strava.js +51 -0
  34. package/esm/auth/static/assets/Page-BMFREPjF.d.ts +5 -0
  35. package/esm/auth/static/assets/Page-BMFREPjF.js +18 -0
  36. package/esm/auth/static/assets/Page-BMOLAIFx.d.ts +5 -0
  37. package/esm/auth/static/assets/Page-BMOLAIFx.js +1 -0
  38. package/esm/auth/static/assets/Page-BwHye0GW.d.ts +5 -0
  39. package/esm/auth/static/assets/Page-BwHye0GW.js +1 -0
  40. package/esm/auth/static/assets/Page-gV58jf2r.css +1 -0
  41. package/esm/auth/static/assets/index-CKmKKRRL.d.ts +53 -0
  42. package/esm/auth/static/assets/index-CKmKKRRL.js +2 -0
  43. package/esm/auth/static/assets/index-R27C_TlP.css +4 -0
  44. package/esm/auth/static/favicon.svg +79 -0
  45. package/esm/auth/static/index.html +14 -0
  46. package/esm/auth/types.d.ts +33 -0
  47. package/esm/auth/types.js +1 -0
  48. package/esm/bin/cmd.d.ts +1 -0
  49. package/esm/bin/cmd.js +408 -0
  50. package/esm/changeLog/index.d.ts +55 -0
  51. package/esm/changeLog/index.js +179 -0
  52. package/esm/cron/index.d.ts +60 -0
  53. package/esm/cron/index.js +102 -0
  54. package/esm/feedback/FeedbackController.d.ts +30 -0
  55. package/esm/feedback/FeedbackController.js +313 -0
  56. package/esm/feedback/index.d.ts +18 -0
  57. package/esm/feedback/index.js +14 -0
  58. package/esm/feedback/ui/DialogIssue.svelte +102 -0
  59. package/esm/feedback/ui/DialogIssue.svelte.d.ts +20 -0
  60. package/esm/feedback/ui/DialogIssues.svelte +91 -0
  61. package/esm/feedback/ui/DialogIssues.svelte.d.ts +20 -0
  62. package/esm/feedback/ui/DialogMilestones.svelte +38 -0
  63. package/esm/feedback/ui/DialogMilestones.svelte.d.ts +18 -0
  64. package/esm/feedback/ui/Feedback.svelte +12 -0
  65. package/esm/feedback/ui/Feedback.svelte.d.ts +16 -0
  66. package/esm/formats/dates.d.ts +18 -0
  67. package/esm/formats/dates.js +35 -0
  68. package/esm/formats/index.d.ts +4 -0
  69. package/esm/formats/index.js +3 -0
  70. package/esm/formats/numbers.d.ts +4 -0
  71. package/esm/formats/numbers.js +34 -0
  72. package/esm/formats/strings.d.ts +11 -0
  73. package/esm/formats/strings.js +109 -0
  74. package/esm/handle/index.d.ts +7 -0
  75. package/esm/handle/index.js +40 -0
  76. package/esm/helper.d.ts +50 -0
  77. package/esm/helper.js +118 -0
  78. package/esm/index.d.ts +103 -0
  79. package/esm/index.js +42 -0
  80. package/esm/kitCellsBuildor.d.ts +45 -0
  81. package/esm/kitCellsBuildor.js +105 -0
  82. package/esm/kitStoreItem.d.ts +28 -0
  83. package/esm/kitStoreItem.js +170 -0
  84. package/esm/kitStoreList.d.ts +33 -0
  85. package/esm/kitStoreList.js +98 -0
  86. package/esm/mail/index.d.ts +11 -0
  87. package/esm/mail/index.js +51 -0
  88. package/esm/theme.d.ts +4 -0
  89. package/esm/theme.js +4 -0
  90. package/esm/ui/Button.svelte +102 -0
  91. package/esm/ui/Button.svelte.d.ts +27 -0
  92. package/esm/ui/Clipboardable.svelte +19 -0
  93. package/esm/ui/Clipboardable.svelte.d.ts +25 -0
  94. package/esm/ui/Field.svelte +288 -0
  95. package/esm/ui/Field.svelte.d.ts +29 -0
  96. package/esm/ui/FieldGroup.svelte +91 -0
  97. package/esm/ui/FieldGroup.svelte.d.ts +30 -0
  98. package/esm/ui/Grid.svelte +246 -0
  99. package/esm/ui/Grid.svelte.d.ts +46 -0
  100. package/esm/ui/GridLoading.svelte +32 -0
  101. package/esm/ui/GridLoading.svelte.d.ts +20 -0
  102. package/esm/ui/GridPaginate.svelte +66 -0
  103. package/esm/ui/GridPaginate.svelte.d.ts +22 -0
  104. package/esm/ui/Icon.svelte +86 -0
  105. package/esm/ui/Icon.svelte.d.ts +46 -0
  106. package/esm/ui/LibIcon.d.ts +23 -0
  107. package/esm/ui/LibIcon.js +28 -0
  108. package/esm/ui/Loading.svelte +11 -0
  109. package/esm/ui/Loading.svelte.d.ts +20 -0
  110. package/esm/ui/Tooltip.svelte +42 -0
  111. package/esm/ui/Tooltip.svelte.d.ts +22 -0
  112. package/esm/ui/dialog/DialogForm.svelte +70 -0
  113. package/esm/ui/dialog/DialogForm.svelte.d.ts +19 -0
  114. package/esm/ui/dialog/DialogManagement.svelte +87 -0
  115. package/esm/ui/dialog/DialogManagement.svelte.d.ts +25 -0
  116. package/esm/ui/dialog/DialogPrimitive.svelte +89 -0
  117. package/esm/ui/dialog/DialogPrimitive.svelte.d.ts +28 -0
  118. package/esm/ui/dialog/FormEditAction.svelte +54 -0
  119. package/esm/ui/dialog/FormEditAction.svelte.d.ts +24 -0
  120. package/esm/ui/dialog/dialog.d.ts +51 -0
  121. package/esm/ui/dialog/dialog.js +98 -0
  122. package/esm/ui/index.d.ts +5 -0
  123. package/esm/ui/index.js +19 -0
  124. package/esm/ui/internals/FieldContainer.svelte +22 -0
  125. package/esm/ui/internals/FieldContainer.svelte.d.ts +30 -0
  126. package/esm/ui/internals/Input.svelte +98 -0
  127. package/esm/ui/internals/Input.svelte.d.ts +35 -0
  128. package/esm/ui/internals/Textarea.svelte +61 -0
  129. package/esm/ui/internals/Textarea.svelte.d.ts +30 -0
  130. package/esm/ui/internals/select/MultiSelectMelt.svelte +217 -0
  131. package/esm/ui/internals/select/MultiSelectMelt.svelte.d.ts +30 -0
  132. package/esm/ui/internals/select/SelectMelt.svelte +238 -0
  133. package/esm/ui/internals/select/SelectMelt.svelte.d.ts +35 -0
  134. package/esm/ui/internals/select/SelectRadio.svelte +37 -0
  135. package/esm/ui/internals/select/SelectRadio.svelte.d.ts +25 -0
  136. package/esm/ui/link/Link.svelte +28 -0
  137. package/esm/ui/link/Link.svelte.d.ts +25 -0
  138. package/esm/ui/link/LinkPlus.svelte +44 -0
  139. package/esm/ui/link/LinkPlus.svelte.d.ts +21 -0
  140. package/esm/utils/tailwind.d.ts +2 -0
  141. package/esm/utils/tailwind.js +3 -0
  142. package/esm/utils/transition.d.ts +10 -0
  143. package/esm/utils/transition.js +33 -0
  144. package/esm/utils/types.d.ts +17 -0
  145. package/esm/utils/types.js +17 -0
  146. package/esm/virtual/Customer.d.ts +4 -0
  147. package/esm/virtual/Customer.js +24 -0
  148. package/esm/virtual/FilterEntity.d.ts +7 -0
  149. package/esm/virtual/FilterEntity.js +34 -0
  150. package/esm/virtual/StateDemoEnum.d.ts +9 -0
  151. package/esm/virtual/StateDemoEnum.js +42 -0
  152. package/esm/virtual/UIEntity.d.ts +16 -0
  153. package/esm/virtual/UIEntity.js +84 -0
  154. package/esm/vite/index.d.ts +8 -0
  155. package/esm/vite/index.js +47 -0
  156. package/package.json +94 -10
package/esm/index.js ADDED
@@ -0,0 +1,42 @@
1
+ import 'remult';
2
+ import { Log } from '@kitql/helpers';
3
+ import { kitStoreItem } from './kitStoreItem.js';
4
+ import { kitStoreList } from './kitStoreList.js';
5
+ import { default as Button } from './ui/Button.svelte';
6
+ import { default as Clipboardable } from './ui/Clipboardable.svelte';
7
+ import { default as DialogManagement } from './ui/dialog/DialogManagement.svelte';
8
+ import { default as FormEditAction } from './ui/dialog/FormEditAction.svelte';
9
+ import { default as Field } from './ui/Field.svelte';
10
+ import { default as FieldGroup } from './ui/FieldGroup.svelte';
11
+ import { default as Grid } from './ui/Grid.svelte';
12
+ import { default as GridPaginate } from './ui/GridPaginate.svelte';
13
+ import { default as Icon } from './ui/Icon.svelte';
14
+ import { default as FieldContainer } from './ui/internals/FieldContainer.svelte';
15
+ import { default as SelectMelt } from './ui/internals/select/SelectMelt.svelte';
16
+ import { default as Link } from './ui/link/Link.svelte';
17
+ import { default as LinkPlus } from './ui/link/LinkPlus.svelte';
18
+ import { default as Loading } from './ui/Loading.svelte';
19
+ import { default as Tooltip } from './ui/Tooltip.svelte';
20
+ export const logFirstly = new Log('firstly');
21
+ export const KitRole = {
22
+ Admin: 'KitAdmin',
23
+ };
24
+ export { Field, FormEditAction, Grid, GridPaginate, FieldGroup, Icon, Link, LinkPlus, Loading, Button, Tooltip, DialogManagement, FieldContainer, SelectMelt, Clipboardable, };
25
+ export { dialog } from './ui/dialog/dialog.js';
26
+ export { KitBaseEnum, getEnum, getEnums } from './KitBaseEnum.js';
27
+ export { KitFields } from './KitFields.js';
28
+ export { KitEntity } from './KitEntity.js';
29
+ export { LogToConsoleCustom } from './SqlDatabase/LogToConsoleCustom.js';
30
+ export { getEntityDisplayValue, isError, kitDbNamesOf, getFieldLinkDisplayValue } from './helper.js';
31
+ export { buildWhere, getPlaceholder, buildSearchWhere, kitCellsBuildor, kitCellBuildor, fieldsOf, } from './kitCellsBuildor.js';
32
+ export { kitStoreItem };
33
+ export { kitStoreList };
34
+ export { FilterEntity } from './virtual/FilterEntity.js';
35
+ export { UIEntity } from './virtual/UIEntity.js';
36
+ // Icons
37
+ export { LibIcon_Empty, LibIcon_Forbidden, LibIcon_ChevronDown, LibIcon_ChevronUp, LibIcon_ChevronLeft, LibIcon_ChevronRight, LibIcon_Search, LibIcon_Check, LibIcon_MultiCheck, LibIcon_Add, LibIcon_MultiAdd, LibIcon_Edit, LibIcon_Delete, LibIcon_Cross, LibIcon_Save, LibIcon_Man, LibIcon_Woman, LibIcon_Send, LibIcon_Load, LibIcon_Settings, LibIcon_Sort, LibIcon_SortAsc, LibIcon_SortDesc, } from './ui/LibIcon.js';
38
+ // Formats & Utils
39
+ export { displayPhone, arrToStr } from './formats/strings.js';
40
+ export { displayCurrency } from './formats/numbers.js';
41
+ export { tw } from './utils/tailwind.js';
42
+ export { litOrStr } from './utils/types.js';
@@ -0,0 +1,45 @@
1
+ import type { SvelteComponent } from 'svelte';
2
+ import { type EntityFilter, type FieldMetadata, type Repository } from 'remult';
3
+ import type { UnArray } from './utils/types.js';
4
+ export type VisibilityMode = 'view' | 'edit' | 'hide';
5
+ type KitCellInternal<Entity> = {
6
+ col?: keyof Entity;
7
+ kind?: 'field' | 'field_link' | 'entity_link' | 'slot' | 'header' | 'component';
8
+ class?: string;
9
+ header?: string;
10
+ headerSlot?: boolean;
11
+ modeEdit?: VisibilityMode;
12
+ modeView?: VisibilityMode;
13
+ clipboardable?: boolean;
14
+ clearable?: boolean;
15
+ component?: new (...args: any[]) => SvelteComponent;
16
+ props?: any;
17
+ rowToProps?: (row: any) => any;
18
+ };
19
+ export type KitCell<Entity> = KitCellInternal<Entity> & {
20
+ field?: FieldMetadata<any, Entity>;
21
+ };
22
+ export type KitCellsInput<Entity> = (keyof Entity | KitCellInternal<Entity>)[];
23
+ /**
24
+ * kitCellsBuildor is a function to build cells for a <Grid /> or <FieldGroup /> component.
25
+ *
26
+ * ```html
27
+ * <script lang="ts">
28
+ * import { repo } from 'remult'
29
+ *
30
+ * const cells = kitCellsBuildor(repo(Site), ['name', 'description'])
31
+ * const store = kitStoreList( repo(Site) )
32
+ * $: store.fetch()
33
+ * </script>
34
+ *
35
+ * <Grid {cells} {store} />
36
+ * ```
37
+ *
38
+ */
39
+ export declare function kitCellsBuildor<Entity>(repo: Repository<Entity>, inputBuildor: KitCellsInput<Entity>): KitCell<Entity>[];
40
+ export declare function kitCellBuildor<Entity>(repo: Repository<Entity>, inputBuildor: UnArray<KitCellsInput<Entity>>): KitCell<Entity>;
41
+ export declare const fieldsOf: <Entity>(b: KitCell<Entity>[]) => FieldMetadata<any, Entity>[];
42
+ export declare const getPlaceholder: <Entity>(fields: FieldMetadata<any, Entity>[]) => string;
43
+ export declare const buildSearchWhere: <Entity>(fields: FieldMetadata<any, Entity>[], search?: string | null) => EntityFilter<Entity>[];
44
+ export declare const buildWhere: <Entity>(defaultWhere: EntityFilter<Entity> | undefined, fields_filter: FieldMetadata<any, Entity>[], fields_search: FieldMetadata<any, Entity>[], obj: Record<string, string>) => EntityFilter<Entity>;
45
+ export {};
@@ -0,0 +1,105 @@
1
+ import {} from 'remult';
2
+ import { getRelationFieldInfo } from 'remult/internals';
3
+ import { getEnum, KitBaseEnum } from './KitBaseEnum.js';
4
+ /**
5
+ * kitCellsBuildor is a function to build cells for a <Grid /> or <FieldGroup /> component.
6
+ *
7
+ * ```html
8
+ * <script lang="ts">
9
+ * import { repo } from 'remult'
10
+ *
11
+ * const cells = kitCellsBuildor(repo(Site), ['name', 'description'])
12
+ * const store = kitStoreList( repo(Site) )
13
+ * $: store.fetch()
14
+ * </script>
15
+ *
16
+ * <Grid {cells} {store} />
17
+ * ```
18
+ *
19
+ */
20
+ export function kitCellsBuildor(repo, inputBuildor) {
21
+ const buildor = [];
22
+ for (let i = 0; i < inputBuildor.length; i++) {
23
+ const item = inputBuildor[i];
24
+ let b;
25
+ if (item instanceof Object) {
26
+ b = { ...item, field: repo.fields[item.col] };
27
+ }
28
+ else {
29
+ b = { col: item, field: repo.fields[item] };
30
+ }
31
+ // Let's tweak defaults...
32
+ if (b.kind === undefined) {
33
+ if (b.field?.options.href) {
34
+ b.kind = 'field_link';
35
+ }
36
+ }
37
+ buildor.push(b);
38
+ }
39
+ return buildor;
40
+ }
41
+ export function kitCellBuildor(repo, inputBuildor) {
42
+ return kitCellsBuildor(repo, [inputBuildor])[0];
43
+ }
44
+ export const fieldsOf = (b) => {
45
+ return b.filter((c) => c.field).map((c) => c.field) ?? [];
46
+ };
47
+ export const getPlaceholder = (fields) => {
48
+ return fields.map((c) => c.caption).join(', ');
49
+ };
50
+ export const buildSearchWhere = (fields, search) => {
51
+ if (!search) {
52
+ return [];
53
+ }
54
+ const f = [
55
+ {
56
+ $or: fields.map((f) => {
57
+ if (f.inputType === 'number') {
58
+ return { [f.key]: search };
59
+ }
60
+ const sSplitted = search.split(' ');
61
+ return {
62
+ $and: sSplitted.map((s) => ({ [f.key]: { $contains: s } })),
63
+ };
64
+ }),
65
+ },
66
+ ];
67
+ return f;
68
+ };
69
+ export const buildWhere = (defaultWhere, fields_filter, fields_search, obj) => {
70
+ const and = [];
71
+ if (defaultWhere) {
72
+ and.push(defaultWhere);
73
+ }
74
+ if (obj.search) {
75
+ and.push(...buildSearchWhere(fields_search, obj.search));
76
+ }
77
+ for (const field of fields_filter) {
78
+ const rfi = getRelationFieldInfo(field);
79
+ // if there is a value
80
+ if (obj[field.key]) {
81
+ if (field.inputType === 'checkbox') {
82
+ // @ts-ignore
83
+ and.push({ [field.key]: obj[field.key] });
84
+ }
85
+ else if (field.inputType === 'selectEnum') {
86
+ // @ts-ignore
87
+ const theEnum = getEnum(field, obj[field.key]);
88
+ // Take the where of the enum if it exists, or it's using this selection as a filter
89
+ // @ts-ignore
90
+ const wheretoUse = theEnum?.where ?? new KitBaseEnum(obj[field.key]);
91
+ // @ts-ignore
92
+ and.push({ [field.key]: wheretoUse });
93
+ }
94
+ else if (rfi.type === 'toOne') {
95
+ // @ts-ignore (stting the id of the relation)
96
+ and.push({ [field.key]: obj[field.key] });
97
+ }
98
+ else {
99
+ console.info(`Not handled filter field ${field.key} ${field.inputType}`);
100
+ }
101
+ }
102
+ }
103
+ // @ts-ignore
104
+ return { $and: and };
105
+ };
@@ -0,0 +1,28 @@
1
+ /// <reference types="svelte" />
2
+ import type { ErrorInfo, FindOptions, Repository } from 'remult';
3
+ type TheStoreItem<T> = {
4
+ item: T | undefined;
5
+ loading?: boolean;
6
+ errors: ErrorInfo<T> | undefined;
7
+ globalError?: string | undefined;
8
+ };
9
+ export declare const kitStoreItem: <T>(repo: Repository<T>, initValues?: TheStoreItem<T>) => {
10
+ subscribe: (this: void, run: import("svelte/store").Subscriber<TheStoreItem<T>>, invalidate?: import("svelte/store").Invalidator<TheStoreItem<T>> | undefined) => import("svelte/store").Unsubscriber;
11
+ create: (item: Partial<T>) => void;
12
+ set: (newItem: TheStoreItem<T>) => void;
13
+ /**
14
+ * if you have keys, build the id with
15
+ * ```ts
16
+ * const id = repo.metadata.idMetadata.getId({a:1,b:2})
17
+ * store.fetch(id)
18
+ * ```
19
+ */
20
+ fetch: (id: Parameters<Repository<T>['findId']>[0], options?: FindOptions<T>, onNewData?: ((item: T) => void) | undefined) => Promise<void>;
21
+ /**
22
+ * `.save()` will `update` or `insert` the current item.
23
+ */
24
+ save: () => Promise<T | undefined>;
25
+ delete: () => Promise<void>;
26
+ onChange: (prop: keyof T, callback: (newValue: any, oldValue: any) => void) => void;
27
+ };
28
+ export {};
@@ -0,0 +1,170 @@
1
+ import { BROWSER } from 'esm-env';
2
+ import { derived, get, writable } from 'svelte/store';
3
+ import { Log } from '@kitql/helpers';
4
+ import { isError } from './helper';
5
+ export const kitStoreItem = (repo, initValues = {
6
+ item: undefined,
7
+ loading: true,
8
+ errors: undefined,
9
+ globalError: undefined,
10
+ }) => {
11
+ const internalStore = writable(initValues);
12
+ // Function to watch changes on a specific property of `item`
13
+ const onChange = (prop, callback) => {
14
+ const itemProperty = derived(internalStore, ($s) => $s.item && $s.item[prop]);
15
+ let oldValue;
16
+ // Subscribe to the derived store to monitor changes
17
+ itemProperty.subscribe((newValue) => {
18
+ if (newValue !== oldValue) {
19
+ if (oldValue !== undefined) {
20
+ // to avoid running on initial undefined state
21
+ callback(newValue, oldValue);
22
+ }
23
+ oldValue = newValue;
24
+ }
25
+ });
26
+ };
27
+ return {
28
+ subscribe: internalStore.subscribe,
29
+ create: (item) => {
30
+ internalStore.set({
31
+ item: repo.create(item),
32
+ loading: false,
33
+ errors: {},
34
+ globalError: undefined,
35
+ });
36
+ },
37
+ // set: internalStore.set,
38
+ set: (newItem) => {
39
+ internalStore.update((s) => {
40
+ return { ...newItem };
41
+ });
42
+ },
43
+ /**
44
+ * if you have keys, build the id with
45
+ * ```ts
46
+ * const id = repo.metadata.idMetadata.getId({a:1,b:2})
47
+ * store.fetch(id)
48
+ * ```
49
+ */
50
+ fetch: async (id, options, onNewData) => {
51
+ if (BROWSER) {
52
+ internalStore.update((s) => ({ ...s, loading: true }));
53
+ try {
54
+ const item = await repo.findId(id, options);
55
+ // lastOptions = options
56
+ internalStore.update((s) => ({
57
+ ...s,
58
+ loading: false,
59
+ item,
60
+ errors: undefined,
61
+ globalError: undefined,
62
+ }));
63
+ if (onNewData) {
64
+ onNewData(item);
65
+ }
66
+ }
67
+ catch (error) {
68
+ if (isError(error)) {
69
+ internalStore.update((s) => ({
70
+ ...s,
71
+ loading: false,
72
+ item: {},
73
+ errors: {},
74
+ // @ts-ignore
75
+ globalError: error.message,
76
+ }));
77
+ }
78
+ }
79
+ }
80
+ },
81
+ /**
82
+ * `.save()` will `update` or `insert` the current item.
83
+ */
84
+ save: async () => {
85
+ const s = get(internalStore);
86
+ try {
87
+ if (!s.item) {
88
+ return;
89
+ }
90
+ const item = await repo.save(s.item);
91
+ internalStore.update((s) => ({
92
+ ...s,
93
+ loading: false,
94
+ item,
95
+ errors: undefined,
96
+ globalError: undefined,
97
+ }));
98
+ return item;
99
+ }
100
+ catch (error) {
101
+ if (isError(error)) {
102
+ if (!error.modelState) {
103
+ internalStore.update((s) => ({
104
+ ...s,
105
+ loading: false,
106
+ item: s.item,
107
+ errors: undefined,
108
+ globalError: error.message,
109
+ }));
110
+ }
111
+ else {
112
+ const errors = {};
113
+ for (const key in error.modelState) {
114
+ // @ts-ignore
115
+ errors[key] = error.modelState[key];
116
+ }
117
+ internalStore.update((s) => ({
118
+ ...s,
119
+ loading: false,
120
+ item: s.item,
121
+ errors,
122
+ globalError: undefined,
123
+ }));
124
+ }
125
+ }
126
+ // After we updated everything, let's throw the error
127
+ throw error;
128
+ }
129
+ },
130
+ delete: async () => {
131
+ const s = get(internalStore);
132
+ if (!s.item) {
133
+ new Log('firstly').error(`To delete an item, you need set it first.`);
134
+ return;
135
+ }
136
+ try {
137
+ await repo.delete(s.item);
138
+ }
139
+ catch (error) {
140
+ if (isError(error)) {
141
+ if (!error.modelState) {
142
+ internalStore.update((s) => ({
143
+ ...s,
144
+ loading: false,
145
+ item: s.item,
146
+ errors: undefined,
147
+ globalError: error.message,
148
+ }));
149
+ }
150
+ else {
151
+ const errors = {};
152
+ for (const key in error.modelState) {
153
+ // @ts-ignore
154
+ errors[key] = error.modelState[key];
155
+ }
156
+ internalStore.update((s) => ({
157
+ ...s,
158
+ loading: false,
159
+ item: s.item,
160
+ errors,
161
+ globalError: undefined,
162
+ }));
163
+ }
164
+ }
165
+ throw error;
166
+ }
167
+ },
168
+ onChange,
169
+ };
170
+ };
@@ -0,0 +1,33 @@
1
+ /// <reference types="svelte" />
2
+ import type { FindOptions, Repository } from 'remult';
3
+ type TheStoreList<T> = {
4
+ items: T[];
5
+ loading: boolean;
6
+ totalCount: number | undefined;
7
+ };
8
+ export type FindOptionsPlus<T> = FindOptions<T> & {
9
+ withCount?: boolean;
10
+ withItems?: boolean;
11
+ };
12
+ /**
13
+ * @param repo remult repository to listen to
14
+ * @param initValues usually the data coming from SSR
15
+ * @returns a store with the initial values and a listen() method to subscribe to changes
16
+ *
17
+ * Example
18
+ * ```ts
19
+ * // get the repo
20
+ * const taskRepo = remult.repo(Task)
21
+ *
22
+ * const tasks = kitStore(taskRepo, data.tasks)
23
+ * $: browser && tasks.listen(data.options)
24
+ * ```
25
+ */
26
+ export declare const kitStoreList: <T>(repo: Repository<T>, initValues?: TheStoreList<T>) => {
27
+ subscribe: (this: void, run: import("svelte/store").Subscriber<TheStoreList<T>>, invalidate?: import("svelte/store").Invalidator<TheStoreList<T>> | undefined) => import("svelte/store").Unsubscriber;
28
+ manualSet: (info: TheStoreList<T>) => void;
29
+ fetch: (options?: FindOptionsPlus<T>, onNewData?: ((items?: T[], totalCount?: number) => void) | undefined) => Promise<void>;
30
+ listen: (options?: FindOptionsPlus<T>) => Promise<void>;
31
+ getRepo: () => Repository<T>;
32
+ };
33
+ export {};
@@ -0,0 +1,98 @@
1
+ import { BROWSER } from 'esm-env';
2
+ import { onDestroy } from 'svelte';
3
+ import { writable } from 'svelte/store';
4
+ /**
5
+ * @param repo remult repository to listen to
6
+ * @param initValues usually the data coming from SSR
7
+ * @returns a store with the initial values and a listen() method to subscribe to changes
8
+ *
9
+ * Example
10
+ * ```ts
11
+ * // get the repo
12
+ * const taskRepo = remult.repo(Task)
13
+ *
14
+ * const tasks = kitStore(taskRepo, data.tasks)
15
+ * $: browser && tasks.listen(data.options)
16
+ * ```
17
+ */
18
+ export const kitStoreList = (repo, initValues = { items: [], loading: true, totalCount: undefined }) => {
19
+ const { subscribe, set, update } = writable(initValues);
20
+ let unSub = null;
21
+ onDestroy(async () => {
22
+ await plzUnSub();
23
+ });
24
+ // if we already have a subscription, unsubscribe (on option update for example)
25
+ const plzUnSub = async () => {
26
+ if (unSub) {
27
+ await unSub();
28
+ unSub = null;
29
+ }
30
+ };
31
+ return {
32
+ subscribe,
33
+ // set,
34
+ manualSet: (info) => {
35
+ set(info);
36
+ },
37
+ fetch: async (options, onNewData) => {
38
+ if (BROWSER) {
39
+ update((s) => ({ ...s, loading: true }));
40
+ const withCount = options?.withCount ?? false;
41
+ const withItems = options?.withItems ?? true;
42
+ if (!withItems && !withCount) {
43
+ throw new Error(`xxx.fetch() withItems and withCount can't be both false!`);
44
+ }
45
+ else if (!withItems && withCount) {
46
+ const totalCount = await repo.count(options?.where);
47
+ set({ loading: false, items: [], totalCount });
48
+ if (onNewData) {
49
+ onNewData(undefined, totalCount);
50
+ }
51
+ }
52
+ else if (withItems && !withCount) {
53
+ const items = await repo.find(options);
54
+ set({ loading: false, items, totalCount: undefined });
55
+ if (onNewData) {
56
+ onNewData(items, undefined);
57
+ }
58
+ }
59
+ else {
60
+ const [items, totalCount] = await Promise.all([
61
+ repo.find({ ...options }),
62
+ repo.count(options?.where),
63
+ ]);
64
+ set({ loading: false, items, totalCount });
65
+ if (onNewData) {
66
+ onNewData(items, totalCount);
67
+ }
68
+ }
69
+ }
70
+ },
71
+ listen: async (options) => {
72
+ if (BROWSER) {
73
+ await plzUnSub();
74
+ unSub = repo.liveQuery({ ...options }).subscribe(async (info) => {
75
+ const withCount = options?.withCount ?? false;
76
+ let totalCount = undefined;
77
+ if (withCount) {
78
+ totalCount = await repo.count(options?.where);
79
+ }
80
+ update((c) => {
81
+ return { ...c, items: info.items, loading: false, ...(withCount ? { totalCount } : {}) };
82
+ });
83
+ });
84
+ }
85
+ else {
86
+ throw new Error(`xxx.listen() Too early!
87
+
88
+ You should do like:
89
+ let tasks = tasksStore<Task>(taskRepo, data.tasks)
90
+ $: browser && tasks.listen()
91
+ `);
92
+ }
93
+ },
94
+ getRepo: () => {
95
+ return repo;
96
+ },
97
+ };
98
+ };
@@ -0,0 +1,11 @@
1
+ import type * as typeNodemailer from 'nodemailer';
2
+ import type Mail from 'nodemailer/lib/mailer';
3
+ export type MailOptions = {
4
+ from?: Mail.Options['from'];
5
+ transport?: Parameters<typeof typeNodemailer.createTransport>[0];
6
+ apiUrl?: Parameters<typeof typeNodemailer.createTestAccount>[0];
7
+ };
8
+ declare let transporter: ReturnType<typeof typeNodemailer.createTransport>;
9
+ export declare const mailInit: (nodemailer: typeof typeNodemailer, o?: MailOptions) => void;
10
+ export declare const sendMail: (topic: string, mailOptions: Parameters<typeof transporter.sendMail>[0]) => ReturnType<typeof transporter.sendMail>;
11
+ export {};
@@ -0,0 +1,51 @@
1
+ import { Log, magenta } from '@kitql/helpers';
2
+ let transporter;
3
+ let options;
4
+ export const mailInit = (nodemailer, o) => {
5
+ options = o;
6
+ if (o?.transport) {
7
+ transporter = nodemailer.createTransport(o?.transport);
8
+ }
9
+ else {
10
+ nodemailerHolder = nodemailer;
11
+ try {
12
+ nodemailer.createTestAccount(options?.apiUrl ?? '', (err, account) => {
13
+ options = { ...options, from: account.user };
14
+ transporter = nodemailer.createTransport({
15
+ host: account.smtp.host,
16
+ port: account.smtp.port,
17
+ secure: account.smtp.secure,
18
+ auth: {
19
+ user: account.user,
20
+ pass: account.pass,
21
+ },
22
+ });
23
+ });
24
+ }
25
+ catch (error) {
26
+ log.error("Error nodemailer.createTestAccount() can't be done.");
27
+ }
28
+ }
29
+ };
30
+ const log = new Log('firstly | mail');
31
+ let nodemailerHolder;
32
+ export const sendMail = async (topic, mailOptions) => {
33
+ try {
34
+ const info = await transporter.sendMail({
35
+ ...mailOptions,
36
+ ...{ from: mailOptions.from ?? options?.from },
37
+ });
38
+ if (!options?.transport) {
39
+ log.info(
40
+ // @ts-ignore
41
+ `${magenta(`[${topic}]`)} - Preview URL: ${nodemailerHolder.getTestMessageUrl(info)}`);
42
+ }
43
+ else {
44
+ log.success(`${magenta(`[${topic}]`)} - Sent to ${mailOptions.to}`);
45
+ }
46
+ return info;
47
+ }
48
+ catch (error) {
49
+ log.error(`${magenta(`[${topic}]`)} - Error`, error);
50
+ }
51
+ };
package/esm/theme.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ export declare const scrollbar: {
2
+ default: string;
3
+ thin: string;
4
+ };
package/esm/theme.js ADDED
@@ -0,0 +1,4 @@
1
+ export const scrollbar = {
2
+ default: 'scrollbar scrollbar-thumb-neutral-focus scrollbar-track-base-200',
3
+ thin: 'sm:scrollbar-thin sm:scrollbar-thumb-neutral-focus sm:scrollbar-track-base-200',
4
+ };