@stacksjs/defaults 0.71.10 → 0.72.1

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.
@@ -177,6 +177,8 @@ Before running migrations on SQLite, `preprocessSqliteMigrations()`:
177
177
  - `seedModel$(modelName, options?): Promise<SeedResult>` -- seed one model by name
178
178
  - `freshSeed(config?): Promise<SeedSummary>` -- calls `seed({ ...config, fresh: true })` (truncates before seeding)
179
179
  - `listSeedableModels(): Promise<Array<{ name, table, count, source: 'default' | 'user' }>>` -- list without seeding
180
+ - `runApplicationSeeders(config?): Promise<ApplicationSeederSummary>` -- runs `database/seeders` classes in deterministic relative-path order
181
+ - `Seeder` -- abstract base class for idempotent application bootstrap seeders
180
182
 
181
183
  ### SeederConfig
182
184
  ```typescript
@@ -198,6 +200,20 @@ interface SeederConfig {
198
200
  - Records inserted in batches of 100
199
201
  - Models sorted by dependency: User (0), Team (1), Project (2), everything else (10)
200
202
  - Missing tables are skipped gracefully
203
+ - `buddy seed` and `buddy migrate:fresh --seed` also run application seeders after model factories
204
+ - Application seeder modules must default-export a class extending `Seeder` and implement `run()`
205
+ - Application seeders are for idempotent bootstrap work that does not belong in model factories, such as an initial workspace or role assignment
206
+
207
+ ```typescript
208
+ // database/seeders/OwnerSeeder.ts
209
+ import { Seeder } from '@stacksjs/database'
210
+
211
+ export default class OwnerSeeder extends Seeder {
212
+ async run(): Promise<void> {
213
+ // Resolve existing records first, then create only what is missing.
214
+ }
215
+ }
216
+ ```
201
217
 
202
218
  ### SeedResult / SeedSummary
203
219
  ```typescript
@@ -244,7 +244,10 @@ traits: {
244
244
  ```
245
245
 
246
246
  `buddy seed` walks every model carrying the trait and fills its table from the
247
- attribute factories. Nothing else is needed - no seeder files, no registration.
247
+ attribute factories. Model fixture data needs no separate seeder or registration.
248
+ Idempotent application bootstrap work can live in `database/seeders` as a
249
+ default-exported class extending `Seeder` from `@stacksjs/database`. Buddy runs
250
+ those application seeders after the model factories.
248
251
 
249
252
  ```bash
250
253
  buddy seed # every model with a useSeeder trait
@@ -9,7 +9,7 @@ export default defineModel({
9
9
  traits: {
10
10
  useUuid: true,
11
11
  useTimestamps: true,
12
- useApi: { uri: 'automations', routes: ['index', 'store', 'show', 'update', 'destroy'], middleware: ['auth'] },
12
+ useApi: { uri: 'automations', routes: ['index', 'store', 'show', 'update', 'destroy'], middleware: ['auth', 'team'] },
13
13
  observe: true,
14
14
  },
15
15
  attributes: {
@@ -8,7 +8,7 @@ export default defineModel({
8
8
  traits: {
9
9
  useUuid: true,
10
10
  useTimestamps: true,
11
- useApi: { uri: 'automation-runs', routes: ['index', 'show'], middleware: ['auth'] },
11
+ useApi: { uri: 'automation-runs', routes: ['index', 'show'], middleware: ['auth', 'team'] },
12
12
  },
13
13
  indexes: [{ name: 'automation_runs_idempotency_unique', columns: ['idempotency_key'], unique: true }],
14
14
  attributes: {
@@ -18,7 +18,7 @@ export default defineModel({
18
18
  useApi: {
19
19
  uri: 'campaigns',
20
20
  routes: ['index', 'store', 'show', 'update', 'destroy'],
21
- middleware: ['auth'],
21
+ middleware: ['auth', 'team'],
22
22
  },
23
23
  useSearch: {
24
24
  displayable: ['id', 'name', 'type', 'status', 'subject', 'scheduledAt', 'sentAt'],
@@ -25,7 +25,7 @@ export default defineModel({
25
25
  // Per-recipient send records carry email + delivery status. Treat
26
26
  // as PII and require auth on all read paths. The transactional
27
27
  // owner-only views in the dashboard are gated separately.
28
- middleware: ['auth'],
28
+ middleware: ['auth', 'team'],
29
29
  },
30
30
  },
31
31
 
@@ -8,7 +8,7 @@ export default defineModel({
8
8
  traits: {
9
9
  useUuid: true,
10
10
  useTimestamps: true,
11
- useApi: { uri: 'campaign-variants', routes: ['index', 'store', 'show', 'update', 'destroy'], middleware: ['auth'] },
11
+ useApi: { uri: 'campaign-variants', routes: ['index', 'store', 'show', 'update', 'destroy'], middleware: ['auth', 'team'] },
12
12
  },
13
13
  indexes: [{ name: 'campaign_variants_name_unique', columns: ['campaign_id', 'name'], unique: true }],
14
14
  attributes: {
@@ -8,7 +8,7 @@ export default defineModel({
8
8
  traits: {
9
9
  useUuid: true,
10
10
  useTimestamps: true,
11
- useApi: { uri: 'communication-suppressions', routes: ['index', 'store', 'show', 'destroy'], middleware: ['auth'] },
11
+ useApi: { uri: 'communication-suppressions', routes: ['index', 'store', 'show', 'destroy'], middleware: ['auth', 'team'] },
12
12
  },
13
13
  indexes: [{ name: 'communication_suppressions_unique', columns: ['team_id', 'channel', 'recipient'], unique: true }],
14
14
  attributes: {
@@ -8,7 +8,7 @@ export default defineModel({
8
8
  traits: {
9
9
  useUuid: true,
10
10
  useTimestamps: true,
11
- useApi: { uri: 'consent-events', routes: ['index', 'show'], middleware: ['auth'] },
11
+ useApi: { uri: 'consent-events', routes: ['index', 'show'], middleware: ['auth', 'team'] },
12
12
  },
13
13
  indexes: [{ name: 'consent_events_lookup', columns: ['team_id', 'channel', 'recipient', 'occurred_at'] }],
14
14
  attributes: {
@@ -8,7 +8,7 @@ export default defineModel({
8
8
  traits: {
9
9
  useUuid: true,
10
10
  useTimestamps: true,
11
- useApi: { uri: 'sender-domains', routes: ['index', 'store', 'show', 'update', 'destroy'], middleware: ['auth'] },
11
+ useApi: { uri: 'sender-domains', routes: ['index', 'store', 'show', 'update', 'destroy'], middleware: ['auth', 'team'] },
12
12
  },
13
13
  indexes: [{ name: 'sender_domains_domain_unique', columns: ['domain'], unique: true }],
14
14
  attributes: {
@@ -29,7 +29,7 @@ export default defineModel({
29
29
  useApi: {
30
30
  uri: 'sites',
31
31
  routes: ['index', 'store', 'show', 'update', 'destroy'],
32
- middleware: ['auth'],
32
+ middleware: ['auth', 'team'],
33
33
  },
34
34
 
35
35
  useSearch: {
@@ -46,7 +46,7 @@ export default defineModel({
46
46
  useApi: {
47
47
  uri: 'team-invitations',
48
48
  routes: ['index', 'show', 'destroy'],
49
- middleware: ['auth'],
49
+ middleware: ['auth', 'team'],
50
50
  },
51
51
  },
52
52
 
@@ -42,7 +42,7 @@ export default defineModel({
42
42
  useApi: {
43
43
  uri: 'team-members',
44
44
  routes: ['index', 'store', 'show', 'update', 'destroy'],
45
- middleware: ['auth'],
45
+ middleware: ['auth', 'team'],
46
46
  },
47
47
  },
48
48
 
@@ -8,7 +8,7 @@ export default defineModel({
8
8
  traits: {
9
9
  useUuid: true,
10
10
  useTimestamps: true,
11
- useApi: { uri: 'usage-events', routes: ['index', 'show'], middleware: ['auth'] },
11
+ useApi: { uri: 'usage-events', routes: ['index', 'show'], middleware: ['auth', 'team'] },
12
12
  },
13
13
  indexes: [
14
14
  { name: 'usage_events_idempotency_unique', columns: ['idempotency_key'], unique: true },
@@ -2,7 +2,7 @@
2
2
  "publisher": "Stacks",
3
3
  "name": "vscode-stacks",
4
4
  "displayName": "Stacks",
5
- "version": "0.71.10",
5
+ "version": "0.72.1",
6
6
  "description": "A modern Stacks development environment.",
7
7
  "license": "MIT",
8
8
  "funding": "https://github.com/sponsors/chrisbbreuer",
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@stacksjs/defaults",
3
3
  "type": "module",
4
4
  "sideEffects": false,
5
- "version": "0.71.10",
5
+ "version": "0.72.1",
6
6
  "description": "The complete managed Stacks application scaffold, including runtime defaults, AI guidance, editor metadata, and npm-backed project support files.",
7
7
  "author": "Chris Breuer",
8
8
  "license": "MIT",
@@ -46,7 +46,7 @@
46
46
  "dependencies": {
47
47
  "@iconify-json/f7": "^1.2.2",
48
48
  "@iconify-json/hugeicons": "^1.2.27",
49
- "@stacksjs/mobile": "^0.71.10",
49
+ "@stacksjs/mobile": "^0.72.1",
50
50
  "@stacksjs/sanitizer": "^0.2.113"
51
51
  },
52
52
  "scripts": {