hologit 0.47.5 → 0.48.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.
@@ -0,0 +1,18 @@
1
+ {
2
+ "name": "hologit",
3
+ "owner": {
4
+ "name": "Jarvus Innovations",
5
+ "email": "hello@jarv.us"
6
+ },
7
+ "metadata": {
8
+ "description": "Skills for working with hologit"
9
+ },
10
+ "plugins": [
11
+ {
12
+ "name": "hologit",
13
+ "source": "./",
14
+ "description": "Hologit configuration and CLI assistance",
15
+ "skills": ["./skills/hologit"]
16
+ }
17
+ ]
18
+ }
@@ -0,0 +1,11 @@
1
+ {
2
+ "name": "hologit",
3
+ "description": "Skills for configuring and using hologit",
4
+ "version": "1.0.0",
5
+ "author": {
6
+ "name": "Jarvus Innovations",
7
+ "email": "hello@jarv.us"
8
+ },
9
+ "repository": "https://github.com/JarvusInnovations/hologit",
10
+ "license": "MIT"
11
+ }
package/README.md CHANGED
@@ -60,19 +60,19 @@ Lenses are configured in `.holo/lenses/` and can be chained together to form com
60
60
  git holo init
61
61
  ```
62
62
 
63
- 2. Create a holobranch:
63
+ 1. Create a holobranch:
64
64
 
65
65
  ```bash
66
66
  git holo branch create my-branch
67
67
  ```
68
68
 
69
- 3. Add a source:
69
+ 1. Add a source:
70
70
 
71
71
  ```bash
72
72
  git holo source create https://github.com/example/repo
73
73
  ```
74
74
 
75
- 4. Project your holobranch:
75
+ 1. Project your holobranch:
76
76
 
77
77
  ```bash
78
78
  git holo project my-branch
@@ -97,6 +97,17 @@ See the [Installation Guide](docs/grand-tour/installation.md) and [Grand Tour](d
97
97
  - **Deployment**: Prepare deployment artifacts with consistent transformations
98
98
  - **Code Generation**: Automate code generation and transformation workflows
99
99
 
100
+ ## Claude Code Plugin
101
+
102
+ Hologit includes a [Claude Code](https://docs.anthropic.com/en/docs/claude-code) plugin that gives Claude deep knowledge of hologit's configuration system, CLI, stock lenses, and workflows.
103
+
104
+ ```bash
105
+ /plugin marketplace add JarvusInnovations/hologit
106
+ /plugin install hologit@hologit
107
+ ```
108
+
109
+ Once installed, Claude can help you configure `.holo/` files, set up sources and mappings, choose and configure stock lenses, and debug projection issues.
110
+
100
111
  ## Documentation
101
112
 
102
113
  - [Installation Guide](docs/grand-tour/installation.md)
@@ -0,0 +1,162 @@
1
+ exports.command = 'inspect [holobranch]';
2
+ exports.desc = 'Display the fully resolved hologit configuration';
3
+
4
+ exports.builder = {
5
+ 'holobranch': {
6
+ describe: 'Name of a specific holobranch to inspect'
7
+ },
8
+ 'ref': {
9
+ describe: 'Commit ref to read configuration from',
10
+ default: 'HEAD'
11
+ },
12
+ 'working': {
13
+ describe: 'Use the (possibly uncommitted) contents of the working tree',
14
+ type: 'boolean',
15
+ default: false
16
+ }
17
+ };
18
+
19
+ exports.handler = async function inspect ({
20
+ holobranch,
21
+ ref = 'HEAD',
22
+ working = false
23
+ }) {
24
+ const { Repo } = require('../lib');
25
+
26
+ const repo = await Repo.getFromEnvironment({ ref, working });
27
+ const workspace = await repo.getWorkspace();
28
+ const { name: workspaceName } = await workspace.getCachedConfig();
29
+
30
+ if (holobranch) {
31
+ const branch = workspace.getBranch(holobranch);
32
+ if (!await branch.isDefined()) {
33
+ throw new Error(`holobranch not defined: ${holobranch}`);
34
+ }
35
+ await printBranch(workspace, workspaceName, branch, '');
36
+ } else {
37
+ await printWorkspace(workspace, workspaceName);
38
+ }
39
+ };
40
+
41
+
42
+ async function printWorkspace (workspace, workspaceName) {
43
+ console.log(`Workspace: ${workspaceName}`);
44
+
45
+ // sources
46
+ const sources = await workspace.getSources();
47
+ if (sources.size) {
48
+ console.log('\nSources:');
49
+ for (const [name, source] of sources) {
50
+ await printSource(source, ' ');
51
+ }
52
+ }
53
+
54
+ // branches
55
+ const branches = await workspace.getBranches();
56
+ if (branches.size) {
57
+ console.log('\nBranches:');
58
+ for (const [name, branch] of branches) {
59
+ if (await branch.isDefined()) {
60
+ console.log('');
61
+ await printBranch(workspace, workspaceName, branch, ' ');
62
+ }
63
+ }
64
+ }
65
+ }
66
+
67
+
68
+ async function printBranch (workspace, workspaceName, branch, indent) {
69
+ const config = await branch.getCachedConfig();
70
+ const label = config.extend
71
+ ? `${branch.name} (extends: ${config.extend})`
72
+ : branch.name;
73
+ console.log(`${indent}${label}`);
74
+
75
+ // mappings
76
+ const mappings = await branch.getMappings();
77
+ if (mappings.size) {
78
+ console.log(`${indent} Mappings (${mappings.size}):`);
79
+ for (const [key, mapping] of mappings) {
80
+ await printMapping(workspace, workspaceName, mapping, `${indent} `);
81
+ }
82
+ }
83
+
84
+ // lenses
85
+ const lenses = await branch.getLenses();
86
+ if (lenses.size) {
87
+ console.log(`${indent} Lenses (${lenses.size}):`);
88
+ for (const [name, lens] of lenses) {
89
+ await printLens(lens, `${indent} `);
90
+ }
91
+ }
92
+ }
93
+
94
+
95
+ async function printMapping (workspace, workspaceName, mapping, indent) {
96
+ const config = await mapping.getCachedConfig();
97
+
98
+ const isWorkspace = config.holosource === workspaceName;
99
+ const sourceLabel = isWorkspace
100
+ ? `${config.holosource} (workspace)`
101
+ : config.holosource;
102
+
103
+ console.log(`${indent}${mapping.key}`);
104
+ console.log(`${indent} source: ${sourceLabel}`);
105
+ console.log(`${indent} files: ${config.files.join(', ')}`);
106
+ console.log(`${indent} root: ${config.root}`);
107
+ console.log(`${indent} output: ${config.output}`);
108
+ console.log(`${indent} layer: ${config.layer}`);
109
+
110
+ if (config.after) {
111
+ console.log(`${indent} after: ${config.after.join(', ')}`);
112
+ }
113
+ if (config.before) {
114
+ console.log(`${indent} before: ${config.before.join(', ')}`);
115
+ }
116
+ }
117
+
118
+
119
+ async function printLens (lens, indent) {
120
+ const config = await lens.getCachedConfig();
121
+
122
+ console.log(`${indent}${lens.name}`);
123
+
124
+ if (config.container) {
125
+ console.log(`${indent} container: ${config.container}`);
126
+ } else if (config.package) {
127
+ console.log(`${indent} package: ${config.package}`);
128
+ }
129
+
130
+ const inputRoot = config.input.root === '.' ? '.' : config.input.root;
131
+ const inputFiles = config.input.files.join(', ');
132
+ console.log(`${indent} input: ${inputRoot}/{${inputFiles}}`);
133
+
134
+ const outputRoot = config.output.root === '.' ? '.' : config.output.root;
135
+ console.log(`${indent} output: ${outputRoot}/ (${config.output.merge})`);
136
+
137
+ if (config.after) {
138
+ console.log(`${indent} after: ${config.after.join(', ')}`);
139
+ }
140
+ if (config.before) {
141
+ console.log(`${indent} before: ${config.before.join(', ')}`);
142
+ }
143
+ }
144
+
145
+
146
+ async function printSource (source, indent) {
147
+ const config = await source.getCachedConfig();
148
+
149
+ if (config.$workspace) {
150
+ console.log(`${indent}${source.name} (workspace)`);
151
+ } else {
152
+ const ref = config.ref || '';
153
+ const url = config.url || '';
154
+ console.log(`${indent}${source.name}`);
155
+ console.log(`${indent} url: ${url}`);
156
+ console.log(`${indent} ref: ${ref}`);
157
+
158
+ if (config.project && config.project.holobranch) {
159
+ console.log(`${indent} project: ${config.project.holobranch}`);
160
+ }
161
+ }
162
+ }
package/lib/Workspace.js CHANGED
@@ -107,24 +107,30 @@ class Workspace extends Configurable {
107
107
  const children = tree ? await tree.getChildren() : {};
108
108
 
109
109
 
110
- // build unsorted map
110
+ // build unsorted map via recursive discovery
111
111
  const childNameRe = /^([^\/]+)\.toml$/;
112
112
  const map = new Map();
113
- for (const childName in children) {
114
- let name;
115
113
 
116
- // process trees or files ending in .toml
114
+ for (const childName in children) {
117
115
  if (children[childName].isTree) {
118
- name = childName;
116
+ // skip .lenses directories (e.g. "docs-site.lenses")
117
+ if (childName.endsWith('.lenses')) {
118
+ continue;
119
+ }
120
+
121
+ // peek inside: if directory contains .toml files it defines
122
+ // a branch's mappings; otherwise it's a namespace — recurse
123
+ await this._discoverBranches(
124
+ children[childName], childName, childNameRe, map
125
+ );
119
126
  } else {
120
127
  const nameMatches = childName.match(childNameRe);
121
128
  if (!nameMatches) {
122
129
  continue;
123
130
  }
124
- [,name] = nameMatches;
131
+ const [,name] = nameMatches;
132
+ map.set(name, this.getBranch(name));
125
133
  }
126
-
127
- map.set(name, this.getBranch(name));
128
134
  }
129
135
 
130
136
 
@@ -133,6 +139,35 @@ class Workspace extends Configurable {
133
139
  return map;
134
140
  }
135
141
 
142
+ async _discoverBranches (tree, prefix, childNameRe, map) {
143
+ const treeChildren = await tree.getChildren();
144
+
145
+ // check if this directory contains any .toml files directly
146
+ let hasTomlFiles = false;
147
+ for (const name in treeChildren) {
148
+ if (!treeChildren[name].isTree && childNameRe.test(name)) {
149
+ hasTomlFiles = true;
150
+ break;
151
+ }
152
+ }
153
+
154
+ if (hasTomlFiles) {
155
+ // directory contains mappings — it defines a branch
156
+ map.set(prefix, this.getBranch(prefix));
157
+ } else {
158
+ // no .toml files — it's a namespace, recurse into subdirectories
159
+ for (const name in treeChildren) {
160
+ if (!treeChildren[name].isTree || name.endsWith('.lenses')) {
161
+ continue;
162
+ }
163
+
164
+ await this._discoverBranches(
165
+ treeChildren[name], prefix + '/' + name, childNameRe, map
166
+ );
167
+ }
168
+ }
169
+ }
170
+
136
171
  getSource (name) {
137
172
  let cache = sourceCache.get(this);
138
173
  const cachedSource = cache && cache.get(name);
@@ -173,7 +208,7 @@ class Workspace extends Configurable {
173
208
 
174
209
  // read tree
175
210
  const tree = await this.root.getSubtree(`.holo/sources`);
176
- const children = await tree.getChildren();
211
+ const children = tree ? await tree.getChildren() : {};
177
212
 
178
213
 
179
214
  // build unsorted map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hologit",
3
- "version": "0.47.5",
3
+ "version": "0.48.1",
4
4
  "description": "Hologit automates the projection of layered composite file trees based on flat, declarative plans",
5
5
  "repository": "https://github.com/JarvusInnovations/hologit",
6
6
  "main": "lib/index.js",
@@ -11,14 +11,14 @@
11
11
  "dependencies": {
12
12
  "@iarna/toml": "^2.2.5",
13
13
  "async-exit-hook": "^2.0.1",
14
- "axios": "^1.13.2",
14
+ "axios": "^1.13.5",
15
15
  "chokidar": "^5.0.0",
16
16
  "debounce": "^3.0.0",
17
17
  "fb-watchman": "^2.0.2",
18
18
  "git-client": "^1.9.4",
19
19
  "hab-client": "^1.1.3",
20
20
  "handlebars": "^4.7.8",
21
- "minimatch": "^10.1.1",
21
+ "minimatch": "^10.2.2",
22
22
  "mz": "^2.7.0",
23
23
  "mz-modules": "^2.1.0",
24
24
  "object-squish": "^1.1.0",