@fougere/cli 0.13.0-alpha.0 → 0.14.0-alpha.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 (40) hide show
  1. package/dist/.fougere/scan.generated.js +1 -1
  2. package/dist/.fougere/scan.generated.js.map +1 -1
  3. package/dist/app/commands/MigrateCommand.d.ts +2 -2
  4. package/dist/app/commands/MigrateCommand.d.ts.map +1 -1
  5. package/dist/app/commands/MigrateCommand.js +15 -13
  6. package/dist/app/commands/MigrateCommand.js.map +1 -1
  7. package/dist/app/commands/NewCommand.d.ts +4 -12
  8. package/dist/app/commands/NewCommand.d.ts.map +1 -1
  9. package/dist/app/commands/NewCommand.js +51 -85
  10. package/dist/app/commands/NewCommand.js.map +1 -1
  11. package/dist/fronds/analysis/entities/Migrate.d.ts +1 -1
  12. package/dist/fronds/analysis/entities/Migrate.d.ts.map +1 -1
  13. package/dist/fronds/analysis/entities/Migrate.js +1 -1
  14. package/dist/fronds/analysis/entities/Migrate.js.map +1 -1
  15. package/dist/fronds/analysis/handlers/MigrateHandler.d.ts +14 -9
  16. package/dist/fronds/analysis/handlers/MigrateHandler.d.ts.map +1 -1
  17. package/dist/fronds/analysis/handlers/MigrateHandler.js +83 -39
  18. package/dist/fronds/analysis/handlers/MigrateHandler.js.map +1 -1
  19. package/dist/fronds/analysis/services/ProjectScan.d.ts +2 -2
  20. package/dist/fronds/analysis/services/ProjectScan.js +2 -2
  21. package/dist/fronds/scaffold/entities/New.d.ts +2 -5
  22. package/dist/fronds/scaffold/entities/New.d.ts.map +1 -1
  23. package/dist/fronds/scaffold/entities/New.js +5 -8
  24. package/dist/fronds/scaffold/entities/New.js.map +1 -1
  25. package/dist/fronds/scaffold/services/ProjectWriter.d.ts +16 -0
  26. package/dist/fronds/scaffold/services/ProjectWriter.d.ts.map +1 -1
  27. package/dist/fronds/scaffold/services/ProjectWriter.js +84 -12
  28. package/dist/fronds/scaffold/services/ProjectWriter.js.map +1 -1
  29. package/dist/src/composer/Composer.d.ts +61 -0
  30. package/dist/src/composer/Composer.d.ts.map +1 -0
  31. package/dist/src/composer/Composer.js +246 -0
  32. package/dist/src/composer/Composer.js.map +1 -0
  33. package/dist/src/composer/Plan.d.ts +36 -0
  34. package/dist/src/composer/Plan.d.ts.map +1 -0
  35. package/dist/src/composer/Plan.js +70 -0
  36. package/dist/src/composer/Plan.js.map +1 -0
  37. package/package.json +16 -15
  38. package/templates/frond/pnpm-workspace.yaml +9 -0
  39. package/templates/workspace/package.json +5 -3
  40. package/templates/workspace/pnpm-workspace.yaml +1 -1
@@ -0,0 +1,246 @@
1
+ import { stripVTControlCharacters } from 'node:util';
2
+ import { Prompt, isCancel } from '@clack/core';
3
+ import pc from 'picocolors';
4
+ import { commandOf, treeOf } from './Plan.js';
5
+ const STEPS = ['project', 'fronds', 'apps'];
6
+ const TITLE = { project: 'Project', fronds: 'Fronds', apps: 'Apps' };
7
+ const QUESTION = {
8
+ project: 'Name',
9
+ fronds: 'Which domains does it hold?',
10
+ apps: 'What consumes them?',
11
+ };
12
+ const MEANING = {
13
+ fronds: 'A frond is a domain — its entities and the operations on them. It runs inside an app, or in a process of its own.',
14
+ apps: 'An app is what people use — pages that call the fronds’ operations.',
15
+ };
16
+ const TYPED = /^[a-z0-9._-]$/;
17
+ const ERASE = new Set(['\x7f', '\b']);
18
+ const visible = (line) => stripVTControlCharacters(line).length;
19
+ const padded = (line, width) => line + ' '.repeat(Math.max(0, width - visible(line)));
20
+ /**
21
+ * `fougere new` in three steps — the project, its fronds, its apps — with the tree the plan
22
+ * writes and the command that writes it with no prompt drawn beside every step.
23
+ *
24
+ * ⏎ moves on and ← goes back. In a list, `r` renames the row under the cursor and `+` adds another
25
+ * piece of the same template. Nothing is written here: the answer is a `Plan`, and whether the
26
+ * directory it names may be replaced.
27
+ *
28
+ * Documented: [the CLI](https://fougere.dev/docs/cli).
29
+ */
30
+ export class Composer {
31
+ options;
32
+ static WIDTH = 36;
33
+ step;
34
+ rows;
35
+ name;
36
+ cursor = 0;
37
+ editing;
38
+ asking = false;
39
+ overwrite = false;
40
+ held = false;
41
+ prompt;
42
+ output;
43
+ constructor(options) {
44
+ this.options = options;
45
+ this.name = options.name;
46
+ this.rows = ['fronds', 'apps'].flatMap((kind) => options.catalog[kind].map((template) => ({ kind, template, name: template, on: false })));
47
+ this.step = 'project';
48
+ this.editing = options.name;
49
+ this.output = options.output ?? process.stdout;
50
+ this.prompt = new Prompt({
51
+ render: () => this.frame(),
52
+ validate: () => this.refusal(),
53
+ input: options.input,
54
+ output: options.output,
55
+ }, false);
56
+ this.prompt.value = '';
57
+ this.prompt.on('cursor', (action) => this.act(action));
58
+ this.prompt.on('key', (char) => this.type(char ?? ''));
59
+ this.prompt.on('finalize', () => { this.prompt.value = { plan: this.plan(), overwrite: this.overwrite }; });
60
+ }
61
+ /** What the screen was left on, or `undefined` when it was cancelled. */
62
+ async ask() {
63
+ const answer = await this.prompt.prompt();
64
+ return isCancel(answer) ? undefined : answer;
65
+ }
66
+ plan() {
67
+ const pieces = (kind) => this.rows.filter((row) => row.kind === kind && row.on).map(({ template, name }) => ({ template, name }));
68
+ return { name: this.name, fronds: pieces('fronds'), apps: pieces('apps') };
69
+ }
70
+ frame(columns = this.output.columns || 80) {
71
+ const plan = this.plan();
72
+ const bar = pc.gray('│');
73
+ if (this.prompt.state === 'submit') {
74
+ return `${pc.green('◇')} ${plan.name} ${pc.dim('— ' + summaryOf(plan) + (this.overwrite ? ', replacing what was there' : ''))}`;
75
+ }
76
+ if (this.prompt.state === 'cancel')
77
+ return `${pc.red('■')} ${pc.dim('Cancelled — nothing was written.')}`;
78
+ const left = this.body();
79
+ const right = treeOf(plan).map((line) => pc.dim(line));
80
+ const side = columns >= Composer.WIDTH + Math.max(...right.map(visible)) + 6;
81
+ const body = side
82
+ ? Array.from({ length: Math.max(left.length, right.length) }, (_, at) => (padded(left[at] ?? '', Composer.WIDTH) + (right[at] ?? '')).trimEnd())
83
+ : [...left, '', ...right];
84
+ const refusal = this.prompt.state === 'error' ? this.prompt.error.trim() : '';
85
+ return [
86
+ `${pc.cyan('◆')} ${pc.bold('New Fougere project')}`,
87
+ bar,
88
+ `${bar} ${this.breadcrumb()}`,
89
+ bar,
90
+ `${bar} ${pc.bold(QUESTION[this.step])}`,
91
+ ...(this.step === 'project' ? [] : [`${bar} ${pc.dim(MEANING[this.step])}`, bar]),
92
+ ...body.map((line) => `${bar} ${line}`),
93
+ bar,
94
+ `${bar} ${pc.dim('Same, with no prompt:')} ${commandOf(plan)}`,
95
+ ...(refusal ? [`${bar} ${pc.yellow(refusal)}`] : []),
96
+ `${pc.gray('└')} ${pc.dim(this.hint())}`,
97
+ ].join('\n');
98
+ }
99
+ breadcrumb() {
100
+ const reached = STEPS.indexOf(this.step);
101
+ return STEPS.map((step, at) => {
102
+ if (at === reached)
103
+ return pc.cyan(pc.bold(`● ${TITLE[step]}`));
104
+ return at < reached ? pc.green(`✓ ${TITLE[step]}`) : pc.dim(`○ ${TITLE[step]}`);
105
+ }).join(pc.dim(' › '));
106
+ }
107
+ body() {
108
+ if (this.step === 'project') {
109
+ const name = this.editing === undefined ? this.name : pc.underline(this.editing) + pc.cyan('▌');
110
+ const lines = [`${pc.cyan('▸')} ${name || pc.dim('<name>')}`];
111
+ return this.asking ? [...lines, '', pc.yellow(`${this.name}/ already exists.`), `Replace it? ${pc.dim('y / n')}`] : lines;
112
+ }
113
+ return this.listed().map(({ row, at }) => {
114
+ const pointer = at === this.cursor ? pc.cyan('▸') : ' ';
115
+ const box = row.on ? pc.green('◼') : pc.dim('◻');
116
+ const name = at === this.cursor && this.editing !== undefined ? pc.underline(this.editing) + pc.cyan('▌') : row.name;
117
+ const renamed = row.name === row.template ? '' : pc.dim(` (${row.template})`);
118
+ return `${pointer} ${box} ${name}${renamed}`;
119
+ });
120
+ }
121
+ hint() {
122
+ if (this.asking)
123
+ return 'y replace · n pick another name · esc quit';
124
+ if (this.editing !== undefined)
125
+ return this.step === 'project' ? 'type the name · ⏎ next · esc quit' : 'type the name · ⏎ keep it · esc quit';
126
+ const next = this.step === 'apps' ? '⏎ write' : '⏎ next';
127
+ return `↑↓ move · space check · + another · r rename · ← back · ${next} · esc quit`;
128
+ }
129
+ /** The rows of the current step, each with its index among them. */
130
+ listed() {
131
+ return this.rows.filter((row) => row.kind === this.step).map((row, at) => ({ row, at }));
132
+ }
133
+ current() {
134
+ return this.listed()[this.cursor]?.row;
135
+ }
136
+ go(step) {
137
+ this.step = step;
138
+ this.cursor = 0;
139
+ this.editing = step === 'project' ? this.name : undefined;
140
+ }
141
+ act(action) {
142
+ if (this.editing !== undefined || this.asking)
143
+ return;
144
+ const last = this.listed().length - 1;
145
+ if (action === 'up')
146
+ this.cursor = this.cursor === 0 ? last : this.cursor - 1;
147
+ if (action === 'down')
148
+ this.cursor = this.cursor === last ? 0 : this.cursor + 1;
149
+ if (action === 'left')
150
+ this.go(STEPS[STEPS.indexOf(this.step) - 1] ?? 'project');
151
+ if (action === 'space') {
152
+ const row = this.current();
153
+ if (row)
154
+ row.on = !row.on;
155
+ }
156
+ }
157
+ type(char) {
158
+ if (this.asking)
159
+ return this.answer(char);
160
+ if (this.editing !== undefined)
161
+ return this.edit(char);
162
+ if (char === '\r' && this.step !== 'apps')
163
+ return this.hold(() => this.go(STEPS[STEPS.indexOf(this.step) + 1]));
164
+ if (char === 'r')
165
+ this.editing = this.current()?.name;
166
+ if (char === '+')
167
+ this.another();
168
+ }
169
+ edit(char) {
170
+ const editing = this.editing ?? '';
171
+ if (ERASE.has(char))
172
+ this.editing = editing.slice(0, -1);
173
+ else if (TYPED.test(char))
174
+ this.editing = editing + char;
175
+ if (char !== '\r')
176
+ return;
177
+ if (this.step === 'project')
178
+ return this.hold(() => this.named(editing));
179
+ this.editing = undefined;
180
+ const row = this.current();
181
+ this.hold(() => { if (editing && row)
182
+ row.name = editing; });
183
+ }
184
+ /** The name is kept, and the step left, only once it can be written. */
185
+ named(name) {
186
+ this.name = name;
187
+ this.overwrite = false;
188
+ if (this.options.refusals({ name, fronds: [], apps: [] }, true).length)
189
+ return;
190
+ this.editing = undefined;
191
+ if (this.options.exists(name))
192
+ this.asking = true;
193
+ else
194
+ this.go('fronds');
195
+ }
196
+ answer(char) {
197
+ if (char === 'y') {
198
+ this.overwrite = true;
199
+ this.asking = false;
200
+ this.go('fronds');
201
+ }
202
+ if (char === 'n') {
203
+ this.asking = false;
204
+ this.editing = this.name;
205
+ }
206
+ if (char === '\r')
207
+ this.held = true;
208
+ }
209
+ another() {
210
+ const row = this.current();
211
+ if (!row)
212
+ return;
213
+ const taken = new Set(this.rows.filter((other) => other.kind === row.kind).map((other) => other.name));
214
+ let count = 2;
215
+ while (taken.has(`${row.template}-${count}`))
216
+ count++;
217
+ this.rows.splice(this.rows.indexOf(row) + 1, 0, { ...row, name: `${row.template}-${count}`, on: true });
218
+ this.cursor++;
219
+ this.editing = this.current()?.name;
220
+ }
221
+ /** ⏎ that moves the screen on is not the ⏎ that writes: the next one is. */
222
+ hold(move) {
223
+ this.held = true;
224
+ move();
225
+ }
226
+ refusal() {
227
+ if (this.step === 'project' && !this.asking) {
228
+ const refused = this.options.refusals({ name: this.name, fronds: [], apps: [] }, true)[0];
229
+ if (refused) {
230
+ this.held = false;
231
+ return refused;
232
+ }
233
+ }
234
+ if (this.held) {
235
+ this.held = false;
236
+ return ' ';
237
+ }
238
+ return this.options.refusals(this.plan(), this.overwrite)[0];
239
+ }
240
+ }
241
+ function summaryOf(plan) {
242
+ const names = (kind) => plan[kind].map((piece) => piece.name).join(', ');
243
+ const parts = ['fronds', 'apps'].filter((kind) => plan[kind].length).map((kind) => `${kind}: ${names(kind)}`);
244
+ return parts.join(' · ') || 'an empty workspace';
245
+ }
246
+ //# sourceMappingURL=Composer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Composer.js","sourceRoot":"","sources":["../../../src/composer/Composer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ export type Kind = 'fronds' | 'apps';
2
+ export interface Piece {
3
+ template: string;
4
+ name: string;
5
+ }
6
+ /**
7
+ * What `fougere new` writes, whoever composed it: the flags state it, the composer builds it,
8
+ * and one writer carries it out once nothing is left to ask.
9
+ */
10
+ export interface Plan {
11
+ name: string;
12
+ fronds: Piece[];
13
+ apps: Piece[];
14
+ }
15
+ export interface Catalog {
16
+ fronds: string[];
17
+ apps: string[];
18
+ }
19
+ export interface Stated {
20
+ name?: string;
21
+ frond?: string;
22
+ app?: string;
23
+ bare?: boolean;
24
+ }
25
+ /** The flags, read as a plan — or `undefined` when they state no composition and the composer should ask. */
26
+ export declare function planOf(stated: Stated): Plan | undefined;
27
+ /** The dual of `planOf`: the line that writes this plan again, with no prompt. */
28
+ export declare function commandOf(plan: Plan, entry?: string): string;
29
+ /** The directories the plan writes, drawn as a tree. */
30
+ export declare function treeOf(plan: Plan): string[];
31
+ /** Everything that stops the plan from being written, in the order a reader fixes it. */
32
+ export declare function refusalsOf(plan: Plan, catalog: Catalog, where: {
33
+ cwd: string;
34
+ replace?: boolean;
35
+ }): string[];
36
+ //# sourceMappingURL=Plan.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Plan.d.ts","sourceRoot":"","sources":["../../../src/composer/Plan.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,IAAI,GAAG,QAAQ,GAAG,MAAM,CAAC;AAErC,MAAM,WAAW,KAAK;IAAG,QAAQ,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE;AAEzD;;;GAGG;AACH,MAAM,WAAW,IAAI;IAAG,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,KAAK,EAAE,CAAC;IAAC,IAAI,EAAE,KAAK,EAAE,CAAA;CAAE;AAEtE,MAAM,WAAW,OAAO;IAAG,MAAM,EAAE,MAAM,EAAE,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CAAE;AAE7D,MAAM,WAAW,MAAM;IAAG,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,OAAO,CAAA;CAAE;AAQvF,6GAA6G;AAC7G,wBAAgB,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAQvD;AAWD,kFAAkF;AAClF,wBAAgB,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,SAAwB,GAAG,MAAM,CAQ3E;AAED,wDAAwD;AACxD,wBAAgB,MAAM,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,EAAE,CAe3C;AAED,yFAAyF;AACzF,wBAAgB,UAAU,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,MAAM,EAAE,CAiB5G"}
@@ -0,0 +1,70 @@
1
+ import { existsSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ const FLAG = { fronds: '--frond', apps: '--app' };
4
+ const PROJECT = /^[a-z0-9][a-z0-9._-]*$/;
5
+ const PIECE = /^[a-z][a-z0-9-]*$/;
6
+ /** The flags, read as a plan — or `undefined` when they state no composition and the composer should ask. */
7
+ export function planOf(stated) {
8
+ if (!stated.bare && !stated.frond && !stated.app)
9
+ return undefined;
10
+ return {
11
+ name: stated.name ?? '',
12
+ fronds: piecesOf(stated.frond ?? ''),
13
+ apps: piecesOf(stated.app ?? ''),
14
+ };
15
+ }
16
+ function piecesOf(spec) {
17
+ return spec.split(',').map((piece) => piece.trim()).filter(Boolean).map((piece) => {
18
+ const [template, name = template, ...rest] = piece.split(':');
19
+ if (rest.length)
20
+ throw new Error(`'${piece}' is a template and a name, 'blog:news' — one colon at most.`);
21
+ return { template, name };
22
+ });
23
+ }
24
+ /** The dual of `planOf`: the line that writes this plan again, with no prompt. */
25
+ export function commandOf(plan, entry = 'pnpm create fougere') {
26
+ const spec = (pieces) => pieces.map(({ template, name }) => (name === template ? template : `${template}:${name}`)).join(',');
27
+ const flags = ['fronds', 'apps']
28
+ .filter((kind) => plan[kind].length)
29
+ .map((kind) => `${FLAG[kind]} ${spec(plan[kind])}`);
30
+ return [entry, plan.name || '<name>', ...(flags.length ? flags : ['--bare'])].join(' ');
31
+ }
32
+ /** The directories the plan writes, drawn as a tree. */
33
+ export function treeOf(plan) {
34
+ const kinds = ['fronds', 'apps'].filter((kind) => plan[kind].length);
35
+ const top = ['fougere.config.ts', 'package.json', ...kinds.map((kind) => `${kind}/`)];
36
+ const lines = [`${plan.name || '<name>'}/`];
37
+ top.forEach((entry, index) => {
38
+ const last = index === top.length - 1;
39
+ lines.push(`${last ? '└─' : '├─'} ${entry}`);
40
+ const kind = kinds.find((candidate) => `${candidate}/` === entry);
41
+ if (!kind)
42
+ return;
43
+ plan[kind].forEach((piece, at) => lines.push(`${last ? ' ' : '│ '}${at === plan[kind].length - 1 ? '└─' : '├─'} ${piece.name}/`));
44
+ });
45
+ return lines;
46
+ }
47
+ /** Everything that stops the plan from being written, in the order a reader fixes it. */
48
+ export function refusalsOf(plan, catalog, where) {
49
+ const refusals = [];
50
+ if (!plan.name)
51
+ refusals.push('The project has no name — fougere new <name>.');
52
+ else if (!PROJECT.test(plan.name))
53
+ refusals.push(`'${plan.name}' is not a package name: lowercase letters, digits, '.', '_' and '-'.`);
54
+ else if (existsSync(join(where.cwd, plan.name)) && !where.replace)
55
+ refusals.push(`${plan.name}/ already exists — pick another name, or pass --force to replace it.`);
56
+ for (const kind of ['fronds', 'apps']) {
57
+ const seen = new Set();
58
+ for (const { template, name } of plan[kind]) {
59
+ if (!catalog[kind].includes(template))
60
+ refusals.push(`No ${kind} template '${template}' — available: ${catalog[kind].join(', ') || '(none)'}.`);
61
+ if (!PIECE.test(name))
62
+ refusals.push(`'${name}' is not a ${kind === 'fronds' ? 'frond' : 'app'} name: a lowercase letter, then letters, digits and '-'.`);
63
+ if (seen.has(name))
64
+ refusals.push(`Two ${kind} are called '${name}' — rename one.`);
65
+ seen.add(name);
66
+ }
67
+ }
68
+ return refusals;
69
+ }
70
+ //# sourceMappingURL=Plan.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Plan.js","sourceRoot":"","sources":["../../../src/composer/Plan.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fougere/cli",
3
- "version": "0.13.0-alpha.0",
3
+ "version": "0.14.0-alpha.0",
4
4
  "description": "The Fougere CLI — compose a workspace, serve a frond, call an operation.",
5
5
  "keywords": [
6
6
  "fougere",
@@ -33,33 +33,34 @@
33
33
  "templates"
34
34
  ],
35
35
  "dependencies": {
36
+ "@clack/core": "0.4.2",
36
37
  "@clack/prompts": "^0.10.0",
37
- "@fougere/compiler": "0.13.0-alpha.0",
38
- "@fougere/container": "0.13.0-alpha.0",
39
- "@fougere/core": "0.13.0-alpha.0",
40
- "@fougere/defaults": "0.13.0-alpha.0",
41
- "@fougere/schema": "0.13.0-alpha.0",
42
- "@fougere/testing": "0.13.0-alpha.0",
43
- "@fougere/transport-http": "0.13.0-alpha.0",
38
+ "@fougere/compiler": "0.14.0-alpha.0",
39
+ "@fougere/container": "0.14.0-alpha.0",
40
+ "@fougere/core": "0.14.0-alpha.0",
41
+ "@fougere/defaults": "0.14.0-alpha.0",
42
+ "@fougere/schema": "0.14.0-alpha.0",
43
+ "@fougere/testing": "0.14.0-alpha.0",
44
+ "@fougere/transport-http": "0.14.0-alpha.0",
44
45
  "citty": "^0.2.1",
45
46
  "jiti": "^2.4.2",
46
47
  "picocolors": "^1.1.1",
47
48
  "safe-regex": "^2.1.1"
48
49
  },
49
50
  "devDependencies": {
50
- "@fougere/admin": "0.13.0-alpha.0",
51
- "@fougere/next": "0.13.0-alpha.0",
52
- "@fougere/nuxt": "0.13.0-alpha.0",
53
- "@fougere/oclif": "0.13.0-alpha.0",
54
- "@fougere/react": "0.13.0-alpha.0",
55
- "@fougere/svelte": "0.13.0-alpha.0",
51
+ "@fougere/admin": "0.14.0-alpha.0",
52
+ "@fougere/next": "0.14.0-alpha.0",
53
+ "@fougere/nuxt": "0.14.0-alpha.0",
54
+ "@fougere/oclif": "0.14.0-alpha.0",
55
+ "@fougere/react": "0.14.0-alpha.0",
56
+ "@fougere/svelte": "0.14.0-alpha.0",
56
57
  "vitest": "^4.1.0"
57
58
  },
58
59
  "publishConfig": {
59
60
  "access": "public"
60
61
  },
61
62
  "peerDependencies": {
62
- "@fougere/adapter-sql": "^0.13.0-alpha.0"
63
+ "@fougere/adapter-sql": "^0.14.0-alpha.0"
63
64
  },
64
65
  "peerDependenciesMeta": {
65
66
  "@fougere/adapter-sql": {
@@ -1,2 +1,11 @@
1
1
  packages:
2
2
  - fronds/*
3
+
4
+ allowBuilds:
5
+ better-sqlite3: false
6
+ esbuild: true
7
+
8
+ # A project is created the day a version is published: the delay pnpm can apply to a fresh
9
+ # release would hold back the very version the scaffold was written for.
10
+ minimumReleaseAgeExclude:
11
+ - '@fougere/*'
@@ -4,15 +4,17 @@
4
4
  "type": "module",
5
5
  "packageManager": "pnpm@12.6.0",
6
6
  "scripts": {
7
- "dev": "pnpm --filter './apps/*' --parallel dev",
8
7
  "build": "pnpm --filter './apps/*' -r build",
9
- "typecheck": "tsc -p fronds"
8
+ "typecheck": "tsc -p fronds",
9
+ "migrate": "fougere migrate --apply"
10
10
  },
11
11
  "dependencies": {
12
12
  "@fougere/core": "latest",
13
- "@fougere/schema": "latest"
13
+ "@fougere/schema": "latest",
14
+ "better-sqlite3": "^13.0.3"
14
15
  },
15
16
  "devDependencies": {
17
+ "@fougere/cli": "latest",
16
18
  "@types/node": "^22.19.15",
17
19
  "typescript": "^5.9.3"
18
20
  }
@@ -3,7 +3,7 @@ packages:
3
3
  - apps/*
4
4
 
5
5
  allowBuilds:
6
- better-sqlite3: true
6
+ better-sqlite3: false
7
7
  esbuild: true
8
8
 
9
9
  # A project is created the day a version is published: the delay pnpm can apply to a fresh