firstly 0.0.5 → 0.0.6

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 (37) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/esm/ROUTES.d.ts +3 -1
  3. package/esm/ROUTES.js +1 -0
  4. package/esm/api/index.d.ts +1 -1
  5. package/esm/auth/AuthController.server.js +50 -9
  6. package/esm/auth/index.d.ts +4 -7
  7. package/esm/auth/index.js +39 -34
  8. package/esm/auth/static/assets/Page-BGTO8LC5.css +1 -0
  9. package/esm/auth/static/assets/Page-DBWJjlEQ.d.ts +4 -0
  10. package/esm/auth/static/assets/Page-DBWJjlEQ.js +1 -0
  11. package/esm/auth/static/assets/Page-RIbXHuZG.d.ts +4 -0
  12. package/esm/auth/static/assets/Page-RIbXHuZG.js +1 -0
  13. package/esm/auth/static/assets/Page-apb_xgZT.d.ts +6 -0
  14. package/esm/auth/static/assets/Page-apb_xgZT.js +18 -0
  15. package/esm/auth/static/assets/{index-R27C_TlP.css → index-CR_3yNaJ.css} +1 -1
  16. package/esm/auth/static/assets/index-qfq98Nyd.d.ts +63 -0
  17. package/esm/auth/static/assets/index-qfq98Nyd.js +2 -0
  18. package/esm/auth/static/index.html +2 -2
  19. package/esm/auth/types.d.ts +16 -22
  20. package/esm/cellsBuildor.js +2 -2
  21. package/esm/index.d.ts +3 -2
  22. package/esm/index.js +2 -1
  23. package/esm/mail/index.d.ts +23 -4
  24. package/esm/mail/index.js +38 -15
  25. package/esm/mail/templates/DefaultMail.svelte +66 -0
  26. package/esm/mail/templates/DefaultMail.svelte.d.ts +28 -0
  27. package/esm/utils/types.d.ts +3 -0
  28. package/package.json +2 -1
  29. package/esm/auth/static/assets/Page-BYzkK4q3.d.ts +0 -5
  30. package/esm/auth/static/assets/Page-BYzkK4q3.js +0 -1
  31. package/esm/auth/static/assets/Page-ByIhtXVt.d.ts +0 -5
  32. package/esm/auth/static/assets/Page-ByIhtXVt.js +0 -8190
  33. package/esm/auth/static/assets/Page-Do7F0Mzd.d.ts +0 -5
  34. package/esm/auth/static/assets/Page-Do7F0Mzd.js +0 -1
  35. package/esm/auth/static/assets/Page-gV58jf2r.css +0 -1
  36. package/esm/auth/static/assets/index-czJ1PA1n.d.ts +0 -53
  37. package/esm/auth/static/assets/index-czJ1PA1n.js +0 -2
package/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # firstly
2
2
 
3
+ ## 0.0.6
4
+
5
+ ### Patch Changes
6
+
7
+ - [#23](https://github.com/jycouet/firstly/pull/23)
8
+ [`c188eb3`](https://github.com/jycouet/firstly/commit/c188eb3d81a9e75b246387512621b5213bbe8dbd)
9
+ Thanks [@jycouet](https://github.com/jycouet)! - fix auth & mail (logs & co)
10
+
3
11
  ## 0.0.5
4
12
 
5
13
  ### Patch Changes
package/esm/ROUTES.d.ts CHANGED
@@ -32,6 +32,7 @@ declare const AllObjs: {
32
32
  repo?: (string | number);
33
33
  }) => string;
34
34
  "/": string;
35
+ "/mail": string;
35
36
  "/remult": string;
36
37
  "/remult/auth": string;
37
38
  "/remult/enum": string;
@@ -40,7 +41,7 @@ declare const AllObjs: {
40
41
  };
41
42
  type AllTypes = typeof AllObjs;
42
43
  export type Routes = keyof AllTypes extends `${string}/${infer Route}` ? `/${Route}` : keyof AllTypes;
43
- export declare const routes: ("/" | "/remult" | "/remult/auth" | "/remult/enum" | "/remult/select" | "/ui" | "firstly_sign_in" | "remult_admin" | "github")[];
44
+ export declare const routes: ("/" | "/mail" | "/remult" | "/remult/auth" | "/remult/enum" | "/remult/select" | "/ui" | "firstly_sign_in" | "remult_admin" | "github")[];
44
45
  /**
45
46
  * To be used like this:
46
47
  * ```ts
@@ -69,6 +70,7 @@ export declare function route<T extends NonFunctionKeys<AllTypes>>(key: T): stri
69
70
  export type KIT_ROUTES = {
70
71
  PAGES: {
71
72
  '/': never;
73
+ '/mail': never;
72
74
  '/remult': never;
73
75
  '/remult/auth': never;
74
76
  '/remult/enum': never;
package/esm/ROUTES.js CHANGED
@@ -9,6 +9,7 @@
9
9
  */
10
10
  const PAGES = {
11
11
  "/": `/`,
12
+ "/mail": `/mail`,
12
13
  "/remult": `/remult`,
13
14
  "/remult/auth": `/remult/auth`,
14
15
  "/remult/enum": `/remult/enum`,
@@ -26,7 +26,7 @@ export type Module = {
26
26
  };
27
27
  type Options = Omit<RemultServerOptions<RequestEvent<Partial<Record<string, string>>, string | null>> & {
28
28
  modules?: Module[] | undefined;
29
- mail?: MailOptions;
29
+ mail?: MailOptions<any>;
30
30
  }, 'entities' | 'controllers' | 'initRequest' | 'initApi'>;
31
31
  /**
32
32
  * it's basically `remultSveltekit` with the `modules` option
@@ -93,8 +93,23 @@ export class AuthControllerServer {
93
93
  await sendMail('invite', {
94
94
  to: email,
95
95
  subject: 'Invitation',
96
- text: `You were invited here: ${url}`,
97
- html: `You were invited <a href="${url}">here</a>`,
96
+ templateProps: {
97
+ title: 'Invitation 👋',
98
+ previewText: 'This is the mail you were waiting for',
99
+ sections: [
100
+ {
101
+ text: 'Today is your lucky day !',
102
+ highlighted: true,
103
+ },
104
+ {
105
+ text: 'You were invited to join the team',
106
+ cta: {
107
+ text: 'JOIN',
108
+ link: url,
109
+ },
110
+ },
111
+ ],
112
+ },
98
113
  });
99
114
  logAuth.success(`Done with ${green('sendMail')} (${url})`);
100
115
  return 'Demo Mail sent !';
@@ -138,7 +153,7 @@ export class AuthControllerServer {
138
153
  await createSession(user.id);
139
154
  }
140
155
  else {
141
- const url = `${remult.context.url.origin}${oSafe.firstlyData.props.ui.providers.password.paths.verify_email}?token=${token}`;
156
+ const url = `${remult.context.url.origin}${oSafe.firstlyData.props.ui?.paths.verify_email}?token=${token}`;
142
157
  if (AUTH_OPTIONS.providers?.password?.verifyMailSend) {
143
158
  await AUTH_OPTIONS.providers?.password.verifyMailSend({ email, url });
144
159
  logAuth.success(`Done with custom ${green('verifyMailSend')} (${yellow(url)})`);
@@ -146,9 +161,20 @@ export class AuthControllerServer {
146
161
  else {
147
162
  await sendMail('signUpPassword', {
148
163
  to: email,
149
- subject: 'Wecome!',
150
- text: `You can validate your account here: ${url}`,
151
- html: `You can validate your account <a href="${url}">here</a>`,
164
+ subject: 'Wecome',
165
+ templateProps: {
166
+ title: 'Wecome 👋',
167
+ previewText: 'This is the mail you were waiting for',
168
+ sections: [
169
+ {
170
+ text: 'You can validate your account',
171
+ cta: {
172
+ text: 'HERE',
173
+ link: url,
174
+ },
175
+ },
176
+ ],
177
+ },
152
178
  });
153
179
  logAuth.success(`Done with ${green('sendMail')} (${url})`);
154
180
  }
@@ -201,7 +227,7 @@ export class AuthControllerServer {
201
227
  authAccount.token = token;
202
228
  authAccount.expiresAt = createDate(new TimeSpan(AUTH_OPTIONS.providers?.password?.resetPasswordExpiresIn ?? 5 * 60, 's'));
203
229
  await remult.repo(oSafe.Account).save(authAccount);
204
- const url = `${remult.context.url.origin}${oSafe.firstlyData.props.ui.providers.password.paths.reset_password}?token=${token}`;
230
+ const url = `${remult.context.url.origin}${oSafe.firstlyData.props.ui?.paths.reset_password}?token=${token}`;
205
231
  if (AUTH_OPTIONS.providers?.password?.resetPasswordSend) {
206
232
  await AUTH_OPTIONS.providers?.password.resetPasswordSend({ email, url });
207
233
  logAuth.success(`Done with custom ${green('resetPasswordSend')} (${yellow(url)})`);
@@ -211,8 +237,23 @@ export class AuthControllerServer {
211
237
  await sendMail('forgotPassword', {
212
238
  to: email,
213
239
  subject: 'Reset your password',
214
- text: `You can reset your password here: ${url}`,
215
- html: `You can reset your password <a href="${url}">here</a>`,
240
+ templateProps: {
241
+ title: 'Reset your password 👋',
242
+ previewText: 'This is the mail you were waiting for',
243
+ sections: [
244
+ {
245
+ text: 'Did you forgot something ?',
246
+ highlighted: true,
247
+ },
248
+ {
249
+ text: 'No worries, you can reset your password',
250
+ cta: {
251
+ text: 'HERE',
252
+ link: url,
253
+ },
254
+ },
255
+ ],
256
+ },
216
257
  });
217
258
  logAuth.success(`Done with ${green('sendMail')} (${url})`);
218
259
  return 'Demo Mail sent !';
@@ -3,9 +3,9 @@ import { Lucia, type SessionCookieOptions } from 'lucia';
3
3
  import type { ClassType, UserInfo } from 'remult';
4
4
  import { Log } from '@kitql/helpers';
5
5
  import type { Module } from '../api';
6
- import type { ResolvedType } from '../utils/types';
6
+ import type { RecursivePartial, ResolvedType } from '../utils/types';
7
7
  import { FFAuthAccount, FFAuthProvider, FFAuthUser, FFAuthUserSession } from './Entities';
8
- import type { firstlyData } from './types';
8
+ import type { firstlyData, firstlyDataAuth } from './types';
9
9
  export type { firstlyData };
10
10
  export { FFAuthUser, FFAuthAccount, FFAuthProvider, FFAuthUserSession };
11
11
  export type AuthorizationURLOptions = Record<string, {
@@ -35,11 +35,8 @@ type AuthOptions<TUserEntity extends FFAuthUser = FFAuthUser, TSessionEntity ext
35
35
  Session?: ClassType<TSessionEntity>;
36
36
  Account?: ClassType<TAccountEntity>;
37
37
  };
38
- ui?: {
39
- paths?: {
40
- base?: string;
41
- };
42
- } | false;
38
+ debug?: boolean;
39
+ ui?: false | RecursivePartial<firstlyDataAuth['ui']>;
43
40
  /** in secondes @default 15 days */
44
41
  sessionExpiresIn?: number;
45
42
  sessionCookie?: SessionCookieOptions;
package/esm/auth/index.js CHANGED
@@ -15,43 +15,47 @@ import { initRoleFromEnv } from './RoleHelpers';
15
15
  export { FFAuthUser, FFAuthAccount, FFAuthProvider, FFAuthUserSession };
16
16
  export const logAuth = new Log('firstly | auth');
17
17
  export { FF_Auth_Role } from './Entities';
18
- export let AUTH_OPTIONS = {};
18
+ export let AUTH_OPTIONS = { ui: {} };
19
+ const buildUrlOrDefault = (base, userSetting, fallback) => {
20
+ if (userSetting) {
21
+ return `${base}/${userSetting}`;
22
+ }
23
+ return `${base}/${fallback}`;
24
+ };
19
25
  export const getSafeOptions = () => {
20
26
  const signUp = AUTH_OPTIONS.signUp ?? true;
21
27
  const base = AUTH_OPTIONS.ui === false ? 'NO_BASE_PATH' : AUTH_OPTIONS.ui?.paths?.base ?? '/ff/auth';
22
- const oAuths = AUTH_OPTIONS.providers?.oAuths?.map((o) => {
23
- return o.name;
24
- }) ?? [];
28
+ // const oAuths =
29
+ // AUTH_OPTIONS.providers?.oAuths?.map((o) => {
30
+ // return o.name
31
+ // }) ?? []
25
32
  const firstlyData = {
26
33
  module: 'auth',
34
+ debug: AUTH_OPTIONS.debug,
27
35
  props: {
28
- ui: {
29
- paths: {
30
- base,
31
- },
32
- providers: {
33
- password: {
34
- dico: {
35
- email: 'Email',
36
- email_placeholder: 'Your email address',
37
- password: 'Password',
38
- btn_sign_up: 'Sign up',
39
- btn_sign_in: 'Sign in',
40
- forgot_password: 'Forgot your password?',
41
- send_password_reset_instructions: 'Send password reset instructions',
42
- back_to_sign_in: 'Back to sign in',
43
- },
44
- paths: {
45
- sign_up: signUp ? `${base}/sign-up` : false,
46
- sign_in: `${base}/sign-in`,
47
- forgot_password: `${base}/forgot-password`,
48
- reset_password: `${base}/reset-password`,
49
- verify_email: `${base}/verify-email`,
50
- },
36
+ ui: AUTH_OPTIONS.ui === false
37
+ ? undefined
38
+ : {
39
+ paths: {
40
+ base,
41
+ sign_up: buildUrlOrDefault(base, AUTH_OPTIONS.ui?.paths?.sign_up, 'sign-up'),
42
+ sign_in: buildUrlOrDefault(base, AUTH_OPTIONS.ui?.paths?.sign_in, 'sign-in'),
43
+ forgot_password: buildUrlOrDefault(base, AUTH_OPTIONS.ui?.paths?.forgot_password, 'forgot-password'),
44
+ reset_password: buildUrlOrDefault(base, AUTH_OPTIONS.ui?.paths?.reset_password, 'reset-password'),
45
+ verify_email: buildUrlOrDefault(base, AUTH_OPTIONS.ui?.paths?.verify_email, 'verify-email'),
46
+ },
47
+ strings: {
48
+ email: AUTH_OPTIONS.ui?.strings?.email ?? 'Email',
49
+ email_placeholder: AUTH_OPTIONS.ui?.strings?.email_placeholder ?? 'Your email address',
50
+ password: AUTH_OPTIONS.ui?.strings?.password ?? 'Password',
51
+ btn_sign_up: AUTH_OPTIONS.ui?.strings?.btn_sign_up ?? 'Sign up',
52
+ btn_sign_in: AUTH_OPTIONS.ui?.strings?.btn_sign_in ?? 'Sign in',
53
+ forgot_password: AUTH_OPTIONS.ui?.strings?.forgot_password ?? 'Forgot your password?',
54
+ send_password_reset_instructions: AUTH_OPTIONS.ui?.strings?.send_password_reset_instructions ??
55
+ 'Send password reset instructions',
56
+ back_to_sign_in: AUTH_OPTIONS.ui?.strings?.back_to_sign_in ?? 'Back to sign in',
51
57
  },
52
- oAuths,
53
58
  },
54
- },
55
59
  },
56
60
  };
57
61
  let redirectUrl = AUTH_OPTIONS.defaultRedirect ?? '/';
@@ -110,11 +114,11 @@ export const auth = (o) => {
110
114
  }
111
115
  },
112
116
  earlyReturn: async ({ event, resolve }) => {
113
- if (AUTH_OPTIONS.ui === false) {
114
- return { early: false };
115
- }
117
+ // if (AUTH_OPTIONS.ui === false) {
118
+ // return { early: false }
119
+ // }
116
120
  const oSafe = getSafeOptions();
117
- if (event.url.pathname === oSafe.firstlyData.props.ui.providers.password.paths.verify_email) {
121
+ if (event.url.pathname === oSafe.firstlyData.props.ui?.paths?.verify_email) {
118
122
  const token = event.url.searchParams.get('token') ?? '';
119
123
  if (!oSafe.password_enabled) {
120
124
  throw Error('Password is not enabled!');
@@ -144,7 +148,8 @@ export const auth = (o) => {
144
148
  if (installedFirstlyPath) {
145
149
  staticPath = `${installedFirstlyPath}/esm/auth/static/`;
146
150
  }
147
- if (event.url.pathname.startsWith(oSafe.firstlyData.props.ui.paths.base)) {
151
+ if (oSafe.firstlyData.props.ui?.paths?.base &&
152
+ event.url.pathname.startsWith(oSafe.firstlyData.props.ui.paths.base)) {
148
153
  const content = read(`${staticPath}index.html`);
149
154
  return {
150
155
  early: true,
@@ -0,0 +1 @@
1
+ form.s-KT008SdmQprk,form.s-N0DaQgJ_T5_C,form.s-85Tmcm64bnMI{display:flex;flex-direction:column}.message.s-85Tmcm64bnMI:empty{display:none}.message.s-85Tmcm64bnMI{background:var(--pico-muted-border-color);padding:var(--pico-form-element-spacing-vertical) var(--pico-form-element-spacing-horizontal);border-radius:var(--pico-border-radius);margin-bottom:calc(var(--pico-typography-spacing-vertical) * 2)}.message.error.s-85Tmcm64bnMI{background:var(--pico-del-color);color:#4c1513}form.s-FRwn6sVlvC6z{display:flex;flex-direction:column}.message.s-FRwn6sVlvC6z:empty{display:none}.message.s-FRwn6sVlvC6z{background:var(--pico-muted-border-color);padding:var(--pico-form-element-spacing-vertical) var(--pico-form-element-spacing-horizontal);border-radius:var(--pico-border-radius);margin-bottom:calc(var(--pico-typography-spacing-vertical) * 2)}.message.error.s-FRwn6sVlvC6z{background:var(--pico-del-color);color:#4c1513}.wrapper.s-NO-a_LAEXXH5{min-height:100vh;display:flex;justify-content:center;align-items:center;margin:0 auto}.form.s-NO-a_LAEXXH5{padding:1rem;max-width:360px;width:100%}.form-footer.s-NO-a_LAEXXH5{margin-top:1rem;display:flex;flex-direction:column;justify-content:center;align-items:center}.fallback.s-NO-a_LAEXXH5{display:flex;justify-content:center;align-items:center}
@@ -0,0 +1,4 @@
1
+ export { v as default };
2
+ declare class v extends l {
3
+ }
4
+ import { S as l } from "./index-qfq98Nyd.js";
@@ -0,0 +1 @@
1
+ import{S as l,b as d,a as f,d as i,h as m,M as p,t as u,n as r,z as h}from"./index-qfq98Nyd.js";function c(a){let e;const n={c:function(){e=p("Hello from files")},l:function(t){throw new Error("options.hydrate only works if the component was compiled with the `hydratable: true` option")},m:function(t,o){u(t,e,o)},p:r,i:r,o:r,d:function(t){t&&h(e)}};return i("SvelteRegisterBlock",{block:n,id:c.name,type:"component",source:"",ctx:a}),n}function w(a,e){let{$$slots:n={},$$scope:s}=e;m("Page",n,[]);const t=[];return Object.keys(e).forEach(o=>{!~t.indexOf(o)&&o.slice(0,2)!=="$$"&&o!=="slot"&&console.warn(`<Page> was created with unknown prop '${o}'`)}),[]}class v extends l{constructor(e){super(e),d(this,e,w,c,f,{}),i("SvelteRegisterComponent",{component:this,tagName:"Page",options:e,id:c.name})}}export{v as default};
@@ -0,0 +1,4 @@
1
+ export { v as default };
2
+ declare class v extends l {
3
+ }
4
+ import { S as l } from "./index-qfq98Nyd.js";
@@ -0,0 +1 @@
1
+ import{S as l,b as d,a as f,d as i,h as m,M as p,t as u,n as r,z as h}from"./index-qfq98Nyd.js";function c(s){let e;const n={c:function(){e=p("Hello from admin")},l:function(t){throw new Error("options.hydrate only works if the component was compiled with the `hydratable: true` option")},m:function(t,o){u(t,e,o)},p:r,i:r,o:r,d:function(t){t&&h(e)}};return i("SvelteRegisterBlock",{block:n,id:c.name,type:"component",source:"",ctx:s}),n}function w(s,e){let{$$slots:n={},$$scope:a}=e;m("Page",n,[]);const t=[];return Object.keys(e).forEach(o=>{!~t.indexOf(o)&&o.slice(0,2)!=="$$"&&o!=="slot"&&console.warn(`<Page> was created with unknown prop '${o}'`)}),[]}class v extends l{constructor(e){super(e),d(this,e,w,c,f,{}),i("SvelteRegisterComponent",{component:this,tagName:"Page",options:e,id:c.name})}}export{v as default};
@@ -0,0 +1,6 @@
1
+ export { Oa as default };
2
+ declare class Oa extends et {
3
+ set firstlyData(e: void);
4
+ get firstlyData(): void;
5
+ }
6
+ import { S as et } from "./index-qfq98Nyd.js";