@appweaver/cli 1.0.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 (76) hide show
  1. package/LICENSE +1 -0
  2. package/README.md +7 -0
  3. package/build/build-command.d.ts +2 -0
  4. package/build/build-command.js +15 -0
  5. package/build/build-project.d.ts +8 -0
  6. package/build/build-project.js +19 -0
  7. package/build/index.d.ts +2 -0
  8. package/build/index.js +18 -0
  9. package/generate/generate-command.d.ts +2 -0
  10. package/generate/generate-command.js +38 -0
  11. package/generate/generate-schema.d.ts +12 -0
  12. package/generate/generate-schema.js +475 -0
  13. package/generate/generate-types.d.ts +10 -0
  14. package/generate/generate-types.js +86 -0
  15. package/generate/index.d.ts +3 -0
  16. package/generate/index.js +19 -0
  17. package/migrate/index.d.ts +1 -0
  18. package/migrate/index.js +17 -0
  19. package/migrate/migrate-command.d.ts +2 -0
  20. package/migrate/migrate-command.js +13 -0
  21. package/migration/index.d.ts +1 -0
  22. package/migration/index.js +17 -0
  23. package/migration/migration-command.d.ts +2 -0
  24. package/migration/migration-command.js +34 -0
  25. package/openapi/index.d.ts +1 -0
  26. package/openapi/index.js +17 -0
  27. package/openapi/openapi-command.d.ts +2 -0
  28. package/openapi/openapi-command.js +46 -0
  29. package/package.json +56 -0
  30. package/seed/index.d.ts +1 -0
  31. package/seed/index.js +17 -0
  32. package/seed/seed-command.d.ts +2 -0
  33. package/seed/seed-command.js +33 -0
  34. package/skill/GUIDELINES.md +298 -0
  35. package/skill/SKILL.md +593 -0
  36. package/skill/references/cache.md +207 -0
  37. package/skill/references/cli.md +213 -0
  38. package/skill/references/client.md +507 -0
  39. package/skill/references/configuration.md +402 -0
  40. package/skill/references/database.md +134 -0
  41. package/skill/references/dependency-injection.md +214 -0
  42. package/skill/references/events.md +152 -0
  43. package/skill/references/mailer.md +235 -0
  44. package/skill/references/queue.md +196 -0
  45. package/skill/references/resources.md +961 -0
  46. package/skill/references/scheduler.md +184 -0
  47. package/skill/references/security.md +694 -0
  48. package/skill/references/storage.md +251 -0
  49. package/start/index.d.ts +2 -0
  50. package/start/index.js +18 -0
  51. package/start/start-command.d.ts +2 -0
  52. package/start/start-command.js +17 -0
  53. package/start/start-project.d.ts +8 -0
  54. package/start/start-project.js +147 -0
  55. package/testing/index.d.ts +1 -0
  56. package/testing/index.js +17 -0
  57. package/testing/testing-command.d.ts +2 -0
  58. package/testing/testing-command.js +96 -0
  59. package/update/index.d.ts +2 -0
  60. package/update/index.js +18 -0
  61. package/update/update-command.d.ts +2 -0
  62. package/update/update-command.js +84 -0
  63. package/update/update-packages.d.ts +10 -0
  64. package/update/update-packages.js +45 -0
  65. package/update/update-skill.d.ts +8 -0
  66. package/update/update-skill.js +93 -0
  67. package/utils/index.d.ts +3 -0
  68. package/utils/index.js +19 -0
  69. package/utils/loader-util.d.ts +29 -0
  70. package/utils/loader-util.js +132 -0
  71. package/utils/path-util.d.ts +41 -0
  72. package/utils/path-util.js +98 -0
  73. package/utils/process-util.d.ts +39 -0
  74. package/utils/process-util.js +92 -0
  75. package/weaver.d.ts +2 -0
  76. package/weaver.js +53 -0
@@ -0,0 +1,298 @@
1
+ # Appweaver Guidelines
2
+
3
+ Appweaver is a TypeScript/Node.js library for building web applications. Built on Fastify (HTTP) and Prisma (ORM), it
4
+ provides factory methods for creating resource models, services, policies, and routes with sensible defaults.
5
+
6
+ ## Project structure
7
+
8
+ - `database/` - migrations, seeders, generated Prisma client
9
+ - `dist/` - transpiled JavaScript output
10
+ - `public/` - static files (if enabled)
11
+ - `src/features/` - application logic (vertical slice architecture)
12
+ - `src/resources/` - resources (models, services, policies, routes)
13
+ - `src/types/` - generated and manual types
14
+ - `src/main.ts` - application entrypoint
15
+ - `test/e2e/` - end-to-end tests
16
+ - `test/unit/` - unit tests
17
+ - `.env` / `.env.{env}` - environment variable overrides (optional)
18
+ - `appweaver.json` / `appweaver.{env}.json` - central configuration
19
+ - `Dockerfile` - Docker image definition
20
+
21
+ **IMPORTANT:** `{env}` is controlled by `NODE_ENV` evironment variable.
22
+
23
+ ## Application entrypoint
24
+
25
+ ```ts
26
+ // src/main.ts
27
+ import { createApp } from '@appweaver/core';
28
+ import { logger } from '@appweaver/common';
29
+
30
+ createApp().catch((err) => logger.error(err));
31
+ ```
32
+
33
+ ## Creating resources
34
+
35
+ Resources are the core building blocks. There are four types: **model**, **service**, **routes**, and **policy**.
36
+ Exported resources are loaded automatically on application start.
37
+
38
+ Dependency chain: **model** → **service** → **routes** → **policy**
39
+
40
+ Only a model is required. If a service exists, a model must exist. If routes exist, a service must exist. Policy is
41
+ independent.
42
+
43
+ **DOS:**
44
+
45
+ - Use default configuration values whenever possible
46
+ - Rely on library defaults for `omit`/`pick`, and `input`/`output` settings
47
+ - Use default `mimeType` and `namePattern` patterns in file configurations unless specifically requested
48
+ - Prefer storing configuration in JSON file (`appweaver.json`) over environment (`.env`) file, but prefer it for secrets
49
+ - Always create all four resource configs (model, service, routes, and policy) unless specified otherwise
50
+
51
+ **DON'TS:**
52
+
53
+ - Don't explicitly set default values in configuration unless specifically requested
54
+ - Don't override `omit`/`pick` for `read`, `create` and `update` settings unnecessarily
55
+ - Don't specify `input`/`output` configurations if defaults suffice
56
+ - Don't modify file's `mimeType` and `namePattern` patterns unless specifically instructed
57
+ - Don't customize index arrays without an explicit requirement
58
+
59
+ ### Model
60
+
61
+ ```ts
62
+ // src/resources/product/model.ts
63
+ import { createModel } from '@appweaver/core';
64
+
65
+ export default createModel({
66
+ name: 'Product',
67
+ scalars: {
68
+ title: { type: 'string', minLength: 1, maxLength: 200 },
69
+ price: { type: 'float', minimum: 0 },
70
+ status: { type: 'enum', default: 'Draft', values: ['Draft', 'Active', 'Sold'] },
71
+ description: { type: 'string', required: false },
72
+ lastViewedAt: { type: 'dateTime', defaultGenerator: 'now()' },
73
+ enabled: { type: 'boolean', default: true }
74
+ },
75
+ relations: {
76
+ category: { model: 'Category', mappedBy: 'products', owner: true, output: { type: 'always' } }
77
+ },
78
+ files: {
79
+ photo: { mimeType: 'image/*', maxSize: '2 MB' }
80
+ },
81
+ create: { omit: ['status'] },
82
+ update: { pick: ['title', 'price', 'status', 'description'] },
83
+ index: ['title']
84
+ });
85
+ ```
86
+
87
+ ### Service
88
+
89
+ ```ts
90
+ // src/resources/product/service.ts
91
+ import { createService } from '@appweaver/core';
92
+
93
+ export default createService({
94
+ modelName: 'Product',
95
+ afterCreate: (resource) => {
96
+ console.log('Product created:', resource.id);
97
+ },
98
+ textSearch: {
99
+ title: { contains: '{input}', mode: 'insensitive' }
100
+ }
101
+ });
102
+ ```
103
+
104
+ ### Routes
105
+
106
+ ```ts
107
+ // src/resources/product/routes.ts
108
+ import { createRoutes } from '@appweaver/core';
109
+
110
+ export default createRoutes({
111
+ modelName: 'Product',
112
+ find: { cache: true, roles: ['Admin', 'User'], rateLimit: { max: 100 } },
113
+ query: { cacheTTL: 5000 },
114
+ create: { permissions: ['product:create'] },
115
+ delete: { exclude: true }
116
+ });
117
+ ```
118
+
119
+ ### Policy
120
+
121
+ ```ts
122
+ // src/resources/product/policy.ts
123
+ import { createPolicy } from '@appweaver/core';
124
+
125
+ export default createPolicy({
126
+ modelName: 'Product',
127
+ checkAccess: (action, resource) => resource.status === 'Draft',
128
+ readRestrictions: (action, resource) => {
129
+ enabled: true;
130
+ },
131
+ files: {
132
+ photo: { accessType: 'public' }
133
+ }
134
+ });
135
+ ```
136
+
137
+ ### Auth model and service
138
+
139
+ Use `createAuthModel` and `createAuthService` for authenticatable users. They must be used together.
140
+
141
+ `createAuthModel` adds: `email`, `passwordHash`, `verifiedEmail`, `twoFactorAuth`, `enabled`, `logoutAt` scalars; a
142
+ virtual `password` field; a `roles` relation; and optional `apiKeys` relation.
143
+
144
+ ```ts
145
+ // src/resources/user/model.ts
146
+ import { createAuthModel } from '@appweaver/core';
147
+
148
+ export default createAuthModel({
149
+ name: 'User',
150
+ scalars: { name: { type: 'string', maxLength: 100 } },
151
+ files: { avatar: { mimeType: 'image/(png|jpeg|gif)', maxSize: '2 MB' } }
152
+ });
153
+ ```
154
+
155
+ ```ts
156
+ // src/resources/user/service.ts
157
+ import { createAuthService } from '@appweaver/core';
158
+
159
+ export default createAuthService({
160
+ modelName: 'User',
161
+ registrationData: (_, email, password) => ({ email, password, roles: [1, 2] })
162
+ });
163
+ ```
164
+
165
+ ## Custom routes, models, and plugins
166
+
167
+ ### Custom route
168
+
169
+ ```ts
170
+ // src/features/custom-route.ts
171
+ import { registerRoute, Router } from '@appweaver/core';
172
+ import { Type } from '@sinclair/typebox';
173
+
174
+ registerRoute(
175
+ async function (router: Router) {
176
+ router.get('/search-result', {
177
+ schema: { summary: 'Search result', response: { 200: Type.Ref('SearchResult') } },
178
+ handler: async () => ({ message: 'Hello, world!' })
179
+ });
180
+ },
181
+ { public: true, cacheTTL: 15000 }
182
+ );
183
+ ```
184
+
185
+ ### Custom model
186
+
187
+ ```ts
188
+ // src/features/custom-model.ts
189
+ import { registerModel } from '@appweaver/core';
190
+ import { Type } from '@sinclair/typebox';
191
+
192
+ registerModel(
193
+ Type.Object(
194
+ { id: Type.Number(), title: Type.String(), score: Type.Number({ minimum: 0, maximum: 1 }) },
195
+ { $id: 'SearchResult' }
196
+ )
197
+ );
198
+ ```
199
+
200
+ ### Plugin
201
+
202
+ ```ts
203
+ // src/plugins/audit-log.ts
204
+ import { registerPlugin } from '@appweaver/core';
205
+
206
+ registerPlugin('audit-log', async (server) => {
207
+ server.addHook('onResponse', async (request, reply) => {
208
+ console.log(`${request.method} ${request.url} → ${reply.statusCode}`);
209
+ });
210
+ });
211
+ ```
212
+
213
+ ## Dependency injection
214
+
215
+ ```ts
216
+ import { Cache } from '@appweaver/common';
217
+ import { define, inject, loadProvider } from '@appweaver/core';
218
+
219
+ define(RedisCacheService, Cache); // register class under abstract token
220
+ define('https://api.example.com', 'ApiBaseUrl'); // register plain value
221
+
222
+ const cache = inject(Cache); // resolve singleton
223
+ const url = inject<string>('ApiBaseUrl'); // resolve by string token
224
+
225
+ // Dynamic provider loading (typical in main.ts)
226
+ loadProvider(__dirname, config.CACHE_PROVIDER, Cache);
227
+ loadProvider(__dirname, config.MAILER_PROVIDER, Mailer, false); // optional
228
+ ```
229
+
230
+ ## Seeders
231
+
232
+ Seeder files export async functions and run in alphabetical order. Prefix filenames with ordinal numbers.
233
+
234
+ ```ts
235
+ // database/seeders/001-create-admin-user.ts
236
+ import { hashPassword } from '@appweaver/core';
237
+ import { db } from '@db/client';
238
+
239
+ export async function createAdminUser(): Promise<void> {
240
+ await db.user.create({
241
+ data: {
242
+ firstName: 'Admin',
243
+ lastName: 'Admin',
244
+ email: 'admin@appweaver.com',
245
+ roles: {
246
+ connectOrCreate: [
247
+ {
248
+ where: { name: 'Admin' },
249
+ create: {
250
+ name: 'Admin',
251
+ permissions: {
252
+ connectOrCreate: [
253
+ { where: { name: '*.read' }, create: { name: '*.read' } },
254
+ { where: { name: '*.write' }, create: { name: '*.write' } }
255
+ ]
256
+ }
257
+ }
258
+ }
259
+ ]
260
+ }
261
+ }
262
+ });
263
+ }
264
+ ```
265
+
266
+ ## Common commands
267
+
268
+ | Command | Description |
269
+ |-------------------------------|-------------------------------------------|
270
+ | `npm run generate` | Generate TypeScript types + Prisma schema |
271
+ | `npm run build` | Build the application |
272
+ | `npm run start` | Start in production mode |
273
+ | `npm run dev` | Start in development (watch) mode |
274
+ | `npm run seed` | Seed the database |
275
+ | `npm run migrate` | Apply pending database migrations |
276
+ | `npm run test` | Run unit tests |
277
+ | `npm run e2e` | Run end-to-end tests |
278
+ | `npm run format` | Format code with Prettier |
279
+ | `npm run lint` | Lint code with ESLint |
280
+ | `weaver migration new <name>` | Create a new database migration |
281
+ | `weaver update` | Update all @appweaver/* packages |
282
+ | `weaver openapi` | Generate OpenAPI specification |
283
+
284
+ ## References
285
+
286
+ - Application CLI (weaver): [cli.md](references/cli.md)
287
+ - Application configuration: [configuration.md](references/configuration.md)
288
+ - Application resources: [resources.md](references/resources.md)
289
+ - Dependency injection: [dependency-injection.md](references/dependency-injection.md)
290
+ - Security details: [security.md](references/security.md)
291
+ - Storage & File management: [storage.md](references/storage.md)
292
+ - Database & Migrations: [database.md](references/database.md)
293
+ - Events & Hooks: [events.md](references/events.md)
294
+ - Cache management: [cache.md](references/cache.md)
295
+ - Queue jobs: [queue.md](references/queue.md)
296
+ - Scheduling jobs: [scheduler.md](references/scheduler.md)
297
+ - Sending emails: [mailer.md](references/mailer.md)
298
+ - Generating an HTTP client for using API: [client.md](references/client.md)