phpxui 0.1.2 → 0.1.4
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 +114 -36
- package/dist/commands/icons.js +1 -25
- package/dist/generators/copy-tailwind.js +1 -27
- package/dist/generators/ensure-package.js +1 -32
- package/dist/generators/php-component.js +1 -27
- package/dist/generators/php-components-bulk.js +1 -42
- package/dist/generators/write-component.js +1 -26
- package/dist/index.js +1 -120
- package/dist/utils/load-config.js +1 -41
- package/dist/utils/scan-installed.js +1 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,46 +1,48 @@
|
|
|
1
|
-
# **phpxui‑cli** —
|
|
1
|
+
# **phpxui‑cli** — Instant PHPXUI Component Generator 🚀
|
|
2
2
|
|
|
3
|
-
> **Generate fully‑typed PHPXUI components for Prisma
|
|
4
|
-
> ⚡ **
|
|
3
|
+
> **Generate fully‑typed PHPXUI components for Prisma PHP right from the terminal.**
|
|
4
|
+
> ⚡ **Add one** → `npx phpxui add Alert` | 🌌 **Add all** → `npx phpxui add --all` | 🔁 **Update installed** → `npx phpxui update`
|
|
5
5
|
|
|
6
6
|
---
|
|
7
7
|
|
|
8
|
-
## ✨
|
|
8
|
+
## ✨ Features
|
|
9
9
|
|
|
10
|
-
| Feature
|
|
11
|
-
|
|
|
12
|
-
| **Bulk install**
|
|
13
|
-
| **
|
|
14
|
-
| **
|
|
15
|
-
| **
|
|
16
|
-
| **
|
|
10
|
+
| Feature | Details |
|
|
11
|
+
| ---------------------- | ---------------------------------------------------------------------------------------------------------------- |
|
|
12
|
+
| **Bulk install** | `--all` downloads every component in one shot. |
|
|
13
|
+
| **Update in place** | `update` scans your `outputDir` and re‑downloads every installed component (overwrite). |
|
|
14
|
+
| **Ready‑to‑use code** | Each file already contains the `$class` merge logic and `{$attributes}` placeholder for **Wave** reactivity. |
|
|
15
|
+
| **Clean paths** | Files are written under `src/Lib/PHPXUI/FancyName.php` with OS‑agnostic separators. |
|
|
16
|
+
| **Friendly output** | Clear green / red summary with relative paths only. |
|
|
17
|
+
| **Automatic icons** | Core **PPIcons** (`x`, `chevron‑down`, `chevron‑right`, etc.) are installed on the very first run. |
|
|
18
|
+
| **Tailwind bootstrap** | Ensures `tw-animate-css` and (on first run / missing file) writes `src/app/globals.css` for a sensible baseline. |
|
|
17
19
|
|
|
18
20
|
---
|
|
19
21
|
|
|
20
|
-
## 📦
|
|
22
|
+
## 📦 Installation
|
|
21
23
|
|
|
22
24
|
```bash
|
|
23
25
|
# Global
|
|
24
26
|
npm install -g phpxui
|
|
25
27
|
|
|
26
|
-
#
|
|
28
|
+
# Or as a dev‑dependency
|
|
27
29
|
npm install -D phpxui
|
|
28
30
|
```
|
|
29
31
|
|
|
30
|
-
> Requires **Node
|
|
32
|
+
> Requires **Node 18+** and a Prisma PHP project (PHP 8.2+).
|
|
31
33
|
|
|
32
34
|
---
|
|
33
35
|
|
|
34
|
-
## 🚀
|
|
36
|
+
## 🚀 Quick Start
|
|
35
37
|
|
|
36
38
|
```bash
|
|
37
|
-
#
|
|
39
|
+
# Add a single component
|
|
38
40
|
npx phpxui add Alert
|
|
39
41
|
|
|
40
|
-
#
|
|
42
|
+
# Add multiple components at once
|
|
41
43
|
npx phpxui add Alert Dialog Badge
|
|
42
44
|
|
|
43
|
-
#
|
|
45
|
+
# Add the entire component set
|
|
44
46
|
npx phpxui add --all
|
|
45
47
|
```
|
|
46
48
|
|
|
@@ -68,11 +70,13 @@ class Alert extends PHPX
|
|
|
68
70
|
{
|
|
69
71
|
public function render(): string
|
|
70
72
|
{
|
|
71
|
-
$attributes = $this->getAttributes();
|
|
72
73
|
$class = $this->getMergeClasses();
|
|
74
|
+
$attributes = $this->getAttributes([
|
|
75
|
+
'class' => $class,
|
|
76
|
+
]);
|
|
73
77
|
|
|
74
78
|
return <<<HTML
|
|
75
|
-
<div {$attributes}
|
|
79
|
+
<div {$attributes}>
|
|
76
80
|
{$this->children}
|
|
77
81
|
</div>
|
|
78
82
|
HTML;
|
|
@@ -82,19 +86,93 @@ class Alert extends PHPX
|
|
|
82
86
|
|
|
83
87
|
---
|
|
84
88
|
|
|
85
|
-
##
|
|
89
|
+
## 🔁 Updating Components
|
|
86
90
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
91
|
+
### Update everything you already installed
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
npx phpxui update
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
What it does:
|
|
98
|
+
|
|
99
|
+
- Reads your `phpxui.json` (creates it if missing)
|
|
100
|
+
- Resolves your `outputDir` (default: `src/Lib/PHPXUI`)
|
|
101
|
+
- Scans that folder for `*.php` files (e.g. `Alert.php`, `Dialog.php`)
|
|
102
|
+
- Re-downloads each matching component from the PHPXUI catalogue
|
|
103
|
+
- **Overwrites files automatically** (no `--force` required)
|
|
104
|
+
|
|
105
|
+
If you have no generated components yet, it will report:
|
|
106
|
+
|
|
107
|
+
- `⚠ No components found to update.`
|
|
108
|
+
|
|
109
|
+
### Update a single component (targeted)
|
|
110
|
+
|
|
111
|
+
If you only want to refresh one component, use `add` with `--force`:
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
npx phpxui add Alert --force
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## 🔧 CLI Usage and Options
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
phpxui <command> [--all] [--force] <component…>
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Commands
|
|
126
|
+
|
|
127
|
+
| Command | Purpose |
|
|
128
|
+
| -------- | ---------------------------------------------------------------------------- |
|
|
129
|
+
| `add` | Generate one or more components by name, or the full catalogue with `--all`. |
|
|
130
|
+
| `update` | Update **all installed** components found in `outputDir` (overwrites). |
|
|
131
|
+
|
|
132
|
+
### Flags / Arguments
|
|
133
|
+
|
|
134
|
+
| Flag / Argument | Description |
|
|
135
|
+
| --------------- | ---------------------------------------------------------------------------- |
|
|
136
|
+
| `<component …>` | One or more component names separated by space (or comma). Applies to `add`. |
|
|
137
|
+
| `--all` | Download the full catalogue in one request. Applies to `add`. |
|
|
138
|
+
| `--force` | Overwrite existing files. Applies to `add`. |
|
|
92
139
|
|
|
93
140
|
> **Note:** The CLI automatically installs a default set of core icons (such as `x`, `chevron-down`, `chevron-right`) on first use. Extra icons are not yet selectable via `phpxui` directly.
|
|
94
141
|
|
|
95
142
|
---
|
|
96
143
|
|
|
97
|
-
##
|
|
144
|
+
## 🧩 Configuration (phpxui.json)
|
|
145
|
+
|
|
146
|
+
On first run, **phpxui‑cli** creates a `phpxui.json` in your project root. The most important fields are:
|
|
147
|
+
|
|
148
|
+
- `outputDir`: where PHPXUI components are written (default: `src/Lib/PHPXUI`)
|
|
149
|
+
- `psr4`: mapping hints for components and icons
|
|
150
|
+
- `iconsInstalled`: internal flag to avoid reinstalling the default icon set
|
|
151
|
+
- `tailwind.css`: where the base CSS should live (default: `src/app/globals.css`)
|
|
152
|
+
|
|
153
|
+
Example:
|
|
154
|
+
|
|
155
|
+
```json
|
|
156
|
+
{
|
|
157
|
+
"outputDir": "src/Lib/PHPXUI",
|
|
158
|
+
"iconsInstalled": false,
|
|
159
|
+
"tailwind": {
|
|
160
|
+
"css": "src/app/globals.css",
|
|
161
|
+
"baseColor": "neutral",
|
|
162
|
+
"cssVariables": true,
|
|
163
|
+
"prefix": ""
|
|
164
|
+
},
|
|
165
|
+
"psr4": {
|
|
166
|
+
"Components": "src/Lib/PHPXUI/",
|
|
167
|
+
"Icons": "src/Lib/PPIcons/"
|
|
168
|
+
},
|
|
169
|
+
"iconLibrary": "ppicons"
|
|
170
|
+
}
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
## 🎨 Using Additional Icons
|
|
98
176
|
|
|
99
177
|
Need more icons? Use the **PPIcons** CLI directly:
|
|
100
178
|
|
|
@@ -102,35 +180,35 @@ Need more icons? Use the **PPIcons** CLI directly:
|
|
|
102
180
|
npx ppicons add menu chevron-left arrow-right
|
|
103
181
|
```
|
|
104
182
|
|
|
105
|
-
This will place the requested icons under `src/Lib/PPIcons` with full PHPXUI typings.
|
|
106
|
-
Browse the complete icon catalogue and usage docs at **
|
|
183
|
+
This will place the requested icons under `src/Lib/PPIcons` with full PHPXUI typings.
|
|
184
|
+
Browse the complete icon catalogue and usage docs at **https://ppicons.tsnc.tech/**.
|
|
107
185
|
|
|
108
186
|
---
|
|
109
187
|
|
|
110
|
-
## 📚
|
|
188
|
+
## 📚 Documentation
|
|
111
189
|
|
|
112
|
-
Full guides and examples live at the
|
|
190
|
+
Full guides and examples live at the PHPXUI documentation site: **https://phpxui.tsnc.tech/**
|
|
113
191
|
|
|
114
192
|
---
|
|
115
193
|
|
|
116
|
-
## 💡
|
|
194
|
+
## 💡 Contributing
|
|
117
195
|
|
|
118
196
|
We welcome contributions to improve **phpxui‑cli**. If you have ideas, find bugs, or want to add features, open an issue or submit a pull request.
|
|
119
197
|
|
|
120
198
|
---
|
|
121
199
|
|
|
122
|
-
## 📄
|
|
200
|
+
## 📄 License
|
|
123
201
|
|
|
124
202
|
`phpxui‑cli` is released under the MIT License. See `LICENSE` for details.
|
|
125
203
|
|
|
126
204
|
---
|
|
127
205
|
|
|
128
|
-
## 👤
|
|
206
|
+
## 👤 Author
|
|
129
207
|
|
|
130
|
-
This project is developed and maintained by **The
|
|
208
|
+
This project is developed and maintained by **The Steel Ninja Code**, continuously pushing the boundaries of PHP development.
|
|
131
209
|
|
|
132
210
|
---
|
|
133
211
|
|
|
134
|
-
## 📧
|
|
212
|
+
## 📧 Contact
|
|
135
213
|
|
|
136
214
|
Questions or feedback? Reach us at [thesteelninjacode@gmail.com](mailto:thesteelninjacode@gmail.com) — we’d love to hear from you!
|
package/dist/commands/icons.js
CHANGED
|
@@ -1,25 +1 @@
|
|
|
1
|
-
"
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.installIcons = installIcons;
|
|
7
|
-
const child_process_1 = require("child_process");
|
|
8
|
-
const chalk_1 = __importDefault(require("chalk"));
|
|
9
|
-
const load_config_1 = require("../utils/load-config");
|
|
10
|
-
async function installIcons(iconList, config) {
|
|
11
|
-
try {
|
|
12
|
-
console.log(chalk_1.default.blue("📦 Installing ppicons CLI..."));
|
|
13
|
-
(0, child_process_1.execSync)("npm install -g ppicons", { stdio: "inherit" });
|
|
14
|
-
const args = iconList.join(" ");
|
|
15
|
-
console.log(chalk_1.default.blue(`✨ Installing default icons: ${args}`));
|
|
16
|
-
(0, child_process_1.execSync)(`npx ppicons add ${args}`, { stdio: "inherit" });
|
|
17
|
-
console.log(chalk_1.default.green("✔ Icons installed in src/Lib/PPIcons"));
|
|
18
|
-
config.iconsInstalled = true;
|
|
19
|
-
(0, load_config_1.savePhpXUIConfig)(config); // ⬅️ persist change
|
|
20
|
-
}
|
|
21
|
-
catch (err) {
|
|
22
|
-
console.error(chalk_1.default.red("✖ Failed to install icons:"), err.message);
|
|
23
|
-
process.exit(1);
|
|
24
|
-
}
|
|
25
|
-
}
|
|
1
|
+
import{execSync}from"child_process";import chalk from"chalk";import{savePhpXUIConfig}from"../utils/load-config.js";export async function installIcons(o,n){try{console.log(chalk.blue("📦 Installing ppicons CLI...")),execSync("npm install -g ppicons",{stdio:"inherit"});const c=o.join(" ");console.log(chalk.blue(`✨ Installing default icons: ${c}`)),execSync(`npx ppicons add ${c}`,{stdio:"inherit"}),console.log(chalk.green("✔ Icons installed in src/Lib/PPIcons")),n.iconsInstalled=!0,savePhpXUIConfig(n)}catch(o){console.error(chalk.red("✖ Failed to install icons:"),o.message),process.exit(1)}}
|
|
@@ -1,27 +1 @@
|
|
|
1
|
-
"
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.copyTailwindCss = copyTailwindCss;
|
|
7
|
-
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
8
|
-
const path_1 = __importDefault(require("path"));
|
|
9
|
-
/**
|
|
10
|
-
* Copy dist/css/tailwind.css into src/app/css/tailwind.css.
|
|
11
|
-
*
|
|
12
|
-
* @param force Overwrite even if the target exists.
|
|
13
|
-
* @returns true → file was copied / overwritten
|
|
14
|
-
* false → skipped (already exists and !force)
|
|
15
|
-
*/
|
|
16
|
-
function copyTailwindCss(force = false) {
|
|
17
|
-
// Path to the CSS bundled with the CLI
|
|
18
|
-
const source = path_1.default.resolve(__dirname, "../css/globals.css");
|
|
19
|
-
// Path inside the user’s project
|
|
20
|
-
const target = path_1.default.resolve(process.cwd(), "src/app/globals.css");
|
|
21
|
-
if (!force && fs_extra_1.default.existsSync(target)) {
|
|
22
|
-
return false; // skip quietly
|
|
23
|
-
}
|
|
24
|
-
fs_extra_1.default.ensureDirSync(path_1.default.dirname(target));
|
|
25
|
-
fs_extra_1.default.copyFileSync(source, target);
|
|
26
|
-
return true;
|
|
27
|
-
}
|
|
1
|
+
import fs from"fs-extra";import path from"path";import{fileURLToPath}from"url";const __filename=fileURLToPath(import.meta.url),__dirname=path.dirname(__filename);export function copyTailwindCss(s=!1){const e=path.resolve(__dirname,"../css/globals.css"),r=path.resolve(process.cwd(),"src/app/globals.css");return!(!s&&fs.existsSync(r))&&(fs.ensureDirSync(path.dirname(r)),fs.copyFileSync(e,r),!0)}
|
|
@@ -1,32 +1 @@
|
|
|
1
|
-
"
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.ensurePackageInstalled = ensurePackageInstalled;
|
|
7
|
-
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
8
|
-
const child_process_1 = require("child_process");
|
|
9
|
-
/**
|
|
10
|
-
* Ensures a package is present in dependencies/devDependencies.
|
|
11
|
-
* Installs it with `npm i -D <pkg>` if missing.
|
|
12
|
-
*
|
|
13
|
-
* @param pkg Package name, e.g. "tw-animate-css"
|
|
14
|
-
* @param quiet If true, suppress install output.
|
|
15
|
-
* @returns true → package was installed now
|
|
16
|
-
* false → package already present
|
|
17
|
-
*/
|
|
18
|
-
function ensurePackageInstalled(pkg, quiet = false) {
|
|
19
|
-
const pkgJsonPath = "package.json";
|
|
20
|
-
if (!fs_extra_1.default.existsSync(pkgJsonPath))
|
|
21
|
-
return false;
|
|
22
|
-
const pkgJson = fs_extra_1.default.readJsonSync(pkgJsonPath);
|
|
23
|
-
const hasIt = (pkgJson.dependencies && pkgJson.dependencies[pkg]) ||
|
|
24
|
-
(pkgJson.devDependencies && pkgJson.devDependencies[pkg]);
|
|
25
|
-
if (hasIt)
|
|
26
|
-
return false;
|
|
27
|
-
const cmd = `npm i -D ${pkg}`;
|
|
28
|
-
if (!quiet)
|
|
29
|
-
console.log(`⬇ Installing missing package: ${pkg} …`);
|
|
30
|
-
(0, child_process_1.execSync)(cmd, { stdio: quiet ? "ignore" : "inherit" });
|
|
31
|
-
return true;
|
|
32
|
-
}
|
|
1
|
+
import fs from"fs-extra";import{execSync}from"child_process";export function ensurePackageInstalled(e,n=!1){const s="package.json";if(!fs.existsSync(s))return!1;const c=fs.readJsonSync(s);if(c.dependencies&&c.dependencies[e]||c.devDependencies&&c.devDependencies[e])return!1;const i=`npm i -D ${e}`;return n||console.log(`⬇ Installing missing package: ${e} …`),execSync(i,{stdio:n?"ignore":"inherit"}),!0}
|
|
@@ -1,27 +1 @@
|
|
|
1
|
-
"
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.generateComponent = generateComponent;
|
|
7
|
-
const node_fetch_1 = __importDefault(require("node-fetch"));
|
|
8
|
-
const write_component_1 = require("./write-component");
|
|
9
|
-
const path_1 = __importDefault(require("path"));
|
|
10
|
-
const SINGLE_URL = "https://phpxui.tsnc.tech/cli";
|
|
11
|
-
async function generateComponent(componentName, targetDir, force = false) {
|
|
12
|
-
const url = `${SINGLE_URL}?component=${encodeURIComponent(componentName)}`;
|
|
13
|
-
const res = await (0, node_fetch_1.default)(url);
|
|
14
|
-
if (!res.ok) {
|
|
15
|
-
throw new Error(`Could not fetch "${componentName}": ${res.status} – ${url}`);
|
|
16
|
-
}
|
|
17
|
-
// El endpoint puede devolver un objeto (uno) o un array (muchos)
|
|
18
|
-
const json = await res.json();
|
|
19
|
-
const components = Array.isArray(json) ? json : [json];
|
|
20
|
-
const writtenPaths = [];
|
|
21
|
-
for (const cmp of components) {
|
|
22
|
-
// Cada objeto contiene { name, content }
|
|
23
|
-
const filePath = await (0, write_component_1.writeComponent)(cmp, targetDir, force);
|
|
24
|
-
writtenPaths.push(path_1.default.relative(process.cwd(), filePath));
|
|
25
|
-
}
|
|
26
|
-
return writtenPaths;
|
|
27
|
-
}
|
|
1
|
+
import fetch from"node-fetch";import{writeComponent}from"./write-component.js";import path from"path";const SINGLE_URL="https://phpxui.tsnc.tech/cli";export async function generateComponent(t,o,n=!1){const e=`${SINGLE_URL}?component=${encodeURIComponent(t)}`,r=await fetch(e);if(!r.ok)throw new Error(`Could not fetch "${t}": ${r.status} – ${e}`);const c=await r.json(),p=Array.isArray(c)?c:[c],s=[];for(const t of p){const e=await writeComponent(t,o,n);s.push(path.relative(process.cwd(),e))}return s}
|
|
@@ -1,42 +1 @@
|
|
|
1
|
-
"
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.generateAllComponents = generateAllComponents;
|
|
7
|
-
const node_fetch_1 = __importDefault(require("node-fetch"));
|
|
8
|
-
const write_component_1 = require("./write-component");
|
|
9
|
-
/** Endpoint that returns every PHPXUI component */
|
|
10
|
-
const BULK_URL = "https://phpxui.tsnc.tech/cli?component=all";
|
|
11
|
-
/**
|
|
12
|
-
* Download all components and write them to disk.
|
|
13
|
-
*
|
|
14
|
-
* @param targetDir Destination folder (e.g. "./src/Lib/PHPXUI")
|
|
15
|
-
* @param force Overwrite if file exists (default: false)
|
|
16
|
-
*/
|
|
17
|
-
async function generateAllComponents(targetDir, force = false) {
|
|
18
|
-
const res = await (0, node_fetch_1.default)(BULK_URL);
|
|
19
|
-
if (!res.ok) {
|
|
20
|
-
throw new Error(`Could not fetch component list: ${res.status} – ${BULK_URL}`);
|
|
21
|
-
}
|
|
22
|
-
// Backend returns [{ name, content }]
|
|
23
|
-
const components = (await res.json());
|
|
24
|
-
console.log(`➡ Received ${components.length} components. Generating…`);
|
|
25
|
-
const ok = [];
|
|
26
|
-
const fail = [];
|
|
27
|
-
/* Small concurrency queue to avoid hammering the FS */
|
|
28
|
-
const BATCH = 10;
|
|
29
|
-
let queue = [];
|
|
30
|
-
for (const cmp of components) {
|
|
31
|
-
const job = (0, write_component_1.writeComponent)(cmp, targetDir, force)
|
|
32
|
-
.then((file) => ok.push(file))
|
|
33
|
-
.catch((e) => fail.push(`${cmp.name}: ${e.message}`));
|
|
34
|
-
queue.push(job);
|
|
35
|
-
if (queue.length >= BATCH) {
|
|
36
|
-
await Promise.allSettled(queue);
|
|
37
|
-
queue = [];
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
await Promise.allSettled(queue);
|
|
41
|
-
return { ok, fail };
|
|
42
|
-
}
|
|
1
|
+
import fetch from"node-fetch";import{writeComponent}from"./write-component.js";const BULK_URL="https://phpxui.tsnc.tech/cli?component=all";export async function generateAllComponents(t,e=!1){const o=await fetch(BULK_URL);if(!o.ok)throw new Error(`Could not fetch component list: ${o.status} – ${BULK_URL}`);const n=await o.json();console.log(`➡ Received ${n.length} components. Generating…`);const s=[],c=[];let a=[];for(const o of n){const n=writeComponent(o,t,e).then(t=>s.push(t)).catch(t=>c.push(`${o.name}: ${t.message}`));a.push(n),a.length>=10&&(await Promise.allSettled(a),a=[])}return await Promise.allSettled(a),{ok:s,fail:c}}
|
|
@@ -1,26 +1 @@
|
|
|
1
|
-
"
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.writeComponent = writeComponent;
|
|
7
|
-
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
8
|
-
const path_1 = __importDefault(require("path"));
|
|
9
|
-
/**
|
|
10
|
-
* Writes a PHPXUI component file to disk.
|
|
11
|
-
*
|
|
12
|
-
* @param componentJson { name: string; content: string }
|
|
13
|
-
* @param targetDir Destination folder
|
|
14
|
-
* @param force Overwrite if file exists
|
|
15
|
-
* @returns Path of the written file
|
|
16
|
-
*/
|
|
17
|
-
async function writeComponent(componentJson, targetDir, force = false) {
|
|
18
|
-
const filePath = path_1.default.join(targetDir, `${componentJson.name}.php`);
|
|
19
|
-
if (!force && (await fs_extra_1.default.pathExists(filePath))) {
|
|
20
|
-
// Skip quietly
|
|
21
|
-
return filePath;
|
|
22
|
-
}
|
|
23
|
-
await fs_extra_1.default.ensureDir(path_1.default.dirname(filePath));
|
|
24
|
-
await fs_extra_1.default.writeFile(filePath, componentJson.content, "utf8");
|
|
25
|
-
return filePath;
|
|
26
|
-
}
|
|
1
|
+
import fs from"fs-extra";import path from"path";export async function writeComponent(t,a,i=!1){const n=path.join(a,`${t.name}.php`);return!i&&await fs.pathExists(n)||(await fs.ensureDir(path.dirname(n)),await fs.writeFile(n,t.content,"utf8")),n}
|
package/dist/index.js
CHANGED
|
@@ -1,121 +1,2 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
"
|
|
3
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
|
-
};
|
|
6
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
const prompts_1 = __importDefault(require("prompts"));
|
|
8
|
-
const chalk_1 = __importDefault(require("chalk"));
|
|
9
|
-
const path_1 = __importDefault(require("path"));
|
|
10
|
-
const php_component_1 = require("./generators/php-component");
|
|
11
|
-
const php_components_bulk_1 = require("./generators/php-components-bulk");
|
|
12
|
-
const ensure_package_1 = require("./generators/ensure-package");
|
|
13
|
-
const copy_tailwind_1 = require("./generators/copy-tailwind");
|
|
14
|
-
const load_config_1 = require("./utils/load-config");
|
|
15
|
-
const icons_1 = require("./commands/icons");
|
|
16
|
-
const CORE_COMPONENTS = ["Slot", "Portal"];
|
|
17
|
-
(async () => {
|
|
18
|
-
const args = process.argv.slice(2);
|
|
19
|
-
const [command, ...rest] = args;
|
|
20
|
-
if (command !== "add") {
|
|
21
|
-
console.log(chalk_1.default.blue("Usage: phpxui add [--all] [--force] <component…>"));
|
|
22
|
-
process.exit(0);
|
|
23
|
-
}
|
|
24
|
-
const flags = { all: false, force: false };
|
|
25
|
-
const names = [];
|
|
26
|
-
for (let i = 0; i < rest.length; i++) {
|
|
27
|
-
const tok = rest[i];
|
|
28
|
-
switch (tok) {
|
|
29
|
-
case "--all":
|
|
30
|
-
flags.all = true;
|
|
31
|
-
break;
|
|
32
|
-
case "--force":
|
|
33
|
-
flags.force = true;
|
|
34
|
-
break;
|
|
35
|
-
default:
|
|
36
|
-
names.push(tok);
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
/* 2) Load config + detect first run */
|
|
40
|
-
const { config, isFirstRun } = (0, load_config_1.loadPhpXUIConfig)();
|
|
41
|
-
if (!config.iconsInstalled) {
|
|
42
|
-
await (0, icons_1.installIcons)([
|
|
43
|
-
"chevron-down",
|
|
44
|
-
"x",
|
|
45
|
-
"chevron-right",
|
|
46
|
-
"ellipsis",
|
|
47
|
-
"chevron-left",
|
|
48
|
-
"arrow-left",
|
|
49
|
-
"arrow-right",
|
|
50
|
-
"check",
|
|
51
|
-
"chevrons-up-down",
|
|
52
|
-
"search",
|
|
53
|
-
"circle",
|
|
54
|
-
"calendar",
|
|
55
|
-
"minus",
|
|
56
|
-
"chevron-up",
|
|
57
|
-
"panel-left",
|
|
58
|
-
], config);
|
|
59
|
-
}
|
|
60
|
-
/* 3) Housekeeping */
|
|
61
|
-
(0, ensure_package_1.ensurePackageInstalled)("tw-animate-css");
|
|
62
|
-
// Tailwind base CSS: only forced on first run
|
|
63
|
-
const cssUpdated = (0, copy_tailwind_1.copyTailwindCss)(isFirstRun /* ignore flags.force here */);
|
|
64
|
-
if (cssUpdated) {
|
|
65
|
-
const relCss = path_1.default
|
|
66
|
-
.relative(process.cwd(), "src/app/globals.css")
|
|
67
|
-
.replace(/\\/g, "/");
|
|
68
|
-
console.log(chalk_1.default.green(isFirstRun
|
|
69
|
-
? `✔ Installed base Tailwind CSS → ${relCss}`
|
|
70
|
-
: `✔ Added Tailwind CSS (missing) → ${relCss}`));
|
|
71
|
-
}
|
|
72
|
-
/* 4) Resolve output directory */
|
|
73
|
-
const targetDir = path_1.default.resolve(config.outputDir || "src/Lib/PHPXUI");
|
|
74
|
-
try {
|
|
75
|
-
// Overwrite policy
|
|
76
|
-
const componentForce = isFirstRun || flags.force;
|
|
77
|
-
/* 5) Bulk mode */
|
|
78
|
-
if (flags.all) {
|
|
79
|
-
const { ok, fail } = await (0, php_components_bulk_1.generateAllComponents)(targetDir, componentForce);
|
|
80
|
-
console.log(chalk_1.default.green(`\n✔ Generated ${ok.length} components in ${path_1.default.relative(process.cwd(), targetDir)}`));
|
|
81
|
-
if (fail.length) {
|
|
82
|
-
console.log(chalk_1.default.red(`✖ ${fail.length} failures:`));
|
|
83
|
-
fail.forEach((m) => console.log(" •", m));
|
|
84
|
-
}
|
|
85
|
-
process.exit(fail.length ? 1 : 0);
|
|
86
|
-
}
|
|
87
|
-
/* 6) Interactive prompt if no names given */
|
|
88
|
-
if (names.length === 0) {
|
|
89
|
-
const { componentList } = await (0, prompts_1.default)({
|
|
90
|
-
type: "text",
|
|
91
|
-
name: "componentList",
|
|
92
|
-
message: "Which components do you want to add? (space- or comma-separated)",
|
|
93
|
-
validate: (v) => (v.trim() ? true : "Enter at least one name"),
|
|
94
|
-
});
|
|
95
|
-
names.push(...componentList.split(/[\s,]+/));
|
|
96
|
-
}
|
|
97
|
-
/* 6.5) Ensure core components first on first-run (unless --all) */
|
|
98
|
-
if (isFirstRun && !flags.all) {
|
|
99
|
-
for (const core of CORE_COMPONENTS) {
|
|
100
|
-
const hasCore = names.some((n) => n.toLowerCase() === core.toLowerCase());
|
|
101
|
-
if (!hasCore) {
|
|
102
|
-
// Put each core at the front in the declared order:
|
|
103
|
-
names.unshift(core);
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
/* 7) Generate each requested component */
|
|
108
|
-
for (const name of names) {
|
|
109
|
-
const saved = await (0, php_component_1.generateComponent)(name, targetDir, componentForce);
|
|
110
|
-
const paths = Array.isArray(saved) ? saved : [saved];
|
|
111
|
-
for (const abs of paths) {
|
|
112
|
-
const rel = path_1.default.relative(process.cwd(), abs).replace(/\\/g, "/");
|
|
113
|
-
console.log(chalk_1.default.green(`✔ ${name} → ${rel}`));
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
catch (err) {
|
|
118
|
-
console.error(chalk_1.default.red("✖ Error:"), err.message);
|
|
119
|
-
process.exit(1);
|
|
120
|
-
}
|
|
121
|
-
})();
|
|
2
|
+
import prompts from"prompts";import chalk from"chalk";import path from"path";import{generateComponent}from"./generators/php-component.js";import{generateAllComponents}from"./generators/php-components-bulk.js";import{ensurePackageInstalled}from"./generators/ensure-package.js";import{copyTailwindCss}from"./generators/copy-tailwind.js";import{loadPhpXUIConfig}from"./utils/load-config.js";import{installIcons}from"./commands/icons.js";import{getInstalledComponents}from"./utils/scan-installed.js";const CORE_COMPONENTS=["Slot","Portal"];(async()=>{const o=process.argv.slice(2),[e,...s]=o;"add"!==e&&"update"!==e&&(console.log(chalk.blue("Usage: phpxui <add|update> [--all] [--force] <component…>")),process.exit(0));const t={all:!1,force:!1},n=[];for(let o=0;o<s.length;o++){const e=s[o];switch(e){case"--all":t.all=!0;break;case"--force":t.force=!0;break;default:n.push(e)}}const{config:a,isFirstRun:l}=loadPhpXUIConfig();a.iconsInstalled||await installIcons(["chevron-down","x","chevron-right","ellipsis","chevron-left","arrow-left","arrow-right","check","chevrons-up-down","search","circle","calendar","minus","chevron-up","panel-left"],a),ensurePackageInstalled("tw-animate-css");if(copyTailwindCss(l)){const o=path.relative(process.cwd(),"src/app/globals.css").replace(/\\/g,"/");console.log(chalk.green(l?`✔ Installed base Tailwind CSS → ${o}`:`✔ Added Tailwind CSS (missing) → ${o}`))}const r=path.resolve(a.outputDir||"src/Lib/PHPXUI");try{if("update"===e){console.log(chalk.blue(`🔎 Scanning for installed components in ${a.outputDir}...`));const o=getInstalledComponents(r);0===o.length&&(console.log(chalk.yellow("⚠ No components found to update.")),process.exit(0)),console.log(chalk.blue(`✨ Found ${o.length} components. Updating...`));const e=[],s=[];for(const t of o)try{const o=await generateComponent(t,r,!0);(Array.isArray(o)?o:[o]).forEach(o=>e.push(path.basename(o))),console.log(chalk.green(`✔ Updated ${t}`))}catch(o){s.push(`${t}: ${o.message}`),console.log(chalk.red(`✖ Failed to update ${t}`))}console.log(chalk.green(`\n✔ Successfully updated ${e.length} components.`)),s.length>0&&(console.log(chalk.red(`✖ ${s.length} failures:`)),s.forEach(o=>console.log(` - ${o}`))),process.exit(0)}const o=l||t.force;if(t.all){const{fail:e}=await generateAllComponents(r,o);process.exit(e.length?1:0)}if(0===n.length){const{componentList:o}=await prompts({type:"text",name:"componentList",message:"Which components do you want to add? (space- or comma-separated)",validate:o=>!!o.trim()||"Enter at least one name"});n.push(...o.split(/[\s,]+/))}if(l&&!t.all)for(const o of CORE_COMPONENTS){n.some(e=>e.toLowerCase()===o.toLowerCase())||n.unshift(o)}for(const e of n){const s=await generateComponent(e,r,o),t=Array.isArray(s)?s:[s];for(const o of t){const s=path.relative(process.cwd(),o).replace(/\\/g,"/");console.log(chalk.green(`✔ ${e} → ${s}`))}}}catch(o){console.error(chalk.red("✖ Error:"),o.message),process.exit(1)}})();
|
|
@@ -1,41 +1 @@
|
|
|
1
|
-
"
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.loadPhpXUIConfig = loadPhpXUIConfig;
|
|
7
|
-
exports.savePhpXUIConfig = savePhpXUIConfig;
|
|
8
|
-
const fs_1 = __importDefault(require("fs"));
|
|
9
|
-
const path_1 = __importDefault(require("path"));
|
|
10
|
-
const defaultConfig = {
|
|
11
|
-
style: "new-york",
|
|
12
|
-
force: false,
|
|
13
|
-
outputDir: "src/Lib/PHPXUI",
|
|
14
|
-
iconsInstalled: false,
|
|
15
|
-
tailwind: {
|
|
16
|
-
css: "src/app/globals.css",
|
|
17
|
-
baseColor: "neutral",
|
|
18
|
-
cssVariables: true,
|
|
19
|
-
prefix: "",
|
|
20
|
-
},
|
|
21
|
-
psr4: {
|
|
22
|
-
Components: "src/Lib/PHPXUI/",
|
|
23
|
-
Icons: "src/Lib/PPIcons/",
|
|
24
|
-
},
|
|
25
|
-
iconLibrary: "ppicons",
|
|
26
|
-
};
|
|
27
|
-
// ⬇️ CHANGED: return { config, isFirstRun }
|
|
28
|
-
function loadPhpXUIConfig() {
|
|
29
|
-
const configPath = path_1.default.resolve("phpxui.json");
|
|
30
|
-
const existed = fs_1.default.existsSync(configPath);
|
|
31
|
-
if (!existed) {
|
|
32
|
-
fs_1.default.writeFileSync(configPath, JSON.stringify(defaultConfig, null, 2));
|
|
33
|
-
console.log("📦 Created default phpxui.json");
|
|
34
|
-
}
|
|
35
|
-
const content = fs_1.default.readFileSync(configPath, "utf-8");
|
|
36
|
-
return { config: JSON.parse(content), isFirstRun: !existed };
|
|
37
|
-
}
|
|
38
|
-
function savePhpXUIConfig(config) {
|
|
39
|
-
const configPath = path_1.default.resolve("phpxui.json");
|
|
40
|
-
fs_1.default.writeFileSync(configPath, JSON.stringify(config, null, 2));
|
|
41
|
-
}
|
|
1
|
+
import fs from"fs";import path from"path";const defaultConfig={style:"new-york",force:!1,outputDir:"src/Lib/PHPXUI",iconsInstalled:!1,tailwind:{css:"src/app/globals.css",baseColor:"neutral",cssVariables:!0,prefix:""},psr4:{Components:"src/Lib/PHPXUI/",Icons:"src/Lib/PPIcons/"},iconLibrary:"ppicons"};export function loadPhpXUIConfig(){const s=path.resolve("phpxui.json"),o=fs.existsSync(s);o||(fs.writeFileSync(s,JSON.stringify(defaultConfig,null,2)),console.log("📦 Created default phpxui.json"));const n=fs.readFileSync(s,"utf-8");return{config:JSON.parse(n),isFirstRun:!o}}export function savePhpXUIConfig(s){const o=path.resolve("phpxui.json");fs.writeFileSync(o,JSON.stringify(s,null,2))}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import fs from"fs-extra";import path from"path";export function getInstalledComponents(t){if(!fs.existsSync(t))return[];return fs.readdirSync(t).filter(t=>t.endsWith(".php")).map(t=>path.basename(t,".php"))}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "phpxui",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "A package for generating Prisma PHP components with a CLI interface.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
],
|
|
24
24
|
"author": "Jefferson Abraham Omier <thesteelninjacode@gmail.com>",
|
|
25
25
|
"license": "MIT",
|
|
26
|
-
"type": "
|
|
26
|
+
"type": "module",
|
|
27
27
|
"devDependencies": {
|
|
28
28
|
"@types/fs-extra": "^11.0.4",
|
|
29
29
|
"@types/node": "^24.0.13",
|