firstly 0.2.1 → 0.4.0

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 (210) hide show
  1. package/CHANGELOG.md +65 -0
  2. package/esm/SqlDatabase/FF_LogToConsole.js +9 -14
  3. package/esm/carbone/CarboneController.js +2 -1
  4. package/esm/changeLog/index.d.ts +0 -10
  5. package/esm/{internals → core}/BaseEnum.d.ts +1 -1
  6. package/esm/core/FF_Entity.js +5 -0
  7. package/esm/core/helper.d.ts +2 -0
  8. package/esm/core/helper.js +3 -0
  9. package/esm/core/index.d.ts +0 -0
  10. package/esm/core/index.js +5 -0
  11. package/esm/core/tailwind.d.ts +21 -0
  12. package/esm/core/tailwind.js +22 -0
  13. package/esm/core/tryCatch.d.ts +44 -0
  14. package/esm/core/tryCatch.js +34 -0
  15. package/esm/cron/server/index.js +1 -1
  16. package/esm/feedback/FeedbackController.js +3 -2
  17. package/esm/feedback/index.d.ts +7 -2
  18. package/esm/feedback/index.js +1 -2
  19. package/esm/feedback/server/index.d.ts +0 -5
  20. package/esm/feedback/server/index.js +1 -1
  21. package/esm/formats/strings.js +2 -2
  22. package/esm/index.d.ts +16 -0
  23. package/esm/index.js +13 -0
  24. package/esm/svelte/FF_Repo.svelte.d.ts +9 -2
  25. package/esm/svelte/FF_Repo.svelte.js +40 -17
  26. package/esm/svelte/class/SP.svelte.js +14 -2
  27. package/esm/svelte/helpers/debounce.js +1 -1
  28. package/esm/svelte/index.d.ts +2 -24
  29. package/esm/svelte/index.js +2 -22
  30. package/esm/{ui → svelte/ui}/Icon.svelte +1 -1
  31. package/esm/virtual/StateDemoEnum.d.ts +3 -3
  32. package/esm/virtual/StateDemoEnum.js +3 -3
  33. package/esm/virtual/UIEntity.js +1 -2
  34. package/package.json +8 -39
  35. package/esm/auth/AuthController.d.ts +0 -58
  36. package/esm/auth/AuthController.js +0 -114
  37. package/esm/auth/Entities.d.ts +0 -47
  38. package/esm/auth/Entities.js +0 -182
  39. package/esm/auth/README.md +0 -3
  40. package/esm/auth/index.d.ts +0 -5
  41. package/esm/auth/index.js +0 -5
  42. package/esm/auth/server/AuthController.server.d.ts +0 -58
  43. package/esm/auth/server/AuthController.server.js +0 -518
  44. package/esm/auth/server/handleAuth.d.ts +0 -4
  45. package/esm/auth/server/handleAuth.js +0 -142
  46. package/esm/auth/server/handleGuard.d.ts +0 -22
  47. package/esm/auth/server/handleGuard.js +0 -34
  48. package/esm/auth/server/helperDb.d.ts +0 -10
  49. package/esm/auth/server/helperDb.js +0 -56
  50. package/esm/auth/server/helperFirstly.d.ts +0 -1
  51. package/esm/auth/server/helperFirstly.js +0 -9
  52. package/esm/auth/server/helperOslo.d.ts +0 -7
  53. package/esm/auth/server/helperOslo.js +0 -24
  54. package/esm/auth/server/helperRemultServer.d.ts +0 -5
  55. package/esm/auth/server/helperRemultServer.js +0 -44
  56. package/esm/auth/server/helperRole.d.ts +0 -19
  57. package/esm/auth/server/helperRole.js +0 -57
  58. package/esm/auth/server/index.d.ts +0 -8
  59. package/esm/auth/server/index.js +0 -8
  60. package/esm/auth/server/module.d.ts +0 -300
  61. package/esm/auth/server/module.js +0 -230
  62. package/esm/auth/server/providers/github.d.ts +0 -33
  63. package/esm/auth/server/providers/github.js +0 -87
  64. package/esm/auth/server/providers/helperProvider.d.ts +0 -1
  65. package/esm/auth/server/providers/helperProvider.js +0 -25
  66. package/esm/auth/static/assets/Page-BHW08QWz.css +0 -1
  67. package/esm/auth/static/assets/Page-BRNWcY5Z.d.ts +0 -2
  68. package/esm/auth/static/assets/Page-BRNWcY5Z.js +0 -1
  69. package/esm/auth/static/assets/Page-CFcEsGK8.d.ts +0 -2
  70. package/esm/auth/static/assets/Page-CFcEsGK8.js +0 -7
  71. package/esm/auth/static/assets/Page-tLVs5slF.d.ts +0 -2
  72. package/esm/auth/static/assets/Page-tLVs5slF.js +0 -1
  73. package/esm/auth/static/assets/index-D38rqu4x.d.ts +0 -201
  74. package/esm/auth/static/assets/index-D38rqu4x.js +0 -2
  75. package/esm/auth/static/assets/index-DKWpA6v7.css +0 -4
  76. package/esm/auth/static/favicon.svg +0 -79
  77. package/esm/auth/static/index.html +0 -13
  78. package/esm/auth/types.d.ts +0 -73
  79. package/esm/bin/cmd.d.ts +0 -1
  80. package/esm/bin/cmd.js +0 -793
  81. package/esm/feedback/ui/DialogIssue.svelte +0 -149
  82. package/esm/feedback/ui/DialogIssue.svelte.d.ts +0 -22
  83. package/esm/feedback/ui/DialogIssues.svelte +0 -114
  84. package/esm/feedback/ui/DialogIssues.svelte.d.ts +0 -22
  85. package/esm/feedback/ui/DialogMilestones.svelte +0 -43
  86. package/esm/feedback/ui/DialogMilestones.svelte.d.ts +0 -20
  87. package/esm/feedback/ui/Feedback.svelte +0 -16
  88. package/esm/feedback/ui/Feedback.svelte.d.ts +0 -18
  89. package/esm/internals/FF_Entity.d.ts +0 -2
  90. package/esm/internals/FF_Entity.js +0 -21
  91. package/esm/internals/FF_Fields.d.ts +0 -11
  92. package/esm/internals/FF_Fields.js +0 -144
  93. package/esm/internals/cellsBuildor.d.ts +0 -47
  94. package/esm/internals/cellsBuildor.js +0 -140
  95. package/esm/internals/helper.d.ts +0 -49
  96. package/esm/internals/helper.js +0 -162
  97. package/esm/internals/index.d.ts +0 -82
  98. package/esm/internals/index.js +0 -45
  99. package/esm/internals/storeItem.d.ts +0 -28
  100. package/esm/internals/storeItem.js +0 -176
  101. package/esm/internals/storeList.d.ts +0 -34
  102. package/esm/internals/storeList.js +0 -108
  103. package/esm/internals/theme.d.ts +0 -4
  104. package/esm/internals/theme.js +0 -4
  105. package/esm/server/index.d.ts +0 -52
  106. package/esm/server/index.js +0 -87
  107. package/esm/svelte/FF_Cell.svelte +0 -103
  108. package/esm/svelte/FF_Cell.svelte.d.ts +0 -33
  109. package/esm/svelte/FF_Cell_Caption.svelte +0 -20
  110. package/esm/svelte/FF_Cell_Caption.svelte.d.ts +0 -31
  111. package/esm/svelte/FF_Cell_Display.svelte +0 -61
  112. package/esm/svelte/FF_Cell_Display.svelte.d.ts +0 -29
  113. package/esm/svelte/FF_Cell_Edit.svelte +0 -104
  114. package/esm/svelte/FF_Cell_Edit.svelte.d.ts +0 -32
  115. package/esm/svelte/FF_Cell_Error.svelte +0 -20
  116. package/esm/svelte/FF_Cell_Error.svelte.d.ts +0 -31
  117. package/esm/svelte/FF_Cell_Hint.svelte +0 -20
  118. package/esm/svelte/FF_Cell_Hint.svelte.d.ts +0 -31
  119. package/esm/svelte/FF_Config.svelte +0 -29
  120. package/esm/svelte/FF_Config.svelte.d.ts +0 -9
  121. package/esm/svelte/FF_Form.svelte +0 -155
  122. package/esm/svelte/FF_Form.svelte.d.ts +0 -37
  123. package/esm/svelte/FF_Grid.svelte +0 -257
  124. package/esm/svelte/FF_Grid.svelte.d.ts +0 -37
  125. package/esm/svelte/FF_Layout.svelte +0 -62
  126. package/esm/svelte/FF_Layout.svelte.d.ts +0 -31
  127. package/esm/svelte/actions/intersection.d.ts +0 -6
  128. package/esm/svelte/actions/intersection.js +0 -17
  129. package/esm/svelte/customField.d.ts +0 -69
  130. package/esm/svelte/customField.js +0 -4
  131. package/esm/svelte/dialog/DialogManagement.svelte +0 -98
  132. package/esm/svelte/dialog/DialogManagement.svelte.d.ts +0 -18
  133. package/esm/svelte/dialog/DialogPrimitive.svelte +0 -156
  134. package/esm/svelte/dialog/DialogPrimitive.svelte.d.ts +0 -38
  135. package/esm/svelte/dialog/dialog.d.ts +0 -58
  136. package/esm/svelte/dialog/dialog.js +0 -130
  137. package/esm/svelte/ff_Config.svelte.d.ts +0 -91
  138. package/esm/svelte/ff_Config.svelte.js +0 -111
  139. package/esm/svelte/firstly.css +0 -14
  140. package/esm/svelte/helpers.d.ts +0 -30
  141. package/esm/svelte/helpers.js +0 -38
  142. package/esm/svelte/tryCatch.d.ts +0 -12
  143. package/esm/svelte/tryCatch.js +0 -18
  144. package/esm/sveltekit/server/index.d.ts +0 -5
  145. package/esm/sveltekit/server/index.js +0 -24
  146. package/esm/ui/Button.svelte +0 -138
  147. package/esm/ui/Button.svelte.d.ts +0 -13
  148. package/esm/ui/Clipboardable.svelte +0 -25
  149. package/esm/ui/Clipboardable.svelte.d.ts +0 -12
  150. package/esm/ui/Field.svelte +0 -382
  151. package/esm/ui/Field.svelte.d.ts +0 -40
  152. package/esm/ui/FieldGroup.svelte +0 -117
  153. package/esm/ui/FieldGroup.svelte.d.ts +0 -44
  154. package/esm/ui/Grid.svelte +0 -265
  155. package/esm/ui/Grid.svelte.d.ts +0 -57
  156. package/esm/ui/Grid2.svelte +0 -293
  157. package/esm/ui/Grid2.svelte.d.ts +0 -57
  158. package/esm/ui/GridLoading.svelte +0 -58
  159. package/esm/ui/GridLoading.svelte.d.ts +0 -23
  160. package/esm/ui/GridPaginate.svelte +0 -69
  161. package/esm/ui/GridPaginate.svelte.d.ts +0 -23
  162. package/esm/ui/GridPaginate2.svelte +0 -25
  163. package/esm/ui/GridPaginate2.svelte.d.ts +0 -7
  164. package/esm/ui/Loading.svelte +0 -16
  165. package/esm/ui/Loading.svelte.d.ts +0 -31
  166. package/esm/ui/Tooltip.svelte +0 -45
  167. package/esm/ui/Tooltip.svelte.d.ts +0 -32
  168. package/esm/ui/dialog/DialogForm.svelte +0 -76
  169. package/esm/ui/dialog/DialogForm.svelte.d.ts +0 -21
  170. package/esm/ui/dialog/DialogManagement.svelte +0 -96
  171. package/esm/ui/dialog/DialogManagement.svelte.d.ts +0 -26
  172. package/esm/ui/dialog/DialogPrimitive.svelte +0 -90
  173. package/esm/ui/dialog/DialogPrimitive.svelte.d.ts +0 -38
  174. package/esm/ui/dialog/FormEditAction.svelte +0 -62
  175. package/esm/ui/dialog/FormEditAction.svelte.d.ts +0 -31
  176. package/esm/ui/dialog/dialog.d.ts +0 -60
  177. package/esm/ui/dialog/dialog.js +0 -100
  178. package/esm/ui/index.d.ts +0 -6
  179. package/esm/ui/index.js +0 -20
  180. package/esm/ui/internals/FieldContainer.svelte +0 -39
  181. package/esm/ui/internals/FieldContainer.svelte.d.ts +0 -18
  182. package/esm/ui/internals/Input.svelte +0 -143
  183. package/esm/ui/internals/Input.svelte.d.ts +0 -37
  184. package/esm/ui/internals/Textarea.svelte +0 -66
  185. package/esm/ui/internals/Textarea.svelte.d.ts +0 -33
  186. package/esm/ui/internals/select/MultiSelectMelt.svelte +0 -260
  187. package/esm/ui/internals/select/MultiSelectMelt.svelte.d.ts +0 -32
  188. package/esm/ui/internals/select/Select2.svelte +0 -88
  189. package/esm/ui/internals/select/Select2.svelte.d.ts +0 -12
  190. package/esm/ui/internals/select/SelectMelt.svelte +0 -280
  191. package/esm/ui/internals/select/SelectMelt.svelte.d.ts +0 -40
  192. package/esm/ui/internals/select/SelectRadio.svelte +0 -43
  193. package/esm/ui/internals/select/SelectRadio.svelte.d.ts +0 -27
  194. package/esm/ui/link/Link.svelte +0 -33
  195. package/esm/ui/link/Link.svelte.d.ts +0 -33
  196. package/esm/ui/link/LinkPlus.svelte +0 -63
  197. package/esm/ui/link/LinkPlus.svelte.d.ts +0 -9
  198. package/esm/utils/tailwind.d.ts +0 -2
  199. package/esm/utils/tailwind.js +0 -3
  200. package/esm/utils/transition.d.ts +0 -9
  201. package/esm/utils/transition.js +0 -33
  202. package/esm/utils/types.js +0 -1
  203. /package/esm/{internals → core}/BaseEnum.js +0 -0
  204. /package/esm/{internals → core}/common.d.ts +0 -0
  205. /package/esm/{internals → core}/common.js +0 -0
  206. /package/esm/{utils → core}/types.d.ts +0 -0
  207. /package/esm/{auth → core}/types.js +0 -0
  208. /package/esm/{ui → svelte/ui}/Icon.svelte.d.ts +0 -0
  209. /package/esm/{ui → svelte/ui}/LibIcon.d.ts +0 -0
  210. /package/esm/{ui → svelte/ui}/LibIcon.js +0 -0
package/esm/bin/cmd.js DELETED
@@ -1,793 +0,0 @@
1
- import * as p from '@clack/prompts';
2
- import { bold, cyan, gray, green, italic, Log } from '@kitql/helpers';
3
- import { read, write } from '@kitql/internals';
4
- // Need this trick to be be replaced by the real lib alias here ;)
5
- const libAlias = '$' + 'lib';
6
- const serverAlias = '$' + 'server';
7
- const modulesAlias = '$' + 'modules';
8
- const pkgFirstly = JSON.parse(read('./node_modules/firstly/package.json') ?? '{}');
9
- const versionOfRemult = pkgFirstly?.peerDependencies?.['remult'] ?? 'latest';
10
- const pkg = JSON.parse(read('./package.json') ?? '{}');
11
- const version = pkg.devDependencies?.['firstly'] ?? pkg.dependencies?.['firstly'] ?? '???';
12
- console.info('');
13
- p.intro(`${green(`⚡️`)} Welcome to firstly world! ${gray(` - v${version}`)}`);
14
- const keys = ['all', 'module-demo', 'dependencies'];
15
- const options = [
16
- {
17
- value: 'all',
18
- label: 'All',
19
- hint: 'If you are starting a new project, this is for you!',
20
- },
21
- {
22
- value: 'module-demo',
23
- label: 'module task',
24
- hint: 'A default module with a task entity and a controller (you can rename the folder and make it yours)',
25
- },
26
- {
27
- value: 'dependencies',
28
- label: 'dependencies',
29
- hint: 'Add all dependencies that make sense to use with firstly',
30
- },
31
- ];
32
- const res = (await p.multiselect({
33
- message: 'You can generate different things here',
34
- options,
35
- }));
36
- // devDependencies
37
- function mergeAndSort(deps, depsToAdd) {
38
- const prepare = {
39
- ...depsToAdd,
40
- ...deps,
41
- };
42
- // sort by name
43
- const sorted = Object.keys(prepare)
44
- .sort()
45
- .reduce((acc, key) => {
46
- acc[key] = prepare[key];
47
- return acc;
48
- }, {});
49
- return sorted;
50
- }
51
- pkg.devDependencies = mergeAndSort(pkg.devDependencies, {
52
- '@kitql/eslint-config': '0.6.0',
53
- '@kitql/helpers': '0.8.12',
54
- pg: '8.12.0',
55
- remult: versionOfRemult,
56
- });
57
- pkg.dependencies = mergeAndSort(pkg.dependencies, {});
58
- pkg.scripts = {
59
- ...pkg.scripts,
60
- '//// ---- BEST PRACTICES ---- ////': '',
61
- lint: 'kitql-lint -d',
62
- format: 'kitql-lint -f -d',
63
- };
64
- if (res.includes('all') || res.includes('dependencies')) {
65
- write('./package.json', [JSON.stringify(pkg, null, 2)]);
66
- }
67
- const obj = {
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
- `,
110
- ],
111
- './.prettierignore': [
112
- `node_modules/
113
- dist/
114
- build
115
- .vs
116
- .vscode
117
- .bob/
118
- .next/
119
- .idea/
120
- .svelte-kit/
121
- .husky/_/
122
- .changeset/
123
- .DS_Store
124
- coverage/
125
- package.json
126
- pnpm-lock.yaml
127
- README.md
128
-
129
- db/
130
- src/lib/ROUTES.ts
131
- `,
132
- ],
133
- './.prettierrc.mjs': [
134
- `import { kitql } from '@kitql/eslint-config/.prettierrc.mjs'
135
-
136
- export default {
137
- ...kitql(),
138
- // Your overrides here
139
- }
140
- `,
141
- ],
142
- '.env.example': [
143
- `# Enable some roles
144
- # FF_ADMIN = 'JYC'
145
- # FF_AUTH_ADMIN = ''
146
-
147
- # Enable GitHub login
148
- # GITHUB_CLIENT_ID = ''
149
- # GITHUB_CLIENT_SECRET = ''
150
- `,
151
- ],
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 '../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': [
252
- `import { FF_Role } from '../internals'
253
- import { firstly, Module } from '../server'
254
- import { auth } from '../auth/server'
255
- import { mail } from '../mail/server'
256
- import { changeLog } from '../changeLog/server'
257
-
258
- import { log, Role } from '${libAlias}'
259
- import { task } from '${modulesAlias}/task/server'
260
-
261
- export const api = firstly({
262
- //----------------------------------------
263
- // To switch to postgres
264
- // NEEDS ON TOP OF THE FILE:
265
- // import { createPostgresConnection } from 'remult/postgres'
266
- // import { DATABASE_URL } from '$env/static/private'
267
- //----------------------------------------
268
- // dataProvider: await createPostgresConnection({
269
- // connectionString: DATABASE_URL,
270
- // }),
271
-
272
- modules: [
273
- //----------------------------------------
274
- // Core Module: auth
275
- //----------------------------------------
276
- auth({
277
- providers: {
278
- demo: [
279
- { name: 'Ermin' },
280
- { name: 'JYC', roles: [FF_Role.FF_Role_Admin] },
281
- { name: 'Noam', roles: [FF_Role.FF_Role_Admin, Role.Boss] },
282
- ],
283
-
284
- // password: {},
285
-
286
- // otp: {},
287
-
288
- oAuths: [
289
- //----------------------------------------
290
- // To enable OAuth via Github
291
- // Instructions by hovering the method \`github\`
292
- // NEEDS ON TOP OF THE FILE:
293
- // import { github } from '../auth/server'
294
- //----------------------------------------
295
- // github(),
296
- ],
297
- },
298
- }),
299
-
300
- //----------------------------------------
301
- // Core Module: mail
302
- //----------------------------------------
303
- mail({
304
- // options
305
- }),
306
-
307
- //----------------------------------------
308
- // example of a userland module
309
- //----------------------------------------
310
- task({ specialInfo: 'hello from userland' }),
311
-
312
- //----------------------------------------
313
- // example of a userland inline module
314
- //----------------------------------------
315
- new Module({
316
- name: 'app',
317
- entities: [],
318
- controllers: [],
319
- initApi: async () => {
320
- log.success('App is ready! 🚀')
321
- },
322
- }),
323
-
324
- //----------------------------------------
325
- // Replace @Entity by @FF_Entity in your entities to enable changeLog on this entity
326
- //----------------------------------------
327
- changeLog(),
328
- ],
329
- })
330
- `,
331
- ],
332
- './src/hooks.server.ts': [
333
- `import { sequence } from '@sveltejs/kit/hooks'
334
- import { redirect } from '@sveltejs/kit'
335
-
336
- import { handleAuth, handleGuard } from '../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
- )
354
- `,
355
- ],
356
- './src/routes/api/[...remult]/+server.ts': [
357
- `import { api } from '${serverAlias}'
358
-
359
- export const { GET, POST, PUT, DELETE } = api
360
- `,
361
- ],
362
- './src/routes/+layout.server.ts': [
363
- `import { remult } from 'remult'
364
-
365
- import type { LayoutServerLoad } from './$types'
366
-
367
- export const load = (async () => {
368
- return { user: remult.user }
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
383
- `,
384
- ],
385
- './src/routes/+layout.svelte': [
386
- `<script lang="ts">
387
- import { untrack } from 'svelte'
388
- import { createSubscriber } from 'svelte/reactivity'
389
-
390
- import { Remult, remult } from 'remult'
391
-
392
- import { route } from '${libAlias}/ROUTES'
393
- import SignIn from '${libAlias}/ui/SignIn.svelte'
394
- import SignOut from '${libAlias}/ui/SignOut.svelte'
395
-
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()
442
- </script>
443
-
444
- <svelte:head>
445
- <title>${pkg.name}</title>
446
- <link
447
- rel="icon"
448
- href="https://raw.githubusercontent.com/jycouet/firstly/main/assets/firstly.png"
449
- />
450
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/water.css@2/out/dark.css" />
451
- </svelte:head>
452
-
453
- <h1>${pkg.name}</h1>
454
-
455
- {#if remult.authenticated()}
456
- <div style="float:right;">
457
- <SignOut></SignOut>
458
- </div>
459
- <span>{remult.user?.name} ({remult.user?.roles})<br /><br /></span>
460
- {:else}
461
- <SignIn demo="Ermin"></SignIn>
462
- <SignIn demo="JYC"></SignIn>
463
- <SignIn demo="Noam"></SignIn>
464
- <br />
465
- <SignIn ffLink></SignIn>
466
- <br />
467
- <SignIn oauth="github"></SignIn>
468
- {/if}
469
-
470
- <hr />
471
-
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?.()}
481
-
482
- <hr />
483
-
484
- <div style="float: right; text-align: right;">
485
- <a href={route('remult_admin')} target="_blank">🚀 admin</a>
486
- <p style="font-size: small;">
487
- <i>Login as <b>JYC</b> to get admin rights ☝️</i>
488
- </p>
489
- </div>
490
- <a href={route('github', { owner: 'jycouet', repo: 'firstly' })} target="_blank"> ⭐️ firstly </a>
491
- |
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 '../internals'
526
- import { FF_Role_Auth } from '../auth'
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
542
- `,
543
- ],
544
- './src/lib/ui/SignIn.svelte': [
545
- `<script lang="ts">
546
- import { isError } from '../internals'
547
- import { AuthController } from '../auth'
548
-
549
- import { goto, invalidateAll } from '$app/navigation'
550
-
551
- import { route } from '${libAlias}/ROUTES'
552
-
553
- // Examples of signin modes
554
- export let demo = ''
555
- export let ffLink = false
556
- export let oauth: 'github' | undefined = undefined
557
-
558
- const signinDemo = async (identif: string) => {
559
- try {
560
- await AuthController.signInDemo(identif)
561
- invalidateAll()
562
- } catch (error) {
563
- if (isError(error)) {
564
- // You will probably not leave this alert in production
565
- alert(error.message)
566
- }
567
- }
568
- }
569
-
570
- async function signinOAuth(provider: 'github') {
571
- try {
572
- window.location.href = await AuthController.signInOAuthGetUrl({
573
- provider,
574
- redirect: window.location.pathname,
575
- })
576
- } catch (error) {
577
- if (isError(error)) {
578
- // You will probably not leave this alert in production
579
- alert(error.message)
580
- }
581
- }
582
- }
583
- </script>
584
-
585
- {#if demo}
586
- <button on:click={() => signinDemo(demo)}>Login as {demo}</button>
587
- {:else if ffLink}
588
- <button on:click={() => goto(route('login'))}>Login with Firstly UI</button>
589
- {:else if oauth}
590
- <button on:click={() => signinOAuth(oauth)}>Login With {oauth}</button>
591
- {/if}
592
- `,
593
- ],
594
- './src/lib/ui/SignOut.svelte': [
595
- `<script lang="ts">
596
- import { isError } from '../internals'
597
- import { AuthController } from '../auth'
598
-
599
- import { invalidateAll } from '$app/navigation'
600
-
601
- const logout = async () => {
602
- try {
603
- await AuthController.signOut()
604
- invalidateAll()
605
- } catch (error) {
606
- if (isError(error)) {
607
- alert(error.message)
608
- }
609
- }
610
- }
611
- </script>
612
-
613
- <button on:click={logout}>Logout</button>
614
- `,
615
- ],
616
- // Task module
617
- './src/modules/task/index.ts': [
618
- `import { Log } from '@kitql/helpers'
619
-
620
- export const log = new Log("Custom Task Log")`,
621
- ],
622
- './src/modules/task/server/index.ts': [
623
- `import { Module } from '../server'
624
-
625
- import { Task } from '../Task'
626
- import { TaskController } from '../TaskController'
627
-
628
- export const task: (o: { specialInfo: string }) => Module = ({ specialInfo }) => {
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
- `,
641
- ],
642
- './src/modules/task/Task.ts': [
643
- `import { Allow, Entity, Field, Fields, ValueListFieldType } from 'remult'
644
- import { BaseEnum, LibIcon_Add, LibIcon_Delete, type BaseEnumOptions } from '../internals'
645
-
646
- @Entity('task', {
647
- allowApiCrud: Allow.authenticated,
648
- })
649
- export class Task {
650
- @Fields.id()
651
- id!: string
652
-
653
- @Fields.createdAt()
654
- createdAt?: Date
655
-
656
- @Fields.string<Task>({
657
- validate: (task) => {
658
- if (task.title.length < 3) throw 'The title must be at least 3 characters long'
659
- },
660
- })
661
- title: string = ''
662
-
663
- @Fields.boolean()
664
- completed: boolean = false
665
-
666
- @Field(() => TypeOfTaskEnum, { inputType: 'selectEnum' })
667
- typeOfTask = TypeOfTaskEnum.EASY
668
- }
669
-
670
- @ValueListFieldType()
671
- export class TypeOfTaskEnum extends BaseEnum {
672
- static EASY = new TypeOfTaskEnum('EASY', {
673
- caption: 'Easy',
674
- icon: { data: LibIcon_Add },
675
- })
676
- static HARD = new TypeOfTaskEnum('HARD', {
677
- caption: 'Hard',
678
- icon: { data: LibIcon_Delete },
679
- })
680
- constructor(id: string, o?: BaseEnumOptions<TypeOfTaskEnum>) {
681
- super(id, o)
682
- }
683
- }
684
- `,
685
- ],
686
- './src/modules/task/TaskController.ts': [
687
- `import { BackendMethod } from 'remult'
688
-
689
- import { log } from '${libAlias}'
690
-
691
- /**
692
- * await TaskController.sayHiFromTask("JYC")
693
- */
694
- export class TaskController {
695
- @BackendMethod({ allowed: true })
696
- static async sayHiFromTask(name: string) {
697
- log.info(\`hello \${name} 👋\`)
698
- }
699
- }
700
- `,
701
- ],
702
- './src/modules/task/ui/TaskAdd.svelte': [
703
- `<script lang="ts">
704
- import { EntityError, repo } from 'remult'
705
-
706
- import { Task } from '${modulesAlias}/task/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/TaskList.svelte': [
736
- `<script lang="ts">
737
- import { repo } from 'remult'
738
-
739
- import { Task } from '${modulesAlias}/task/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/TaskAdd.svelte'
768
- import TaskList from '${modulesAlias}/task/ui/TaskList.svelte'
769
- </script>
770
-
771
- <h1>Task Module</h1>
772
-
773
- <TaskAdd />
774
- <TaskList />
775
- `,
776
- ],
777
- };
778
- for (const [path, content] of Object.entries(obj)) {
779
- if (res.includes('all')) {
780
- write(path, content);
781
- }
782
- else {
783
- if (res.includes('module-demo')) {
784
- if (path.startsWith('./src/modules/task')) {
785
- write(path, content);
786
- }
787
- }
788
- }
789
- }
790
- p.outro(`🎉 Everything is ok, happy coding!`);
791
- new Log('').info(gray(italic(`${bold('❔ More help')} ` +
792
- `at ${cyan('https://github.com/jycouet/firstly')} ` +
793
- `(📄 Docs, ⭐ Github, 📣 Discord, ...)\n`)));