firstly 0.0.16-next.2 → 0.1.0-next.3
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 +33 -0
- package/esm/FF_Entity.d.ts +1 -1
- package/esm/FF_Entity.js +9 -9
- package/esm/ROUTES.d.ts +1 -1
- package/esm/ROUTES.js +2 -2
- package/esm/SqlDatabase/FF_LogToConsole.d.ts +14 -0
- package/esm/SqlDatabase/FF_LogToConsole.js +24 -5
- package/esm/auth/Entities.d.ts +2 -1
- package/esm/auth/Entities.js +18 -14
- package/esm/auth/server/AuthController.server.js +86 -93
- package/esm/auth/server/handleAuth.d.ts +4 -2
- package/esm/auth/server/handleAuth.js +8 -4
- package/esm/auth/server/helperRole.d.ts +11 -4
- package/esm/auth/server/helperRole.js +29 -20
- package/esm/auth/server/index.d.ts +1 -0
- package/esm/auth/server/index.js +1 -0
- package/esm/auth/server/module.d.ts +27 -5
- package/esm/auth/server/module.js +24 -10
- package/esm/auth/server/providers/github.js +13 -2
- package/esm/auth/static/assets/Page-BHW08QWz.css +1 -0
- package/esm/auth/static/assets/{Page-BorYIfy9.d.ts → Page-CTZPxniP.d.ts} +2 -2
- package/esm/auth/static/assets/Page-CTZPxniP.js +1 -0
- package/esm/auth/static/assets/{Page-CqsLm8yQ.d.ts → Page-D0d9iZO-.d.ts} +2 -2
- package/esm/auth/static/assets/{Page-CqsLm8yQ.js → Page-D0d9iZO-.js} +1 -1
- package/esm/auth/static/assets/{Page-Cm4MsdIa.d.ts → Page-DXshwJi7.d.ts} +2 -2
- package/esm/auth/static/assets/Page-DXshwJi7.js +20 -0
- package/esm/auth/static/assets/{index-Borxa2ns.d.ts → index-LRDptjak.d.ts} +3 -20
- package/esm/auth/static/assets/{index-Borxa2ns.js → index-LRDptjak.js} +2 -2
- package/esm/auth/static/index.html +1 -1
- package/esm/auth/types.d.ts +1 -0
- package/esm/bin/cmd.js +16 -16
- package/esm/changeLog/changeLogEntities.d.ts +21 -0
- package/esm/changeLog/changeLogEntities.js +57 -0
- package/esm/changeLog/index.d.ts +3 -15
- package/esm/changeLog/index.js +3 -51
- package/esm/changeLog/server/index.d.ts +39 -28
- package/esm/changeLog/server/index.js +40 -29
- package/esm/cron/Cron.d.ts +11 -0
- package/esm/cron/Cron.js +43 -0
- package/esm/cron/Role_Cron.d.ts +3 -0
- package/esm/cron/Role_Cron.js +3 -0
- package/esm/cron/index.d.ts +3 -0
- package/esm/cron/index.js +3 -0
- package/esm/cron/server/index.d.ts +29 -11
- package/esm/cron/server/index.js +29 -13
- package/esm/feedback/FeedbackController.d.ts +3 -1
- package/esm/feedback/FeedbackController.js +23 -1
- package/esm/feedback/server/index.d.ts +2 -2
- package/esm/feedback/server/index.js +2 -2
- package/esm/feedback/types.d.ts +6 -0
- package/esm/feedback/ui/DialogIssue.svelte +8 -1
- package/esm/feedback/ui/DialogIssues.svelte +1 -1
- package/esm/formats/index.d.ts +1 -1
- package/esm/formats/index.js +1 -1
- package/esm/formats/strings.d.ts +2 -0
- package/esm/formats/strings.js +22 -0
- package/esm/index.d.ts +1 -2
- package/esm/index.js +0 -2
- package/esm/mail/Mail.d.ts +13 -0
- package/esm/mail/Mail.js +51 -0
- package/esm/mail/Role_Mail.d.ts +3 -0
- package/esm/mail/Role_Mail.js +3 -0
- package/esm/mail/index.d.ts +7 -2
- package/esm/mail/index.js +7 -2
- package/esm/mail/server/formatMailHelper.d.ts +16 -0
- package/esm/mail/server/formatMailHelper.js +113 -0
- package/esm/mail/server/index.d.ts +32 -19
- package/esm/mail/server/index.js +113 -38
- package/esm/server/index.d.ts +9 -6
- package/esm/server/index.js +28 -50
- package/esm/svelte/FF_Layout.svelte +2 -2
- package/esm/svelte/dialog/DialogManagement.svelte +2 -2
- package/esm/svelte/helpers.d.ts +1 -0
- package/esm/svelte/index.d.ts +1 -0
- package/esm/svelte/index.js +1 -0
- package/esm/svelte/initRemultSvelteReactivity.d.ts +1 -0
- package/esm/svelte/initRemultSvelteReactivity.js +29 -0
- package/esm/sveltekit/server/index.d.ts +2 -2
- package/esm/sveltekit/server/index.js +2 -2
- package/esm/ui/Button.svelte +1 -1
- package/esm/ui/Field.svelte +5 -3
- package/esm/ui/Field.svelte.d.ts +4 -1
- package/esm/ui/FieldGroup.svelte +2 -1
- package/esm/ui/FieldGroup.svelte.d.ts +4 -1
- package/esm/ui/GridPaginate.svelte +2 -2
- package/esm/ui/GridPaginate2.svelte +1 -1
- package/esm/ui/Loading.svelte +1 -1
- package/esm/ui/Tooltip.svelte +1 -1
- package/esm/ui/dialog/DialogForm.svelte +3 -3
- package/esm/ui/dialog/DialogManagement.svelte +2 -2
- package/esm/ui/dialog/DialogPrimitive.svelte +2 -2
- package/esm/ui/dialog/FormEditAction.svelte +2 -2
- package/esm/ui/internals/FieldContainer.svelte +2 -2
- package/esm/ui/internals/Textarea.svelte +2 -2
- package/esm/ui/internals/select/MultiSelectMelt.svelte +6 -6
- package/esm/ui/internals/select/SelectMelt.svelte +28 -14
- package/esm/ui/internals/select/SelectMelt.svelte.d.ts +4 -1
- package/esm/ui/link/LinkPlus.svelte +2 -2
- package/esm/vite/index.js +50 -52
- package/package.json +15 -12
- package/esm/auth/static/assets/Page-BorYIfy9.js +0 -1
- package/esm/auth/static/assets/Page-Cm4MsdIa.js +0 -20
- package/esm/auth/static/assets/Page-JfNiCSIG.css +0 -1
- package/esm/mail/templates/DefaultMail.svelte +0 -86
- package/esm/mail/templates/DefaultMail.svelte.d.ts +0 -30
|
@@ -1,38 +1,51 @@
|
|
|
1
1
|
import type * as typeNodemailer from 'nodemailer';
|
|
2
2
|
import type JSONTransport from 'nodemailer/lib/json-transport';
|
|
3
|
-
import type Mail from 'nodemailer/lib/mailer';
|
|
4
3
|
import type SendmailTransport from 'nodemailer/lib/sendmail-transport';
|
|
5
4
|
import type SESTransport from 'nodemailer/lib/ses-transport';
|
|
6
5
|
import type SMTPPool from 'nodemailer/lib/smtp-pool';
|
|
7
6
|
import type SMTPTransport from 'nodemailer/lib/smtp-transport';
|
|
8
7
|
import type StreamTransport from 'nodemailer/lib/stream-transport';
|
|
9
|
-
import
|
|
10
|
-
import {
|
|
11
|
-
|
|
12
|
-
export type
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
from?:
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
8
|
+
import { Module } from 'remult/server';
|
|
9
|
+
import { type MailStyle } from './formatMailHelper';
|
|
10
|
+
export type TransportTypes = SMTPPool | SMTPPool.Options | SendmailTransport | SendmailTransport.Options | StreamTransport | StreamTransport.Options | JSONTransport | JSONTransport.Options | SESTransport | SESTransport.Options | SMTPTransport | SMTPTransport.Options | string;
|
|
11
|
+
export type DefaultOptions = typeNodemailer.SendMailOptions;
|
|
12
|
+
type GlobalEasyOptions = {
|
|
13
|
+
saveHtml?: boolean;
|
|
14
|
+
from?: DefaultOptions['from'];
|
|
15
|
+
service?: string;
|
|
16
|
+
primaryColor?: string;
|
|
17
|
+
secondaryColor?: string;
|
|
18
|
+
footer?: string;
|
|
19
|
+
toHtml?: (args: MailStyle) => string;
|
|
20
|
+
};
|
|
21
|
+
export type MailOptions = GlobalEasyOptions & {
|
|
22
|
+
nodemailer?: {
|
|
23
|
+
transport?: TransportTypes;
|
|
24
|
+
defaults?: DefaultOptions;
|
|
19
25
|
};
|
|
20
|
-
transport?: TransportTypes;
|
|
21
|
-
defaults?: DefaultOptions;
|
|
22
|
-
apiUrl?: Parameters<typeof typeNodemailer.createTestAccount>[0];
|
|
23
26
|
};
|
|
24
27
|
declare let transporter: ReturnType<typeof typeNodemailer.createTransport>;
|
|
25
28
|
declare module 'remult' {
|
|
26
29
|
interface RemultContext {
|
|
27
|
-
/** Better checking is it's present or not, that's why it's "?" */
|
|
28
30
|
sendMail?: SendMail;
|
|
29
31
|
}
|
|
30
32
|
}
|
|
31
33
|
export type SendMail = typeof sendMail;
|
|
32
|
-
export declare const sendMail:
|
|
34
|
+
export declare const sendMail: (
|
|
33
35
|
/** usefull for logs, it has NO impact on the mail itself */
|
|
34
|
-
topic: string,
|
|
35
|
-
|
|
36
|
+
topic: string, easyOptions: GlobalEasyOptions & {
|
|
37
|
+
to: Required<DefaultOptions>['to'];
|
|
38
|
+
subject: Required<DefaultOptions>['subject'];
|
|
39
|
+
title?: string;
|
|
40
|
+
sections: {
|
|
41
|
+
html: string;
|
|
42
|
+
cta?: {
|
|
43
|
+
html: string;
|
|
44
|
+
link: string;
|
|
45
|
+
} | undefined;
|
|
46
|
+
}[];
|
|
47
|
+
}, options?: {
|
|
48
|
+
nodemailer?: MailOptions['nodemailer'];
|
|
36
49
|
}) => ReturnType<typeof transporter.sendMail>;
|
|
37
|
-
export declare const mail: (o?: MailOptions
|
|
50
|
+
export declare const mail: (o?: MailOptions) => Module<unknown>;
|
|
38
51
|
export {};
|
package/esm/mail/server/index.js
CHANGED
|
@@ -1,22 +1,38 @@
|
|
|
1
1
|
import nodemailer from 'nodemailer';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { remult } from 'remult';
|
|
2
|
+
import { remult, repo } from 'remult';
|
|
3
|
+
import { Module } from 'remult/server';
|
|
5
4
|
import { cyan, green, magenta, red, sleep, white } from '@kitql/helpers';
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
5
|
+
import { log, mailEntities } from '../index';
|
|
6
|
+
import { toHtml } from './formatMailHelper';
|
|
8
7
|
let transporter;
|
|
9
8
|
let globalOptions;
|
|
10
9
|
const initMail = async (o) => {
|
|
11
|
-
globalOptions =
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
globalOptions = {
|
|
11
|
+
...o,
|
|
12
|
+
nodemailer: {
|
|
13
|
+
...o?.nodemailer,
|
|
14
|
+
defaults: {
|
|
15
|
+
from: o?.from,
|
|
16
|
+
...o?.nodemailer?.defaults,
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
};
|
|
20
|
+
if (o?.nodemailer?.transport) {
|
|
21
|
+
transporter = nodemailer.createTransport(o?.nodemailer?.transport, o?.nodemailer?.defaults);
|
|
14
22
|
}
|
|
15
23
|
else {
|
|
16
24
|
try {
|
|
17
|
-
nodemailer.createTestAccount(
|
|
25
|
+
nodemailer.createTestAccount((err, account) => {
|
|
18
26
|
if (account) {
|
|
19
|
-
globalOptions = {
|
|
27
|
+
globalOptions = {
|
|
28
|
+
...globalOptions,
|
|
29
|
+
...{
|
|
30
|
+
...globalOptions?.nodemailer,
|
|
31
|
+
nodemailer: {
|
|
32
|
+
defaults: { from: account.user },
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
};
|
|
20
36
|
transporter = nodemailer.createTransport({
|
|
21
37
|
host: account.smtp.host,
|
|
22
38
|
port: account.smtp.port,
|
|
@@ -28,16 +44,52 @@ const initMail = async (o) => {
|
|
|
28
44
|
});
|
|
29
45
|
}
|
|
30
46
|
else {
|
|
31
|
-
|
|
47
|
+
log.error("Error nodemailer.createTestAccount() can't be done.");
|
|
32
48
|
}
|
|
33
49
|
});
|
|
34
50
|
}
|
|
35
51
|
catch (error) {
|
|
36
|
-
|
|
52
|
+
log.error("Error nodemailer.createTestAccount() can't be done.");
|
|
37
53
|
}
|
|
38
54
|
}
|
|
39
55
|
};
|
|
40
|
-
export const sendMail = async (topic,
|
|
56
|
+
export const sendMail = async (topic, easyOptions, options) => {
|
|
57
|
+
let { nodemailer: nodemailerOptions } = options ?? {};
|
|
58
|
+
const easyOptionsToUse = {
|
|
59
|
+
...easyOptions,
|
|
60
|
+
service: easyOptions.service ?? globalOptions?.service,
|
|
61
|
+
primaryColor: easyOptions.primaryColor ?? globalOptions?.primaryColor,
|
|
62
|
+
secondaryColor: easyOptions.secondaryColor ?? globalOptions?.secondaryColor,
|
|
63
|
+
footer: easyOptions.footer ?? globalOptions?.footer,
|
|
64
|
+
from: easyOptions.from ?? globalOptions?.from,
|
|
65
|
+
};
|
|
66
|
+
let { primaryColor, secondaryColor, title, footer, service } = easyOptionsToUse;
|
|
67
|
+
const { subject, sections, to } = easyOptionsToUse;
|
|
68
|
+
service = service ?? 'service';
|
|
69
|
+
primaryColor = primaryColor ?? '#0d0f70';
|
|
70
|
+
secondaryColor = secondaryColor ?? '#653eae';
|
|
71
|
+
title = title ?? subject ?? 'subject';
|
|
72
|
+
footer = footer ?? 'The team wishes you a great day 🚀';
|
|
73
|
+
const metadata = {
|
|
74
|
+
service,
|
|
75
|
+
primaryColor,
|
|
76
|
+
secondaryColor,
|
|
77
|
+
subject,
|
|
78
|
+
title,
|
|
79
|
+
footer,
|
|
80
|
+
sections,
|
|
81
|
+
};
|
|
82
|
+
const html = easyOptionsToUse.toHtml ? easyOptionsToUse.toHtml(metadata) : toHtml(metadata);
|
|
83
|
+
nodemailerOptions = {
|
|
84
|
+
defaults: {
|
|
85
|
+
...globalOptions?.nodemailer?.defaults,
|
|
86
|
+
to,
|
|
87
|
+
subject,
|
|
88
|
+
html,
|
|
89
|
+
...nodemailerOptions?.defaults,
|
|
90
|
+
from: easyOptionsToUse.from ?? globalOptions?.from,
|
|
91
|
+
},
|
|
92
|
+
};
|
|
41
93
|
// if the transporter is not ready, wait for it! (it can happen only if nothing is set...)
|
|
42
94
|
for (let i = 0; i < 30; i++) {
|
|
43
95
|
if (transporter !== undefined) {
|
|
@@ -46,47 +98,70 @@ export const sendMail = async (topic, mailOptions) => {
|
|
|
46
98
|
await sleep(100);
|
|
47
99
|
}
|
|
48
100
|
try {
|
|
49
|
-
if (!
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
mailOptions.html = render({ template, props, options: { plainText: false, pretty: true } });
|
|
57
|
-
}
|
|
58
|
-
const info = await transporter.sendMail({
|
|
59
|
-
...mailOptions,
|
|
60
|
-
...{ from: mailOptions.from ?? globalOptions?.from },
|
|
61
|
-
});
|
|
62
|
-
if (!globalOptions?.transport) {
|
|
63
|
-
mailModule.log.error(`${magenta(`[${topic}]`)} - ⚠️ ${red(`mail not configured`)} ⚠️
|
|
64
|
-
We are still nice and generated you an email preview link:
|
|
65
|
-
👉 ${cyan(String(nodemailer.getTestMessageUrl(
|
|
66
|
-
// @ts-ignore
|
|
67
|
-
info)))}
|
|
68
|
-
|
|
69
|
-
To really send mails, check out the doc ${white(`https://firstly.fun/modules/mail`)}.
|
|
101
|
+
if (!globalOptions?.nodemailer?.transport) {
|
|
102
|
+
const info = await transporter.sendMail({ ...nodemailerOptions.defaults });
|
|
103
|
+
log.error(`${magenta(`[${topic}]`)} - ⚠️ ${red(`mail not configured`)} ⚠️
|
|
104
|
+
We are still nice and generated you an email preview link (the mail we not really sent):
|
|
105
|
+
👉 ${cyan(String(nodemailer.getTestMessageUrl(info)))}
|
|
106
|
+
|
|
107
|
+
To really send mails, check out the doc ${white(`https://firstly.fun/modules/mail`)}.
|
|
70
108
|
`);
|
|
109
|
+
await repo(mailEntities.Mail).insert({
|
|
110
|
+
status: 'transport_not_configured',
|
|
111
|
+
to: JSON.stringify(to),
|
|
112
|
+
html: easyOptionsToUse.saveHtml ? html : '',
|
|
113
|
+
topic,
|
|
114
|
+
metadata,
|
|
115
|
+
});
|
|
116
|
+
return info;
|
|
71
117
|
}
|
|
72
118
|
else {
|
|
73
|
-
|
|
119
|
+
const info = await transporter.sendMail({ ...nodemailerOptions.defaults });
|
|
120
|
+
log.success(`${magenta(`[${topic}]`)} - Sent to ${typeof nodemailerOptions.defaults?.to === 'string' ? green(nodemailerOptions.defaults?.to) : nodemailerOptions.defaults?.to}`);
|
|
121
|
+
await repo(mailEntities.Mail).insert({
|
|
122
|
+
status: 'sent',
|
|
123
|
+
to: JSON.stringify(to),
|
|
124
|
+
html: easyOptionsToUse.saveHtml ? html : '',
|
|
125
|
+
topic,
|
|
126
|
+
metadata,
|
|
127
|
+
});
|
|
128
|
+
return info;
|
|
74
129
|
}
|
|
75
|
-
return info;
|
|
76
130
|
}
|
|
77
131
|
catch (error) {
|
|
78
|
-
|
|
132
|
+
if (error instanceof Error && error.message.includes('Missing credentials for "PLAIN"')) {
|
|
133
|
+
log.error(`${magenta(`[${topic}]`)} - ⚠️ ${red(`mail not well configured`)} ⚠️
|
|
134
|
+
👉 transport used:
|
|
135
|
+
${cyan(JSON.stringify(globalOptions?.nodemailer?.transport, null, 2))}
|
|
136
|
+
`);
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
log.error(`${magenta(`[${topic}]`)} - Error`, error);
|
|
140
|
+
}
|
|
141
|
+
await repo(mailEntities.Mail).insert({
|
|
142
|
+
status: 'error',
|
|
143
|
+
errorInfo: JSON.stringify(error),
|
|
144
|
+
to: JSON.stringify(to),
|
|
145
|
+
html: easyOptionsToUse.saveHtml ? html : '',
|
|
146
|
+
topic,
|
|
147
|
+
metadata,
|
|
148
|
+
});
|
|
149
|
+
throw error;
|
|
79
150
|
}
|
|
80
151
|
};
|
|
81
152
|
const mailModule = new Module({
|
|
82
|
-
|
|
153
|
+
key: 'mail',
|
|
83
154
|
priority: -888,
|
|
155
|
+
entities: Object.values(mailEntities),
|
|
84
156
|
});
|
|
85
157
|
export const mail = (o) => {
|
|
86
158
|
mailModule.initApi = () => {
|
|
87
159
|
initMail(o);
|
|
160
|
+
// Need to init in the 2 places!
|
|
161
|
+
remult.context.sendMail = sendMail;
|
|
88
162
|
};
|
|
89
163
|
mailModule.initRequest = async () => {
|
|
164
|
+
// Need to init in the 2 places!
|
|
90
165
|
remult.context.sendMail = sendMail;
|
|
91
166
|
};
|
|
92
167
|
return mailModule;
|
package/esm/server/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { RequestEvent } from '@sveltejs/kit';
|
|
2
2
|
import { type ClassType } from 'remult';
|
|
3
|
-
import type
|
|
3
|
+
import { type RemultServerOptions } from 'remult/server';
|
|
4
4
|
import { Log } from '@kitql/helpers';
|
|
5
5
|
type ModuleInput = {
|
|
6
6
|
/**
|
|
@@ -12,9 +12,10 @@ type ModuleInput = {
|
|
|
12
12
|
controllers?: ClassType<any>[];
|
|
13
13
|
initApi?: RemultServerOptions<RequestEvent>['initApi'];
|
|
14
14
|
initRequest?: RemultServerOptions<RequestEvent>['initRequest'];
|
|
15
|
-
modules
|
|
15
|
+
/** @deprecated use `remult` modules instead */
|
|
16
|
+
modulesFF?: ModuleFF[];
|
|
16
17
|
};
|
|
17
|
-
export declare class
|
|
18
|
+
export declare class ModuleFF {
|
|
18
19
|
name: string;
|
|
19
20
|
log: Log;
|
|
20
21
|
priority?: number;
|
|
@@ -22,11 +23,13 @@ export declare class Module {
|
|
|
22
23
|
controllers?: ClassType<any>[];
|
|
23
24
|
initApi?: RemultServerOptions<RequestEvent>['initApi'];
|
|
24
25
|
initRequest?: RemultServerOptions<RequestEvent>['initRequest'];
|
|
25
|
-
modules
|
|
26
|
+
/** @deprecated use `remult` modules instead */
|
|
27
|
+
modulesFF?: ModuleFF[];
|
|
26
28
|
constructor(input: ModuleInput);
|
|
27
29
|
}
|
|
28
30
|
type Options = RemultServerOptions<RequestEvent<Partial<Record<string, string>>, string | null>> & {
|
|
29
|
-
modules
|
|
31
|
+
/** @deprecated use `remult` modules instead */
|
|
32
|
+
modulesFF?: ModuleFF[] | undefined;
|
|
30
33
|
};
|
|
31
34
|
declare module 'remult' {
|
|
32
35
|
interface RemultContext {
|
|
@@ -45,5 +48,5 @@ export declare const firstly: (o: Options) => import("remult/remult-sveltekit").
|
|
|
45
48
|
/**
|
|
46
49
|
* Full flat and ordered list by index and concatenaining the modules name
|
|
47
50
|
*/
|
|
48
|
-
export declare const modulesFlatAndOrdered: (modules:
|
|
51
|
+
export declare const modulesFlatAndOrdered: (modules: ModuleFF[]) => ModuleFF[];
|
|
49
52
|
export {};
|
package/esm/server/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {} from 'remult';
|
|
2
|
-
import {
|
|
2
|
+
import { remultApi } from 'remult/remult-sveltekit';
|
|
3
|
+
import { Module } from 'remult/server';
|
|
3
4
|
import { Log } from '@kitql/helpers';
|
|
4
|
-
import { building } from '$app/environment';
|
|
5
5
|
import { sveltekit } from '../sveltekit/server';
|
|
6
|
-
export class
|
|
6
|
+
export class ModuleFF {
|
|
7
7
|
name;
|
|
8
8
|
log;
|
|
9
9
|
priority;
|
|
@@ -11,7 +11,8 @@ export class Module {
|
|
|
11
11
|
controllers;
|
|
12
12
|
initApi;
|
|
13
13
|
initRequest;
|
|
14
|
-
modules
|
|
14
|
+
/** @deprecated use `remult` modules instead */
|
|
15
|
+
modulesFF;
|
|
15
16
|
constructor(input) {
|
|
16
17
|
this.name = input.name;
|
|
17
18
|
this.log = new Log(`firstly | ${this.name}`);
|
|
@@ -20,7 +21,7 @@ export class Module {
|
|
|
20
21
|
this.controllers = input.controllers;
|
|
21
22
|
this.initApi = input.initApi;
|
|
22
23
|
this.initRequest = input.initRequest;
|
|
23
|
-
this.
|
|
24
|
+
this.modulesFF = input.modulesFF;
|
|
24
25
|
}
|
|
25
26
|
}
|
|
26
27
|
export let entities = [];
|
|
@@ -29,18 +30,24 @@ export let entities = [];
|
|
|
29
30
|
* @deprecated will be done directly in remult when modules will be in 😉
|
|
30
31
|
*/
|
|
31
32
|
export const firstly = (o) => {
|
|
32
|
-
const modulesSorted = modulesFlatAndOrdered([
|
|
33
|
-
|
|
34
|
-
new Module({
|
|
35
|
-
|
|
36
|
-
entities:
|
|
37
|
-
controllers:
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
})
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
33
|
+
const modulesSorted = modulesFlatAndOrdered([...[...(o.modulesFF ?? []), sveltekit()]]);
|
|
34
|
+
const ffModulesToRemult = modulesSorted.map((m) => {
|
|
35
|
+
return new Module({
|
|
36
|
+
key: m.name,
|
|
37
|
+
entities: m.entities ?? [],
|
|
38
|
+
controllers: m.controllers ?? [],
|
|
39
|
+
initApi: m.initApi,
|
|
40
|
+
initRequest: m.initRequest,
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
// REMULT P1: With Generate Migrations it's a bit hard to get all entities from all modules.
|
|
44
|
+
entities = [
|
|
45
|
+
...modulesSorted.flatMap((m) => m.entities ?? []),
|
|
46
|
+
...(o.entities ?? []),
|
|
47
|
+
//Managing only the first level... should be ok for now...
|
|
48
|
+
...(o?.modules?.flatMap((m) => m.entities ?? []) ?? []),
|
|
49
|
+
];
|
|
50
|
+
return remultApi({
|
|
44
51
|
// Changing the default default of remult
|
|
45
52
|
logApiEndPoints: false,
|
|
46
53
|
admin: true,
|
|
@@ -56,37 +63,8 @@ export const firstly = (o) => {
|
|
|
56
63
|
},
|
|
57
64
|
// Add user configuration
|
|
58
65
|
...o,
|
|
59
|
-
//
|
|
60
|
-
|
|
61
|
-
controllers: modulesSorted.flatMap((m) => m.controllers ?? []),
|
|
62
|
-
initRequest: async (kitEvent, op) => {
|
|
63
|
-
for (let i = 0; i < modulesSorted.length; i++) {
|
|
64
|
-
const f = modulesSorted[i].initRequest;
|
|
65
|
-
if (f) {
|
|
66
|
-
try {
|
|
67
|
-
await f(kitEvent, op);
|
|
68
|
-
}
|
|
69
|
-
catch (error) {
|
|
70
|
-
modulesSorted[i].log.error(error);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
},
|
|
75
|
-
initApi: async (r) => {
|
|
76
|
-
if (!building) {
|
|
77
|
-
for (let i = 0; i < modulesSorted.length; i++) {
|
|
78
|
-
const f = modulesSorted[i].initApi;
|
|
79
|
-
if (f) {
|
|
80
|
-
try {
|
|
81
|
-
await f(r);
|
|
82
|
-
}
|
|
83
|
-
catch (error) {
|
|
84
|
-
modulesSorted[i].log.error(error);
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
},
|
|
66
|
+
// native remult modules
|
|
67
|
+
modules: [...(o.modules ?? []), ...ffModulesToRemult],
|
|
90
68
|
});
|
|
91
69
|
};
|
|
92
70
|
/**
|
|
@@ -97,9 +75,9 @@ export const modulesFlatAndOrdered = (modules) => {
|
|
|
97
75
|
return modules.reduce((acc, module) => {
|
|
98
76
|
const fullName = parentName ? `${parentName}-${module.name}` : module.name;
|
|
99
77
|
// Create a new module object without the 'modules' property
|
|
100
|
-
const {
|
|
78
|
+
const { modulesFF: _, ...flatModule } = module;
|
|
101
79
|
const newModule = { ...flatModule, name: fullName };
|
|
102
|
-
const subModules = module.
|
|
80
|
+
const subModules = module.modulesFF ? flattenModules(module.modulesFF, fullName) : [];
|
|
103
81
|
return [...acc, newModule, ...subModules];
|
|
104
82
|
}, []);
|
|
105
83
|
};
|
|
@@ -39,14 +39,14 @@
|
|
|
39
39
|
onchange={() => (selectedThing = group.key)}
|
|
40
40
|
aria-label={group.caption}
|
|
41
41
|
/>
|
|
42
|
-
<div role="tabpanel" class="tab-content
|
|
42
|
+
<div role="tabpanel" class="tab-content rounded-box border-base-300 bg-base-100 p-6">
|
|
43
43
|
<FF_Form {r} groups={[group]} show={{ title: false }}></FF_Form>
|
|
44
44
|
</div>
|
|
45
45
|
{/each}
|
|
46
46
|
</div>
|
|
47
47
|
{:else if layoutToUse.type === 'accordion'}
|
|
48
48
|
{#each layoutToUse.groups ?? [] as group (group.key)}
|
|
49
|
-
<div class="bg-base-100
|
|
49
|
+
<div class="collapse bg-base-100">
|
|
50
50
|
<input
|
|
51
51
|
type="radio"
|
|
52
52
|
name="my-accordion"
|
|
@@ -85,10 +85,10 @@
|
|
|
85
85
|
<p>Hey 🫵 developer, you are missing a few things 🤡!</p>
|
|
86
86
|
<p>Or use use one of the custom built in dialog like</p>
|
|
87
87
|
|
|
88
|
-
<pre class="bg-base-300
|
|
88
|
+
<pre class="mt-2 bg-base-300 p-2 text-xs">await dialog.confirmDelete('The Car')</pre>
|
|
89
89
|
|
|
90
90
|
<p>Or pass you own component</p>
|
|
91
|
-
<pre class="bg-base-300
|
|
91
|
+
<pre class="mt-2 bg-base-300 p-2 text-xs">{`await dialog.show({
|
|
92
92
|
detail: { caption: 'Interlocuteur' },
|
|
93
93
|
component: CreateCarForm,
|
|
94
94
|
props: { isEdit: false },
|
package/esm/svelte/helpers.d.ts
CHANGED
package/esm/svelte/index.d.ts
CHANGED
|
@@ -20,6 +20,7 @@ export { overwriteOptions, deepMerge, isOfType } from './helpers';
|
|
|
20
20
|
export { dialog } from './dialog/dialog';
|
|
21
21
|
export { SP } from './class/SP.svelte';
|
|
22
22
|
export type { ParamDefinition } from './class/SP.svelte';
|
|
23
|
+
export { initRemultSvelteReactivity } from './initRemultSvelteReactivity';
|
|
23
24
|
declare module 'remult' {
|
|
24
25
|
interface FieldOptions<entityType = unknown, valueType = unknown> {
|
|
25
26
|
ui?: CellMetadata<valueType, entityType>['ui'];
|
package/esm/svelte/index.js
CHANGED
|
@@ -16,6 +16,7 @@ export { tryCatch, tryCatchSync } from './tryCatch';
|
|
|
16
16
|
export { overwriteOptions, deepMerge, isOfType } from './helpers';
|
|
17
17
|
export { dialog } from './dialog/dialog';
|
|
18
18
|
export { SP } from './class/SP.svelte';
|
|
19
|
+
export { initRemultSvelteReactivity } from './initRemultSvelteReactivity';
|
|
19
20
|
// - [ ] Try to pnpm pack to see what css is needed.
|
|
20
21
|
// - [ ] let's look at the data-ff-xxx story ?
|
|
21
22
|
// - [ ] how lib defaults should be configured ?
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function initRemultSvelteReactivity(): void;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { createSubscriber } from 'svelte/reactivity';
|
|
2
|
+
import { Remult, remult } from 'remult';
|
|
3
|
+
// To be done once in the application.
|
|
4
|
+
export function initRemultSvelteReactivity() {
|
|
5
|
+
// Auth reactivity (remult.user, remult.authenticated(), ...)
|
|
6
|
+
{
|
|
7
|
+
let update = () => { };
|
|
8
|
+
const s = createSubscriber((u) => {
|
|
9
|
+
update = u;
|
|
10
|
+
});
|
|
11
|
+
remult.subscribeAuth({
|
|
12
|
+
reportObserved: () => s(),
|
|
13
|
+
reportChanged: () => update(),
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
// Entities reactivity
|
|
17
|
+
{
|
|
18
|
+
Remult.entityRefInit = (x) => {
|
|
19
|
+
let update = () => { };
|
|
20
|
+
const s = createSubscriber((u) => {
|
|
21
|
+
update = u;
|
|
22
|
+
});
|
|
23
|
+
x.subscribe({
|
|
24
|
+
reportObserved: () => s(),
|
|
25
|
+
reportChanged: () => update(),
|
|
26
|
+
});
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { remult } from 'remult';
|
|
2
|
-
import {
|
|
2
|
+
import { ModuleFF } from '../../server';
|
|
3
3
|
/**
|
|
4
4
|
* @deprecated will be done directly in remult when modules will be in 😉
|
|
5
5
|
*/
|
|
6
6
|
export const sveltekit = () => {
|
|
7
|
-
return new
|
|
7
|
+
return new ModuleFF({
|
|
8
8
|
name: 'sveltekit',
|
|
9
9
|
priority: -779,
|
|
10
10
|
entities: [],
|
package/esm/ui/Button.svelte
CHANGED
|
@@ -102,7 +102,7 @@
|
|
|
102
102
|
{...$content}
|
|
103
103
|
use:content
|
|
104
104
|
transition:fade={{ duration: 100 }}
|
|
105
|
-
class="
|
|
105
|
+
class="z-30 rounded-lg bg-base-300 ring-1 ring-black"
|
|
106
106
|
>
|
|
107
107
|
<div {...$arrow} use:arrow></div>
|
|
108
108
|
<div class="px-4 py-1">
|
package/esm/ui/Field.svelte
CHANGED
|
@@ -40,6 +40,7 @@
|
|
|
40
40
|
|
|
41
41
|
export let clearable: boolean | undefined = undefined
|
|
42
42
|
export let disabled = false
|
|
43
|
+
export let createRequest: ((args: { input: string; id: string }) => void) | undefined = undefined
|
|
43
44
|
|
|
44
45
|
const dispatch = createEventDispatcher()
|
|
45
46
|
|
|
@@ -246,7 +247,8 @@
|
|
|
246
247
|
error = e.detail
|
|
247
248
|
}}
|
|
248
249
|
createOptionWhenNoResult={!!cell.field?.options.createOptionWhenNoResult}
|
|
249
|
-
|
|
250
|
+
{createRequest}
|
|
251
|
+
default_select_if_one_item={!!cell.field?.options.default_select_if_one_item}
|
|
250
252
|
/>
|
|
251
253
|
{/if}
|
|
252
254
|
{:else if metaType.kind === 'enum'}
|
|
@@ -301,7 +303,7 @@
|
|
|
301
303
|
{...common(cell.field)}
|
|
302
304
|
autocomplete="off"
|
|
303
305
|
class={tw(
|
|
304
|
-
`join-item placeholder:text-base-content/30
|
|
306
|
+
`join-item w-full bg-transparent placeholder:text-base-content/30`,
|
|
305
307
|
metaType.subKind === 'number' && 'text-end',
|
|
306
308
|
)}
|
|
307
309
|
type={metaType.subKind.replaceAll('dateOnly', 'date')}
|
|
@@ -328,6 +330,6 @@
|
|
|
328
330
|
/>
|
|
329
331
|
{:else}
|
|
330
332
|
<!-- This shoud NEVER be displayed -->
|
|
331
|
-
<span class="
|
|
333
|
+
<span class="flex items-center pl-2 text-error">Type "{cell.field?.inputType}" not managed!</span>
|
|
332
334
|
{/if}
|
|
333
335
|
</FieldContainer>
|
package/esm/ui/Field.svelte.d.ts
CHANGED
|
@@ -12,9 +12,12 @@ declare class __sveltets_Render<T extends Record<any, any>> {
|
|
|
12
12
|
focus?: boolean | undefined;
|
|
13
13
|
clearable?: boolean | undefined | undefined;
|
|
14
14
|
disabled?: boolean | undefined;
|
|
15
|
+
createRequest?: ((args: {
|
|
16
|
+
input: string;
|
|
17
|
+
id: string;
|
|
18
|
+
}) => void) | undefined;
|
|
15
19
|
};
|
|
16
20
|
events(): {
|
|
17
|
-
createRequest: CustomEvent<any>;
|
|
18
21
|
selected: CustomEvent<any>;
|
|
19
22
|
} & {
|
|
20
23
|
[evt: string]: CustomEvent<any>;
|
package/esm/ui/FieldGroup.svelte
CHANGED
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
export let store: StoreItem<T>
|
|
18
18
|
|
|
19
19
|
export let focusKey: string | null | undefined = null
|
|
20
|
+
export let createRequest: ((args: { input: string; id: string }) => void) | undefined = undefined
|
|
20
21
|
|
|
21
22
|
const getError = (errors: any, field: FieldMetadata<any, any>) => {
|
|
22
23
|
const fo = getRelationFieldInfo(field)
|
|
@@ -105,7 +106,7 @@
|
|
|
105
106
|
bind:value={$store.item[cell.field.key]}
|
|
106
107
|
error={getError($store.errors, cell.field)}
|
|
107
108
|
{focus}
|
|
108
|
-
|
|
109
|
+
{createRequest}
|
|
109
110
|
/>
|
|
110
111
|
<!-- disabled={isDisableFieldDynamic(cell)} -->
|
|
111
112
|
{:else}
|
|
@@ -7,9 +7,12 @@ declare class __sveltets_Render<T extends Record<any, any>> {
|
|
|
7
7
|
cells: Cell<T>[];
|
|
8
8
|
store: StoreItem<T>;
|
|
9
9
|
focusKey?: string | null | undefined;
|
|
10
|
+
createRequest?: ((args: {
|
|
11
|
+
input: string;
|
|
12
|
+
id: string;
|
|
13
|
+
}) => void) | undefined;
|
|
10
14
|
};
|
|
11
15
|
events(): {
|
|
12
|
-
createRequest: CustomEvent<any>;
|
|
13
16
|
changed: CustomEvent<any>;
|
|
14
17
|
} & {
|
|
15
18
|
[evt: string]: CustomEvent<any>;
|