firstly 0.0.12 → 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.
- package/CHANGELOG.md +16 -0
- package/esm/ROUTES.d.ts +2 -0
- package/esm/ROUTES.js +1 -0
- package/esm/api/index.d.ts +9 -0
- package/esm/api/index.js +3 -1
- package/esm/auth/AuthController.d.ts +12 -23
- package/esm/auth/AuthController.js +12 -31
- package/esm/auth/server/AuthController.server.d.ts +11 -11
- package/esm/auth/server/AuthController.server.js +99 -34
- package/esm/auth/server/handleGuard.d.ts +16 -0
- package/esm/auth/server/handleGuard.js +67 -0
- package/esm/auth/server/helperFirstly.d.ts +1 -1
- package/esm/auth/server/helperFirstly.js +1 -0
- package/esm/auth/server/index.d.ts +3 -1
- package/esm/auth/server/index.js +3 -1
- package/esm/auth/server/module.d.ts +105 -89
- package/esm/auth/server/module.js +55 -42
- package/esm/auth/server/providers/github.d.ts +4 -2
- package/esm/auth/server/providers/github.js +2 -2
- package/esm/auth/static/assets/Page-B0XXxe0N.d.ts +6 -0
- package/esm/auth/static/assets/Page-B0XXxe0N.js +1 -0
- package/esm/auth/static/assets/Page-DdKMiUZn.d.ts +6 -0
- package/esm/auth/static/assets/Page-DdKMiUZn.js +20 -0
- package/esm/auth/static/assets/Page-UV_hqY7I.d.ts +6 -0
- package/esm/auth/static/assets/Page-UV_hqY7I.js +1 -0
- package/esm/auth/static/assets/Page-mK42zGEw.css +1 -0
- package/esm/auth/static/assets/index-C9jzxOBu.d.ts +151 -0
- package/esm/auth/static/assets/index-C9jzxOBu.js +42 -0
- package/esm/auth/static/assets/index-DKWpA6v7.css +4 -0
- package/esm/auth/static/index.html +11 -11
- package/esm/auth/types.d.ts +26 -3
- package/esm/bin/cmd.js +423 -152
- package/esm/cellsBuildor.js +1 -1
- package/esm/common.d.ts +5 -0
- package/esm/common.js +8 -0
- package/esm/cron/server/index.js +1 -1
- package/esm/feedback/FeedbackController.js +58 -53
- package/esm/feedback/server/index.d.ts +6 -15
- package/esm/feedback/server/index.js +4 -5
- package/esm/feedback/types.d.ts +14 -0
- package/esm/feedback/types.js +4 -0
- package/esm/feedback/ui/DialogIssue.svelte +131 -119
- package/esm/feedback/ui/DialogIssue.svelte.d.ts +20 -18
- package/esm/feedback/ui/DialogIssues.svelte +108 -99
- package/esm/feedback/ui/DialogIssues.svelte.d.ts +20 -18
- package/esm/feedback/ui/DialogMilestones.svelte +40 -34
- package/esm/feedback/ui/DialogMilestones.svelte.d.ts +18 -16
- package/esm/feedback/ui/Feedback.svelte +11 -9
- package/esm/feedback/ui/Feedback.svelte.d.ts +16 -14
- package/esm/index.d.ts +2 -5
- package/esm/index.js +2 -8
- package/esm/mail/server/index.d.ts +9 -2
- package/esm/mail/server/index.js +3 -1
- package/esm/mail/templates/DefaultMail.svelte +81 -61
- package/esm/mail/templates/DefaultMail.svelte.d.ts +28 -26
- package/esm/server/index.d.ts +0 -0
- package/esm/server/index.js +1 -0
- package/esm/storeItem.d.ts +1 -4
- package/esm/storeItem.js +1 -1
- package/esm/storeList.d.ts +1 -4
- package/esm/sveltekit/server/index.d.ts +3 -9
- package/esm/sveltekit/server/index.js +3 -0
- package/esm/ui/Button.svelte +112 -89
- package/esm/ui/Button.svelte.d.ts +34 -24
- package/esm/ui/Clipboardable.svelte +24 -17
- package/esm/ui/Clipboardable.svelte.d.ts +34 -23
- package/esm/ui/Field.svelte +328 -285
- package/esm/ui/Field.svelte.d.ts +15 -8
- package/esm/ui/FieldGroup.svelte +112 -91
- package/esm/ui/FieldGroup.svelte.d.ts +17 -6
- package/esm/ui/Grid.svelte +322 -308
- package/esm/ui/Grid.svelte.d.ts +17 -6
- package/esm/ui/GridLoading.svelte +28 -27
- package/esm/ui/GridLoading.svelte.d.ts +19 -17
- package/esm/ui/GridPaginate.svelte +68 -61
- package/esm/ui/GridPaginate.svelte.d.ts +21 -19
- package/esm/ui/Icon.svelte +116 -80
- package/esm/ui/Icon.svelte.d.ts +52 -43
- package/esm/ui/Loading.svelte +10 -8
- package/esm/ui/Loading.svelte.d.ts +29 -18
- package/esm/ui/Tooltip.svelte +38 -35
- package/esm/ui/Tooltip.svelte.d.ts +30 -20
- package/esm/ui/dialog/DialogForm.svelte +70 -63
- package/esm/ui/dialog/DialogForm.svelte.d.ts +18 -16
- package/esm/ui/dialog/DialogManagement.svelte +74 -74
- package/esm/ui/dialog/DialogManagement.svelte.d.ts +22 -21
- package/esm/ui/dialog/DialogPrimitive.svelte +82 -76
- package/esm/ui/dialog/DialogPrimitive.svelte.d.ts +35 -25
- package/esm/ui/dialog/FormEditAction.svelte +58 -50
- package/esm/ui/dialog/FormEditAction.svelte.d.ts +13 -6
- package/esm/ui/dialog/dialog.d.ts +1 -4
- package/esm/ui/internals/FieldContainer.svelte +24 -17
- package/esm/ui/internals/FieldContainer.svelte.d.ts +37 -28
- package/esm/ui/internals/Input.svelte +136 -102
- package/esm/ui/internals/Input.svelte.d.ts +34 -32
- package/esm/ui/internals/Textarea.svelte +60 -52
- package/esm/ui/internals/Textarea.svelte.d.ts +31 -28
- package/esm/ui/internals/select/MultiSelectMelt.svelte +243 -199
- package/esm/ui/internals/select/MultiSelectMelt.svelte.d.ts +29 -27
- package/esm/ui/internals/select/SelectMelt.svelte +254 -219
- package/esm/ui/internals/select/SelectMelt.svelte.d.ts +34 -32
- package/esm/ui/internals/select/SelectRadio.svelte +39 -33
- package/esm/ui/internals/select/SelectRadio.svelte.d.ts +24 -22
- package/esm/ui/link/Link.svelte +25 -20
- package/esm/ui/link/Link.svelte.d.ts +31 -23
- package/esm/ui/link/LinkPlus.svelte +52 -51
- package/esm/ui/link/LinkPlus.svelte.d.ts +20 -18
- package/esm/vite/index.d.ts +2 -3
- package/esm/vite/index.js +33 -26
- package/package.json +16 -20
- package/esm/auth/static/assets/Page-Bb8bFlrP.d.ts +0 -4
- package/esm/auth/static/assets/Page-Bb8bFlrP.js +0 -1
- package/esm/auth/static/assets/Page-BxomFlZ8.d.ts +0 -4
- package/esm/auth/static/assets/Page-BxomFlZ8.js +0 -1
- package/esm/auth/static/assets/Page-CaIYu0-y.d.ts +0 -6
- package/esm/auth/static/assets/Page-CaIYu0-y.js +0 -19
- package/esm/auth/static/assets/Page-MkYglNtu.css +0 -1
- package/esm/auth/static/assets/index-Bl0Bk5u0.d.ts +0 -64
- package/esm/auth/static/assets/index-Bl0Bk5u0.js +0 -2
- package/esm/auth/static/assets/index-R27C_TlP.css +0 -4
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
|
|
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('');
|
|
@@ -47,14 +49,12 @@ function mergeAndSort(deps, depsToAdd) {
|
|
|
47
49
|
return sorted;
|
|
48
50
|
}
|
|
49
51
|
pkg.devDependencies = mergeAndSort(pkg.devDependencies, {
|
|
50
|
-
'@kitql/eslint-config': '0.
|
|
51
|
-
'@kitql/helpers': '0.8.
|
|
52
|
+
'@kitql/eslint-config': '0.5.8',
|
|
53
|
+
'@kitql/helpers': '0.8.12',
|
|
52
54
|
pg: '8.12.0',
|
|
53
|
-
remult:
|
|
54
|
-
});
|
|
55
|
-
pkg.dependencies = mergeAndSort(pkg.dependencies, {
|
|
56
|
-
oslo: '^1.2.1',
|
|
55
|
+
remult: versionOfRemult,
|
|
57
56
|
});
|
|
57
|
+
pkg.dependencies = mergeAndSort(pkg.dependencies, {});
|
|
58
58
|
pkg.scripts = {
|
|
59
59
|
...pkg.scripts,
|
|
60
60
|
'//// ---- BEST PRACTICES ---- ////': '',
|
|
@@ -65,14 +65,48 @@ if (res.includes('all') || res.includes('dependencies')) {
|
|
|
65
65
|
write('./package.json', [JSON.stringify(pkg, null, 2)]);
|
|
66
66
|
}
|
|
67
67
|
const obj = {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
68
|
+
// Configs
|
|
69
|
+
'./.npmrc': [
|
|
70
|
+
`engine-strict=true
|
|
71
|
+
|
|
72
|
+
public-hoist-pattern[]=*eslint*
|
|
73
|
+
public-hoist-pattern[]=*prettier*
|
|
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
|
|
96
|
+
`,
|
|
97
|
+
],
|
|
98
|
+
'./eslint.config.js': [
|
|
99
|
+
`import { kitql } from '@kitql/eslint-config'
|
|
100
|
+
|
|
101
|
+
/** @type { import("eslint").Linter.Config[] } */
|
|
102
|
+
export default [
|
|
103
|
+
...kitql({ pnpmCatalogs: { enable: false } }),
|
|
104
|
+
{
|
|
105
|
+
name: 'APP:ignores',
|
|
106
|
+
ignores: ['**/*.svelte.ts'],
|
|
107
|
+
},
|
|
108
|
+
]
|
|
109
|
+
`,
|
|
76
110
|
],
|
|
77
111
|
'./.prettierignore': [
|
|
78
112
|
`node_modules/
|
|
@@ -96,16 +130,14 @@ db/
|
|
|
96
130
|
src/lib/ROUTES.ts
|
|
97
131
|
`,
|
|
98
132
|
],
|
|
99
|
-
'./.prettierrc.
|
|
100
|
-
`
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
module.exports = {
|
|
106
|
-
...prettierConfig,
|
|
133
|
+
'./.prettierrc.mjs': [
|
|
134
|
+
`import { kitql } from '@kitql/eslint-config/.prettierrc.mjs'
|
|
135
|
+
|
|
136
|
+
export default {
|
|
137
|
+
...kitql(),
|
|
107
138
|
// Your overrides here
|
|
108
|
-
}
|
|
139
|
+
}
|
|
140
|
+
`,
|
|
109
141
|
],
|
|
110
142
|
'.env.example': [
|
|
111
143
|
`# Enable some roles
|
|
@@ -117,26 +149,114 @@ module.exports = {
|
|
|
117
149
|
# GITHUB_CLIENT_SECRET = ''
|
|
118
150
|
`,
|
|
119
151
|
],
|
|
120
|
-
'./
|
|
121
|
-
`
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
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'
|
|
126
177
|
|
|
127
|
-
import {
|
|
178
|
+
import { firstly } from 'firstly/vite'
|
|
128
179
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
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
|
+
},
|
|
134
219
|
}
|
|
135
220
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
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': [
|
|
252
|
+
`import { FF_Role } from 'firstly'
|
|
253
|
+
import { firstly, Module } from 'firstly/api'
|
|
254
|
+
import { auth } from 'firstly/auth/server'
|
|
255
|
+
import { mail } from 'firstly/mail/server'
|
|
256
|
+
import { changeLog } from 'firstly/changeLog/server'
|
|
257
|
+
|
|
258
|
+
import { log, Role } from '${libAlias}'
|
|
259
|
+
import { task } from '${modulesAlias}/task/server'
|
|
140
260
|
|
|
141
261
|
export const api = firstly({
|
|
142
262
|
//----------------------------------------
|
|
@@ -157,8 +277,8 @@ export const api = firstly({
|
|
|
157
277
|
providers: {
|
|
158
278
|
demo: [
|
|
159
279
|
{ name: 'Ermin' },
|
|
160
|
-
{ name: 'JYC', roles: [FF_Role.
|
|
161
|
-
{ name: 'Noam', roles: [FF_Role.
|
|
280
|
+
{ name: 'JYC', roles: [FF_Role.FF_Role_Admin] },
|
|
281
|
+
{ name: 'Noam', roles: [FF_Role.FF_Role_Admin, Role.Boss] },
|
|
162
282
|
],
|
|
163
283
|
|
|
164
284
|
// password: {},
|
|
@@ -170,13 +290,20 @@ export const api = firstly({
|
|
|
170
290
|
// To enable OAuth via Github
|
|
171
291
|
// Instructions by hovering the method \`github\`
|
|
172
292
|
// NEEDS ON TOP OF THE FILE:
|
|
173
|
-
// import { github } from 'firstly/auth/
|
|
293
|
+
// import { github } from 'firstly/auth/server'
|
|
174
294
|
//----------------------------------------
|
|
175
295
|
// github(),
|
|
176
296
|
],
|
|
177
297
|
},
|
|
178
298
|
}),
|
|
179
299
|
|
|
300
|
+
//----------------------------------------
|
|
301
|
+
// Core Module: mail
|
|
302
|
+
//----------------------------------------
|
|
303
|
+
mail({
|
|
304
|
+
// options
|
|
305
|
+
}),
|
|
306
|
+
|
|
180
307
|
//----------------------------------------
|
|
181
308
|
// example of a userland module
|
|
182
309
|
//----------------------------------------
|
|
@@ -185,14 +312,14 @@ export const api = firstly({
|
|
|
185
312
|
//----------------------------------------
|
|
186
313
|
// example of a userland inline module
|
|
187
314
|
//----------------------------------------
|
|
188
|
-
{
|
|
315
|
+
new Module({
|
|
189
316
|
name: 'app',
|
|
190
317
|
entities: [],
|
|
191
318
|
controllers: [],
|
|
192
319
|
initApi: async () => {
|
|
193
320
|
log.success('App is ready! 🚀')
|
|
194
321
|
},
|
|
195
|
-
},
|
|
322
|
+
}),
|
|
196
323
|
|
|
197
324
|
//----------------------------------------
|
|
198
325
|
// Replace @Entity by @FF_Entity in your entities to enable changeLog on this entity
|
|
@@ -204,21 +331,34 @@ export const api = firstly({
|
|
|
204
331
|
],
|
|
205
332
|
'./src/hooks.server.ts': [
|
|
206
333
|
`import { sequence } from '@sveltejs/kit/hooks'
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
import {
|
|
211
|
-
|
|
212
|
-
|
|
334
|
+
import { redirect } from '@sveltejs/kit'
|
|
335
|
+
|
|
336
|
+
import { handleAuth, handleGuard } from 'firstly/auth/server'
|
|
337
|
+
import { route } from '${libAlias}/ROUTES'
|
|
338
|
+
import { api as handleRemult } from '${serverAlias}'
|
|
339
|
+
|
|
340
|
+
export const handle = sequence(
|
|
341
|
+
//
|
|
342
|
+
handleRemult,
|
|
343
|
+
handleAuth,
|
|
344
|
+
// client side guard is not here!
|
|
345
|
+
handleGuard({
|
|
346
|
+
authenticated: ['/app*'],
|
|
347
|
+
redirectToLogin: route('/'),
|
|
348
|
+
// You want to redirect to the firstly UI ? change redirectToLogin to this 👇
|
|
349
|
+
// redirectToLogin: route('login'),
|
|
350
|
+
redirectAuthenticated: route('/app'),
|
|
351
|
+
redirect,
|
|
352
|
+
})
|
|
353
|
+
)
|
|
213
354
|
`,
|
|
214
355
|
],
|
|
215
356
|
'./src/routes/api/[...remult]/+server.ts': [
|
|
216
|
-
`import { api } from '${
|
|
357
|
+
`import { api } from '${serverAlias}'
|
|
217
358
|
|
|
218
359
|
export const { GET, POST, PUT, DELETE } = api
|
|
219
360
|
`,
|
|
220
361
|
],
|
|
221
|
-
'./src/routes/+page.svelte': [`Home 👋`, ``],
|
|
222
362
|
'./src/routes/+layout.server.ts': [
|
|
223
363
|
`import { remult } from 'remult'
|
|
224
364
|
|
|
@@ -227,20 +367,78 @@ import type { LayoutServerLoad } from './$types'
|
|
|
227
367
|
export const load = (async () => {
|
|
228
368
|
return { user: remult.user }
|
|
229
369
|
}) satisfies LayoutServerLoad
|
|
370
|
+
`,
|
|
371
|
+
],
|
|
372
|
+
'./src/routes/+layout.ts': [
|
|
373
|
+
`import { remult } from 'remult'
|
|
374
|
+
import type { LayoutLoad } from './$types'
|
|
375
|
+
|
|
376
|
+
export const load = (async (event) => {
|
|
377
|
+
// Instruct remult to use the special svelte fetch
|
|
378
|
+
// Like this univeral load will work in SSR & CSR
|
|
379
|
+
remult.useFetch(event.fetch)
|
|
380
|
+
// return repo(Task).find()
|
|
381
|
+
return { ...event.data }
|
|
382
|
+
}) satisfies LayoutLoad
|
|
230
383
|
`,
|
|
231
384
|
],
|
|
232
385
|
'./src/routes/+layout.svelte': [
|
|
233
386
|
`<script lang="ts">
|
|
234
|
-
import {
|
|
387
|
+
import { untrack } from 'svelte'
|
|
388
|
+
import { createSubscriber } from 'svelte/reactivity'
|
|
389
|
+
|
|
390
|
+
import { Remult, remult } from 'remult'
|
|
235
391
|
|
|
236
392
|
import { route } from '${libAlias}/ROUTES'
|
|
237
393
|
import SignIn from '${libAlias}/ui/SignIn.svelte'
|
|
238
394
|
import SignOut from '${libAlias}/ui/SignOut.svelte'
|
|
239
395
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
396
|
+
import type { LayoutData } from './$types'
|
|
397
|
+
|
|
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()
|
|
244
442
|
</script>
|
|
245
443
|
|
|
246
444
|
<svelte:head>
|
|
@@ -265,12 +463,21 @@ export const load = (async () => {
|
|
|
265
463
|
<SignIn demo="Noam"></SignIn>
|
|
266
464
|
<br />
|
|
267
465
|
<SignIn ffLink></SignIn>
|
|
466
|
+
<br />
|
|
268
467
|
<SignIn oauth="github"></SignIn>
|
|
269
468
|
{/if}
|
|
270
469
|
|
|
271
470
|
<hr />
|
|
272
471
|
|
|
273
|
-
<
|
|
472
|
+
<a href={route('/')}>Home</a> |
|
|
473
|
+
{#if remult.authenticated()}
|
|
474
|
+
<a href={route('/app')}>App (Protected route)</a> |
|
|
475
|
+
{/if}
|
|
476
|
+
<a href={route('/demo/task')}>Demo task</a>
|
|
477
|
+
|
|
478
|
+
<hr />
|
|
479
|
+
|
|
480
|
+
{@render children?.()}
|
|
274
481
|
|
|
275
482
|
<hr />
|
|
276
483
|
|
|
@@ -283,16 +490,65 @@ export const load = (async () => {
|
|
|
283
490
|
<a href={route('github', { owner: 'jycouet', repo: 'firstly' })} target="_blank"> ⭐️ firstly </a>
|
|
284
491
|
|
|
|
285
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
|
|
286
542
|
`,
|
|
287
543
|
],
|
|
288
544
|
'./src/lib/ui/SignIn.svelte': [
|
|
289
545
|
`<script lang="ts">
|
|
290
546
|
import { isError } from 'firstly'
|
|
291
|
-
import {
|
|
547
|
+
import { AuthController } from 'firstly/auth/client'
|
|
292
548
|
|
|
293
549
|
import { goto, invalidateAll } from '$app/navigation'
|
|
294
550
|
|
|
295
|
-
import { route } from '
|
|
551
|
+
import { route } from '${libAlias}/ROUTES'
|
|
296
552
|
|
|
297
553
|
// Examples of signin modes
|
|
298
554
|
export let demo = ''
|
|
@@ -301,7 +557,7 @@ export const load = (async () => {
|
|
|
301
557
|
|
|
302
558
|
const signinDemo = async (identif: string) => {
|
|
303
559
|
try {
|
|
304
|
-
await
|
|
560
|
+
await AuthController.signInDemo(identif)
|
|
305
561
|
invalidateAll()
|
|
306
562
|
} catch (error) {
|
|
307
563
|
if (isError(error)) {
|
|
@@ -313,7 +569,7 @@ export const load = (async () => {
|
|
|
313
569
|
|
|
314
570
|
async function signinOAuth(provider: 'github') {
|
|
315
571
|
try {
|
|
316
|
-
window.location.href = await
|
|
572
|
+
window.location.href = await AuthController.signInOAuthGetUrl({
|
|
317
573
|
provider,
|
|
318
574
|
redirect: window.location.pathname,
|
|
319
575
|
})
|
|
@@ -329,7 +585,7 @@ export const load = (async () => {
|
|
|
329
585
|
{#if demo}
|
|
330
586
|
<button on:click={() => signinDemo(demo)}>Login as {demo}</button>
|
|
331
587
|
{:else if ffLink}
|
|
332
|
-
<button on:click={() => goto(route('
|
|
588
|
+
<button on:click={() => goto(route('login'))}>Login with Firstly UI</button>
|
|
333
589
|
{:else if oauth}
|
|
334
590
|
<button on:click={() => signinOAuth(oauth)}>Login With {oauth}</button>
|
|
335
591
|
{/if}
|
|
@@ -338,13 +594,13 @@ export const load = (async () => {
|
|
|
338
594
|
'./src/lib/ui/SignOut.svelte': [
|
|
339
595
|
`<script lang="ts">
|
|
340
596
|
import { isError } from 'firstly'
|
|
341
|
-
import {
|
|
597
|
+
import { AuthController } from 'firstly/auth/client'
|
|
342
598
|
|
|
343
599
|
import { invalidateAll } from '$app/navigation'
|
|
344
600
|
|
|
345
601
|
const logout = async () => {
|
|
346
602
|
try {
|
|
347
|
-
await
|
|
603
|
+
await AuthController.signOut()
|
|
348
604
|
invalidateAll()
|
|
349
605
|
} catch (error) {
|
|
350
606
|
if (isError(error)) {
|
|
@@ -357,98 +613,38 @@ export const load = (async () => {
|
|
|
357
613
|
<button on:click={logout}>Logout</button>
|
|
358
614
|
`,
|
|
359
615
|
],
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
"compilerOptions": {
|
|
364
|
-
"experimentalDecorators": true,
|
|
365
|
-
"allowJs": true,
|
|
366
|
-
"checkJs": true,
|
|
367
|
-
"esModuleInterop": true,
|
|
368
|
-
"forceConsistentCasingInFileNames": true,
|
|
369
|
-
"resolveJsonModule": true,
|
|
370
|
-
"skipLibCheck": true,
|
|
371
|
-
"sourceMap": true,
|
|
372
|
-
"strict": true,
|
|
373
|
-
"moduleResolution": "bundler"
|
|
374
|
-
}
|
|
375
|
-
// Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias
|
|
376
|
-
//
|
|
377
|
-
// If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes
|
|
378
|
-
// from the referenced tsconfig.json - TypeScript does not merge them in
|
|
379
|
-
}
|
|
380
|
-
`,
|
|
381
|
-
],
|
|
382
|
-
'./vite.config.ts': [
|
|
383
|
-
`import { sveltekit } from '@sveltejs/kit/vite'
|
|
384
|
-
import { defineConfig } from 'vite'
|
|
385
|
-
|
|
386
|
-
import { firstly } from 'firstly/vite'
|
|
387
|
-
|
|
388
|
-
import type { KIT_ROUTES } from '${libAlias}/ROUTES'
|
|
616
|
+
// Task module
|
|
617
|
+
'./src/modules/task/index.ts': [
|
|
618
|
+
`import { Log } from '@kitql/helpers'
|
|
389
619
|
|
|
390
|
-
export
|
|
391
|
-
plugins: [
|
|
392
|
-
firstly<KIT_ROUTES>({
|
|
393
|
-
kitRoutes: {
|
|
394
|
-
LINKS: {
|
|
395
|
-
firstly_sign_in: 'ff/auth/sign-in',
|
|
396
|
-
github: 'https://github.com/[owner]/[repo]',
|
|
397
|
-
remult_admin: 'api/admin',
|
|
398
|
-
},
|
|
399
|
-
}
|
|
400
|
-
}),
|
|
401
|
-
sveltekit(),
|
|
402
|
-
],
|
|
403
|
-
})
|
|
404
|
-
`,
|
|
620
|
+
export const log = new Log("Custom Task Log")`,
|
|
405
621
|
],
|
|
406
|
-
'
|
|
407
|
-
`
|
|
622
|
+
'./src/modules/task/server/index.ts': [
|
|
623
|
+
`import { Module } from 'firstly/api'
|
|
408
624
|
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
/build
|
|
412
|
-
|
|
413
|
-
# Env
|
|
414
|
-
.env
|
|
415
|
-
.env.*
|
|
416
|
-
!.env.example
|
|
417
|
-
!.env.test
|
|
418
|
-
|
|
419
|
-
# Vite
|
|
420
|
-
vite.config.js.timestamp-*
|
|
421
|
-
vite.config.ts.timestamp-*
|
|
422
|
-
|
|
423
|
-
# Firstly / Remult
|
|
424
|
-
/db
|
|
425
|
-
`,
|
|
426
|
-
],
|
|
427
|
-
'./src/lib/firstly/modules/task/index.ts': [
|
|
428
|
-
`import type { Module } from 'firstly/api'
|
|
429
|
-
|
|
430
|
-
import { log } from '${libAlias}/firstly'
|
|
431
|
-
|
|
432
|
-
import { Task } from './Task'
|
|
433
|
-
import { TaskController } from './TaskController'
|
|
625
|
+
import { Task } from '../client/Task'
|
|
626
|
+
import { TaskController } from '../client/TaskController'
|
|
434
627
|
|
|
435
628
|
export const task: (o: { specialInfo: string }) => Module = ({ specialInfo }) => {
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
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
|
+
`,
|
|
445
641
|
],
|
|
446
|
-
'./src/
|
|
447
|
-
`import { Entity, Field, Fields, ValueListFieldType } from 'remult'
|
|
642
|
+
'./src/modules/task/client/Task.ts': [
|
|
643
|
+
`import { Allow, Entity, Field, Fields, ValueListFieldType } from 'remult'
|
|
448
644
|
import { BaseEnum, LibIcon_Add, LibIcon_Delete, type BaseEnumOptions } from 'firstly'
|
|
449
645
|
|
|
450
646
|
@Entity('task', {
|
|
451
|
-
allowApiCrud:
|
|
647
|
+
allowApiCrud: Allow.authenticated,
|
|
452
648
|
})
|
|
453
649
|
export class Task {
|
|
454
650
|
@Fields.cuid()
|
|
@@ -487,10 +683,10 @@ export class TypeOfTaskEnum extends BaseEnum {
|
|
|
487
683
|
}
|
|
488
684
|
`,
|
|
489
685
|
],
|
|
490
|
-
'./src/
|
|
686
|
+
'./src/modules/task/client/TaskController.ts': [
|
|
491
687
|
`import { BackendMethod } from 'remult'
|
|
492
688
|
|
|
493
|
-
import { log } from '${libAlias}
|
|
689
|
+
import { log } from '${libAlias}'
|
|
494
690
|
|
|
495
691
|
/**
|
|
496
692
|
* await TaskController.sayHiFromTask("JYC")
|
|
@@ -501,6 +697,81 @@ export class TaskController {
|
|
|
501
697
|
log.info(\`hello \${name} 👋\`)
|
|
502
698
|
}
|
|
503
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 />
|
|
504
775
|
`,
|
|
505
776
|
],
|
|
506
777
|
};
|
|
@@ -510,7 +781,7 @@ for (const [path, content] of Object.entries(obj)) {
|
|
|
510
781
|
}
|
|
511
782
|
else {
|
|
512
783
|
if (res.includes('module-demo')) {
|
|
513
|
-
if (path.startsWith('./src/
|
|
784
|
+
if (path.startsWith('./src/modules/task')) {
|
|
514
785
|
write(path, content);
|
|
515
786
|
}
|
|
516
787
|
}
|