Skip to content

Commit a2b69be

Browse files
committed
feat: Added apt, npm login, nvm and pnpm
1 parent 78066a9 commit a2b69be

6 files changed

Lines changed: 175 additions & 5 deletions

File tree

CLAUDE.md

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,69 @@ parameterSettings: {
374374
}
375375
```
376376

377+
### defaultConfig and exampleConfigs
378+
379+
Every resource should have a `defaultConfig` and `exampleConfigs`. These are surfaced in the Codify Editor to help users get started quickly.
380+
381+
**`defaultConfig`** — pre-fills the resource form with sensible starting values:
382+
- Use Syncthing's/asdf's/AWS's own documented defaults where applicable
383+
- For required fields with no sensible default (e.g. `deviceId`, `plugin`, `awsAccessKeyId`), use the placeholder string `'<Replace me here!'>`
384+
- For optional array fields that default to empty (e.g. `plugins`, `aliases`, `paths`), set them to `[]`
385+
- Omit fields that are purely user-specific (e.g. paths, names, credentials) — don't guess
386+
- If the resource declares `operatingSystems: [OS.Darwin]` or `operatingSystems: [OS.Linux]` (i.e. only one OS, not both), do NOT add `os` to `defaultConfig` (it's not on the typed config interface). Instead, add `os: ['darwin']` or `os: ['linux']` only to the config entries inside `exampleConfigs`. Skip entirely when the resource supports both OS.
387+
388+
**`exampleConfigs`** — up to two named examples (`example1`, `example2`):
389+
- `example1`: a minimal, focused single-resource example showing the most common use case
390+
- `example2`: either a more advanced single-resource variant, OR a multi-resource example that shows the full end-to-end setup (e.g. install the tool + configure it)
391+
- Multi-resource examples (configs array with multiple types) are especially useful when the resource `dependsOn` another — show installing the dependency too
392+
- Every example needs a `title` (short, noun-phrase) and a `description` (one sentence explaining what it does and why)
393+
- Use realistic but obviously-placeholder values for sensitive fields (`'<Replace me here!'>`), not real credentials
394+
- Don't add step-numbering ("Step 1 of 3") in descriptions — it doesn't make sense when viewed from a single resource page
395+
- If the resource is OS-specific (only Darwin or only Linux), add `os: ['darwin']` or `os: ['linux']` to each config entry in the example so the editor filters it correctly
396+
397+
**Structure:**
398+
```typescript
399+
import { ExampleConfig } from '@codifycli/plugin-core';
400+
401+
const defaultConfig: Partial<MyConfig> = {
402+
someField: 'sensible-default',
403+
optionalArray: [],
404+
// Add os: ['darwin'] or os: ['linux'] if operatingSystems is not [OS.Darwin, OS.Linux]
405+
}
406+
407+
const exampleBasic: ExampleConfig = {
408+
title: 'Basic my-resource setup',
409+
description: 'One sentence explaining what this example does and who it is for.',
410+
configs: [{
411+
type: 'my-resource',
412+
someField: 'example-value',
413+
// Add os: ['darwin'] or os: ['linux'] if the resource is OS-specific
414+
}]
415+
}
416+
417+
const exampleWithDependency: ExampleConfig = {
418+
title: 'Full my-resource setup',
419+
description: 'Install the prerequisite and configure my-resource in one go.',
420+
configs: [
421+
{ type: 'prerequisite-resource' },
422+
{ type: 'my-resource', someField: 'example-value' },
423+
]
424+
}
425+
426+
// Inside getSettings():
427+
return {
428+
id: 'my-resource',
429+
defaultConfig,
430+
exampleConfigs: {
431+
example1: exampleBasic,
432+
example2: exampleWithDependency,
433+
},
434+
// ...
435+
}
436+
```
437+
438+
**When there is a shared multi-resource example** (e.g. the asdf full-install example used across `asdf`, `asdf-plugin`, and `asdf-install`): define it once in a separate `examples.ts` file in the resource folder and spread it into `exampleConfigs` using `...exampleSharedConfigs`. Use a consistent description across all three rather than per-resource step labels.
439+
377440
### Dependencies
378441

379442
Resources can declare dependencies on other resources:

src/resources/apt/apt.ts

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { CreatePlan, Resource, ResourceSettings, SpawnStatus, getPty } from '@codifycli/plugin-core';
2-
import { OS, ResourceConfig } from '@codifycli/schemas';
1+
import { CreatePlan, ExampleConfig, Resource, ResourceSettings, SpawnStatus, getPty } from '@codifycli/plugin-core';
2+
import { OS, ResourceConfig, ResourceOs } from '@codifycli/schemas';
33

44
import schema from './apt-schema.json';
55
import { AptInstallParameter, AptPackage } from './install-parameter.js';
@@ -9,11 +9,45 @@ export interface AptConfig extends ResourceConfig {
99
update?: boolean;
1010
}
1111

12+
const defaultConfig: Partial<AptConfig> = {
13+
install: [],
14+
os: [ResourceOs.LINUX]
15+
}
16+
17+
const exampleBasic: ExampleConfig = {
18+
title: 'Install apt packages',
19+
description: 'Install a set of common development packages using apt on a Debian-based system.',
20+
configs: [{
21+
type: 'apt',
22+
os: [ResourceOs.LINUX],
23+
install: ['curl', 'git', 'build-essential'],
24+
}]
25+
}
26+
27+
const exampleVersionPinned: ExampleConfig = {
28+
title: 'Install apt packages with pinned versions',
29+
description: 'Install packages using apt, with specific versions pinned for reproducibility.',
30+
configs: [{
31+
type: 'apt',
32+
os: [ResourceOs.LINUX],
33+
install: [
34+
'curl',
35+
{ name: 'nodejs', version: '20.*' },
36+
{ name: 'python3', version: '3.12.*' },
37+
],
38+
}]
39+
}
40+
1241
export class AptResource extends Resource<AptConfig> {
1342

1443
override getSettings(): ResourceSettings<AptConfig> {
1544
return {
1645
id: 'apt',
46+
defaultConfig,
47+
exampleConfigs: {
48+
example1: exampleBasic,
49+
example2: exampleVersionPinned,
50+
},
1751
operatingSystems: [OS.Linux],
1852
schema,
1953
removeStatefulParametersBeforeDestroy: true,

src/resources/javascript/npm/npm-login-schema.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
"properties": {
99
"authToken": {
1010
"type": "string",
11-
"description": "The npm auth token used for authenticating with the registry. If not provided, then web login is assumed"
11+
"description": "The npm auth token used for authenticating with the registry. If not provided, then web login is assumed. Generate one at https://www.npmjs.com/settings/<username>/tokens by creating a 'Classic Token' (Automation or Read/Write). Tokens look like: npm_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
1212
},
1313
"scope": {
1414
"type": "string",

src/resources/javascript/npm/npm-login.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import {
22
CreatePlan,
33
DestroyPlan,
4+
ExampleConfig,
45
getPty,
56
ModifyPlan,
67
ParameterChange,
@@ -21,10 +22,40 @@ export interface NpmLoginConfig extends ResourceConfig {
2122
registry?: string; // Example: "https://registry.npmjs.org/"
2223
}
2324

25+
const defaultConfig: Partial<NpmLoginConfig> = {
26+
registry: 'https://registry.npmjs.org/',
27+
}
28+
29+
const exampleBasicLogin: ExampleConfig = {
30+
title: 'npm registry login',
31+
description: 'Authenticate with the public npm registry using a personal access token stored in ~/.npmrc. Tokens are generated at https://www.npmjs.com/settings/<username>/tokens by creating a Classic Token',
32+
configs: [{
33+
type: 'npm-login',
34+
authToken: '<Replace me here!>',
35+
registry: 'https://registry.npmjs.org/',
36+
}]
37+
}
38+
39+
const exampleScopedLogin: ExampleConfig = {
40+
title: 'Scoped private registry login',
41+
description: 'Authenticate with a private npm registry and bind it to a package scope, so all @myorg/* packages resolve to that registry. Tokens are generated at https://www.npmjs.com/settings/<username>/tokens by creating a Classic Token',
42+
configs: [{
43+
type: 'npm-login',
44+
authToken: '<Replace me here!>',
45+
scope: '@myorg',
46+
registry: 'https://npm.pkg.github.com/',
47+
}]
48+
}
49+
2450
export class NpmLoginResource extends Resource<NpmLoginConfig> {
2551
getSettings(): ResourceSettings<NpmLoginConfig> {
2652
return {
2753
id: 'npm-login',
54+
defaultConfig,
55+
exampleConfigs: {
56+
example1: exampleBasicLogin,
57+
example2: exampleScopedLogin,
58+
},
2859
operatingSystems: [OS.Darwin, OS.Linux],
2960
schema,
3061
isSensitive: true,

src/resources/javascript/nvm/nvm.ts

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { getPty, Resource, ResourceSettings, SpawnStatus } from '@codifycli/plugin-core';
1+
import { ExampleConfig, getPty, Resource, ResourceSettings, SpawnStatus } from '@codifycli/plugin-core';
22
import { OS, ResourceConfig } from '@codifycli/schemas';
33
import * as os from 'node:os';
44

@@ -13,11 +13,40 @@ export interface NvmConfig extends ResourceConfig {
1313
nodeVersions?: string[],
1414
}
1515

16+
const defaultConfig: Partial<NvmConfig> = {
17+
nodeVersions: [],
18+
}
19+
20+
const exampleLts: ExampleConfig = {
21+
title: 'Install Node.js LTS via nvm',
22+
description: 'Install nvm and set the latest LTS release as the global Node.js version.',
23+
configs: [{
24+
type: 'nvm',
25+
nodeVersions: ['lts'],
26+
global: 'lts',
27+
}]
28+
}
29+
30+
const exampleMultiVersion: ExampleConfig = {
31+
title: 'Install multiple Node.js versions via nvm',
32+
description: 'Install nvm with multiple Node.js versions side by side, using Node.js 22 as the global default.',
33+
configs: [{
34+
type: 'nvm',
35+
nodeVersions: ['18', '20', '22'],
36+
global: '22',
37+
}]
38+
}
39+
1640
export class NvmResource extends Resource<NvmConfig> {
1741

1842
getSettings(): ResourceSettings<NvmConfig> {
1943
return {
2044
id: 'nvm',
45+
defaultConfig,
46+
exampleConfigs: {
47+
example1: exampleLts,
48+
example2: exampleMultiVersion,
49+
},
2150
operatingSystems: [OS.Darwin, OS.Linux],
2251
schema: Schema,
2352
parameterSettings: {

src/resources/javascript/pnpm/pnpm.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { CreatePlan, DestroyPlan, RefreshContext, Resource, ResourceSettings, getPty } from '@codifycli/plugin-core';
1+
import { CreatePlan, DestroyPlan, ExampleConfig, RefreshContext, Resource, ResourceSettings, getPty } from '@codifycli/plugin-core';
22
import { OS, ResourceConfig } from '@codifycli/schemas';
33
import fs from 'node:fs/promises';
44
import os from 'node:os';
@@ -14,10 +14,23 @@ export interface PnpmConfig extends ResourceConfig {
1414
globalEnvNodeVersion?: string;
1515
}
1616

17+
const exampleWithNode: ExampleConfig = {
18+
title: 'Install pnpm with a global Node.js version',
19+
description: 'Install a specific version of pnpm and activate a global Node.js version via pnpm env.',
20+
configs: [{
21+
type: 'pnpm',
22+
version: '10',
23+
globalEnvNodeVersion: '22.0.0',
24+
}]
25+
}
26+
1727
export class Pnpm extends Resource<PnpmConfig> {
1828
getSettings(): ResourceSettings<PnpmConfig> {
1929
return {
2030
id: 'pnpm',
31+
exampleConfigs: {
32+
example1: exampleWithNode,
33+
},
2134
operatingSystems: [OS.Darwin, OS.Linux],
2235
schema,
2336
parameterSettings: {

0 commit comments

Comments
 (0)