@clubz/cli 0.1.0 → 0.1.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 ADDED
@@ -0,0 +1,82 @@
1
+ # @clubz/cli
2
+
3
+ The official Command Line Interface for building widgets and pages for the **Clubz Community Builder**.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install -g @clubz/cli
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ### 1. Create a new Widget
14
+
15
+ Scaffold a new widget project with the official React + Vite + TypeScript template.
16
+
17
+ ```bash
18
+ clubz init my-awesome-widget
19
+ cd my-awesome-widget
20
+ npm install
21
+ ```
22
+
23
+ ### 2. Develop Locally (Simulator)
24
+
25
+ Start the local development server. This launches a **Local Simulator** that mimics the Clubz mobile environment (IFrame, SDK communication, etc.), allowing you to test your widget in isolation.
26
+
27
+ ```bash
28
+ npm run dev
29
+ # OR
30
+ clubz dev
31
+ ```
32
+
33
+ The simulator will open at `http://localhost:3000` (or the next available port).
34
+
35
+ ### 3. Deploy
36
+
37
+ Package your widget and deploy it to the Clubz platform.
38
+
39
+ ```bash
40
+ npm run deploy
41
+ # OR
42
+ clubz deploy
43
+ ```
44
+
45
+ ## Project Structure
46
+
47
+ A standard Clubz widget project looks like this:
48
+
49
+ ```
50
+ my-widget/
51
+ ├── src/
52
+ │ ├── App.tsx # Your main widget code
53
+ │ └── main.tsx # Entry point
54
+ ├── clubz.json # Widget metadata (name, version, permissions)
55
+ ├── package.json
56
+ └── vite.config.ts # Vite configuration
57
+ ```
58
+
59
+ ## SDK Integration
60
+
61
+ The CLI templates come pre-configured with `@clubz/sdk`. Use it to interact with the host application:
62
+
63
+ ```ts
64
+ import { bridge } from '@clubz/sdk';
65
+
66
+ // Get user info
67
+ const user = await bridge.getUser();
68
+
69
+ // Show a native toast
70
+ await bridge.showToast({ message: 'Hello from Widget!', type: 'success' });
71
+ ```
72
+
73
+ ## Contributing
74
+
75
+ This CLI is part of the Clubz monorepo.
76
+
77
+ ### Local Setup
78
+
79
+ 1. Clone the repository.
80
+ 2. Install dependencies: `npm install`
81
+ 3. Build the CLI: `npm run build`
82
+ 4. Link globally for testing: `npm link`
@@ -31,8 +31,8 @@ async function initCommand(name) {
31
31
  let templateDir = path_1.default.join(__dirname, '../../templates', templateName); // from dist/commands or src/commands
32
32
  // Fallback if structure is different (e.g. src vs dist) - explicit check
33
33
  if (!fs_extra_1.default.existsSync(templateDir)) {
34
- // Try source path if we are running ts-node directly?
35
- templateDir = path_1.default.join(__dirname, '../../../src/templates', templateName);
34
+ // Try source path if we are running from dist but templates are in src (common in local dev)
35
+ templateDir = path_1.default.join(__dirname, '../../src/templates', templateName);
36
36
  }
37
37
  if (!fs_extra_1.default.existsSync(templateDir)) {
38
38
  console.error(chalk_1.default.red(`❌ Template not found at ${templateDir}`));
@@ -0,0 +1,21 @@
1
+ {
2
+ "name": "My Amazing Widget",
3
+ "description": "A widget built for Clubz",
4
+ "version": "1.0.0",
5
+ "type": "widget",
6
+ "config": {
7
+ "props": [
8
+ {
9
+ "name": "title",
10
+ "type": "string",
11
+ "label": "Titre du widget",
12
+ "default": "Hello World"
13
+ }
14
+ ]
15
+ },
16
+ "permissions": [],
17
+ "tags": [
18
+ "beta",
19
+ "react"
20
+ ]
21
+ }
@@ -0,0 +1,13 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>Clubz Widget</title>
7
+ </head>
8
+ <body>
9
+ <div id="root"></div>
10
+ <script type="module" src="/src/main.tsx"></script>
11
+ <script src="https://cdn.tailwindcss.com"></script>
12
+ </body>
13
+ </html>
@@ -0,0 +1,23 @@
1
+ {
2
+ "name": "my-clubz-widget",
3
+ "private": true,
4
+ "version": "0.0.0",
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "vite",
8
+ "build": "tsc && vite build",
9
+ "preview": "vite preview"
10
+ },
11
+ "dependencies": {
12
+ "react": "^18.2.0",
13
+ "react-dom": "^18.2.0",
14
+ "@clubz/sdk": "latest"
15
+ },
16
+ "devDependencies": {
17
+ "@types/react": "^18.2.66",
18
+ "@types/react-dom": "^18.2.22",
19
+ "@vitejs/plugin-react": "^4.2.1",
20
+ "typescript": "^5.2.2",
21
+ "vite": "^5.2.0"
22
+ }
23
+ }
@@ -0,0 +1,35 @@
1
+ import { useEffect, useState } from 'react'
2
+ import { bridge } from '@clubz/sdk'
3
+
4
+ function App() {
5
+ const [user, setUser] = useState<{ name: string } | null>(null)
6
+
7
+ useEffect(() => {
8
+ // Determine user context via Bridge
9
+ bridge.getUser().then((u: any) => setUser(u)).catch(() => console.log('Guest mode'))
10
+ }, [])
11
+
12
+ const handleVibrate = () => {
13
+ bridge.vibrate();
14
+ }
15
+
16
+ return (
17
+ <div className="w-full h-full min-h-[200px] bg-white rounded-xl p-6 border border-slate-200 flex flex-col items-center justify-center">
18
+ <h1 className="text-xl font-bold text-slate-800 mb-2">
19
+ Hello {user ? user.name : 'Guest'}!
20
+ </h1>
21
+ <p className="text-slate-500 text-center mb-4">
22
+ Welcome to your new Clubz Widget.
23
+ </p>
24
+
25
+ <button
26
+ onClick={handleVibrate}
27
+ className="px-4 py-2 bg-blue-600 text-white rounded-lg active:bg-blue-700 transition"
28
+ >
29
+ Test Vibration
30
+ </button>
31
+ </div>
32
+ )
33
+ }
34
+
35
+ export default App
@@ -0,0 +1,9 @@
1
+ import React from 'react'
2
+ import ReactDOM from 'react-dom/client'
3
+ import App from './App.tsx'
4
+
5
+ ReactDOM.createRoot(document.getElementById('root')!).render(
6
+ <React.StrictMode>
7
+ <App />
8
+ </React.StrictMode>,
9
+ )
@@ -0,0 +1,18 @@
1
+ import { defineConfig } from 'vite'
2
+ import react from '@vitejs/plugin-react'
3
+
4
+ // https://vitejs.dev/config/
5
+ export default defineConfig({
6
+ plugins: [react()],
7
+ build: {
8
+ rollupOptions: {
9
+ output: {
10
+ // Ensure we get a single recognizable entry point if possible,
11
+ // though standard vite build is fine for the platform zipper.
12
+ entryFileNames: 'assets/[name].js',
13
+ chunkFileNames: 'assets/[name].js',
14
+ assetFileNames: 'assets/[name].[ext]'
15
+ }
16
+ }
17
+ }
18
+ })
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@clubz/cli",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "bin": {
5
5
  "clubz": "bin/clubz.js"
6
6
  },
7
7
  "main": "dist/index.js",
8
8
  "scripts": {
9
- "build": "tsc",
9
+ "build": "tsc && cp -r src/templates dist/templates",
10
10
  "dev": "tsc -w"
11
11
  },
12
12
  "publishConfig": {
@@ -33,8 +33,8 @@ export async function initCommand(name: string) {
33
33
 
34
34
  // Fallback if structure is different (e.g. src vs dist) - explicit check
35
35
  if (!fs.existsSync(templateDir)) {
36
- // Try source path if we are running ts-node directly?
37
- templateDir = path.join(__dirname, '../../../src/templates', templateName);
36
+ // Try source path if we are running from dist but templates are in src (common in local dev)
37
+ templateDir = path.join(__dirname, '../../src/templates', templateName);
38
38
  }
39
39
 
40
40
  if (!fs.existsSync(templateDir)) {