create-switch-framework-app 0.1.0 → 0.2.2

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.
Files changed (37) hide show
  1. package/README.md +25 -25
  2. package/bin/create-switch-framework-app.js +48 -35
  3. package/package.json +1 -1
  4. package/templates/electron/base/app/(tabs)/+not-found.js +157 -157
  5. package/templates/electron/base/app/(tabs)/_layout.js +57 -93
  6. package/templates/electron/base/app/(tabs)/explore.js +55 -44
  7. package/templates/electron/base/app/(tabs)/index.js +10 -24
  8. package/templates/electron/base/app/+not-found.js +148 -158
  9. package/templates/electron/base/app/_layout.js +24 -44
  10. package/templates/electron/base/app/index.js +16 -30
  11. package/templates/electron/base/assets/logo.svg +5 -5
  12. package/templates/electron/base/components/SwSplashScreen.js +1 -1
  13. package/templates/electron/base/components/SwStarterSplashScreen.js +130 -140
  14. package/templates/electron/base/components/SwTabBar.js +146 -153
  15. package/templates/electron/base/electron/electron-builder.json +19 -19
  16. package/templates/electron/base/electron/main.js +30 -30
  17. package/templates/electron/base/electron/preload.js +5 -5
  18. package/templates/electron/base/index.js +2 -3
  19. package/templates/electron/base/main.js +1 -1
  20. package/templates/electron/base/preload.js +1 -1
  21. package/templates/electron/base/server.js +27 -42
  22. package/templates/web/base/app/(tabs)/+not-found.js +157 -157
  23. package/templates/web/base/app/(tabs)/_layout.js +57 -93
  24. package/templates/web/base/app/(tabs)/explore.js +55 -44
  25. package/templates/web/base/app/(tabs)/index.js +10 -24
  26. package/templates/web/base/app/+not-found.js +148 -158
  27. package/templates/web/base/app/_layout.js +24 -44
  28. package/templates/web/base/app/index.js +16 -30
  29. package/templates/web/base/assets/logo.svg +5 -5
  30. package/templates/web/base/components/SwSplashScreen.js +1 -1
  31. package/templates/web/base/components/SwStarterSplashScreen.js +130 -140
  32. package/templates/web/base/components/SwTabBar.js +146 -153
  33. package/templates/web/base/index.js +2 -3
  34. package/templates/electron/base/app/(tabs)/register.js +0 -12
  35. package/templates/electron/base/app/register.js +0 -12
  36. package/templates/web/base/app/(tabs)/register.js +0 -12
  37. package/templates/web/base/app/register.js +0 -12
package/README.md CHANGED
@@ -1,25 +1,25 @@
1
- # create-switch-framework-app
2
-
3
- Status: Under maintenance. Documentation is not ready yet.
4
-
5
- create-switch-framework-app is a CLI for initializing apps that use Switch Framework tools.
6
-
7
- It can scaffold projects for:
8
-
9
- - Web app development
10
- - Electron desktop app development
11
-
12
- ## Usage
13
-
14
- ```bash
15
- npx create-switch-framework-app my-app
16
- ```
17
-
18
- Or install globally:
19
-
20
- ```bash
21
- npm i -g create-switch-framework-app
22
- create-switch-framework-app my-app
23
- ```
24
-
25
- Made by Switcherfaiz
1
+ # create-switch-framework-app
2
+
3
+ Status: Under maintenance. Documentation is not ready yet.
4
+
5
+ create-switch-framework-app is a CLI for initializing apps that use Switch Framework tools.
6
+
7
+ It can scaffold projects for:
8
+
9
+ - Web app development
10
+ - Electron desktop app development
11
+
12
+ ## Usage
13
+
14
+ ```bash
15
+ npx create-switch-framework-app my-app
16
+ ```
17
+
18
+ Or install globally:
19
+
20
+ ```bash
21
+ npm i -g create-switch-framework-app
22
+ create-switch-framework-app my-app
23
+ ```
24
+
25
+ Made by Switcherfaiz
@@ -150,37 +150,29 @@ async function askQuestions({ projectName, yes, noInstall, appTypeOverride, port
150
150
  function serverJsTemplate({ port, appType }) {
151
151
  const staticRoot = appType === 'both' ? 'web' : '.';
152
152
 
153
- return `const express = require('express');\n` +
154
- `const session = require('express-session');\n` +
153
+ return `require('dotenv').config();\n\n` +
155
154
  `const path = require('node:path');\n` +
156
- `require('dotenv').config();\n\n` +
157
- `const { checkRestrict } = require('switch-framework-backend/middleware');\n\n` +
158
- `const app = express();\n` +
159
- `const PORT = process.env.PORT ? Number(process.env.PORT) : ${port};\n\n` +
160
- `app.use(express.json({ limit: '25mb' }));\n\n` +
161
- `app.use(session({\n` +
162
- ` secret: process.env.SESSION_SECRET || 'dev-secret',\n` +
163
- ` resave: false,\n` +
164
- ` saveUninitialized: false\n` +
165
- `}));\n\n` +
166
- `// Serve switch-framework to the browser from node_modules\n` +
167
- `app.use('/switch-framework', express.static(path.join(__dirname, 'node_modules', 'switch-framework')));\n\n` +
168
- `// Serve project files\n` +
169
- `app.use(express.static(path.join(__dirname, '${staticRoot}')));\n\n` +
170
- `const restrictConfig = {\n` +
171
- ` public: ['/', '/login'],\n` +
172
- ` rules: [\n` +
173
- ` { prefix: '/admin', roles: ['admin'] },\n` +
174
- ` { prefix: '/billing', roles: ['billing', 'admin'] },\n` +
175
- ` { path: '/login', roles: ['*'] }\n` +
176
- ` ]\n` +
177
- `};\n\n` +
178
- `app.use(checkRestrict(restrictConfig));\n\n` +
179
- `app.get('*', (req, res) => {\n` +
180
- ` res.sendFile(path.join(__dirname, '${staticRoot}', 'index.html'));\n` +
155
+ `const switchFrameworkBackend = require('switch-framework-backend');\n\n` +
156
+ `switchFrameworkBackend.config({\n` +
157
+ ` PORT: process.env.PORT ? Number(process.env.PORT) : ${port},\n` +
158
+ ` staticRoot: path.join(__dirname, '${staticRoot}'),\n` +
159
+ ` session: {\n` +
160
+ ` secret: process.env.SESSION_SECRET || 'dev-secret',\n` +
161
+ ` resave: false,\n` +
162
+ ` saveUninitialized: false\n` +
163
+ ` }\n` +
181
164
  `});\n\n` +
182
- `app.listen(PORT, () => {\n` +
183
- ` console.log('Switch Framework app running at http://localhost:' + PORT);\n` +
165
+ `const app = switchFrameworkBackend();\n\n` +
166
+ `app.initServer((server) => {\n` +
167
+ ` const restrictConfig = {\n` +
168
+ ` public: ['/', '/login'],\n` +
169
+ ` rules: [\n` +
170
+ ` { prefix: '/admin', roles: ['admin'] },\n` +
171
+ ` { prefix: '/billing', roles: ['billing', 'admin'] },\n` +
172
+ ` { path: '/login', roles: ['*'] }\n` +
173
+ ` ]\n` +
174
+ ` };\n` +
175
+ ` server.use(switchFrameworkBackend.checkRestrict(restrictConfig));\n` +
184
176
  `});\n`;
185
177
  }
186
178
 
@@ -252,8 +244,8 @@ function createPackageJson({ packageName, appType, port, useLocal }) {
252
244
  // When --use-local is set, we intentionally do NOT add switch-framework deps to package.json
253
245
  // to avoid npm registry fetching during testing. We will npm link them instead.
254
246
  if (!useLocal) {
255
- deps['switch-framework'] = '^0.1.0';
256
- deps['switch-framework-backend'] = '^0.1.0';
247
+ deps['switch-framework'] = '^0.2.1';
248
+ deps['switch-framework-backend'] = '^0.2.0';
257
249
  }
258
250
 
259
251
  const pkg = {
@@ -270,8 +262,8 @@ function createPackageJson({ packageName, appType, port, useLocal }) {
270
262
 
271
263
  if (appType === 'electron' || appType === 'both') {
272
264
  pkg.devDependencies = {
273
- electron: '^31.3.1',
274
- 'electron-builder': '^24.13.3'
265
+ electron: 'latest',
266
+ 'electron-builder': 'latest'
275
267
  };
276
268
  }
277
269
 
@@ -289,9 +281,10 @@ async function copyDir(srcDir, destDir) {
289
281
  });
290
282
  }
291
283
 
292
- async function runNpmInstall({ cwd }) {
284
+ async function runNpmInstall({ cwd, packages = [] }) {
285
+ const args = packages.length ? ['install', ...packages] : ['install'];
293
286
  return new Promise((resolve, reject) => {
294
- const child = require('node:child_process').spawn('npm', ['install'], {
287
+ const child = require('node:child_process').spawn('npm', args, {
295
288
  cwd,
296
289
  stdio: 'inherit',
297
290
  shell: process.platform === 'win32'
@@ -323,7 +316,22 @@ async function runNpmLink({ cwd, packages }) {
323
316
  });
324
317
  }
325
318
 
319
+ const DOCS_URL = 'https://github.com/Switcherfaiz/switch-framework-docs';
320
+
321
+ function getCliVersion() {
322
+ try {
323
+ const pkgPath = path.join(__dirname, '..', 'package.json');
324
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
325
+ return pkg.version || '0.0.0';
326
+ } catch {
327
+ return '0.0.0';
328
+ }
329
+ }
330
+
326
331
  async function main() {
332
+ const cliVersion = getCliVersion();
333
+ console.log(chalk.cyan(`\nWelcome to switch-framework CLI v${cliVersion}\n`));
334
+
327
335
  const { help, yes, noInstall, useLocal, appType: appTypeArg, port: portArg, projectName: rawProjectName } = parseArgs(process.argv);
328
336
  if (help) {
329
337
  printHelp();
@@ -447,6 +455,10 @@ async function main() {
447
455
  spinner.start('Installing dependencies (npm install)...');
448
456
  try {
449
457
  await runNpmInstall({ cwd: targetDir });
458
+ if (!useLocal) {
459
+ spinner.start('Ensuring switch-framework packages...');
460
+ await runNpmInstall({ cwd: targetDir, packages: ['switch-framework', 'switch-framework-backend'] });
461
+ }
450
462
  spinner.succeed('Dependencies installed');
451
463
  } catch (e) {
452
464
  spinner.warn('npm install failed (project was still created)');
@@ -491,6 +503,7 @@ async function main() {
491
503
  console.log('\nNote: web UI lives in ./web and electron files in ./electron');
492
504
  }
493
505
 
506
+ console.log('\n' + chalk.gray('Read the docs: ') + chalk.cyan(DOCS_URL));
494
507
  console.log('');
495
508
  } catch (err) {
496
509
  spinner.fail('Failed');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-switch-framework-app",
3
- "version": "0.1.0",
3
+ "version": "0.2.2",
4
4
  "description": "Create a Switch Framework app",
5
5
  "github": "https://github.com/Switcherfaiz/create-switch-framework-app",
6
6
  "author":"Switcherfaiz",
@@ -1,158 +1,158 @@
1
- export const screen = {
2
- name: '+not-found',
3
- path: '/+not-found',
4
- title: 'Not Found',
5
- tag: 'sw-user-not-found-screen',
6
- layout: 'stack'
7
- };
8
-
9
- export class SwUserNotFoundScreen extends HTMLElement {
10
- constructor() {
11
- super();
12
- this.attachShadow({ mode: 'open' });
13
- }
14
-
15
- static get observedAttributes() {
16
- return ['path'];
17
- }
18
-
19
- connectedCallback() {
20
- this.render();
21
- }
22
-
23
- attributeChangedCallback() {
24
- this.render();
25
- }
26
-
27
- render() {
28
- const path = this.getAttribute('path') || window.location.pathname || '';
29
-
30
- this.shadowRoot.innerHTML = `
31
- ${this.styleSheet()}
32
- <div class="wrap">
33
- <div class="card">
34
- <div class="code">404</div>
35
- <div class="h">This screen does not exist</div>
36
- <div class="p">No screen is registered for:</div>
37
- <div class="path">${path}</div>
38
-
39
- <div class="row">
40
- <button class="btn" id="home">Go to Home</button>
41
- <button class="btn secondary" id="back">Go Back</button>
42
- </div>
43
- </div>
44
- </div>
45
- `;
46
-
47
- this.shadowRoot.getElementById('home')?.addEventListener('click', () => {
48
- const navigate = globalStates?.getState ? globalStates.getState('navigate') : null;
49
- if (typeof navigate === 'function') navigate('home');
50
- });
51
-
52
- this.shadowRoot.getElementById('back')?.addEventListener('click', () => {
53
- const goBack = globalStates?.getState ? globalStates.getState('go_back') : null;
54
- if (typeof goBack === 'function') goBack();
55
- else window.history.back();
56
- });
57
- }
58
-
59
- styleSheet() {
60
- return `
61
- <style>
62
- :host {
63
- display: block;
64
- width: 100%;
65
- min-height: 100dvh;
66
- font-family: var(--font);
67
- }
68
-
69
- * {
70
- box-sizing: border-box;
71
- font-family: inherit;
72
- }
73
-
74
- .wrap {
75
- min-height: 100vh;
76
- display: flex;
77
- align-items: center;
78
- justify-content: center;
79
- padding: 18px;
80
- }
81
-
82
- .card {
83
- width: min(680px, 100%);
84
- background: transparent;
85
- border: none;
86
- border-radius: 18px;
87
- padding: 18px;
88
- box-shadow: none;
89
- }
90
-
91
- .code {
92
- font-weight: 1000;
93
- font-size: 44px;
94
- line-height: 1;
95
- color: var(--main_text);
96
- }
97
-
98
- .h {
99
- margin-top: 10px;
100
- font-weight: 1000;
101
- font-size: 20px;
102
- color: var(--main_text);
103
- }
104
-
105
- .p {
106
- margin-top: 6px;
107
- color: var(--sub_text);
108
- font-weight: 800;
109
- }
110
-
111
- .path {
112
- margin-top: 10px;
113
- padding: 10px 12px;
114
- border-radius: 14px;
115
- background: var(--surface_2);
116
- border: 1px solid var(--border_light);
117
- font-weight: 900;
118
- color: var(--main_text);
119
- word-break: break-word;
120
- }
121
-
122
- .row {
123
- margin-top: 14px;
124
- display: flex;
125
- gap: 10px;
126
- flex-wrap: wrap;
127
- }
128
-
129
- .btn {
130
- border: none;
131
- background: linear-gradient(135deg, #0091ff 0%, #0073e6 100%);
132
- color: #fff;
133
- font-weight: 1000;
134
- border-radius: 999px;
135
- padding: 10px 14px;
136
- cursor: pointer;
137
- }
138
-
139
- .btn:hover {
140
- opacity: 0.9;
141
- }
142
-
143
- .btn.secondary {
144
- background: var(--surface_2);
145
- color: var(--main_text);
146
- }
147
-
148
- .btn.secondary:hover {
149
- background: var(--surface_3);
150
- }
151
- </style>
152
- `;
153
- }
154
- }
155
-
156
- if (!customElements.get('sw-user-not-found-screen')) {
157
- customElements.define('sw-user-not-found-screen', SwUserNotFoundScreen);
1
+ export const screen = {
2
+ name: '+not-found',
3
+ path: '/+not-found',
4
+ title: 'Not Found',
5
+ tag: 'sw-user-not-found-screen',
6
+ layout: 'stack'
7
+ };
8
+
9
+ export class SwUserNotFoundScreen extends HTMLElement {
10
+ constructor() {
11
+ super();
12
+ this.attachShadow({ mode: 'open' });
13
+ }
14
+
15
+ static get observedAttributes() {
16
+ return ['path'];
17
+ }
18
+
19
+ connectedCallback() {
20
+ this.render();
21
+ }
22
+
23
+ attributeChangedCallback() {
24
+ this.render();
25
+ }
26
+
27
+ render() {
28
+ const path = this.getAttribute('path') || window.location.pathname || '';
29
+
30
+ this.shadowRoot.innerHTML = `
31
+ ${this.styleSheet()}
32
+ <div class="wrap">
33
+ <div class="card">
34
+ <div class="code">404</div>
35
+ <div class="h">This screen does not exist</div>
36
+ <div class="p">No screen is registered for:</div>
37
+ <div class="path">${path}</div>
38
+
39
+ <div class="row">
40
+ <button class="btn" id="home">Go to Home</button>
41
+ <button class="btn secondary" id="back">Go Back</button>
42
+ </div>
43
+ </div>
44
+ </div>
45
+ `;
46
+
47
+ this.shadowRoot.getElementById('home')?.addEventListener('click', () => {
48
+ const navigate = globalStates?.getState ? globalStates.getState('navigate') : null;
49
+ if (typeof navigate === 'function') navigate('home');
50
+ });
51
+
52
+ this.shadowRoot.getElementById('back')?.addEventListener('click', () => {
53
+ const goBack = globalStates?.getState ? globalStates.getState('go_back') : null;
54
+ if (typeof goBack === 'function') goBack();
55
+ else window.history.back();
56
+ });
57
+ }
58
+
59
+ styleSheet() {
60
+ return `
61
+ <style>
62
+ :host {
63
+ display: block;
64
+ width: 100%;
65
+ min-height: 100dvh;
66
+ font-family: var(--font);
67
+ }
68
+
69
+ * {
70
+ box-sizing: border-box;
71
+ font-family: inherit;
72
+ }
73
+
74
+ .wrap {
75
+ min-height: 100vh;
76
+ display: flex;
77
+ align-items: center;
78
+ justify-content: center;
79
+ padding: 18px;
80
+ }
81
+
82
+ .card {
83
+ width: min(680px, 100%);
84
+ background: transparent;
85
+ border: none;
86
+ border-radius: 18px;
87
+ padding: 18px;
88
+ box-shadow: none;
89
+ }
90
+
91
+ .code {
92
+ font-weight: 1000;
93
+ font-size: 44px;
94
+ line-height: 1;
95
+ color: var(--main_text);
96
+ }
97
+
98
+ .h {
99
+ margin-top: 10px;
100
+ font-weight: 1000;
101
+ font-size: 20px;
102
+ color: var(--main_text);
103
+ }
104
+
105
+ .p {
106
+ margin-top: 6px;
107
+ color: var(--sub_text);
108
+ font-weight: 800;
109
+ }
110
+
111
+ .path {
112
+ margin-top: 10px;
113
+ padding: 10px 12px;
114
+ border-radius: 14px;
115
+ background: var(--surface_2);
116
+ border: 1px solid var(--border_light);
117
+ font-weight: 900;
118
+ color: var(--main_text);
119
+ word-break: break-word;
120
+ }
121
+
122
+ .row {
123
+ margin-top: 14px;
124
+ display: flex;
125
+ gap: 10px;
126
+ flex-wrap: wrap;
127
+ }
128
+
129
+ .btn {
130
+ border: none;
131
+ background: linear-gradient(135deg, #0091ff 0%, #0073e6 100%);
132
+ color: #fff;
133
+ font-weight: 1000;
134
+ border-radius: 999px;
135
+ padding: 10px 14px;
136
+ cursor: pointer;
137
+ }
138
+
139
+ .btn:hover {
140
+ opacity: 0.9;
141
+ }
142
+
143
+ .btn.secondary {
144
+ background: var(--surface_2);
145
+ color: var(--main_text);
146
+ }
147
+
148
+ .btn.secondary:hover {
149
+ background: var(--surface_3);
150
+ }
151
+ </style>
152
+ `;
153
+ }
154
+ }
155
+
156
+ if (!customElements.get('sw-user-not-found-screen')) {
157
+ customElements.define('sw-user-not-found-screen', SwUserNotFoundScreen);
158
158
  }