@appweaver/create-weaver-app 1.0.18 → 1.0.20

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.
@@ -40,6 +40,7 @@ program
40
40
  .option('--agent [agent]', `The AI agent for which to configure guidelines and skill files (${agentTypes.join(', ')}).`, parseAgentType, 'claude')
41
41
  .option('--bun', 'Use Bun as application runtime.')
42
42
  .option('--skipInstall', 'Skip all dependencies installation.')
43
+ .option('--noDocker', 'Skip copying Dockerfile and docker-compose.yml files.')
43
44
  .option('--noRedis', 'Skip IoRedis package installation.')
44
45
  .option('--noQueue', 'Skip BullQueue package installation.')
45
46
  .option('--noMailer', 'Skip Nodemailer package installation.')
@@ -77,6 +78,17 @@ program
77
78
  // Copy template contents into a new directory
78
79
  const templateDir = node_path_1.default.join(__dirname, './templates/default');
79
80
  await promises_1.default.cp(templateDir, destDir, { recursive: true });
81
+ // Remove Docker-related files if --noDocker flag is set
82
+ if (command.getOptionValue('noDocker')) {
83
+ const dockerFiles = [
84
+ 'Dockerfile',
85
+ 'Dockerfile.bun',
86
+ 'docker-compose.yml.tpl'
87
+ ];
88
+ for (const dockerFile of dockerFiles) {
89
+ await promises_1.default.rm(node_path_1.default.join(destDir, dockerFile), { force: true });
90
+ }
91
+ }
80
92
  // Define all variables used in template files with .tpl extension
81
93
  const variables = {
82
94
  NAME: name.charAt(0).toUpperCase() + name.slice(1),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@appweaver/create-weaver-app",
3
- "version": "1.0.18",
3
+ "version": "1.0.20",
4
4
  "description": "Appweaver - the backend framework for AI-first development (@create-weaver-app)",
5
5
  "author": "Luka Matosevic",
6
6
  "license": "MIT",
package/skill/SKILL.md CHANGED
@@ -65,6 +65,7 @@ create-weaver-app <name> [description] [options]
65
65
  | `--agent` | The AI agent for which to configure guidelines and skill files | `claude` |
66
66
  | `--bun` | Use Bun as application runtime. (default is node and npm) | false |
67
67
  | `--skipInstall` | Skip all dependencies installation. | false |
68
+ | `--noDocker` | Skip Dockerfile, Dockerfile.bun and docker-compose.yml files | false |
68
69
  | `--noRedis` | Skip ioredis | false |
69
70
  | `--noQueue` | Skip bullmq | false |
70
71
  | `--noMailer` | Skip nodemailer | false |
@@ -128,7 +129,7 @@ const app = createApp({ autoStart: false, scanPath: './dist/my/app/path' });
128
129
 
129
130
  // custom init logic...
130
131
 
131
- app.start().then(address => {
132
+ app.start().then((address) => {
132
133
  logger.info(address);
133
134
  });
134
135
  ```
@@ -412,14 +413,11 @@ optional dependencies on other named plugins.
412
413
  // src/plugins/audit-log.ts
413
414
  import { registerPlugin } from '@appweaver/core';
414
415
 
415
- registerPlugin(
416
- 'audit-log',
417
- async (server) => {
418
- server.addHook('onResponse', async (request, reply) => {
419
- console.log(`${request.method} ${request.url} → ${reply.statusCode}`);
420
- });
421
- }
422
- );
416
+ registerPlugin('audit-log', async (server) => {
417
+ server.addHook('onResponse', async (request, reply) => {
418
+ console.log(`${request.method} ${request.url} → ${reply.statusCode}`);
419
+ });
420
+ });
423
421
  ```
424
422
 
425
423
  ### Dependency injection
@@ -431,10 +429,10 @@ lazily instantiated as singletons on the first injection.
431
429
  import { Cache } from '@appweaver/common';
432
430
  import { define, inject } from '@appweaver/core';
433
431
 
434
- define(RedisCacheService, Cache); // register class under abstract token
432
+ define(RedisCacheService, Cache); // register class under abstract token
435
433
  define('https://api.example.com', 'ApiBaseUrl'); // register plain value
436
434
 
437
- const cache = inject(Cache); // resolves singleton instance
435
+ const cache = inject(Cache); // resolves singleton instance
438
436
  const url = inject<string>('ApiBaseUrl'); // resolves by string token
439
437
  ```
440
438
 
@@ -445,11 +443,11 @@ This is the standard pattern for wiring infrastructure providers in `main.ts`.
445
443
  import { loadProvider } from '@appweaver/core';
446
444
  import { Database, Cache } from '@appweaver/common';
447
445
 
448
- loadProvider(__dirname, config.DATABASE_PROVIDER, Database); // required provider
446
+ loadProvider(__dirname, config.DATABASE_PROVIDER, Database); // required provider
449
447
  loadProvider(__dirname, config.CACHE_PROVIDER, Cache);
450
448
  loadProvider(__dirname, config.MAILER_PROVIDER, Mailer, false); // optional (no error if provider cannot be loaded)
451
449
 
452
- const cache: Mailer | undefined = inject(Mailer, false); // optional injection
450
+ const cache: Mailer | undefined = inject(Mailer, false); // optional injection
453
451
  ```
454
452
 
455
453
  ### Writing a seeder
@@ -13,6 +13,9 @@ Configuration is loaded and merged in the following order (later sources overrid
13
13
  4. **Default .env file** `.env`
14
14
  5. **Environment-specific .env file** `.env.{NODE_ENV}` (overrides all above)
15
15
 
16
+ `.env` values support `${VAR_NAME}` expansion referencing any other environment variable; escape as `\${VAR_NAME}` to
17
+ keep it literal.
18
+
16
19
  ## JSON configuration format
17
20
 
18
21
  Configuration in JSON files is nested under the `config` key using camelCase property names. This is the preferred way
@@ -53,12 +56,12 @@ The config object provides type-safe accessor methods:
53
56
  ```ts
54
57
  import { config } from '@appweaver/common';
55
58
 
56
- config.env('APP_ENV', 'prod'); // string
57
- config.str('APP_NAME', 'MyApp'); // string
58
- config.int('SERVER_PORT', 5000); // number (integer)
59
- config.float('SOME_RATIO', 0.5); // number (float)
60
- config.bool('CACHE_ENABLED', true); // boolean
61
- config.arr('CORS_METHODS', ['*']); // string[]
59
+ config.env('APP_ENV', 'prod'); // string
60
+ config.str('APP_NAME', 'MyApp'); // string
61
+ config.int('SERVER_PORT', 5000); // number (integer)
62
+ config.float('SOME_RATIO', 0.5); // number (float)
63
+ config.bool('CACHE_ENABLED', true); // boolean
64
+ config.arr('CORS_METHODS', ['*']); // string[]
62
65
  ```
63
66
 
64
67
  The config object is frozen with `Object.freeze()` after loading to prevent runtime mutations.
@@ -67,7 +70,7 @@ The config object is frozen with `Object.freeze()` after loading to prevent runt
67
70
 
68
71
  ## Configuration properties
69
72
 
70
- ### Application (APP_*)
73
+ ### Application (APP\_\*)
71
74
 
72
75
  | Property | Type | Default | Description |
73
76
  |--------------------------|----------|------------------------------------|-----------------------------------------------------------------------------------------------------------|
@@ -83,7 +86,7 @@ The config object is frozen with `Object.freeze()` after loading to prevent runt
83
86
  | `APP_MAIN_FILE_PATH` | string | `'<srcPath>/main.ts'` | Path to main application entrypoint file. |
84
87
  | `APP_AUTOLOAD_MODULES` | string[] | `[]` | Module paths to auto-load on startup. |
85
88
 
86
- ### Logging (LOG_*)
89
+ ### Logging (LOG\_\*)
87
90
 
88
91
  | Property | Type | Default | Description |
89
92
  |------------------------|---------|----------|------------------------------------------------------------------------------------------|
@@ -97,7 +100,7 @@ The config object is frozen with `Object.freeze()` after loading to prevent runt
97
100
  | `LOG_ROTATE_COMPRESS` | boolean | `true` | Compress rotated log files with gzip. |
98
101
  | `LOG_PRETTY` | boolean | `false` | Enable pretty-printed JSON logs. |
99
102
 
100
- ### Server (SERVER_*)
103
+ ### Server (SERVER\_\*)
101
104
 
102
105
  | Property | Type | Default | Description |
103
106
  |----------------------------------|----------|--------------|------------------------------------------------------------|
@@ -114,7 +117,7 @@ The config object is frozen with `Object.freeze()` after loading to prevent runt
114
117
  | `SERVER_TRUST_PROXY` | boolean | `true` | Trust `X-Forwarded-*` headers from reverse proxies. |
115
118
  | `SERVER_REQUEST_LOGGING_ENABLED` | boolean | `false` | Enable HTTP request/response logging. |
116
119
 
117
- ### Rate limiting (RATE_LIMIT_*)
120
+ ### Rate limiting (RATE*LIMIT*\*)
118
121
 
119
122
  | Property | Type | Default | Description |
120
123
  |-------------------------|-----------|-----------|------------------------------------------------------------------|
@@ -124,7 +127,7 @@ The config object is frozen with `Object.freeze()` after loading to prevent runt
124
127
  | `RATE_LIMIT_ALLOW_LIST` | string[]? | - | IP addresses/patterns exempt from rate limiting. |
125
128
  | `RATE_LIMIT_STORE` | enum | `'redis'` | Store backend for tracking limits. Values: `redis`, `in-memory`. |
126
129
 
127
- ### Swagger / OpenAPI (SWAGGER_*)
130
+ ### Swagger / OpenAPI (SWAGGER\_\*)
128
131
 
129
132
  | Property | Type | Default | Description |
130
133
  |-------------------------|---------|--------------|---------------------------------------------|
@@ -132,7 +135,7 @@ The config object is frozen with `Object.freeze()` after loading to prevent runt
132
135
  | `SWAGGER_PATH` | string | `'/swagger'` | URL path for the Swagger UI. |
133
136
  | `SWAGGER_HIDE_UNTAGGED` | boolean | `false` | Hide untagged endpoints from documentation. |
134
137
 
135
- ### Health check (HEALTH_CHECK_*)
138
+ ### Health check (HEALTH*CHECK*\*)
136
139
 
137
140
  | Property | Type | Default | Description |
138
141
  |-------------------------------|-----------|-------------|---------------------------------------------------------------|
@@ -143,7 +146,7 @@ The config object is frozen with `Object.freeze()` after loading to prevent runt
143
146
  | `HEALTH_CHECK_PICK_INSTANCES` | string[]? | - | List of health check instance names to include in response. |
144
147
  | `HEALTH_CHECK_OMIT_INSTANCES` | string[]? | - | List of health check instance names to exclude from response. |
145
148
 
146
- ### CORS (CORS_*)
149
+ ### CORS (CORS\_\*)
147
150
 
148
151
  | Property | Type | Default | Description |
149
152
  |------------------------|----------|---------|-----------------------------------------------|
@@ -154,7 +157,7 @@ The config object is frozen with `Object.freeze()` after loading to prevent runt
154
157
  | `CORS_MAX_AGE` | integer | `86400` | Preflight response cache duration in seconds. |
155
158
  | `CORS_CREDENTIALS` | boolean | `true` | Allow credentials (cookies, auth headers). |
156
159
 
157
- ### Resources (RESOURCE_*)
160
+ ### Resources (RESOURCE\_\*)
158
161
 
159
162
  | Property | Type | Default | Description |
160
163
  |---------------------------------|--------|--------------------------------------|---------------------------------------------|
@@ -164,7 +167,7 @@ The config object is frozen with `Object.freeze()` after loading to prevent runt
164
167
  | `RESOURCE_ROUTES_PATTERN` | string | `'<srcPath>/resources/*/routes.ts'` | Glob pattern for resource routes files. |
165
168
  | `RESOURCE_GENERATED_TYPES_PATH` | string | `'<srcPath>/types/generated.ts'` | Output path for generated TypeScript types. |
166
169
 
167
- ### Data export (EXPORT_*)
170
+ ### Data export (EXPORT\_\*)
168
171
 
169
172
  | Property | Type | Default | Description |
170
173
  |-----------------------------|---------|---------|--------------------------------------------------|
@@ -174,7 +177,7 @@ The config object is frozen with `Object.freeze()` after loading to prevent runt
174
177
  | `EXPORT_CSV_ADD_HEADERS` | boolean | `true` | Include a header row in CSV exports. |
175
178
  | `EXPORT_CSV_ADD_SEP_ROW` | boolean | `false` | Add separator row (BOM) for Excel compatibility. |
176
179
 
177
- ### Security (SECURITY_*)
180
+ ### Security (SECURITY\_\*)
178
181
 
179
182
  #### General
180
183
 
@@ -284,7 +287,7 @@ The config object is frozen with `Object.freeze()` after loading to prevent runt
284
287
  | `SECURITY_OAUTH2_CUSTOM_CLIENT_SECRET` | string? | - | Custom OAuth2 client secret. |
285
288
  | `SECURITY_OAUTH2_CUSTOM_ISSUER` | string? | - | OpenID Connect issuer URL (used for discovery). |
286
289
 
287
- ### Database (DATABASE_*)
290
+ ### Database (DATABASE\_\*)
288
291
 
289
292
  | Property | Type | Default | Description |
290
293
  |-----------------------------------|----------|----------------------------------------------|--------------------------------------------------------------------------|
@@ -299,7 +302,7 @@ The config object is frozen with `Object.freeze()` after loading to prevent runt
299
302
  | `DATABASE_LOG_EVENTS` | string[] | `[]` | List of database events to log. Values: `query`, `info`, `warn`, `error` |
300
303
  | `DATABASE_PROVIDER` | string | `'@appweaver/core/database/prisma-database'` | Database provider implementation path. |
301
304
 
302
- ### File storage (STORAGE_*)
305
+ ### File storage (STORAGE\_\*)
303
306
 
304
307
  | Property | Type | Default | Description |
305
308
  |------------------------------|---------|------------------------------------------------|-----------------------------------------------|
@@ -309,21 +312,21 @@ The config object is frozen with `Object.freeze()` after loading to prevent runt
309
312
  | `STORAGE_FILES_ROUTE_PREFIX` | string | `/files` | URL prefix for file access routes. |
310
313
  | `STORAGE_PROVIDER` | string | `'@appweaver/core/storage/filesystem-storage'` | Storage provider implementation path. |
311
314
 
312
- ### Redis (REDIS_*)
315
+ ### Redis (REDIS\_\*)
313
316
 
314
317
  | Property | Type | Default | Description |
315
318
  |------------------|--------|----------------------------------|-------------------------------------|
316
319
  | `REDIS_URL` | string | `'redis://localhost:6379/0'` | Redis connection URL. |
317
320
  | `REDIS_PROVIDER` | string | `'@appweaver/core/memory/redis'` | Redis provider implementation path. |
318
321
 
319
- ### In-memory store (MEMORY_*)
322
+ ### In-memory store (MEMORY\_\*)
320
323
 
321
324
  | Property | Type | Default | Description |
322
325
  |-------------------|---------|--------------------------------------|-----------------------------------------|
323
326
  | `MEMORY_MAX_SIZE` | string? | - | Maximum size of the in-memory store. |
324
327
  | `MEMORY_PROVIDER` | string | `'@appweaver/core/memory/in-memory'` | In-memory provider implementation path. |
325
328
 
326
- ### Cache (CACHE_*)
329
+ ### Cache (CACHE\_\*)
327
330
 
328
331
  | Property | Type | Default | Description |
329
332
  |-------------------------------|---------|---------------------------------------|------------------------------------------------------------------------|
@@ -340,7 +343,7 @@ The config object is frozen with `Object.freeze()` after loading to prevent runt
340
343
  | `CACHE_INVALIDATION_DEFERRED` | boolean | `false` | Defer invalidation to a background process. |
341
344
  | `CACHE_PROVIDER` | string | `'@appweaver/core/cache/redis-cache'` | Cache provider implementation path. |
342
345
 
343
- ### Job queue (QUEUE_*)
346
+ ### Job queue (QUEUE\_\*)
344
347
 
345
348
  | Property | Type | Default | Description |
346
349
  |--------------------------------|----------|--------------------------------------|--------------------------------------------------------|
@@ -353,21 +356,21 @@ The config object is frozen with `Object.freeze()` after loading to prevent runt
353
356
  | `QUEUE_RETRY_BACKOFF_TYPE` | enum | `'fixed'` | Retry backoff type. Values: `fixed`, `exponential`. |
354
357
  | `QUEUE_PROVIDER` | string | `'@appweaver/core/queue/bull-queue'` | Job queue provider implementation path. |
355
358
 
356
- ### Scheduler (SCHEDULER_*)
359
+ ### Scheduler (SCHEDULER\_\*)
357
360
 
358
361
  | Property | Type | Default | Description |
359
362
  |----------------------------|---------|----------------------------------------------|---------------------------------------------------|
360
363
  | `SCHEDULER_AUTO_START_JOB` | boolean | `true` | Auto-start scheduled jobs on application startup. |
361
364
  | `SCHEDULER_PROVIDER` | string | `'@appweaver/core/scheduler/cron-scheduler'` | Scheduler provider implementation path. |
362
365
 
363
- ### Events (EVENTS_*)
366
+ ### Events (EVENTS\_\*)
364
367
 
365
368
  | Property | Type | Default | Description |
366
369
  |------------------------|---------|----------------------------------------|---------------------------------------------|
367
370
  | `EVENTS_MAX_LISTENERS` | integer | `20` | Maximum event listeners per event type. |
368
371
  | `EVENTS_PROVIDER` | string | `'@appweaver/core/events/node-events'` | Event emitter provider implementation path. |
369
372
 
370
- ### Mailer (MAILER_*)
373
+ ### Mailer (MAILER\_\*)
371
374
 
372
375
  | Property | Type | Default | Description |
373
376
  |-------------------------|---------|----------------------------------------|------------------------------------------|
@@ -380,7 +383,7 @@ The config object is frozen with `Object.freeze()` after loading to prevent runt
380
383
  | `MAILER_SMTP_USER` | string? | - | SMTP authentication username. |
381
384
  | `MAILER_SMTP_PASSWORD` | string? | - | SMTP authentication password. |
382
385
 
383
- ### System (SYSTEM_*)
386
+ ### System (SYSTEM\_\*)
384
387
 
385
388
  | Property | Type | Default | Description |
386
389
  |---------------------------------|---------|------------------------|---------------------------------------------------|
@@ -11,13 +11,13 @@ services:
11
11
  start_period: 5s
12
12
  start_interval: 5s
13
13
  ports:
14
- - "127.0.0.1:54312:5432"
14
+ - "127.0.0.1:5433:5432"
15
15
  environment:
16
16
  POSTGRES_DB: "${DB_NAME}"
17
17
  POSTGRES_USER: "${DB_USER}"
18
18
  POSTGRES_PASSWORD: "${DB_PASSWORD}"
19
19
  volumes:
20
- - postgres-data:/var/lib/postgresql/data
20
+ - postgres-data:/var/lib/postgresql
21
21
  networks:
22
22
  - {{LOWER_NAME}}
23
23
 
@@ -33,7 +33,7 @@ services:
33
33
  start_period: 5s
34
34
  start_interval: 5s
35
35
  ports:
36
- - "127.0.0.1:6380:6379"
36
+ - "127.0.0.1:6378:6379"
37
37
  volumes:
38
38
  - redis-data:/data
39
39
  networks:
@@ -43,6 +43,8 @@ services:
43
43
  image: {{LOWER_NAME}}:latest
44
44
  container_name: {{LOWER_NAME}}-migrations
45
45
  restart: no
46
+ build:
47
+ context: .
46
48
  depends_on:
47
49
  postgres:
48
50
  condition: service_healthy
@@ -52,6 +54,21 @@ services:
52
54
  networks:
53
55
  - {{LOWER_NAME}}
54
56
 
57
+ {{LOWER_NAME}}.seed:
58
+ image: {{LOWER_NAME}}:latest
59
+ container_name: {{LOWER_NAME}}-seed
60
+ restart: no
61
+ build:
62
+ context: .
63
+ depends_on:
64
+ {{LOWER_NAME}}.migrations:
65
+ condition: service_completed_successfully
66
+ env_file:
67
+ - .env
68
+ command: [ "seed" ]
69
+ networks:
70
+ - {{LOWER_NAME}}
71
+
55
72
  {{LOWER_NAME}}:
56
73
  image: {{LOWER_NAME}}:latest
57
74
  container_name: {{LOWER_NAME}}
@@ -59,7 +76,7 @@ services:
59
76
  build:
60
77
  context: .
61
78
  healthcheck:
62
- test: "wget -qO - http://127.0.0.1:3030/health/ready || exit 1"
79
+ test: "wget -qO - http://127.0.0.1:{{PORT}}/health/ready || exit 1"
63
80
  interval: 30s
64
81
  timeout: 10s
65
82
  retries: 5
@@ -68,10 +85,10 @@ services:
68
85
  depends_on:
69
86
  redis:
70
87
  condition: service_healthy
71
- {{LOWER_NAME}}.migrations:
88
+ {{LOWER_NAME}}.seed:
72
89
  condition: service_completed_successfully
73
90
  ports:
74
- - "127.0.0.1:3030:3003"
91
+ - "127.0.0.1:{{PORT}}:{{PORT}}"
75
92
  volumes:
76
93
  - ./storage:/usr/app/storage
77
94
  - ./logs:/usr/app/logs
@@ -10,15 +10,15 @@ fi
10
10
 
11
11
  if [ "$role" = "app" ]; then
12
12
  echo "Starting application..."
13
- npm run start
13
+ npx weaver start
14
14
 
15
15
  elif [ "$role" = "migrations" ]; then
16
16
  echo "Executing migrations..."
17
- npm run migrate
17
+ npx weaver migrate
18
18
 
19
19
  elif [ "$role" = "seed" ]; then
20
20
  echo "Seeding database..."
21
- npm run seed
21
+ npx weaver seed
22
22
 
23
23
  else
24
24
  echo "Could not match the container role \"$role\""
@@ -10,15 +10,15 @@ fi
10
10
 
11
11
  if [ "$role" = "app" ]; then
12
12
  echo "Starting application..."
13
- bun run start
13
+ bun weaver start
14
14
 
15
15
  elif [ "$role" = "migrations" ]; then
16
16
  echo "Executing migrations..."
17
- bun run migrate
17
+ bun weaver migrate
18
18
 
19
19
  elif [ "$role" = "seed" ]; then
20
20
  echo "Seeding database..."
21
- bun run seed
21
+ bun weaver seed
22
22
 
23
23
  else
24
24
  echo "Could not match the container role \"$role\""