@cellajs/cli 0.0.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.
- package/README.md +184 -0
- package/dist/config.d.ts +113 -0
- package/dist/config.js +44 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +4216 -0
- package/dist/index.js.map +1 -0
- package/index.js +3 -0
- package/package.json +122 -0
package/README.md
ADDED
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
# @cellajs/cli
|
|
2
|
+
|
|
3
|
+
Keep your Cella-based app in sync with upstream template updates while preserving your
|
|
4
|
+
customizations.
|
|
5
|
+
|
|
6
|
+
## Usage
|
|
7
|
+
|
|
8
|
+
From your monorepo root, run `pnpm cella` for the interactive menu, or call a service directly:
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
pnpm cella analyze
|
|
12
|
+
pnpm cella sync --hard
|
|
13
|
+
pnpm cella audit --check-overrides
|
|
14
|
+
pnpm cella contributions --fork raak --json
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Services
|
|
18
|
+
|
|
19
|
+
| Service | Description |
|
|
20
|
+
|---------|-------------|
|
|
21
|
+
| `analyze` | Dry run to see what would change on sync |
|
|
22
|
+
| `sync` | Merge upstream changes onto a fresh branch and open a squash-merge PR into `main` |
|
|
23
|
+
| `audit` | Check for outdated packages & vulnerabilities |
|
|
24
|
+
| `stats` | Count files by category and workspace package |
|
|
25
|
+
| `forks` * | Run normal sync inside local fork repositories |
|
|
26
|
+
| `contributions` * | Pull and adopt changes from local forks |
|
|
27
|
+
|
|
28
|
+
\* `forks` and `contributions` only appear in the menu when you have `forks` configured in `cella.config.ts`. These are for upstream template developers who maintain multiple downstream forks.
|
|
29
|
+
|
|
30
|
+
## CLI options
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
pnpm cella [service] [options]
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Per-service help: `pnpm cella <service> --help`.
|
|
37
|
+
|
|
38
|
+
| Service | Useful options |
|
|
39
|
+
|---------|----------------|
|
|
40
|
+
| analyze | `--log`, `--list`, `--json`, `--scope <all\|risk\|protected>`, `--diff <path>`, `--open-diff <path>` |
|
|
41
|
+
| sync | `--log`, `--hard`, `--unpinned`, `--track <release\|branch>` |
|
|
42
|
+
| audit | `--list`, `--force`, `--check-overrides` |
|
|
43
|
+
| forks | `--fork <name>`, `--log`, `--hard`, `-V, --verbose` |
|
|
44
|
+
| contributions | `--fork <name>`, `--list`, `--json`, `--diff <path>` |
|
|
45
|
+
| stats | `--coverage`, `-V, --verbose` |
|
|
46
|
+
|
|
47
|
+
| Global flag | Description |
|
|
48
|
+
|-------------|-------------|
|
|
49
|
+
| `-v, --version` | Output the current version |
|
|
50
|
+
| `-h, --help` | Display help message |
|
|
51
|
+
|
|
52
|
+
## Configuration
|
|
53
|
+
|
|
54
|
+
Sync behavior lives in `cella.config.ts` at your monorepo root (a sensible default ships with new
|
|
55
|
+
apps). To deviate files or folders from the template:
|
|
56
|
+
|
|
57
|
+
- **`ignored`** — files completely excluded from sync (existing and new)
|
|
58
|
+
- **`pinned`** — full fork control: existing, modified, or deleted files are preserved
|
|
59
|
+
|
|
60
|
+
## Upstream tracking
|
|
61
|
+
|
|
62
|
+
The sync CLI tracks upstream cella one of two ways, set via `settings.upstreamTrack`:
|
|
63
|
+
|
|
64
|
+
| Mode | Behavior | For |
|
|
65
|
+
|------|----------|-----|
|
|
66
|
+
| `release` (default) | Sync to a last cella release tag. Stable and reviewable — each bump maps to a changelog. | Most forks |
|
|
67
|
+
| `branch` | Follow the bleeding-edge tip of `settings.upstreamBranch`. | cella maintainers, active development |
|
|
68
|
+
|
|
69
|
+
For a one-off run that ignores the configured mode, pass `--track`:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
pnpm cella sync --track branch # follow the tip once, without editing config
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Sync workflow
|
|
76
|
+
|
|
77
|
+
`pnpm cella sync` never commits to `main` directly.
|
|
78
|
+
|
|
79
|
+
```
|
|
80
|
+
main ──▶ cella/sync/<stamp> ──(3-way merge)──▶ PR ──(squash)──▶ main
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
It runs a real git 3-way merge and leaves the result **staged** — it never auto-commits on the
|
|
84
|
+
first pass. `sync` is **idempotent and two-phase**:
|
|
85
|
+
|
|
86
|
+
1. **First run** cuts the branch and stages the merge, then stops so you can review (and resolve
|
|
87
|
+
any conflicts in your IDE — `git add` the resolved files).
|
|
88
|
+
2. **Re-run `pnpm cella sync`** on the same branch to finish: it reconciles dependencies
|
|
89
|
+
(`pnpm install` + `pnpm check`), stages everything, commits the delta, pushes to `origin`,
|
|
90
|
+
opens a PR into `main` (via `gh`), and switches you back to `main`.
|
|
91
|
+
|
|
92
|
+
When you commit, the in-progress merge state (`MERGE_HEAD`) is discarded, so the staged delta
|
|
93
|
+
collapses into a **single-parent commit** (`chore: sync upstream cella <sha>`). This keeps the PR
|
|
94
|
+
to one clean commit with the incremental diff — a two-parent merge commit would instead list the
|
|
95
|
+
upstream branch's entire history, because the fork doesn't share pushed ancestry with upstream
|
|
96
|
+
and the local `git replace` graft that makes merges incremental is never pushed. Ancestry lives
|
|
97
|
+
in `refs/cella/last-sync` (and the committed `cella.manifest.json` for fresh clones), so
|
|
98
|
+
`git merge-base` keeps working across throwaway branches — each is safe to delete once its PR
|
|
99
|
+
lands. The three-segment name can't collide with git's ref namespacing.
|
|
100
|
+
|
|
101
|
+
If conflicts remain when you re-run, `sync` lists them and stops (never starting a second cycle
|
|
102
|
+
mid-merge). If `pnpm check`, the push, or `gh` fails, it degrades gracefully — reporting the
|
|
103
|
+
issue and printing the remaining manual steps:
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
git push -u origin cella/sync/<stamp>
|
|
107
|
+
gh pr create --base main --head cella/sync/<stamp> --fill
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Sync rules
|
|
111
|
+
|
|
112
|
+
For each file, `sync` compares fork and upstream **content** (blob comparison) and resolves it
|
|
113
|
+
per the table below. Unconfigured files converge on upstream; `ignored` and `pinned` let you opt
|
|
114
|
+
out:
|
|
115
|
+
|
|
116
|
+
| Scenario | `ignored` | `pinned` | Default |
|
|
117
|
+
|----------|:---------:|:--------:|:-------:|
|
|
118
|
+
| Content identical | ✅ Keep | ✅ Keep | ✅ Keep |
|
|
119
|
+
| Content differs | ⏭️ Skip | ✅ Keep yours | ⬇️ Take upstream |
|
|
120
|
+
| New upstream file | ⏭️ Skip | ✅ Keep (respect deletion) | ➕ Add file |
|
|
121
|
+
| Deleted in upstream | ✅ Keep | ✅ Keep | 🗑️ Delete |
|
|
122
|
+
| Only in your app | ✅ Keep | ✅ Keep | ✅ Keep |
|
|
123
|
+
|
|
124
|
+
**Choosing an override:** `ignored` = file never syncs and is fully hidden (app-specific docs,
|
|
125
|
+
assets, config you own). `pinned` = your version always wins but stays visible (files you
|
|
126
|
+
customize). Unconfigured = syncs automatically. Run `pnpm cella analyze` first to preview.
|
|
127
|
+
|
|
128
|
+
### Aggressive sync flags
|
|
129
|
+
|
|
130
|
+
Two opt-in flags make `sync` more aggressive. Both resurface full upstream history (natural merge-base, not the last-sync point), so expect a larger diff and a post-run warning — cherry-pick deliberately. They compose (`--hard --unpinned`).
|
|
131
|
+
|
|
132
|
+
| Flag | Effect |
|
|
133
|
+
|------|--------|
|
|
134
|
+
| `--hard` | Overwrites `drifted` files with upstream (local-only changes are replaced) |
|
|
135
|
+
| `--unpinned` | Ignores `pinned` files so upstream surfaces as `behind`/`diverged`; managed files stay pinned |
|
|
136
|
+
|
|
137
|
+
## Status indicators
|
|
138
|
+
|
|
139
|
+
During analysis and sync, files are displayed with status indicators:
|
|
140
|
+
|
|
141
|
+
| Symbol | Label | Meaning | Action |
|
|
142
|
+
|:------:|-------|---------|--------|
|
|
143
|
+
| ◇ | `managed` | Package/config file changed | Handled separately by cella |
|
|
144
|
+
| ⨂ | `ignored` | Protected by ignored config | Excluded from sync |
|
|
145
|
+
| ✓ | `identical` | Fork matches upstream | No action needed |
|
|
146
|
+
| ↑ | `ahead` | Fork changed (pinned) | Protected, keeping fork |
|
|
147
|
+
| ! | `drifted` | Fork changed, not protected | At risk, consider pinning |
|
|
148
|
+
| ↓ | `behind` | Upstream has changes | Will sync from upstream |
|
|
149
|
+
| ⇅ | `diverged` | Both sides changed | Will merge from upstream |
|
|
150
|
+
| ⨀ | `pinned` | Both changed, fork wins | Protected, keeping fork |
|
|
151
|
+
| + | `local` | Only in fork, never in upstream | No action needed |
|
|
152
|
+
|
|
153
|
+
## Package.json sync
|
|
154
|
+
|
|
155
|
+
`packageJsonSync` controls which package.json sections sync from upstream:
|
|
156
|
+
|
|
157
|
+
```typescript
|
|
158
|
+
packageJsonSync: ['dependencies', 'devDependencies', 'scripts']
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
**Supported keys:** `dependencies`, `devDependencies`, `peerDependencies`, `optionalDependencies`, `scripts`, `engines`, `packageManager`, `overrides`
|
|
162
|
+
|
|
163
|
+
It **adds** new keys and **updates** existing ones to match upstream, but never **removes** keys
|
|
164
|
+
that only exist in your fork — so extra dependencies and scripts survive each sync.
|
|
165
|
+
|
|
166
|
+
## Contributions (pull from forks)
|
|
167
|
+
|
|
168
|
+
Upstream can pull modifications from local forks and selectively adopt them.
|
|
169
|
+
|
|
170
|
+
### Configuration
|
|
171
|
+
|
|
172
|
+
List your local forks in `cella.config.ts`:
|
|
173
|
+
|
|
174
|
+
```typescript
|
|
175
|
+
forks: [
|
|
176
|
+
{ name: 'raak', localPath: '../raak', pullBranch: 'main' },
|
|
177
|
+
],
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### Pulling contributions
|
|
181
|
+
|
|
182
|
+
Run `pnpm cella contributions` (or pick **contributions** from the menu). Select one or more
|
|
183
|
+
forks; cella fetches each fork's `pullBranch`, builds a clean local `contrib/<fork>` branch with
|
|
184
|
+
only that fork's contributed files. Accepted files are checked out from the contrib branch and staged for review.
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sync CLI v2 - Configuration Types
|
|
3
|
+
*
|
|
4
|
+
* Simplified configuration for worktree-based merge approach.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/** Valid package.json keys that can be synced */
|
|
8
|
+
type PackageJsonSyncKey = 'dependencies' | 'devDependencies' | 'peerDependencies' | 'optionalDependencies' | 'scripts' | 'engines' | 'packageManager' | 'overrides' | 'pnpm';
|
|
9
|
+
/**
|
|
10
|
+
* Sync settings - all configurable options for the sync CLI.
|
|
11
|
+
* Hover over each property for documentation.
|
|
12
|
+
*/
|
|
13
|
+
interface SyncSettings {
|
|
14
|
+
/** Upstream repository URL (e.g., 'git@github.com:cellajs/cella.git') */
|
|
15
|
+
upstreamUrl: string;
|
|
16
|
+
/**
|
|
17
|
+
* Upstream branch, used for `upstreamTrack: 'branch'` and for GitHub file links.
|
|
18
|
+
* Defaults to 'main'.
|
|
19
|
+
*/
|
|
20
|
+
upstreamBranch?: string;
|
|
21
|
+
/**
|
|
22
|
+
* How to track upstream cella. Defaults to 'release'.
|
|
23
|
+
* - 'release' (default): sync to a published cella release tag (`v*`). Stable and
|
|
24
|
+
* reviewable — each bump maps to a changelog. Uses the latest release.
|
|
25
|
+
* - 'branch': follow the bleeding-edge tip of `upstreamBranch`. For cella
|
|
26
|
+
* maintainers and forks doing active development on top of unreleased changes.
|
|
27
|
+
*/
|
|
28
|
+
upstreamTrack?: 'release' | 'branch';
|
|
29
|
+
/**
|
|
30
|
+
* Trunk branch that `pnpm cella sync` cuts the temporary branch from and that you open the
|
|
31
|
+
* squash-merge PR into. Defaults to 'main'. Cutting fresh from trunk each cycle keeps every
|
|
32
|
+
* PR limited to that cycle's upstream delta (no accumulation) and `main` linear.
|
|
33
|
+
*/
|
|
34
|
+
releaseBase?: string;
|
|
35
|
+
/** Which package.json keys to sync (default: ['dependencies', 'devDependencies']) */
|
|
36
|
+
packageJsonSync?: PackageJsonSyncKey[];
|
|
37
|
+
/**
|
|
38
|
+
* Automatically run packages sync after the sync service completes.
|
|
39
|
+
* When true (default), the packages service is hidden from the menu
|
|
40
|
+
* and runs automatically as part of sync.
|
|
41
|
+
* Set to false to keep packages as a separate manual service.
|
|
42
|
+
*/
|
|
43
|
+
syncWithPackages?: boolean;
|
|
44
|
+
/**
|
|
45
|
+
* How to link files in CLI output.
|
|
46
|
+
* - 'commit' (default): Link to the commit that changed the file on GitHub.
|
|
47
|
+
* - 'file': Link to the file in the repo at the upstream branch on GitHub.
|
|
48
|
+
* - 'local': Open the upstream file in VS Code from the auto-managed upstream view worktree.
|
|
49
|
+
*/
|
|
50
|
+
fileLinkMode?: 'commit' | 'file' | 'local';
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Configuration for a downstream fork repository that cella interacts with.
|
|
54
|
+
*
|
|
55
|
+
* Cella is the upstream/source-of-truth. For each fork it can:
|
|
56
|
+
* - pull contributions FROM the fork's `pullBranch` (contributions service)
|
|
57
|
+
* - run the normal temporary-branch sync flow inside the fork (forks service)
|
|
58
|
+
*/
|
|
59
|
+
interface ForkConfig {
|
|
60
|
+
/** Display name for the fork (also used as the contrib/<name> branch slug) */
|
|
61
|
+
name: string;
|
|
62
|
+
/** Local path to the fork repository (relative to this config or absolute) */
|
|
63
|
+
localPath: string;
|
|
64
|
+
/**
|
|
65
|
+
* Git remote URL of the fork (e.g. 'git@github.com:org/fork.git').
|
|
66
|
+
* When set, the contributions service fetches the fork's `pullBranch` from this
|
|
67
|
+
* remote (the authoritative committed ref) instead of the local clone, so the
|
|
68
|
+
* comparison no longer depends on the local checkout being up to date. The local
|
|
69
|
+
* clone is still used to read the fork's owned-folder territory when available.
|
|
70
|
+
*/
|
|
71
|
+
remoteUrl?: string;
|
|
72
|
+
/** Fork branch that cella pulls contributions from (contributions service) */
|
|
73
|
+
pullBranch: string;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* User-configurable sync options for cella.config.ts.
|
|
77
|
+
* Simplified for v2 - no long-lived sync branch or squash options.
|
|
78
|
+
*/
|
|
79
|
+
interface CellaCliConfig {
|
|
80
|
+
/** Core sync settings */
|
|
81
|
+
settings: SyncSettings;
|
|
82
|
+
/**
|
|
83
|
+
* File overrides for controlling sync behavior per folder/file.
|
|
84
|
+
*/
|
|
85
|
+
overrides?: {
|
|
86
|
+
/**
|
|
87
|
+
* Paths the fork fully owns — never synced (existing or new).
|
|
88
|
+
* Exact paths or directory prefixes, not globs: 'bench' matches 'bench/' and
|
|
89
|
+
* everything under it, 'README.md' matches that exact file.
|
|
90
|
+
* Local territory: upstream cannot add, modify, or delete anything under these.
|
|
91
|
+
*/
|
|
92
|
+
ignored?: string[];
|
|
93
|
+
/**
|
|
94
|
+
* Paths pinned to fork — fork wins on conflicts.
|
|
95
|
+
* Exact paths or directory prefixes, not globs: 'bench' matches 'bench/' and
|
|
96
|
+
* everything under it, 'README.md' matches that exact file.
|
|
97
|
+
* Non-conflicting upstream changes merge normally.
|
|
98
|
+
* If fork deleted a pinned file, deletion is respected.
|
|
99
|
+
*/
|
|
100
|
+
pinned?: string[];
|
|
101
|
+
};
|
|
102
|
+
/**
|
|
103
|
+
* Downstream fork repositories that cella interacts with (for upstream template repos).
|
|
104
|
+
* When configured, the 'forks' and 'contributions' services appear in the CLI menu.
|
|
105
|
+
*/
|
|
106
|
+
forks?: ForkConfig[];
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Helper function for defining cella.config.ts with type checking.
|
|
110
|
+
*/
|
|
111
|
+
declare function defineConfig(config: CellaCliConfig): CellaCliConfig;
|
|
112
|
+
|
|
113
|
+
export { type CellaCliConfig, type PackageJsonSyncKey, defineConfig };
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
// src/config/types.ts
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
function defineConfig(config) {
|
|
4
|
+
return config;
|
|
5
|
+
}
|
|
6
|
+
var cellaConfigSchema = z.object({
|
|
7
|
+
settings: z.object({
|
|
8
|
+
upstreamUrl: z.string().min(1),
|
|
9
|
+
upstreamBranch: z.string().min(1).optional(),
|
|
10
|
+
upstreamTrack: z.enum(["release", "branch"]).optional(),
|
|
11
|
+
releaseBase: z.string().min(1).optional(),
|
|
12
|
+
packageJsonSync: z.array(
|
|
13
|
+
z.enum([
|
|
14
|
+
"dependencies",
|
|
15
|
+
"devDependencies",
|
|
16
|
+
"peerDependencies",
|
|
17
|
+
"optionalDependencies",
|
|
18
|
+
"scripts",
|
|
19
|
+
"engines",
|
|
20
|
+
"packageManager",
|
|
21
|
+
"overrides",
|
|
22
|
+
"pnpm"
|
|
23
|
+
])
|
|
24
|
+
).optional(),
|
|
25
|
+
syncWithPackages: z.boolean().optional(),
|
|
26
|
+
fileLinkMode: z.enum(["commit", "file", "local"]).optional()
|
|
27
|
+
}).strict(),
|
|
28
|
+
overrides: z.object({
|
|
29
|
+
ignored: z.array(z.string()).optional(),
|
|
30
|
+
pinned: z.array(z.string()).optional()
|
|
31
|
+
}).strict().optional(),
|
|
32
|
+
forks: z.array(
|
|
33
|
+
z.object({
|
|
34
|
+
name: z.string().min(1),
|
|
35
|
+
localPath: z.string().min(1),
|
|
36
|
+
remoteUrl: z.string().optional(),
|
|
37
|
+
pullBranch: z.string().min(1)
|
|
38
|
+
}).strict()
|
|
39
|
+
).optional()
|
|
40
|
+
}).strict();
|
|
41
|
+
export {
|
|
42
|
+
defineConfig
|
|
43
|
+
};
|
|
44
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/config/types.ts"],"sourcesContent":["/**\n * Sync CLI v2 - Configuration Types\n *\n * Simplified configuration for worktree-based merge approach.\n */\n\nimport { z } from 'zod';\n\n// ─────────────────────────────────────────────────────────────────────────────\n// PUBLIC API - for cella.config.ts\n// ─────────────────────────────────────────────────────────────────────────────\n\n/** Valid package.json keys that can be synced */\nexport type PackageJsonSyncKey =\n | 'dependencies'\n | 'devDependencies'\n | 'peerDependencies'\n | 'optionalDependencies'\n | 'scripts'\n | 'engines'\n | 'packageManager'\n | 'overrides'\n | 'pnpm';\n\n/**\n * Sync settings - all configurable options for the sync CLI.\n * Hover over each property for documentation.\n */\nexport interface SyncSettings {\n /** Upstream repository URL (e.g., 'git@github.com:cellajs/cella.git') */\n upstreamUrl: string;\n\n /**\n * Upstream branch, used for `upstreamTrack: 'branch'` and for GitHub file links.\n * Defaults to 'main'.\n */\n upstreamBranch?: string;\n\n /**\n * How to track upstream cella. Defaults to 'release'.\n * - 'release' (default): sync to a published cella release tag (`v*`). Stable and\n * reviewable — each bump maps to a changelog. Uses the latest release.\n * - 'branch': follow the bleeding-edge tip of `upstreamBranch`. For cella\n * maintainers and forks doing active development on top of unreleased changes.\n */\n upstreamTrack?: 'release' | 'branch';\n\n /**\n * Trunk branch that `pnpm cella sync` cuts the temporary branch from and that you open the\n * squash-merge PR into. Defaults to 'main'. Cutting fresh from trunk each cycle keeps every\n * PR limited to that cycle's upstream delta (no accumulation) and `main` linear.\n */\n releaseBase?: string;\n\n /** Which package.json keys to sync (default: ['dependencies', 'devDependencies']) */\n packageJsonSync?: PackageJsonSyncKey[];\n\n /**\n * Automatically run packages sync after the sync service completes.\n * When true (default), the packages service is hidden from the menu\n * and runs automatically as part of sync.\n * Set to false to keep packages as a separate manual service.\n */\n syncWithPackages?: boolean;\n\n /**\n * How to link files in CLI output.\n * - 'commit' (default): Link to the commit that changed the file on GitHub.\n * - 'file': Link to the file in the repo at the upstream branch on GitHub.\n * - 'local': Open the upstream file in VS Code from the auto-managed upstream view worktree.\n */\n fileLinkMode?: 'commit' | 'file' | 'local';\n}\n\n/**\n * Configuration for a downstream fork repository that cella interacts with.\n *\n * Cella is the upstream/source-of-truth. For each fork it can:\n * - pull contributions FROM the fork's `pullBranch` (contributions service)\n * - run the normal temporary-branch sync flow inside the fork (forks service)\n */\nexport interface ForkConfig {\n /** Display name for the fork (also used as the contrib/<name> branch slug) */\n name: string;\n /** Local path to the fork repository (relative to this config or absolute) */\n localPath: string;\n /**\n * Git remote URL of the fork (e.g. 'git@github.com:org/fork.git').\n * When set, the contributions service fetches the fork's `pullBranch` from this\n * remote (the authoritative committed ref) instead of the local clone, so the\n * comparison no longer depends on the local checkout being up to date. The local\n * clone is still used to read the fork's owned-folder territory when available.\n */\n remoteUrl?: string;\n /** Fork branch that cella pulls contributions from (contributions service) */\n pullBranch: string;\n}\n\n/**\n * User-configurable sync options for cella.config.ts.\n * Simplified for v2 - no long-lived sync branch or squash options.\n */\nexport interface CellaCliConfig {\n /** Core sync settings */\n settings: SyncSettings;\n\n /**\n * File overrides for controlling sync behavior per folder/file.\n */\n overrides?: {\n /**\n * Paths the fork fully owns — never synced (existing or new).\n * Exact paths or directory prefixes, not globs: 'bench' matches 'bench/' and\n * everything under it, 'README.md' matches that exact file.\n * Local territory: upstream cannot add, modify, or delete anything under these.\n */\n ignored?: string[];\n\n /**\n * Paths pinned to fork — fork wins on conflicts.\n * Exact paths or directory prefixes, not globs: 'bench' matches 'bench/' and\n * everything under it, 'README.md' matches that exact file.\n * Non-conflicting upstream changes merge normally.\n * If fork deleted a pinned file, deletion is respected.\n */\n pinned?: string[];\n };\n\n /**\n * Downstream fork repositories that cella interacts with (for upstream template repos).\n * When configured, the 'forks' and 'contributions' services appear in the CLI menu.\n */\n forks?: ForkConfig[];\n}\n\n/**\n * Helper function for defining cella.config.ts with type checking.\n */\nexport function defineConfig(config: CellaCliConfig): CellaCliConfig {\n return config;\n}\n\n/**\n * Strict runtime schema mirroring {@link CellaCliConfig}.\n *\n * The TS interfaces above stay the source of truth (and keep their hover docs for\n * config authors). This schema is what's enforced at load time: `.strict()` rejects\n * unknown keys, so a typo like `ignoredFolders` instead of `ignored` fails closed\n * instead of silently dropping sync protection (tsx does not typecheck the config).\n *\n * The `satisfies z.ZodType<CellaCliConfig>` assertion keeps schema and interface in\n * lockstep: if either drifts (a renamed/removed/mis-typed field), TypeScript errors here.\n */\nexport const cellaConfigSchema = z\n .object({\n settings: z\n .object({\n upstreamUrl: z.string().min(1),\n upstreamBranch: z.string().min(1).optional(),\n upstreamTrack: z.enum(['release', 'branch']).optional(),\n releaseBase: z.string().min(1).optional(),\n packageJsonSync: z\n .array(\n z.enum([\n 'dependencies',\n 'devDependencies',\n 'peerDependencies',\n 'optionalDependencies',\n 'scripts',\n 'engines',\n 'packageManager',\n 'overrides',\n 'pnpm',\n ]),\n )\n .optional(),\n syncWithPackages: z.boolean().optional(),\n fileLinkMode: z.enum(['commit', 'file', 'local']).optional(),\n })\n .strict(),\n overrides: z\n .object({\n ignored: z.array(z.string()).optional(),\n pinned: z.array(z.string()).optional(),\n })\n .strict()\n .optional(),\n forks: z\n .array(\n z\n .object({\n name: z.string().min(1),\n localPath: z.string().min(1),\n remoteUrl: z.string().optional(),\n pullBranch: z.string().min(1),\n })\n .strict(),\n )\n .optional(),\n })\n .strict() satisfies z.ZodType<CellaCliConfig>;\n\n// ─────────────────────────────────────────────────────────────────────────────\n// INTERNAL TYPES - for sync modules\n// ─────────────────────────────────────────────────────────────────────────────\n\n/** Sync services available in the CLI */\nexport type SyncService = 'analyze' | 'sync' | 'audit' | 'forks' | 'contributions' | 'stats';\n\n/** Analyze output scope for interactive and machine-readable flows */\nexport type AnalyzeScope = 'all' | 'risk' | 'protected';\n\n/** Runtime configuration with all resolved values */\nexport interface RuntimeConfig extends CellaCliConfig {\n /** Resolved fork repository path */\n forkPath: string;\n\n /** Full upstream remote ref (e.g., 'cella-upstream/development') */\n upstreamRef: string;\n\n /** Selected sync service */\n service: SyncService;\n\n /** Write full file list to log file */\n logFile: boolean;\n\n /** Non-interactive list output (for LLM/agent usage) */\n list: boolean;\n\n /** Machine-readable JSON output (for tooling/agent usage) */\n json: boolean;\n\n /** Print the unified diff for a single contributed file, then exit (contributions; for tooling/agents) */\n diff?: string;\n\n /** Open a VS Code side-by-side diff for one file, then exit (analyze) */\n openDiff?: string;\n\n /** Scope of files returned in analyze list/json output */\n scope?: AnalyzeScope;\n\n /** Show verbose output */\n verbose: boolean;\n\n /** Pre-selected fork name (skips fork selection prompt) */\n fork?: string;\n\n /** Overwrite drifted files with upstream version (aggressive realignment) */\n hard?: boolean;\n\n /**\n * Disable pinned entries (cella.config.ts overrides.pinned) for this sync so upstream\n * versions surface as behind/diverged. Managed files stay pinned because cella\n * handles them separately. Like --hard, uses the natural merge-base to resurface\n * full upstream history.\n */\n unpinned?: boolean;\n\n /**\n * Override upstream tracking for this run (analyze/sync), ignoring `settings.upstreamTrack`.\n * 'branch' follows the upstream branch tip (bleeding edge); 'release' uses a release tag.\n */\n track?: 'release' | 'branch';\n\n /** Bypass pnpm metadata cache for fresh registry data (audit service) */\n force?: boolean;\n\n /** Check which pnpm.overrides are still needed (audit service) */\n checkOverrides?: boolean;\n\n /** Regenerate test coverage before showing the stats summary (stats service) */\n coverage?: boolean;\n}\n\n/** File status after analysis */\nexport type FileStatus =\n | 'identical' // No changes needed\n | 'ahead' // Fork is ahead, protected (pinned/ignored)\n | 'local' // Local file (never existed upstream)\n | 'drifted' // Fork is ahead, NOT protected (at risk)\n | 'behind' // Upstream has changes to sync\n | 'diverged' // Both changed, will merge\n | 'pinned' // Fork wins on conflict\n | 'ignored' // Excluded from sync entirely\n | 'deleted' // Fork deleted, will stay deleted\n | 'renamed'; // Upstream renamed file\n\n/** Analyzed file with status and metadata */\nexport interface AnalyzedFile {\n path: string;\n status: FileStatus;\n /** True if file is in ignored list */\n isIgnored: boolean;\n /** True if file is in pinned list */\n isPinned: boolean;\n /** True if file exists in fork */\n existsInFork: boolean;\n /** True if file exists in upstream */\n existsInUpstream: boolean;\n /** True if file has merge conflict */\n hasConflict?: boolean;\n /** Relative date when file was last changed (since merge-base) */\n changedAt?: string;\n /** Short commit hash of the last change */\n changedCommit?: string;\n /** For diverged files: relative date of upstream change */\n upstreamChangedAt?: string;\n /** For diverged files: short commit hash of the upstream change */\n upstreamCommit?: string;\n /** For renamed files: the original path before rename */\n renamedFrom?: string;\n}\n\n/** Summary counts by status */\nexport interface AnalysisSummary {\n /** Changed package/config files that are handled separately from normal sync categories */\n managed: number;\n identical: number;\n ahead: number;\n local: number;\n drifted: number;\n behind: number;\n diverged: number;\n pinned: number;\n ignored: number;\n deleted: number;\n renamed: number;\n total: number;\n}\n\n/** Merge result from merge-engine */\nexport interface MergeResult {\n success: boolean;\n /** Upstream branch name for file links */\n upstreamBranch?: string;\n /** Resolved concrete upstream ref that was merged (branch ref or release tag ref) */\n upstreamRef?: string;\n /** Upstream release tag synced (when tracking releases) */\n upstreamTag?: string;\n files: AnalyzedFile[];\n summary: AnalysisSummary;\n conflicts: string[];\n /** Upstream GitHub URL base for commit links */\n upstreamGitHubUrl?: string;\n /** Upstream commit info */\n upstreamCommit?: {\n hash: string;\n message: string;\n date: string;\n };\n /** Commits included in this sync range (oldest-first when rendered) */\n upstreamCommits?: Array<{\n hash: string;\n message: string;\n date: string;\n }>;\n /** Files that were auto-merged by git (diverged without remaining conflicts) */\n autoMergedFiles?: string[];\n}\n"],"mappings":";AAMA,SAAS,SAAS;AAoIX,SAAS,aAAa,QAAwC;AACnE,SAAO;AACT;AAaO,IAAM,oBAAoB,EAC9B,OAAO;AAAA,EACN,UAAU,EACP,OAAO;AAAA,IACN,aAAa,EAAE,OAAO,EAAE,IAAI,CAAC;AAAA,IAC7B,gBAAgB,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA,IAC3C,eAAe,EAAE,KAAK,CAAC,WAAW,QAAQ,CAAC,EAAE,SAAS;AAAA,IACtD,aAAa,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA,IACxC,iBAAiB,EACd;AAAA,MACC,EAAE,KAAK;AAAA,QACL;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC;AAAA,IACH,EACC,SAAS;AAAA,IACZ,kBAAkB,EAAE,QAAQ,EAAE,SAAS;AAAA,IACvC,cAAc,EAAE,KAAK,CAAC,UAAU,QAAQ,OAAO,CAAC,EAAE,SAAS;AAAA,EAC7D,CAAC,EACA,OAAO;AAAA,EACV,WAAW,EACR,OAAO;AAAA,IACN,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS;AAAA,IACtC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS;AAAA,EACvC,CAAC,EACA,OAAO,EACP,SAAS;AAAA,EACZ,OAAO,EACJ;AAAA,IACC,EACG,OAAO;AAAA,MACN,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC;AAAA,MACtB,WAAW,EAAE,OAAO,EAAE,IAAI,CAAC;AAAA,MAC3B,WAAW,EAAE,OAAO,EAAE,SAAS;AAAA,MAC/B,YAAY,EAAE,OAAO,EAAE,IAAI,CAAC;AAAA,IAC9B,CAAC,EACA,OAAO;AAAA,EACZ,EACC,SAAS;AACd,CAAC,EACA,OAAO;","names":[]}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|