@r0hitsharma/uikit-cli 0.12.0-rohit-fork-ci.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,218 @@
1
+ import path from 'node:path';
2
+ /**
3
+ * Package and workspace discovery for monorepos
4
+ */
5
+ export class PackageDiscovery {
6
+ fs;
7
+ constructor(fs) {
8
+ this.fs = fs;
9
+ }
10
+ /**
11
+ * Find the consumer root by walking up from `startDir`. Prefers a monorepo
12
+ * root (a `package.json` with a `workspaces` field); if none exists anywhere
13
+ * up the tree, falls back to the nearest single package that depends on an
14
+ * `@r0hitsharma/*` package — so link/unlink work for a plain
15
+ * non-workspaces consumer, not just a monorepo.
16
+ */
17
+ findConsumerRoot(startDir) {
18
+ let current = startDir;
19
+ let singlePackageRoot = null;
20
+ while (true) {
21
+ const pkgPath = path.join(current, 'package.json');
22
+ if (this.fs.exists(pkgPath)) {
23
+ try {
24
+ const pkg = this.fs.readJson(pkgPath);
25
+ // A workspaces root always wins (unchanged monorepo behavior).
26
+ if (pkg.workspaces) {
27
+ return current;
28
+ }
29
+ // Otherwise remember the nearest package that consumes uikit, as a
30
+ // fallback if no workspaces root turns up above it.
31
+ if (singlePackageRoot === null && this.dependsOnUikit(pkg)) {
32
+ singlePackageRoot = current;
33
+ }
34
+ }
35
+ catch {
36
+ // Continue searching if parse fails
37
+ }
38
+ }
39
+ const parent = path.dirname(current);
40
+ if (parent === current) {
41
+ if (singlePackageRoot !== null) {
42
+ return singlePackageRoot;
43
+ }
44
+ throw new Error(`Could not find a consumer root.\n` +
45
+ `Searched from: ${startDir}\n` +
46
+ `Found no package.json with a "workspaces" field, and none depending ` +
47
+ `on an @r0hitsharma/* package.\n` +
48
+ `Run from inside your consumer project (a monorepo root or a single ` +
49
+ `package that installs uikit).`);
50
+ }
51
+ current = parent;
52
+ }
53
+ }
54
+ dependsOnUikit(pkg) {
55
+ const fields = [
56
+ pkg.dependencies,
57
+ pkg.devDependencies,
58
+ pkg.peerDependencies,
59
+ pkg.optionalDependencies,
60
+ ];
61
+ return fields.some((field) => field &&
62
+ Object.keys(field).some((name) => name.startsWith('@r0hitsharma/')));
63
+ }
64
+ /**
65
+ * Find uikit root by walking up looking for valid uikit monorepo structure
66
+ */
67
+ findUIKitRoot(startDir) {
68
+ let current = startDir;
69
+ while (true) {
70
+ if (this.isValidUIKitRoot(current)) {
71
+ return current;
72
+ }
73
+ const parent = path.dirname(current);
74
+ if (parent === current) {
75
+ return null;
76
+ }
77
+ current = parent;
78
+ }
79
+ }
80
+ /**
81
+ * Find uikit root from consumer by looking for sibling "uikit" directory
82
+ */
83
+ findUIKitRootFromConsumer(consumerRoot) {
84
+ const candidateNames = ['uikit'];
85
+ let current = consumerRoot;
86
+ while (true) {
87
+ for (const candidateName of candidateNames) {
88
+ const candidate = path.join(current, candidateName);
89
+ if (this.isValidUIKitRoot(candidate)) {
90
+ return candidate;
91
+ }
92
+ }
93
+ const parent = path.dirname(current);
94
+ if (parent === current) {
95
+ return null;
96
+ }
97
+ current = parent;
98
+ }
99
+ }
100
+ /**
101
+ * Check if directory is a valid uikit root (has design-system package)
102
+ */
103
+ isValidUIKitRoot(rootDir) {
104
+ if (!this.fs.exists(rootDir)) {
105
+ return false;
106
+ }
107
+ try {
108
+ const workspaces = this.loadWorkspaces(rootDir);
109
+ return workspaces.some((ws) => ws.name === '@r0hitsharma/design-system');
110
+ }
111
+ catch {
112
+ return false;
113
+ }
114
+ }
115
+ /**
116
+ * Load all workspaces from a monorepo root
117
+ */
118
+ loadWorkspaces(rootDir) {
119
+ const patterns = this.getWorkspacePatterns(rootDir);
120
+ const workspaces = [];
121
+ if (process.env.UIKIT_DEBUG) {
122
+ console.log('[DEBUG loadWorkspaces] rootDir:', rootDir, 'patterns:', patterns);
123
+ }
124
+ for (const pattern of patterns) {
125
+ const resolved = this.resolveWorkspacePattern(rootDir, pattern);
126
+ if (process.env.UIKIT_DEBUG) {
127
+ console.log('[DEBUG loadWorkspaces] pattern:', pattern, 'resolved to:', resolved);
128
+ }
129
+ for (const dir of resolved) {
130
+ const ws = this.readPackageAsWorkspace(rootDir, dir);
131
+ if (ws) {
132
+ workspaces.push(ws);
133
+ }
134
+ else if (process.env.UIKIT_DEBUG) {
135
+ console.log('[DEBUG loadWorkspaces] Skipping (no/invalid package.json):', dir);
136
+ }
137
+ }
138
+ }
139
+ return workspaces.filter((ws) => Boolean(ws.name));
140
+ }
141
+ /**
142
+ * Load consumer workspaces, falling back to the root package itself when the
143
+ * consumer is a single, non-workspaces package (`location: ''`). This is what
144
+ * lets link/unlink target a plain consumer, not only a monorepo.
145
+ */
146
+ loadConsumerWorkspaces(rootDir) {
147
+ const workspaces = this.loadWorkspaces(rootDir);
148
+ if (workspaces.length > 0) {
149
+ return workspaces;
150
+ }
151
+ const root = this.readPackageAsWorkspace(rootDir, rootDir);
152
+ return root && root.name ? [root] : [];
153
+ }
154
+ /** Read a directory's package.json into a WorkspaceInfo, or null if absent/invalid. */
155
+ readPackageAsWorkspace(rootDir, dir) {
156
+ const pkgPath = path.join(dir, 'package.json');
157
+ if (!this.fs.exists(pkgPath)) {
158
+ return null;
159
+ }
160
+ try {
161
+ const pkg = this.fs.readJson(pkgPath);
162
+ return {
163
+ name: pkg.name ?? null,
164
+ location: path.relative(rootDir, dir),
165
+ path: dir,
166
+ dependencies: pkg.dependencies ?? {},
167
+ devDependencies: pkg.devDependencies ?? {},
168
+ peerDependencies: pkg.peerDependencies ?? {},
169
+ optionalDependencies: pkg.optionalDependencies ?? {},
170
+ };
171
+ }
172
+ catch {
173
+ return null;
174
+ }
175
+ }
176
+ getWorkspacePatterns(rootDir) {
177
+ const pkgPath = path.join(rootDir, 'package.json');
178
+ if (!this.fs.exists(pkgPath)) {
179
+ return [];
180
+ }
181
+ try {
182
+ const pkg = this.fs.readJson(pkgPath);
183
+ if (Array.isArray(pkg.workspaces)) {
184
+ return pkg.workspaces;
185
+ }
186
+ if (pkg.workspaces && Array.isArray(pkg.workspaces.packages)) {
187
+ return pkg.workspaces.packages;
188
+ }
189
+ }
190
+ catch {
191
+ // Return empty if parse fails
192
+ }
193
+ return [];
194
+ }
195
+ resolveWorkspacePattern(rootDir, pattern) {
196
+ // Handle simple glob patterns like "packages/*"
197
+ if (pattern.includes('*')) {
198
+ // Only support "dir/*" pattern for now
199
+ if (pattern.endsWith('/*')) {
200
+ const baseDir = pattern.slice(0, -2);
201
+ const basePath = path.join(rootDir, baseDir);
202
+ if (!this.fs.exists(basePath) || !this.fs.isDirectory(basePath)) {
203
+ return [];
204
+ }
205
+ const entries = this.fs.readDir(basePath);
206
+ return entries
207
+ .filter((entry) => !entry.startsWith('.') && entry !== 'node_modules')
208
+ .map((entry) => path.join(basePath, entry))
209
+ .filter((p) => this.fs.isDirectory(p));
210
+ }
211
+ // Unsupported pattern
212
+ return [];
213
+ }
214
+ // Static pattern, return as-is if it's a directory
215
+ const fullPath = path.join(rootDir, pattern);
216
+ return this.fs.isDirectory(fullPath) ? [fullPath] : [];
217
+ }
218
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Shell argument escaping utility
3
+ */
4
+ export function shellEscape(arg) {
5
+ if (/^[a-zA-Z0-9_\-./:=]+$/.test(arg)) {
6
+ return arg;
7
+ }
8
+ return `'${arg.replace(/'/g, "'\\''")}'`;
9
+ }
@@ -0,0 +1,16 @@
1
+ import { createRequire } from 'node:module';
2
+ import path from 'node:path';
3
+ const requireFromCli = createRequire(import.meta.url);
4
+ /**
5
+ * Resolve a CLI binary from uikit-cli dependencies so consumers
6
+ * don't need tool packages installed in their own workspace.
7
+ */
8
+ export function resolveCliBinary(packageName, binaryPath) {
9
+ try {
10
+ const packageJsonPath = requireFromCli.resolve(`${packageName}/package.json`);
11
+ return path.join(path.dirname(packageJsonPath), binaryPath);
12
+ }
13
+ catch {
14
+ throw new Error(`Could not resolve ${packageName} binary from @r0hitsharma/uikit-cli dependencies.`);
15
+ }
16
+ }
package/dist/types.js ADDED
@@ -0,0 +1 @@
1
+ export {};
package/package.json ADDED
@@ -0,0 +1,40 @@
1
+ {
2
+ "name": "@r0hitsharma/uikit-cli",
3
+ "type": "module",
4
+ "description": "CLI for managing local uikit package linking in consumer workspaces",
5
+ "scripts": {
6
+ "build": "tsc -b && npm run wrapper",
7
+ "wrapper": "./scripts/create-wrapper.sh",
8
+ "clean": "rm -rf dist",
9
+ "type:check": "tsc -p tsconfig.json --noEmit",
10
+ "lint": "oxlint -c oxlint.config.ts --max-warnings=0 src",
11
+ "lint:fix": "oxlint -c oxlint.config.ts --fix src",
12
+ "format": "oxfmt -c oxfmt.config.ts --write src",
13
+ "format:check": "oxfmt -c oxfmt.config.ts --check src",
14
+ "test": "vitest run",
15
+ "prepare": "npm run build"
16
+ },
17
+ "bin": {
18
+ "uikit-cli": "./dist/cli.sh"
19
+ },
20
+ "publishConfig": {
21
+ "access": "public"
22
+ },
23
+ "dependencies": {
24
+ "oxfmt": "0.67.0",
25
+ "oxlint": "1.82.0"
26
+ },
27
+ "devDependencies": {
28
+ "@r0hitsharma/oxfmt-config": "*",
29
+ "@r0hitsharma/tsconfig": "*",
30
+ "@types/node": "24.13.3",
31
+ "vitest": "^4.1.9"
32
+ },
33
+ "files": [
34
+ "dist"
35
+ ],
36
+ "version": "0.12.0-rohit-fork-ci.1",
37
+ "repository": {
38
+ "url": "https://github.com/r0hitsharma/uikit"
39
+ }
40
+ }