@autofictional/cli 0.1.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 +56 -0
- package/dist/commands/install.d.ts +1 -0
- package/dist/commands/install.js +131 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +21 -0
- package/dist/utils/detect.d.ts +7 -0
- package/dist/utils/detect.js +87 -0
- package/dist/utils/generate-id.d.ts +1 -0
- package/dist/utils/generate-id.js +40 -0
- package/dist/utils/patch.d.ts +1 -0
- package/dist/utils/patch.js +122 -0
- package/package.json +41 -0
package/README.md
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# @autofictional/cli
|
|
2
|
+
|
|
3
|
+
CLI tool to install Autofictional autonomous sidebar adaptation into your React app.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
From your project directory (frontend or root):
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
node path/to/packages/cli/dist/index.js install
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Or if published to npm:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npx autofictional
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Requirements
|
|
20
|
+
|
|
21
|
+
- React 18+
|
|
22
|
+
- Tailwind CSS
|
|
23
|
+
- shadcn Sidebar component (must be installed first)
|
|
24
|
+
|
|
25
|
+
## What it does
|
|
26
|
+
|
|
27
|
+
1. Detects your project setup (React, Tailwind, shadcn Sidebar)
|
|
28
|
+
2. Installs `@autofictional/runtime` package
|
|
29
|
+
3. Generates a unique app ID
|
|
30
|
+
4. Patches your main entry file to wrap your app with `<AutofictionalProvider>`
|
|
31
|
+
|
|
32
|
+
## Safety
|
|
33
|
+
|
|
34
|
+
- Creates a backup of your main file (`.backup` extension)
|
|
35
|
+
- Exits safely if patching fails
|
|
36
|
+
- Will not install if already installed
|
|
37
|
+
|
|
38
|
+
## Verification
|
|
39
|
+
|
|
40
|
+
After installation:
|
|
41
|
+
|
|
42
|
+
1. Start your dev server: `npm run dev`
|
|
43
|
+
2. Visit `/autofictional-test` to verify the installation
|
|
44
|
+
3. Check for no console errors
|
|
45
|
+
4. Verify `AutofictionalProvider` is mounted
|
|
46
|
+
|
|
47
|
+
## NIGHT 1 Status
|
|
48
|
+
|
|
49
|
+
✅ Runtime skeleton installed
|
|
50
|
+
✅ Provider renders children without behavior
|
|
51
|
+
✅ No UI changes yet
|
|
52
|
+
✅ No backend yet
|
|
53
|
+
✅ No sidebar changes yet
|
|
54
|
+
|
|
55
|
+
This is NIGHT 1 of the MVP - the foundation is in place for autonomous sidebar adaptation.
|
|
56
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function install(): Promise<void>;
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.install = install;
|
|
40
|
+
const fs = __importStar(require("fs"));
|
|
41
|
+
const path = __importStar(require("path"));
|
|
42
|
+
const child_process_1 = require("child_process");
|
|
43
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
44
|
+
const detect_1 = require("../utils/detect");
|
|
45
|
+
const patch_1 = require("../utils/patch");
|
|
46
|
+
const generate_id_1 = require("../utils/generate-id");
|
|
47
|
+
async function install() {
|
|
48
|
+
console.log(chalk_1.default.bold.blue('\n🚀 Autofictional Installer\n'));
|
|
49
|
+
const cwd = process.cwd();
|
|
50
|
+
// Step 1: Detect React + Tailwind
|
|
51
|
+
console.log(chalk_1.default.dim('→ Detecting project setup...'));
|
|
52
|
+
const detection = (0, detect_1.detectProject)(cwd);
|
|
53
|
+
if (!detection.hasReact) {
|
|
54
|
+
console.error(chalk_1.default.red('✗ React not detected. Autofictional requires React.'));
|
|
55
|
+
process.exit(1);
|
|
56
|
+
}
|
|
57
|
+
if (!detection.hasTailwind) {
|
|
58
|
+
console.error(chalk_1.default.red('✗ Tailwind CSS not detected. Autofictional requires Tailwind.'));
|
|
59
|
+
process.exit(1);
|
|
60
|
+
}
|
|
61
|
+
if (!detection.hasShadcnSidebar) {
|
|
62
|
+
console.error(chalk_1.default.red('✗ shadcn Sidebar not detected. Please install it first.'));
|
|
63
|
+
console.log(chalk_1.default.dim(' Run: npx shadcn@latest add sidebar'));
|
|
64
|
+
process.exit(1);
|
|
65
|
+
}
|
|
66
|
+
console.log(chalk_1.default.green('✓ React detected'));
|
|
67
|
+
console.log(chalk_1.default.green('✓ Tailwind CSS detected'));
|
|
68
|
+
console.log(chalk_1.default.green('✓ shadcn Sidebar detected'));
|
|
69
|
+
// Step 2: Install @autofictional/runtime
|
|
70
|
+
console.log(chalk_1.default.dim('\n→ Installing @autofictional/runtime...'));
|
|
71
|
+
try {
|
|
72
|
+
// Try local package first (for development)
|
|
73
|
+
const runtimePath = path.resolve(__dirname, '../../../runtime');
|
|
74
|
+
const packageJsonPath = path.join(cwd, 'package.json');
|
|
75
|
+
// Check if we're in a monorepo with local packages
|
|
76
|
+
if (fs.existsSync(runtimePath) && fs.existsSync(packageJsonPath)) {
|
|
77
|
+
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
|
|
78
|
+
const isMonorepo = packageJson.workspaces || fs.existsSync(path.join(cwd, '..', 'packages'));
|
|
79
|
+
if (isMonorepo) {
|
|
80
|
+
// Use npm link for local development
|
|
81
|
+
console.log(chalk_1.default.dim(' Detected local development - using npm link...'));
|
|
82
|
+
(0, child_process_1.execSync)('npm link', { cwd: runtimePath, stdio: 'ignore' });
|
|
83
|
+
(0, child_process_1.execSync)('npm link @autofictional/runtime', { cwd, stdio: 'ignore' });
|
|
84
|
+
console.log(chalk_1.default.green('✓ Runtime linked (local development)'));
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
// Install from npm
|
|
88
|
+
console.log(chalk_1.default.dim(' Installing from npm...'));
|
|
89
|
+
(0, child_process_1.execSync)('npm install @autofictional/runtime', { cwd, stdio: 'inherit' });
|
|
90
|
+
console.log(chalk_1.default.green('✓ Runtime installed from npm'));
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
// Install from npm
|
|
95
|
+
console.log(chalk_1.default.dim(' Installing from npm...'));
|
|
96
|
+
(0, child_process_1.execSync)('npm install @autofictional/runtime', { cwd, stdio: 'inherit' });
|
|
97
|
+
console.log(chalk_1.default.green('✓ Runtime installed from npm'));
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
catch (error) {
|
|
101
|
+
console.error(chalk_1.default.red('✗ Failed to install runtime'));
|
|
102
|
+
console.error(chalk_1.default.dim(' Try: npm install @autofictional/runtime'));
|
|
103
|
+
console.error(error);
|
|
104
|
+
process.exit(1);
|
|
105
|
+
}
|
|
106
|
+
// Step 3: Generate app ID
|
|
107
|
+
const appId = (0, generate_id_1.generateAppId)();
|
|
108
|
+
console.log(chalk_1.default.dim(`\n→ Generated app ID: ${appId}`));
|
|
109
|
+
// Step 4: Patch main file
|
|
110
|
+
console.log(chalk_1.default.dim('\n→ Patching app entry point...'));
|
|
111
|
+
const mainFile = detection.mainFile;
|
|
112
|
+
if (!mainFile) {
|
|
113
|
+
console.error(chalk_1.default.red('✗ Could not find app entry point (main.tsx/main.jsx/index.tsx/index.jsx)'));
|
|
114
|
+
process.exit(1);
|
|
115
|
+
}
|
|
116
|
+
try {
|
|
117
|
+
(0, patch_1.patchMainFile)(mainFile, appId);
|
|
118
|
+
console.log(chalk_1.default.green(`✓ Patched ${path.relative(cwd, mainFile)}`));
|
|
119
|
+
}
|
|
120
|
+
catch (error) {
|
|
121
|
+
console.error(chalk_1.default.red('✗ Failed to patch main file'));
|
|
122
|
+
console.error(error);
|
|
123
|
+
process.exit(1);
|
|
124
|
+
}
|
|
125
|
+
// Success
|
|
126
|
+
console.log(chalk_1.default.bold.green('\n✓ Autofictional installed successfully!\n'));
|
|
127
|
+
console.log(chalk_1.default.dim('Next steps:'));
|
|
128
|
+
console.log(chalk_1.default.dim(' 1. Start your dev server'));
|
|
129
|
+
console.log(chalk_1.default.dim(' 2. Check console for errors'));
|
|
130
|
+
console.log(chalk_1.default.dim(' 3. Verify AutofictionalProvider is mounted\n'));
|
|
131
|
+
}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
const commander_1 = require("commander");
|
|
5
|
+
const install_1 = require("./commands/install");
|
|
6
|
+
const program = new commander_1.Command();
|
|
7
|
+
program
|
|
8
|
+
.name('autofictional')
|
|
9
|
+
.description('Install Autofictional autonomous sidebar adaptation')
|
|
10
|
+
.version('0.1.0');
|
|
11
|
+
program
|
|
12
|
+
.command('install')
|
|
13
|
+
.description('Install Autofictional runtime into your app')
|
|
14
|
+
.action(install_1.install);
|
|
15
|
+
// Default to install if no command specified
|
|
16
|
+
if (process.argv.length === 2) {
|
|
17
|
+
(0, install_1.install)();
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
program.parse(process.argv);
|
|
21
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.detectProject = detectProject;
|
|
37
|
+
const fs = __importStar(require("fs"));
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
function detectProject(cwd) {
|
|
40
|
+
const detection = {
|
|
41
|
+
hasReact: false,
|
|
42
|
+
hasTailwind: false,
|
|
43
|
+
hasShadcnSidebar: false,
|
|
44
|
+
mainFile: null,
|
|
45
|
+
};
|
|
46
|
+
// Check for package.json and dependencies
|
|
47
|
+
const packageJsonPath = path.join(cwd, 'package.json');
|
|
48
|
+
if (fs.existsSync(packageJsonPath)) {
|
|
49
|
+
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
|
|
50
|
+
const allDeps = {
|
|
51
|
+
...packageJson.dependencies,
|
|
52
|
+
...packageJson.devDependencies,
|
|
53
|
+
};
|
|
54
|
+
detection.hasReact = 'react' in allDeps;
|
|
55
|
+
detection.hasTailwind = 'tailwindcss' in allDeps;
|
|
56
|
+
}
|
|
57
|
+
// Check for shadcn sidebar component
|
|
58
|
+
const possibleSidebarPaths = [
|
|
59
|
+
path.join(cwd, 'src/components/ui/sidebar.tsx'),
|
|
60
|
+
path.join(cwd, 'components/ui/sidebar.tsx'),
|
|
61
|
+
path.join(cwd, 'frontend/src/components/ui/sidebar.tsx'),
|
|
62
|
+
];
|
|
63
|
+
for (const sidebarPath of possibleSidebarPaths) {
|
|
64
|
+
if (fs.existsSync(sidebarPath)) {
|
|
65
|
+
detection.hasShadcnSidebar = true;
|
|
66
|
+
break;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
// Find main entry file
|
|
70
|
+
const possibleMainFiles = [
|
|
71
|
+
path.join(cwd, 'src/main.tsx'),
|
|
72
|
+
path.join(cwd, 'src/main.jsx'),
|
|
73
|
+
path.join(cwd, 'src/index.tsx'),
|
|
74
|
+
path.join(cwd, 'src/index.jsx'),
|
|
75
|
+
path.join(cwd, 'frontend/src/main.tsx'),
|
|
76
|
+
path.join(cwd, 'frontend/src/main.jsx'),
|
|
77
|
+
path.join(cwd, 'frontend/src/index.tsx'),
|
|
78
|
+
path.join(cwd, 'frontend/src/index.jsx'),
|
|
79
|
+
];
|
|
80
|
+
for (const mainFile of possibleMainFiles) {
|
|
81
|
+
if (fs.existsSync(mainFile)) {
|
|
82
|
+
detection.mainFile = mainFile;
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return detection;
|
|
87
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function generateAppId(): string;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.generateAppId = generateAppId;
|
|
37
|
+
const crypto = __importStar(require("crypto"));
|
|
38
|
+
function generateAppId() {
|
|
39
|
+
return 'app_' + crypto.randomBytes(16).toString('hex');
|
|
40
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function patchMainFile(mainFilePath: string, appId: string): void;
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.patchMainFile = patchMainFile;
|
|
37
|
+
const fs = __importStar(require("fs"));
|
|
38
|
+
function patchMainFile(mainFilePath, appId) {
|
|
39
|
+
const content = fs.readFileSync(mainFilePath, 'utf-8');
|
|
40
|
+
// Check if already patched
|
|
41
|
+
if (content.includes('AutofictionalProvider')) {
|
|
42
|
+
throw new Error('AutofictionalProvider already exists in main file. Aborting to avoid duplicate installation.');
|
|
43
|
+
}
|
|
44
|
+
// Parse the file structure
|
|
45
|
+
const lines = content.split('\n');
|
|
46
|
+
// Find import section end
|
|
47
|
+
let lastImportIndex = -1;
|
|
48
|
+
for (let i = 0; i < lines.length; i++) {
|
|
49
|
+
if (lines[i].trim().startsWith('import ')) {
|
|
50
|
+
lastImportIndex = i;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
// Find ReactDOM.createRoot call
|
|
54
|
+
let rootCallIndex = -1;
|
|
55
|
+
let rootCallEndIndex = -1;
|
|
56
|
+
let indentLevel = 0;
|
|
57
|
+
for (let i = 0; i < lines.length; i++) {
|
|
58
|
+
if (lines[i].includes('ReactDOM.createRoot') || lines[i].includes('createRoot')) {
|
|
59
|
+
rootCallIndex = i;
|
|
60
|
+
// Find the closing parenthesis of the render call
|
|
61
|
+
let depth = 0;
|
|
62
|
+
for (let j = i; j < lines.length; j++) {
|
|
63
|
+
const line = lines[j];
|
|
64
|
+
depth += (line.match(/\(/g) || []).length;
|
|
65
|
+
depth -= (line.match(/\)/g) || []).length;
|
|
66
|
+
if (depth === 0 && line.includes(')')) {
|
|
67
|
+
rootCallEndIndex = j;
|
|
68
|
+
break;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
break;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
if (rootCallIndex === -1 || rootCallEndIndex === -1) {
|
|
75
|
+
throw new Error('Could not find ReactDOM.createRoot call. Manual installation required.');
|
|
76
|
+
}
|
|
77
|
+
// Detect indentation
|
|
78
|
+
const rootLine = lines[rootCallIndex];
|
|
79
|
+
const indent = rootLine.match(/^(\s*)/)?.[1] || ' ';
|
|
80
|
+
// Extract the content between <React.StrictMode> tags or the RouterProvider
|
|
81
|
+
let contentStart = -1;
|
|
82
|
+
let contentEnd = -1;
|
|
83
|
+
for (let i = rootCallIndex; i <= rootCallEndIndex; i++) {
|
|
84
|
+
if (lines[i].includes('<React.StrictMode>') || lines[i].includes('<RouterProvider') || lines[i].includes('<App')) {
|
|
85
|
+
contentStart = i;
|
|
86
|
+
break;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
for (let i = rootCallEndIndex; i >= rootCallIndex; i--) {
|
|
90
|
+
if (lines[i].includes('</React.StrictMode>') || lines[i].includes('/>') || lines[i].includes('</App>')) {
|
|
91
|
+
contentEnd = i;
|
|
92
|
+
break;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
if (contentStart === -1 || contentEnd === -1) {
|
|
96
|
+
throw new Error('Could not parse render content. Manual installation required.');
|
|
97
|
+
}
|
|
98
|
+
// Build the new content
|
|
99
|
+
const newLines = [...lines];
|
|
100
|
+
// Add import after last import
|
|
101
|
+
const importLine = `import { AutofictionalProvider } from '@autofictional/runtime';`;
|
|
102
|
+
newLines.splice(lastImportIndex + 1, 0, importLine);
|
|
103
|
+
// Adjust indices after insertion
|
|
104
|
+
contentStart += 1;
|
|
105
|
+
contentEnd += 1;
|
|
106
|
+
// Extract the wrapped content
|
|
107
|
+
const wrappedContent = newLines.slice(contentStart, contentEnd + 1);
|
|
108
|
+
// Indent the wrapped content
|
|
109
|
+
const indentedContent = wrappedContent.map(line => indent + ' ' + line.trimStart());
|
|
110
|
+
// Create the provider wrapper
|
|
111
|
+
const providerStart = `${indent} <AutofictionalProvider appId="${appId}">`;
|
|
112
|
+
const providerEnd = `${indent} </AutofictionalProvider>`;
|
|
113
|
+
// Replace the content
|
|
114
|
+
newLines.splice(contentStart, contentEnd - contentStart + 1, providerStart, ...indentedContent, providerEnd);
|
|
115
|
+
// Write back
|
|
116
|
+
const newContent = newLines.join('\n');
|
|
117
|
+
// Create backup
|
|
118
|
+
const backupPath = mainFilePath + '.backup';
|
|
119
|
+
fs.writeFileSync(backupPath, content);
|
|
120
|
+
// Write new content
|
|
121
|
+
fs.writeFileSync(mainFilePath, newContent);
|
|
122
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@autofictional/cli",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "CLI tool to install Autofictional runtime",
|
|
5
|
+
"author": "",
|
|
6
|
+
"license": "UNLICENSED",
|
|
7
|
+
"bin": {
|
|
8
|
+
"autofictional": "./dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "https://github.com/andreamorales/autofictional.git",
|
|
13
|
+
"directory": "packages/cli"
|
|
14
|
+
},
|
|
15
|
+
"homepage": "https://github.com/andreamorales/autofictional#readme",
|
|
16
|
+
"bugs": {
|
|
17
|
+
"url": "https://github.com/andreamorales/autofictional/issues"
|
|
18
|
+
},
|
|
19
|
+
"scripts": {
|
|
20
|
+
"build": "tsc",
|
|
21
|
+
"dev": "tsc --watch",
|
|
22
|
+
"prepublishOnly": "npm run build"
|
|
23
|
+
},
|
|
24
|
+
"publishConfig": {
|
|
25
|
+
"access": "public"
|
|
26
|
+
},
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"chalk": "^4.1.2",
|
|
29
|
+
"commander": "^11.0.0",
|
|
30
|
+
"prompts": "^2.4.2"
|
|
31
|
+
},
|
|
32
|
+
"devDependencies": {
|
|
33
|
+
"@types/node": "^20.0.0",
|
|
34
|
+
"@types/prompts": "^2.4.4",
|
|
35
|
+
"typescript": "^5.0.0"
|
|
36
|
+
},
|
|
37
|
+
"files": [
|
|
38
|
+
"dist"
|
|
39
|
+
]
|
|
40
|
+
}
|
|
41
|
+
|