@forgeailab/spark 0.1.3 → 0.3.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.
- package/README.md +1 -15
- package/package.json +8 -9
- package/src/commands/add.ts +6 -17
- package/src/commands/check.ts +6 -37
- package/src/commands/info.ts +1 -8
- package/src/commands/preset.ts +1 -0
- package/src/internal/board.ts +503 -0
- package/src/internal/skill-utils.ts +233 -0
- package/src/internal/state.ts +89 -0
- package/src/io/board.ts +32 -68
- package/src/io/env.ts +8 -3
- package/src/io/files.ts +22 -7
- package/src/io/skills.ts +1 -1
- package/src/io/state.ts +1 -1
- package/packs/README.md +0 -132
- package/packs/ai-anthropic/files/app/api/ai/route.ts +0 -57
- package/packs/ai-anthropic/files/lib/anthropic.ts +0 -15
- package/packs/ai-anthropic/pack.toml +0 -32
- package/packs/ai-anthropic/skills/ai-feature-patterns/SKILL.md +0 -87
- package/packs/ai-anthropic/tasks.yaml +0 -9
- package/packs/ai-openai/files/app/api/ai-openai/route.ts +0 -55
- package/packs/ai-openai/files/lib/openai.ts +0 -21
- package/packs/ai-openai/pack.toml +0 -30
- package/packs/ai-openai/tasks.yaml +0 -9
- package/packs/analytics-posthog/files/components/PostHogProvider.tsx +0 -19
- package/packs/analytics-posthog/files/lib/posthog/client.ts +0 -20
- package/packs/analytics-posthog/files/lib/posthog/server.ts +0 -24
- package/packs/analytics-posthog/pack.toml +0 -35
- package/packs/analytics-posthog/tasks.yaml +0 -15
- package/packs/auth-better-auth/files/app/(auth)/login/page.tsx +0 -58
- package/packs/auth-better-auth/files/app/api/auth/[...all]/route.ts +0 -4
- package/packs/auth-better-auth/files/lib/auth.ts +0 -21
- package/packs/auth-better-auth/pack.toml +0 -32
- package/packs/auth-better-auth/tasks.yaml +0 -10
- package/packs/auth-better-auth-pg/files/app/api/auth/[...all]/route.ts +0 -4
- package/packs/auth-better-auth-pg/files/lib/auth.ts +0 -86
- package/packs/auth-better-auth-pg/pack.toml +0 -32
- package/packs/auth-better-auth-pg/tasks.yaml +0 -17
- package/packs/auth-supabase/files/app/(auth)/login/page.tsx +0 -64
- package/packs/auth-supabase/files/app/auth/callback/route.ts +0 -15
- package/packs/auth-supabase/files/middleware.ts +0 -41
- package/packs/auth-supabase/pack.toml +0 -34
- package/packs/auth-supabase/tasks.yaml +0 -10
- package/packs/db-postgres/files/compose/postgres.yml +0 -28
- package/packs/db-postgres/files/docker-compose.include.yml +0 -1
- package/packs/db-postgres/files/docker-compose.yml +0 -6
- package/packs/db-postgres/files/drizzle.config.ts +0 -10
- package/packs/db-postgres/files/lib/db/index.ts +0 -10
- package/packs/db-postgres/files/lib/db/schema.ts +0 -11
- package/packs/db-postgres/pack.toml +0 -53
- package/packs/db-postgres/tasks.yaml +0 -11
- package/packs/db-sqlite/files/drizzle.config.ts +0 -10
- package/packs/db-sqlite/files/lib/db.ts +0 -8
- package/packs/db-sqlite/files/lib/schema.ts +0 -13
- package/packs/db-sqlite/pack.toml +0 -34
- package/packs/db-sqlite/tasks.yaml +0 -6
- package/packs/db-supabase/files/lib/supabase/client.ts +0 -8
- package/packs/db-supabase/files/lib/supabase/server.ts +0 -27
- package/packs/db-supabase/pack.toml +0 -32
- package/packs/db-supabase/skills/supabase-patterns/SKILL.md +0 -82
- package/packs/db-supabase/tasks.yaml +0 -6
- package/packs/deploy-vercel/files/docs/deploy.md +0 -21
- package/packs/deploy-vercel/files/vercel.json +0 -4
- package/packs/deploy-vercel/pack.toml +0 -30
- package/packs/deploy-vercel/tasks.yaml +0 -14
- package/packs/docker-compose-dev/files/.env.docker.example +0 -2
- package/packs/docker-compose-dev/files/compose/redis.yml +0 -17
- package/packs/docker-compose-dev/files/docker-compose.include.yml +0 -1
- package/packs/docker-compose-dev/files/docker-compose.yml +0 -6
- package/packs/docker-compose-dev/pack.toml +0 -38
- package/packs/docker-compose-dev/tasks.yaml +0 -9
- package/packs/email-resend/files/app/api/email/test/route.ts +0 -38
- package/packs/email-resend/files/emails/welcome.tsx +0 -66
- package/packs/email-resend/files/lib/email.ts +0 -40
- package/packs/email-resend/pack.toml +0 -34
- package/packs/email-resend/tasks.yaml +0 -9
- package/packs/example/pack.toml +0 -69
- package/packs/payments-stripe/files/app/api/billing-portal/route.ts +0 -24
- package/packs/payments-stripe/files/app/api/checkout/route.ts +0 -58
- package/packs/payments-stripe/files/app/api/webhooks/stripe/route.ts +0 -84
- package/packs/payments-stripe/files/lib/stripe.ts +0 -60
- package/packs/payments-stripe/pack.toml +0 -49
- package/packs/payments-stripe/skills/stripe-patterns/SKILL.md +0 -93
- package/packs/payments-stripe/tasks.yaml +0 -16
- package/packs/sync-zero/files/components/ZeroProvider.tsx +0 -3
- package/packs/sync-zero/files/compose/zero-cache.yml +0 -26
- package/packs/sync-zero/files/docker-compose.include.yml +0 -1
- package/packs/sync-zero/files/docker-compose.yml +0 -6
- package/packs/sync-zero/files/lib/zero/client.ts +0 -18
- package/packs/sync-zero/files/lib/zero/schema.ts +0 -17
- package/packs/sync-zero/files/zero.config.ts +0 -26
- package/packs/sync-zero/pack.toml +0 -61
- package/packs/sync-zero/skills/zero-patterns/SKILL.md +0 -69
- package/packs/sync-zero/tasks.yaml +0 -16
- package/packs/testing-playwright/files/e2e/example.spec.ts +0 -7
- package/packs/testing-playwright/files/playwright.config.ts +0 -33
- package/packs/testing-playwright/pack.toml +0 -25
- package/packs/testing-playwright/tasks.yaml +0 -9
- package/packs/ui-shadcn/files/app/globals.css +0 -56
- package/packs/ui-shadcn/files/components/ui/button.tsx +0 -47
- package/packs/ui-shadcn/files/components/ui/card.tsx +0 -33
- package/packs/ui-shadcn/files/lib/utils.ts +0 -6
- package/packs/ui-shadcn/files/postcss.config.mjs +0 -7
- package/packs/ui-shadcn/files/tailwind.config.ts +0 -57
- package/packs/ui-shadcn/pack.toml +0 -44
- package/packs/ui-shadcn/skills/shadcn-dashboard-patterns/SKILL.md +0 -85
- package/packs/ui-shadcn/tasks.yaml +0 -6
- package/presets/docs-site.toml +0 -4
- package/presets/internal-tool.toml +0 -4
- package/presets/lean-saas.toml +0 -4
- package/presets/local-ai-mvp.toml +0 -4
- package/presets/saas-classic.toml +0 -4
- package/src/runtime-package.ts +0 -132
- package/templates/README.md +0 -43
- package/templates/astro/README.md +0 -3
- package/templates/astro/template.toml +0 -4
- package/templates/astro-starlight/README.md +0 -3
- package/templates/astro-starlight/template.toml +0 -4
- package/templates/nextjs/.ai/architecture.md +0 -13
- package/templates/nextjs/.ai/board.md +0 -7
- package/templates/nextjs/.ai/product-spec.md +0 -11
- package/templates/nextjs/.claude/skills/.gitkeep +0 -0
- package/templates/nextjs/.codex/skills/.gitkeep +0 -0
- package/templates/nextjs/AGENTS.md +0 -95
- package/templates/nextjs/CLAUDE.md +0 -3
- package/templates/nextjs/README.md +0 -20
- package/templates/nextjs/app/(app)/home/page.tsx +0 -43
- package/templates/nextjs/app/(app)/home/posts-panel.tsx +0 -83
- package/templates/nextjs/app/(app)/layout.tsx +0 -12
- package/templates/nextjs/app/(auth)/login/page.tsx +0 -97
- package/templates/nextjs/app/globals.css +0 -23
- package/templates/nextjs/app/layout.tsx +0 -20
- package/templates/nextjs/app/page.tsx +0 -39
- package/templates/nextjs/lib/auth-placeholder.ts +0 -21
- package/templates/nextjs/lib/posts-placeholder.ts +0 -30
- package/templates/nextjs/next.config.ts +0 -5
- package/templates/nextjs/package.json +0 -26
- package/templates/nextjs/postcss.config.mjs +0 -7
- package/templates/nextjs/spark.config.json +0 -4
- package/templates/nextjs/template.toml +0 -4
- package/templates/nextjs/tsconfig.json +0 -27
- package/templates/nextjs/types/post.ts +0 -13
- package/templates/one/README.md +0 -5
- package/templates/one/template.toml +0 -4
- package/templates/vite-react/README.md +0 -3
- package/templates/vite-react/template.toml +0 -4
package/README.md
CHANGED
|
@@ -36,13 +36,6 @@ Print everything the install would do — files touched, env vars added, deps in
|
|
|
36
36
|
spark info payments-stripe
|
|
37
37
|
```
|
|
38
38
|
|
|
39
|
-
For **hybrid** packs (those with a `[runtime_package]` block in their manifest), `info` also prints:
|
|
40
|
-
|
|
41
|
-
- `Install mode: hybrid` (vs `copy` for the rest)
|
|
42
|
-
- `Runtime helper: <package> (range <X>, resolved <Y>)` — the npm name + manifest version range + the version currently installed in the project's `package.json` (or `not installed`).
|
|
43
|
-
|
|
44
|
-
For copy packs `info` prints `Install mode: copy` and omits the helper line.
|
|
45
|
-
|
|
46
39
|
### `add <pack...> [--dry-run]`
|
|
47
40
|
|
|
48
41
|
Resolve the requested packs against the registry + installed set + active scaffold, then apply. Idempotent: running it twice with the same args is a no-op.
|
|
@@ -58,13 +51,6 @@ The resolver enforces:
|
|
|
58
51
|
- **Exclusivity.** Capabilities classified exclusive (`db`, `auth`, `payments`, `ui-kit`, `sync`) reject double-installs. Non-exclusive caps (`ai-sdk`, `analytics`, `email`, `blob-storage`, `e2e`, `deploy-target`, `local-runtime`) coexist.
|
|
59
52
|
- **Scaffold compatibility.** A pack with `compatible_scaffolds = ["nextjs"]` refuses to install on a `vite-react` project.
|
|
60
53
|
|
|
61
|
-
**Hybrid pack install.** When a pack declares `[runtime_package]`, the CLI adds the helper package to the same `bun add` batch as the pack's explicit runtime deps. Two resolution modes:
|
|
62
|
-
|
|
63
|
-
- **Dev mode** — `SPARK_ROOT` is set and `${SPARK_ROOT}/libs/<helper>/` exists. The helper is linked via `file:` to the workspace path. Used by the reference app and `/tmp/spark-validate` smoke installs.
|
|
64
|
-
- **Published mode** — otherwise. The helper is installed by `<npm-name>@<range>` from the manifest's `[runtime_package].version`.
|
|
65
|
-
|
|
66
|
-
Either way the pack's `[dependencies].runtime` array MUST NOT also list the helper — the CLI handles it implicitly (see Decision 6 in the runtime-packages design doc).
|
|
67
|
-
|
|
68
54
|
### `preset <name>`
|
|
69
55
|
|
|
70
56
|
Apply a named bundle from `presets/<name>.toml`. Refuses if the active scaffold is not in the preset's `compatible_scaffolds`.
|
|
@@ -75,7 +61,7 @@ spark preset lean-saas
|
|
|
75
61
|
|
|
76
62
|
### `check`
|
|
77
63
|
|
|
78
|
-
Audit `.spark/state.json` against the filesystem. Reports missing files, missing env vars in `.env.local`, deleted seeded tasks.
|
|
64
|
+
Audit `.spark/state.json` against the filesystem. Reports missing files, missing env vars in `.env.local`, and deleted seeded tasks. **Does not repair.**
|
|
79
65
|
|
|
80
66
|
```bash
|
|
81
67
|
spark check
|
package/package.json
CHANGED
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@forgeailab/spark",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "CLI for managing feature packs in an spark-scaffolded project.",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "git+https://github.com/ForgeAILab/spark.git",
|
|
8
|
+
"directory": "packages/spark"
|
|
9
|
+
},
|
|
5
10
|
"type": "module",
|
|
6
11
|
"publishConfig": {
|
|
7
12
|
"access": "public"
|
|
8
13
|
},
|
|
9
14
|
"files": [
|
|
10
15
|
"src",
|
|
11
|
-
"README.md"
|
|
12
|
-
"packs",
|
|
13
|
-
"presets",
|
|
14
|
-
"templates"
|
|
16
|
+
"README.md"
|
|
15
17
|
],
|
|
16
18
|
"bin": {
|
|
17
19
|
"spark": "./src/cli.ts"
|
|
@@ -21,10 +23,7 @@
|
|
|
21
23
|
"typecheck": "tsc --noEmit"
|
|
22
24
|
},
|
|
23
25
|
"dependencies": {
|
|
24
|
-
"@forgeailab/spark-schema": "
|
|
25
|
-
"@forgeailab/spark-state": "^0.1.3",
|
|
26
|
-
"@forgeailab/spark-skill-utils": "^0.1.3",
|
|
27
|
-
"@forgeailab/spark-board": "^0.1.3",
|
|
26
|
+
"@forgeailab/spark-schema": "0.3.0",
|
|
28
27
|
"@clack/prompts": "latest",
|
|
29
28
|
"citty": "latest",
|
|
30
29
|
"picocolors": "latest",
|
package/src/commands/add.ts
CHANGED
|
@@ -17,7 +17,6 @@ import { readRegistry, type Registry } from '../io/registry.ts';
|
|
|
17
17
|
import { addInstalledPack, installedPackNames, readState, writeState } from '../io/state.ts';
|
|
18
18
|
import { seedBoardTasks } from '../io/board.ts';
|
|
19
19
|
import { copyPackSkills } from '../io/skills.ts';
|
|
20
|
-
import { assertRuntimeHelperNotRedeclared, resolveRuntimeHelper } from '../runtime-package.ts';
|
|
21
20
|
|
|
22
21
|
type AddOutput = Pick<Console, 'log' | 'error'>;
|
|
23
22
|
|
|
@@ -66,20 +65,8 @@ function formatResolverError(error: ResolverError): string {
|
|
|
66
65
|
return `Unknown pack: ${error.pack}`;
|
|
67
66
|
}
|
|
68
67
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
for (const pack of plan.packs) {
|
|
73
|
-
assertRuntimeHelperNotRedeclared(pack.name, pack.manifest);
|
|
74
|
-
dependencies.push(...(pack.manifest.dependencies?.runtime ?? []));
|
|
75
|
-
|
|
76
|
-
const helper = await resolveRuntimeHelper(pack.manifest);
|
|
77
|
-
if (helper) {
|
|
78
|
-
dependencies.push(helper);
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
return dependencies;
|
|
68
|
+
function packRuntimeDependencies(plan: InstallPlan): string[] {
|
|
69
|
+
return plan.packs.flatMap((pack) => pack.manifest.dependencies?.runtime ?? []);
|
|
83
70
|
}
|
|
84
71
|
|
|
85
72
|
function packDevDependencies(plan: InstallPlan): string[] {
|
|
@@ -182,11 +169,13 @@ function stateEntryForPack(
|
|
|
182
169
|
skillFiles: readonly string[],
|
|
183
170
|
touchedEnvFiles: readonly string[],
|
|
184
171
|
): StateInstalledPack {
|
|
172
|
+
const now = new Date();
|
|
173
|
+
const packInstallChange = `pack-install-${now.getUTCFullYear()}-${String(now.getUTCMonth() + 1).padStart(2, '0')}-${String(now.getUTCDate()).padStart(2, '0')}`;
|
|
185
174
|
const fileTargets = [
|
|
186
175
|
...fileRecords.map((record) => record.to),
|
|
187
176
|
...skillFiles,
|
|
188
177
|
...touchedEnvFiles,
|
|
189
|
-
...(taskIds.length > 0 ? [
|
|
178
|
+
...(taskIds.length > 0 ? [`docs/spark/changes/${packInstallChange}/tasks.md`] : []),
|
|
190
179
|
];
|
|
191
180
|
|
|
192
181
|
return {
|
|
@@ -235,7 +224,7 @@ export async function runAdd(requestedPacks: readonly string[], options: AddOpti
|
|
|
235
224
|
};
|
|
236
225
|
}
|
|
237
226
|
|
|
238
|
-
const runtimeDependencies =
|
|
227
|
+
const runtimeDependencies = packRuntimeDependencies(plan);
|
|
239
228
|
const devDependencies = packDevDependencies(plan);
|
|
240
229
|
|
|
241
230
|
if (options.dryRun) {
|
package/src/commands/check.ts
CHANGED
|
@@ -2,11 +2,10 @@ import { readFile, stat } from 'node:fs/promises';
|
|
|
2
2
|
import { join } from 'node:path';
|
|
3
3
|
import { defineCommand } from 'citty';
|
|
4
4
|
import pc from 'picocolors';
|
|
5
|
-
import {
|
|
5
|
+
import type { AppSkillsConfig } from '../config.ts';
|
|
6
6
|
import { missingBoardTasks } from '../io/board.ts';
|
|
7
|
-
import {
|
|
7
|
+
import type { Registry } from '../io/registry.ts';
|
|
8
8
|
import { readState } from '../io/state.ts';
|
|
9
|
-
import { installedRuntimeHelperSpecifier } from '../runtime-package.ts';
|
|
10
9
|
|
|
11
10
|
type CheckOutput = Pick<Console, 'log' | 'error'>;
|
|
12
11
|
|
|
@@ -14,7 +13,6 @@ export type DriftReport = {
|
|
|
14
13
|
missingFiles: string[];
|
|
15
14
|
missingEnv: string[];
|
|
16
15
|
missingTasks: string[];
|
|
17
|
-
missingHelpers: string[];
|
|
18
16
|
};
|
|
19
17
|
|
|
20
18
|
export type CheckOptions = {
|
|
@@ -56,13 +54,9 @@ async function readEnvLocal(projectRoot: string): Promise<string> {
|
|
|
56
54
|
export async function runCheck(
|
|
57
55
|
projectRoot = process.cwd(),
|
|
58
56
|
output: CheckOutput = console,
|
|
59
|
-
|
|
57
|
+
_options: CheckOptions = {},
|
|
60
58
|
): Promise<DriftReport> {
|
|
61
|
-
const
|
|
62
|
-
options.config ? Promise.resolve(options.config) : readConfig(projectRoot),
|
|
63
|
-
options.registry ? Promise.resolve(options.registry) : readRegistry(projectRoot),
|
|
64
|
-
readState(projectRoot),
|
|
65
|
-
]);
|
|
59
|
+
const state = await readState(projectRoot);
|
|
66
60
|
const recordedFiles = [
|
|
67
61
|
...new Set(state.installed_packs.flatMap((pack) => pack.files)),
|
|
68
62
|
].sort();
|
|
@@ -79,33 +73,17 @@ export async function runCheck(
|
|
|
79
73
|
const envLocal = await readEnvLocal(projectRoot);
|
|
80
74
|
const missingEnv = recordedEnv.filter((key) => !hasEnvVar(envLocal, key));
|
|
81
75
|
const missingTasks = await missingBoardTasks(projectRoot, recordedTasks);
|
|
82
|
-
const missingHelpers: string[] = [];
|
|
83
|
-
|
|
84
|
-
for (const pack of state.installed_packs) {
|
|
85
|
-
const runtimePackage = registry.packs.get(pack.name)?.manifest.runtime_package;
|
|
86
|
-
if (!runtimePackage) {
|
|
87
|
-
continue;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
if (!(await installedRuntimeHelperSpecifier(projectRoot, runtimePackage))) {
|
|
91
|
-
missingHelpers.push(
|
|
92
|
-
`${pack.name}: helper package ${runtimePackage.package} missing from package.json`,
|
|
93
|
-
);
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
76
|
|
|
97
77
|
if (
|
|
98
78
|
missingFiles.length === 0 &&
|
|
99
79
|
missingEnv.length === 0 &&
|
|
100
|
-
missingTasks.length === 0
|
|
101
|
-
missingHelpers.length === 0
|
|
80
|
+
missingTasks.length === 0
|
|
102
81
|
) {
|
|
103
82
|
output.log(pc.green('OK: spark state matches the project filesystem.'));
|
|
104
83
|
return {
|
|
105
84
|
missingFiles,
|
|
106
85
|
missingEnv,
|
|
107
86
|
missingTasks,
|
|
108
|
-
missingHelpers,
|
|
109
87
|
};
|
|
110
88
|
}
|
|
111
89
|
|
|
@@ -132,18 +110,10 @@ export async function runCheck(
|
|
|
132
110
|
}
|
|
133
111
|
}
|
|
134
112
|
|
|
135
|
-
if (missingHelpers.length > 0) {
|
|
136
|
-
output.error('drift: helper packages');
|
|
137
|
-
for (const helper of missingHelpers) {
|
|
138
|
-
output.error(` ${helper}`);
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
|
|
142
113
|
return {
|
|
143
114
|
missingFiles,
|
|
144
115
|
missingEnv,
|
|
145
116
|
missingTasks,
|
|
146
|
-
missingHelpers,
|
|
147
117
|
};
|
|
148
118
|
}
|
|
149
119
|
|
|
@@ -157,8 +127,7 @@ export const checkCommand = defineCommand({
|
|
|
157
127
|
if (
|
|
158
128
|
report.missingFiles.length > 0 ||
|
|
159
129
|
report.missingEnv.length > 0 ||
|
|
160
|
-
report.missingTasks.length > 0
|
|
161
|
-
report.missingHelpers.length > 0
|
|
130
|
+
report.missingTasks.length > 0
|
|
162
131
|
) {
|
|
163
132
|
process.exitCode = 1;
|
|
164
133
|
}
|
package/src/commands/info.ts
CHANGED
|
@@ -3,7 +3,6 @@ import pc from 'picocolors';
|
|
|
3
3
|
import { readConfig, type AppSkillsConfig } from '../config.ts';
|
|
4
4
|
import { readRegistry, type Registry } from '../io/registry.ts';
|
|
5
5
|
import { installedPackNames, readState } from '../io/state.ts';
|
|
6
|
-
import { formatResolvedRuntimeHelper } from '../runtime-package.ts';
|
|
7
6
|
|
|
8
7
|
type InfoOutput = Pick<Console, 'log'>;
|
|
9
8
|
|
|
@@ -50,13 +49,7 @@ export async function runInfo(
|
|
|
50
49
|
output.log(pc.bold(`${manifest.name}@${manifest.version}`));
|
|
51
50
|
output.log(manifest.description ?? '');
|
|
52
51
|
output.log(`status: ${installed ? 'installed' : 'available'}`);
|
|
53
|
-
output.log(
|
|
54
|
-
if (manifest.runtime_package) {
|
|
55
|
-
const resolved = await formatResolvedRuntimeHelper(projectRoot, manifest.runtime_package);
|
|
56
|
-
output.log(
|
|
57
|
-
`Runtime helper: ${manifest.runtime_package.package} (range ${manifest.runtime_package.version}, resolved ${resolved})`,
|
|
58
|
-
);
|
|
59
|
-
}
|
|
52
|
+
output.log('Install mode: copy');
|
|
60
53
|
output.log(`category: ${manifest.category}`);
|
|
61
54
|
output.log(`provides: ${formatList(manifest.provides)}`);
|
|
62
55
|
output.log(`requires: ${formatList(manifest.requires)}`);
|