firstly 0.0.13 → 0.0.14

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 (104) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/esm/ROUTES.d.ts +2 -0
  3. package/esm/ROUTES.js +1 -0
  4. package/esm/api/index.d.ts +8 -0
  5. package/esm/auth/AuthController.d.ts +12 -23
  6. package/esm/auth/AuthController.js +12 -31
  7. package/esm/auth/server/AuthController.server.d.ts +11 -11
  8. package/esm/auth/server/AuthController.server.js +83 -18
  9. package/esm/auth/server/helperFirstly.d.ts +1 -1
  10. package/esm/auth/server/helperFirstly.js +1 -0
  11. package/esm/auth/server/module.d.ts +3 -6
  12. package/esm/auth/server/providers/github.d.ts +2 -1
  13. package/esm/auth/server/providers/github.js +1 -1
  14. package/esm/auth/static/assets/Page-B0XXxe0N.d.ts +6 -0
  15. package/esm/auth/static/assets/Page-B0XXxe0N.js +1 -0
  16. package/esm/auth/static/assets/Page-DdKMiUZn.d.ts +6 -0
  17. package/esm/auth/static/assets/Page-DdKMiUZn.js +20 -0
  18. package/esm/auth/static/assets/Page-UV_hqY7I.d.ts +6 -0
  19. package/esm/auth/static/assets/Page-UV_hqY7I.js +1 -0
  20. package/esm/auth/static/assets/Page-mK42zGEw.css +1 -0
  21. package/esm/auth/static/assets/index-C9jzxOBu.d.ts +151 -0
  22. package/esm/auth/static/assets/index-C9jzxOBu.js +42 -0
  23. package/esm/auth/static/index.html +2 -2
  24. package/esm/auth/types.d.ts +26 -3
  25. package/esm/bin/cmd.js +339 -139
  26. package/esm/feedback/FeedbackController.js +57 -51
  27. package/esm/feedback/server/index.d.ts +6 -15
  28. package/esm/feedback/server/index.js +4 -5
  29. package/esm/feedback/types.d.ts +14 -0
  30. package/esm/feedback/types.js +4 -0
  31. package/esm/feedback/ui/DialogIssue.svelte +78 -62
  32. package/esm/feedback/ui/DialogIssue.svelte.d.ts +20 -18
  33. package/esm/feedback/ui/DialogIssues.svelte +37 -28
  34. package/esm/feedback/ui/DialogIssues.svelte.d.ts +20 -18
  35. package/esm/feedback/ui/DialogMilestones.svelte +18 -12
  36. package/esm/feedback/ui/DialogMilestones.svelte.d.ts +18 -16
  37. package/esm/feedback/ui/Feedback.svelte +11 -9
  38. package/esm/feedback/ui/Feedback.svelte.d.ts +16 -14
  39. package/esm/mail/server/index.d.ts +9 -2
  40. package/esm/mail/server/index.js +3 -1
  41. package/esm/mail/templates/DefaultMail.svelte +64 -44
  42. package/esm/mail/templates/DefaultMail.svelte.d.ts +28 -26
  43. package/esm/server/index.d.ts +0 -0
  44. package/esm/server/index.js +1 -0
  45. package/esm/storeItem.d.ts +1 -1
  46. package/esm/storeList.d.ts +1 -1
  47. package/esm/sveltekit/server/index.d.ts +0 -9
  48. package/esm/ui/Button.svelte +79 -56
  49. package/esm/ui/Button.svelte.d.ts +34 -24
  50. package/esm/ui/Clipboardable.svelte +18 -11
  51. package/esm/ui/Clipboardable.svelte.d.ts +34 -23
  52. package/esm/ui/Field.svelte +189 -136
  53. package/esm/ui/Field.svelte.d.ts +13 -6
  54. package/esm/ui/FieldGroup.svelte +74 -53
  55. package/esm/ui/FieldGroup.svelte.d.ts +17 -6
  56. package/esm/ui/Grid.svelte +110 -86
  57. package/esm/ui/Grid.svelte.d.ts +17 -6
  58. package/esm/ui/GridLoading.svelte +10 -5
  59. package/esm/ui/GridLoading.svelte.d.ts +19 -17
  60. package/esm/ui/GridPaginate.svelte +30 -23
  61. package/esm/ui/GridPaginate.svelte.d.ts +21 -19
  62. package/esm/ui/Icon.svelte +67 -32
  63. package/esm/ui/Icon.svelte.d.ts +52 -43
  64. package/esm/ui/Loading.svelte +5 -3
  65. package/esm/ui/Loading.svelte.d.ts +29 -18
  66. package/esm/ui/Tooltip.svelte +22 -19
  67. package/esm/ui/Tooltip.svelte.d.ts +30 -20
  68. package/esm/ui/dialog/DialogForm.svelte +48 -41
  69. package/esm/ui/dialog/DialogForm.svelte.d.ts +18 -16
  70. package/esm/ui/dialog/DialogManagement.svelte.d.ts +22 -21
  71. package/esm/ui/dialog/DialogPrimitive.svelte +32 -26
  72. package/esm/ui/dialog/DialogPrimitive.svelte.d.ts +35 -25
  73. package/esm/ui/dialog/FormEditAction.svelte +20 -12
  74. package/esm/ui/dialog/FormEditAction.svelte.d.ts +13 -6
  75. package/esm/ui/dialog/dialog.d.ts +1 -1
  76. package/esm/ui/internals/FieldContainer.svelte +13 -6
  77. package/esm/ui/internals/FieldContainer.svelte.d.ts +37 -28
  78. package/esm/ui/internals/Input.svelte +110 -76
  79. package/esm/ui/internals/Input.svelte.d.ts +34 -32
  80. package/esm/ui/internals/Textarea.svelte +39 -31
  81. package/esm/ui/internals/Textarea.svelte.d.ts +31 -28
  82. package/esm/ui/internals/select/MultiSelectMelt.svelte +174 -126
  83. package/esm/ui/internals/select/MultiSelectMelt.svelte.d.ts +29 -27
  84. package/esm/ui/internals/select/SelectMelt.svelte +168 -133
  85. package/esm/ui/internals/select/SelectMelt.svelte.d.ts +34 -32
  86. package/esm/ui/internals/select/SelectRadio.svelte +17 -11
  87. package/esm/ui/internals/select/SelectRadio.svelte.d.ts +24 -22
  88. package/esm/ui/link/Link.svelte +11 -6
  89. package/esm/ui/link/Link.svelte.d.ts +31 -22
  90. package/esm/ui/link/LinkPlus.svelte +19 -16
  91. package/esm/ui/link/LinkPlus.svelte.d.ts +20 -18
  92. package/esm/vite/index.d.ts +2 -3
  93. package/esm/vite/index.js +33 -26
  94. package/package.json +5 -5
  95. package/esm/auth/static/assets/Page-BUfjaN-D.d.ts +0 -5
  96. package/esm/auth/static/assets/Page-BUfjaN-D.js +0 -19
  97. package/esm/auth/static/assets/Page-CJ58H1vl.css +0 -1
  98. package/esm/auth/static/assets/Page-CaDAqmBS.d.ts +0 -5
  99. package/esm/auth/static/assets/Page-CaDAqmBS.js +0 -1
  100. package/esm/auth/static/assets/Page-DhdZddzJ.d.ts +0 -5
  101. package/esm/auth/static/assets/Page-DhdZddzJ.js +0 -1
  102. package/esm/auth/static/assets/index-D-Ztdt2o.d.ts +0 -54
  103. package/esm/auth/static/assets/index-D-Ztdt2o.js +0 -2
  104. /package/esm/auth/static/assets/{index-BDy4A_14.css → index-DKWpA6v7.css} +0 -0
package/esm/bin/cmd.js CHANGED
@@ -3,8 +3,10 @@ import { bold, cyan, gray, green, italic, Log } from '@kitql/helpers';
3
3
  import { read, write } from '@kitql/internals';
4
4
  // Need this trick to be be replaced by the real lib alias here ;)
5
5
  const libAlias = '$' + 'lib';
6
+ const serverAlias = '$' + 'server';
7
+ const modulesAlias = '$' + 'modules';
6
8
  const pkgFirstly = JSON.parse(read('./node_modules/firstly/package.json') ?? '{}');
7
- const versionFirstly = pkgFirstly?.peerDependencies?.['remult'] ?? 'latest';
9
+ const versionOfRemult = pkgFirstly?.peerDependencies?.['remult'] ?? 'latest';
8
10
  const pkg = JSON.parse(read('./package.json') ?? '{}');
9
11
  const version = pkg.devDependencies?.['firstly'] ?? pkg.dependencies?.['firstly'] ?? '???';
10
12
  console.info('');
@@ -50,7 +52,7 @@ pkg.devDependencies = mergeAndSort(pkg.devDependencies, {
50
52
  '@kitql/eslint-config': '0.5.8',
51
53
  '@kitql/helpers': '0.8.12',
52
54
  pg: '8.12.0',
53
- remult: versionFirstly,
55
+ remult: versionOfRemult,
54
56
  });
55
57
  pkg.dependencies = mergeAndSort(pkg.dependencies, {});
56
58
  pkg.scripts = {
@@ -63,12 +65,34 @@ if (res.includes('all') || res.includes('dependencies')) {
63
65
  write('./package.json', [JSON.stringify(pkg, null, 2)]);
64
66
  }
65
67
  const obj = {
68
+ // Configs
66
69
  './.npmrc': [
67
70
  `engine-strict=true
68
71
 
69
72
  public-hoist-pattern[]=*eslint*
70
73
  public-hoist-pattern[]=*prettier*
71
74
  public-hoist-pattern[]=*globals*
75
+ `,
76
+ ],
77
+ './.gitignore': [
78
+ `node_modules
79
+
80
+ # Output
81
+ /.svelte-kit
82
+ /build
83
+
84
+ # Env
85
+ .env
86
+ .env.*
87
+ !.env.example
88
+ !.env.test
89
+
90
+ # Vite
91
+ vite.config.js.timestamp-*
92
+ vite.config.ts.timestamp-*
93
+
94
+ # Firstly / Remult
95
+ /db
72
96
  `,
73
97
  ],
74
98
  './eslint.config.js': [
@@ -125,26 +149,114 @@ export default {
125
149
  # GITHUB_CLIENT_SECRET = ''
126
150
  `,
127
151
  ],
128
- './src/lib/firstly/index.ts': [
152
+ './tsconfig.json': [
153
+ `{
154
+ "extends": "./.svelte-kit/tsconfig.json",
155
+ "compilerOptions": {
156
+ "experimentalDecorators": true,
157
+ "allowJs": true,
158
+ "checkJs": true,
159
+ "esModuleInterop": true,
160
+ "forceConsistentCasingInFileNames": true,
161
+ "resolveJsonModule": true,
162
+ "skipLibCheck": true,
163
+ "sourceMap": true,
164
+ "strict": true,
165
+ "moduleResolution": "bundler"
166
+ }
167
+ // Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias
168
+ //
169
+ // If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes
170
+ // from the referenced tsconfig.json - TypeScript does not merge them in
171
+ }
172
+ `,
173
+ ],
174
+ './vite.config.ts': [
175
+ `import { sveltekit } from '@sveltejs/kit/vite'
176
+ import { defineConfig } from 'vite'
177
+
178
+ import { firstly } from 'firstly/vite'
179
+
180
+ import type { KIT_ROUTES } from '${libAlias}/ROUTES'
181
+
182
+ export default defineConfig({
183
+ plugins: [
184
+ // @ts-ignore JYC TODO (vite 5 / vite 6...)
185
+ firstly<KIT_ROUTES>({
186
+ kitRoutes: {
187
+ LINKS: {
188
+ login: 'ff/auth/sign-in',
189
+ github: 'https://github.com/[owner]/[repo]',
190
+ remult_admin: 'api/admin',
191
+ },
192
+ }
193
+ }),
194
+ sveltekit(),
195
+ ],
196
+ })
197
+ `,
198
+ ],
199
+ './svelte.config.js': [
200
+ `import adapter from '@sveltejs/adapter-auto'
201
+ import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'
202
+
203
+ /** @type {import('@sveltejs/kit').Config} */
204
+ const config = {
205
+ // Consult https://svelte.dev/docs/kit/integrations
206
+ // for more information about preprocessors
207
+ preprocess: vitePreprocess(),
208
+
209
+ kit: {
210
+ // adapter-auto only supports some environments, see https://svelte.dev/docs/kit/adapter-auto for a list.
211
+ // If your environment is not supported, or you settled on a specific environment, switch out the adapter.
212
+ // See https://svelte.dev/docs/kit/adapters for more information about adapters.
213
+ adapter: adapter(),
214
+ alias: {
215
+ $modules: './src/modules',
216
+ $server: './src/server',
217
+ },
218
+ },
219
+ }
220
+
221
+ export default config
222
+ `,
223
+ ],
224
+ // App files
225
+ './src/app.d.ts': [
226
+ `// See https://svelte.dev/docs/kit/types#app.d.ts
227
+ // for information about these interfaces
228
+ declare global {
229
+ namespace App {
230
+ // interface Error {}
231
+ // interface Locals {}
232
+ // interface PageData {}
233
+ // interface PageState {}
234
+ // interface Platform {}
235
+ }
236
+ }
237
+
238
+ declare module 'remult' {
239
+ export interface UserInfo {
240
+ // Your custom user info
241
+ }
242
+
243
+ export interface FieldOptions<entityType, valueType> {
244
+ placeholder?: string
245
+ }
246
+ }
247
+
248
+ export { }
249
+ `,
250
+ ],
251
+ './src/server/index.ts': [
129
252
  `import { FF_Role } from 'firstly'
130
253
  import { firstly, Module } from 'firstly/api'
131
254
  import { auth } from 'firstly/auth/server'
255
+ import { mail } from 'firstly/mail/server'
132
256
  import { changeLog } from 'firstly/changeLog/server'
133
- import { Log } from '@kitql/helpers'
134
257
 
135
- import { task } from './modules/task'
136
-
137
- /**
138
- * Your roles, use them in your app !
139
- */
140
- export const Role = {
141
- Boss: 'Boss',
142
- }
143
-
144
- /**
145
- * Your logs with a nice prefix, use \`log.info("Hello")\` / \`log.success("Yeah")\` / \`log.error("Ho nooo!")\` and see !
146
- */
147
- export const log = new Log('${pkg.name}')
258
+ import { log, Role } from '${libAlias}'
259
+ import { task } from '${modulesAlias}/task/server'
148
260
 
149
261
  export const api = firstly({
150
262
  //----------------------------------------
@@ -185,6 +297,13 @@ export const api = firstly({
185
297
  },
186
298
  }),
187
299
 
300
+ //----------------------------------------
301
+ // Core Module: mail
302
+ //----------------------------------------
303
+ mail({
304
+ // options
305
+ }),
306
+
188
307
  //----------------------------------------
189
308
  // example of a userland module
190
309
  //----------------------------------------
@@ -215,8 +334,8 @@ export const api = firstly({
215
334
  import { redirect } from '@sveltejs/kit'
216
335
 
217
336
  import { handleAuth, handleGuard } from 'firstly/auth/server'
218
- import { api as handleRemult } from '${libAlias}/firstly'
219
337
  import { route } from '${libAlias}/ROUTES'
338
+ import { api as handleRemult } from '${serverAlias}'
220
339
 
221
340
  export const handle = sequence(
222
341
  //
@@ -235,25 +354,9 @@ export const handle = sequence(
235
354
  `,
236
355
  ],
237
356
  './src/routes/api/[...remult]/+server.ts': [
238
- `import { api } from '${libAlias}/firstly'
357
+ `import { api } from '${serverAlias}'
239
358
 
240
359
  export const { GET, POST, PUT, DELETE } = api
241
- `,
242
- ],
243
- './src/routes/+page.svelte': [
244
- `<h1>Home</h1>
245
-
246
- <p>
247
- Welcome here
248
- </p>`,
249
- ],
250
- './src/routes/app/+page.svelte': [
251
- `<h1>App</h1>
252
-
253
- <p>
254
- Only autenticated users can see this page!
255
- </p>
256
-
257
360
  `,
258
361
  ],
259
362
  './src/routes/+layout.server.ts': [
@@ -277,32 +380,65 @@ export const load = (async (event) => {
277
380
  // return repo(Task).find()
278
381
  return { ...event.data }
279
382
  }) satisfies LayoutLoad
280
- `,
281
- ],
282
- './src/routes/+page.ts': [
283
- `import { remult } from 'remult'
284
- import type { PageLoad } from './$types'
285
-
286
- export const load = (async (event) => {
287
- // Instruct remult to use the special svelte fetch
288
- // Like this univeral load will work in SSR & CSR
289
- remult.useFetch(event.fetch)
290
- // return repo(Task).find()
291
- }) satisfies PageLoad
292
383
  `,
293
384
  ],
294
385
  './src/routes/+layout.svelte': [
295
386
  `<script lang="ts">
296
- import { remult } from 'remult'
387
+ import { untrack } from 'svelte'
388
+ import { createSubscriber } from 'svelte/reactivity'
389
+
390
+ import { Remult, remult } from 'remult'
297
391
 
298
392
  import { route } from '${libAlias}/ROUTES'
299
393
  import SignIn from '${libAlias}/ui/SignIn.svelte'
300
394
  import SignOut from '${libAlias}/ui/SignOut.svelte'
301
395
 
302
- import type { LayoutData } from './$types'
396
+ import type { LayoutData } from './$types'
303
397
 
304
- export let data: LayoutData
305
- $: remult.user = data.user
398
+ interface Props {
399
+ data: LayoutData
400
+ children?: import('svelte').Snippet
401
+ }
402
+
403
+ let { data, children }: Props = $props()
404
+
405
+ $effect(() => {
406
+ // Trigger the effect only on data.user update
407
+ data.user
408
+ untrack(() => {
409
+ remult.user = data.user
410
+ })
411
+ })
412
+
413
+ // To be done once in the application.
414
+ function initRemultSvelteReactivity() {
415
+ // Auth reactivity (remult.user, remult.authenticated(), ...)
416
+ {
417
+ let update = () => {}
418
+ let s = createSubscriber((u) => {
419
+ update = u
420
+ })
421
+ remult.subscribeAuth({
422
+ reportObserved: () => s(),
423
+ reportChanged: () => update(),
424
+ })
425
+ }
426
+
427
+ // Entities reactivity
428
+ {
429
+ Remult.entityRefInit = (x) => {
430
+ let update = () => {}
431
+ let s = createSubscriber((u) => {
432
+ update = u
433
+ })
434
+ x.subscribe({
435
+ reportObserved: () => s(),
436
+ reportChanged: () => update(),
437
+ })
438
+ }
439
+ }
440
+ }
441
+ initRemultSvelteReactivity()
306
442
  </script>
307
443
 
308
444
  <svelte:head>
@@ -335,12 +471,13 @@ export const load = (async (event) => {
335
471
 
336
472
  <a href={route('/')}>Home</a> |
337
473
  {#if remult.authenticated()}
338
- <a href={route('/app')}>App (Protected route)</a>
474
+ <a href={route('/app')}>App (Protected route)</a> |
339
475
  {/if}
476
+ <a href={route('/demo/task')}>Demo task</a>
340
477
 
341
478
  <hr />
342
479
 
343
- <slot />
480
+ {@render children?.()}
344
481
 
345
482
  <hr />
346
483
 
@@ -353,6 +490,55 @@ export const load = (async (event) => {
353
490
  <a href={route('github', { owner: 'jycouet', repo: 'firstly' })} target="_blank"> ⭐️ firstly </a>
354
491
  |
355
492
  <a href={route('github', { owner: 'remult', repo: 'remult' })} target="_blank">⭐️ remult</a>
493
+ `,
494
+ ],
495
+ './src/routes/+page.ts': [
496
+ `import { remult } from 'remult'
497
+ import type { PageLoad } from './$types'
498
+
499
+ export const load = (async (event) => {
500
+ // Instruct remult to use the special svelte fetch
501
+ // Like this univeral load will work in SSR & CSR
502
+ remult.useFetch(event.fetch)
503
+ // return repo(Task).find()
504
+ }) satisfies PageLoad
505
+ `,
506
+ ],
507
+ './src/routes/+page.svelte': [
508
+ `<h1>Home</h1>
509
+
510
+ <p>
511
+ Welcome here
512
+ </p>`,
513
+ ],
514
+ './src/routes/app/+page.svelte': [
515
+ `<h1>App</h1>
516
+
517
+ <p>
518
+ Only autenticated users can see this page!
519
+ </p>
520
+
521
+ `,
522
+ ],
523
+ // Lib files
524
+ './src/lib/index.ts': [
525
+ `import { FF_Role } from 'firstly'
526
+ import { FF_Role_Auth } from 'firstly/auth/client'
527
+ import { Log } from '@kitql/helpers'
528
+
529
+ /**
530
+ * Your logs with a nice prefix, use \`log.info("Hello")\` / \`log.success("Yeah")\` / \`log.error("Ho nooo!")\` and see !
531
+ */
532
+ export const log = new Log('${pkg.name}')
533
+
534
+ /**
535
+ * Your roles, use them in your app !
536
+ */
537
+ export const Role = {
538
+ Boss: 'Boss',
539
+ ...FF_Role_Auth,
540
+ ...FF_Role,
541
+ } as const
356
542
  `,
357
543
  ],
358
544
  './src/lib/ui/SignIn.svelte': [
@@ -427,99 +613,38 @@ export const load = (async (event) => {
427
613
  <button on:click={logout}>Logout</button>
428
614
  `,
429
615
  ],
430
- './tsconfig.json': [
431
- `{
432
- "extends": "./.svelte-kit/tsconfig.json",
433
- "compilerOptions": {
434
- "experimentalDecorators": true,
435
- "allowJs": true,
436
- "checkJs": true,
437
- "esModuleInterop": true,
438
- "forceConsistentCasingInFileNames": true,
439
- "resolveJsonModule": true,
440
- "skipLibCheck": true,
441
- "sourceMap": true,
442
- "strict": true,
443
- "moduleResolution": "bundler"
444
- }
445
- // Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias
446
- //
447
- // If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes
448
- // from the referenced tsconfig.json - TypeScript does not merge them in
449
- }
450
- `,
451
- ],
452
- './vite.config.ts': [
453
- `import { sveltekit } from '@sveltejs/kit/vite'
454
- import { defineConfig } from 'vite'
455
-
456
- import { firstly } from 'firstly/vite'
457
-
458
- import type { KIT_ROUTES } from '${libAlias}/ROUTES'
616
+ // Task module
617
+ './src/modules/task/index.ts': [
618
+ `import { Log } from '@kitql/helpers'
459
619
 
460
- export default defineConfig({
461
- plugins: [
462
- // @ts-ignore JYC TODO (vite 5 / vite 6...)
463
- firstly<KIT_ROUTES>({
464
- kitRoutes: {
465
- LINKS: {
466
- login: 'ff/auth/sign-in',
467
- github: 'https://github.com/[owner]/[repo]',
468
- remult_admin: 'api/admin',
469
- },
470
- }
471
- }),
472
- sveltekit(),
473
- ],
474
- })
475
- `,
476
- ],
477
- './.gitignore': [
478
- `node_modules
479
-
480
- # Output
481
- /.svelte-kit
482
- /build
483
-
484
- # Env
485
- .env
486
- .env.*
487
- !.env.example
488
- !.env.test
489
-
490
- # Vite
491
- vite.config.js.timestamp-*
492
- vite.config.ts.timestamp-*
493
-
494
- # Firstly / Remult
495
- /db
496
- `,
620
+ export const log = new Log("Custom Task Log")`,
497
621
  ],
498
- './src/lib/firstly/modules/task/index.ts': [
622
+ './src/modules/task/server/index.ts': [
499
623
  `import { Module } from 'firstly/api'
500
624
 
501
- import { log } from '${libAlias}/firstly'
502
-
503
- import { Task } from './Task'
504
- import { TaskController } from './TaskController'
625
+ import { Task } from '../client/Task'
626
+ import { TaskController } from '../client/TaskController'
505
627
 
506
628
  export const task: (o: { specialInfo: string }) => Module = ({ specialInfo }) => {
507
- return new Module({
508
- name: 'task',
509
- entities: [Task],
510
- controllers: [TaskController],
511
- initApi: async () => {
512
- log.success(\`Task module is ready! 🚀 (specialInfo: \${specialInfo})\`)
513
- },
514
- })
515
- }`,
629
+ const m = new Module({
630
+ name: 'task',
631
+ entities: [Task],
632
+ controllers: [TaskController],
633
+ initApi: async () => {
634
+ m.log.success(\`Task module is ready! 🚀 (specialInfo: \${specialInfo})\`)
635
+ },
636
+ })
637
+
638
+ return m
639
+ }
640
+ `,
516
641
  ],
517
- './src/lib/firstly/modules/task/Task.ts': [
518
- `import { Entity, Field, Fields, ValueListFieldType } from 'remult'
642
+ './src/modules/task/client/Task.ts': [
643
+ `import { Allow, Entity, Field, Fields, ValueListFieldType } from 'remult'
519
644
  import { BaseEnum, LibIcon_Add, LibIcon_Delete, type BaseEnumOptions } from 'firstly'
520
645
 
521
646
  @Entity('task', {
522
- allowApiCrud: true,
647
+ allowApiCrud: Allow.authenticated,
523
648
  })
524
649
  export class Task {
525
650
  @Fields.cuid()
@@ -558,10 +683,10 @@ export class TypeOfTaskEnum extends BaseEnum {
558
683
  }
559
684
  `,
560
685
  ],
561
- './src/lib/firstly/modules/task/TaskController.ts': [
686
+ './src/modules/task/client/TaskController.ts': [
562
687
  `import { BackendMethod } from 'remult'
563
688
 
564
- import { log } from '${libAlias}/firstly'
689
+ import { log } from '${libAlias}'
565
690
 
566
691
  /**
567
692
  * await TaskController.sayHiFromTask("JYC")
@@ -572,6 +697,81 @@ export class TaskController {
572
697
  log.info(\`hello \${name} 👋\`)
573
698
  }
574
699
  }
700
+ `,
701
+ ],
702
+ './src/modules/task/ui/svelte/TaskAdd.svelte': [
703
+ `<script lang="ts">
704
+ import { EntityError, repo } from 'remult'
705
+
706
+ import { Task } from '${modulesAlias}/task/client/Task'
707
+
708
+ let task = $state(repo(Task).create())
709
+ let error = $state<EntityError<Task> | null>(null)
710
+
711
+ const add = async (e: Event) => {
712
+ e.preventDefault()
713
+ error = null
714
+ try {
715
+ await repo(Task).insert(task)
716
+ task = repo(Task).create()
717
+ } catch (e) {
718
+ if (e instanceof EntityError) {
719
+ error = e
720
+ }
721
+ }
722
+ }
723
+ </script>
724
+
725
+ <form onsubmit={add}>
726
+ <p>
727
+ {error?.modelState?.title}
728
+ </p>
729
+ <label for={repo(Task).fields.title.key}>{repo(Task).fields.title.caption}</label>
730
+ <input id={repo(Task).fields.title.key} type="text" bind:value={task.title} />
731
+ <button disabled={!repo(Task).metadata.apiInsertAllowed()}>Add</button>
732
+ </form>
733
+ `,
734
+ ],
735
+ './src/modules/task/ui/svelte/TaskList.svelte': [
736
+ `<script lang="ts">
737
+ import { repo } from 'remult'
738
+
739
+ import { Task } from '${modulesAlias}/task/client/Task'
740
+
741
+ let list: Task[] = $state([])
742
+
743
+ $effect(() => {
744
+ if (repo(Task).metadata.apiReadAllowed) {
745
+ return repo(Task)
746
+ .liveQuery()
747
+ .subscribe((info) => {
748
+ list = info.applyChanges(list)
749
+ })
750
+ }
751
+ })
752
+ </script>
753
+
754
+ {#if repo(Task).metadata.apiReadAllowed}
755
+ <ul>
756
+ {#each list as task (task.id)}
757
+ <li>{task.title}</li>
758
+ {/each}
759
+ </ul>
760
+ {:else}
761
+ <p>Login to see the task list!</p>
762
+ {/if}
763
+ `,
764
+ ],
765
+ './src/routes/demo/task/+page.svelte': [
766
+ `<script lang="ts">
767
+ import TaskAdd from '${modulesAlias}/task/ui/svelte/TaskAdd.svelte'
768
+ import TaskList from '${modulesAlias}/task/ui/svelte/TaskList.svelte'
769
+ </script>
770
+
771
+ <h1>Task Module</h1>
772
+
773
+ <TaskAdd />
774
+ <TaskList />
575
775
  `,
576
776
  ],
577
777
  };
@@ -581,7 +781,7 @@ for (const [path, content] of Object.entries(obj)) {
581
781
  }
582
782
  else {
583
783
  if (res.includes('module-demo')) {
584
- if (path.startsWith('./src/lib/firstly/modules/task')) {
784
+ if (path.startsWith('./src/modules/task')) {
585
785
  write(path, content);
586
786
  }
587
787
  }