create-nativecore 0.1.0 → 0.2.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.
Files changed (175) hide show
  1. package/README.md +10 -18
  2. package/bin/index.mjs +407 -489
  3. package/package.json +4 -3
  4. package/template/.env.example +28 -0
  5. package/template/.htmlhintrc +14 -0
  6. package/template/api/data/dashboard.json +11 -0
  7. package/template/api/data/users.json +18 -0
  8. package/template/api/mockApi.js +161 -0
  9. package/template/assets/icon.svg +13 -0
  10. package/template/assets/logo.svg +25 -0
  11. package/template/eslint.config.js +94 -0
  12. package/template/index.html +137 -0
  13. package/template/manifest.json +19 -0
  14. package/template/public/.well-known/security.txt +9 -0
  15. package/template/public/_headers +24 -0
  16. package/template/public/_redirects +14 -0
  17. package/template/public/assets/icon.svg +13 -0
  18. package/template/public/assets/logo.svg +25 -0
  19. package/template/public/manifest.json +19 -0
  20. package/template/public/robots.txt +13 -0
  21. package/template/public/sitemap.xml +27 -0
  22. package/template/scripts/build-for-bots.mjs +121 -0
  23. package/template/scripts/convert-to-ts.mjs +106 -0
  24. package/template/scripts/fix-encoding.mjs +38 -0
  25. package/template/scripts/fix-svg-paths.mjs +32 -0
  26. package/template/scripts/generate-cf-router.mjs +52 -0
  27. package/template/scripts/inject-dev-tools.mjs +41 -0
  28. package/template/scripts/inject-version.mjs +65 -0
  29. package/template/scripts/make-component.mjs +445 -0
  30. package/template/scripts/make-component.mjs.backup +432 -0
  31. package/template/scripts/make-controller.mjs +119 -0
  32. package/template/scripts/make-core-component.mjs +303 -0
  33. package/template/scripts/make-view.mjs +346 -0
  34. package/template/scripts/minify.mjs +71 -0
  35. package/template/scripts/prepare-static-assets.mjs +141 -0
  36. package/template/scripts/prompt-bot-build.mjs +223 -0
  37. package/template/scripts/remove-component.mjs +170 -0
  38. package/template/scripts/remove-core-component.mjs +156 -0
  39. package/template/scripts/remove-dev.mjs +13 -0
  40. package/template/scripts/remove-view.mjs +200 -0
  41. package/template/scripts/strip-dev-blocks.mjs +30 -0
  42. package/template/scripts/watch-compile.mjs +69 -0
  43. package/template/server.js +1066 -0
  44. package/template/src/app.ts +115 -0
  45. package/template/src/components/appRegistry.ts +8 -0
  46. package/template/src/components/core/app-footer.ts +27 -0
  47. package/template/src/components/core/app-header.ts +175 -0
  48. package/template/src/components/core/app-sidebar.ts +238 -0
  49. package/template/src/components/core/loading-spinner.ts +25 -0
  50. package/template/src/components/core/nc-a.ts +313 -0
  51. package/template/src/components/core/nc-accordion.ts +186 -0
  52. package/template/src/components/core/nc-alert.ts +153 -0
  53. package/template/src/components/core/nc-animation.ts +1150 -0
  54. package/template/src/components/core/nc-autocomplete.ts +271 -0
  55. package/template/src/components/core/nc-avatar-group.ts +113 -0
  56. package/template/src/components/core/nc-avatar.ts +148 -0
  57. package/template/src/components/core/nc-badge.ts +86 -0
  58. package/template/src/components/core/nc-bottom-nav.ts +214 -0
  59. package/template/src/components/core/nc-breadcrumb.ts +96 -0
  60. package/template/src/components/core/nc-button.ts +307 -0
  61. package/template/src/components/core/nc-card.ts +160 -0
  62. package/template/src/components/core/nc-checkbox.ts +282 -0
  63. package/template/src/components/core/nc-chip.ts +115 -0
  64. package/template/src/components/core/nc-code.ts +314 -0
  65. package/template/src/components/core/nc-collapsible.ts +154 -0
  66. package/template/src/components/core/nc-color-picker.ts +268 -0
  67. package/template/src/components/core/nc-copy-button.ts +119 -0
  68. package/template/src/components/core/nc-date-picker.ts +443 -0
  69. package/template/src/components/core/nc-div.ts +280 -0
  70. package/template/src/components/core/nc-divider.ts +81 -0
  71. package/template/src/components/core/nc-drawer.ts +230 -0
  72. package/template/src/components/core/nc-dropdown.ts +178 -0
  73. package/template/src/components/core/nc-empty-state.ts +134 -0
  74. package/template/src/components/core/nc-file-upload.ts +354 -0
  75. package/template/src/components/core/nc-form.ts +312 -0
  76. package/template/src/components/core/nc-image.ts +184 -0
  77. package/template/src/components/core/nc-input.ts +383 -0
  78. package/template/src/components/core/nc-kbd.ts +48 -0
  79. package/template/src/components/core/nc-menu-item.ts +193 -0
  80. package/template/src/components/core/nc-menu.ts +376 -0
  81. package/template/src/components/core/nc-modal.ts +238 -0
  82. package/template/src/components/core/nc-nav-item.ts +151 -0
  83. package/template/src/components/core/nc-number-input.ts +350 -0
  84. package/template/src/components/core/nc-otp-input.ts +235 -0
  85. package/template/src/components/core/nc-pagination.ts +178 -0
  86. package/template/src/components/core/nc-popover.ts +260 -0
  87. package/template/src/components/core/nc-progress-circular.ts +119 -0
  88. package/template/src/components/core/nc-progress.ts +134 -0
  89. package/template/src/components/core/nc-radio.ts +235 -0
  90. package/template/src/components/core/nc-rating.ts +266 -0
  91. package/template/src/components/core/nc-rich-text.ts +283 -0
  92. package/template/src/components/core/nc-scroll-top.ts +116 -0
  93. package/template/src/components/core/nc-select.ts +452 -0
  94. package/template/src/components/core/nc-skeleton.ts +107 -0
  95. package/template/src/components/core/nc-slider.ts +285 -0
  96. package/template/src/components/core/nc-snackbar.ts +230 -0
  97. package/template/src/components/core/nc-splash.ts +343 -0
  98. package/template/src/components/core/nc-stepper.ts +247 -0
  99. package/template/src/components/core/nc-switch.ts +281 -0
  100. package/template/src/components/core/nc-tab-item.ts +138 -0
  101. package/template/src/components/core/nc-table.ts +279 -0
  102. package/template/src/components/core/nc-tabs.ts +554 -0
  103. package/template/src/components/core/nc-tag-input.ts +279 -0
  104. package/template/src/components/core/nc-textarea.ts +216 -0
  105. package/template/src/components/core/nc-time-picker.ts +438 -0
  106. package/template/src/components/core/nc-timeline.ts +186 -0
  107. package/template/src/components/core/nc-tooltip.ts +143 -0
  108. package/template/src/components/frameworkRegistry.ts +68 -0
  109. package/template/src/components/preloadRegistry.ts +28 -0
  110. package/template/src/components/registry.ts +8 -0
  111. package/template/src/components/ui/dashboard-signal-lab.ts +284 -0
  112. package/template/src/constants/apiEndpoints.ts +27 -0
  113. package/template/src/constants/errorMessages.ts +23 -0
  114. package/template/src/constants/index.ts +8 -0
  115. package/template/src/constants/routePaths.ts +15 -0
  116. package/template/src/constants/storageKeys.ts +18 -0
  117. package/template/src/controllers/dashboard.controller.ts +200 -0
  118. package/template/src/controllers/home.controller.ts +21 -0
  119. package/template/src/controllers/index.ts +11 -0
  120. package/template/src/controllers/login.controller.ts +131 -0
  121. package/template/src/core/component.ts +354 -0
  122. package/template/src/core/errorHandler.ts +85 -0
  123. package/template/src/core/gpu-animation.ts +604 -0
  124. package/template/src/core/http.ts +173 -0
  125. package/template/src/core/lazyComponents.ts +90 -0
  126. package/template/src/core/router.ts +642 -0
  127. package/template/src/core/signals.ts +146 -0
  128. package/template/src/core/state.ts +248 -0
  129. package/template/src/dev/component-editor.ts +1363 -0
  130. package/template/src/dev/component-overlay.ts +278 -0
  131. package/template/src/dev/context-menu.ts +223 -0
  132. package/template/src/dev/denc-tools.ts +250 -0
  133. package/template/src/dev/hmr.ts +189 -0
  134. package/template/src/dev/nfbs.code-workspace +27 -0
  135. package/template/src/dev/outline-panel.ts +1247 -0
  136. package/template/src/middleware/auth.middleware.ts +23 -0
  137. package/template/src/routes/routes.ts +38 -0
  138. package/template/src/services/api.service.ts +394 -0
  139. package/template/src/services/auth.service.ts +176 -0
  140. package/template/src/services/index.ts +8 -0
  141. package/template/src/services/logger.service.ts +74 -0
  142. package/template/src/services/storage.service.ts +88 -0
  143. package/template/src/stores/appStore.ts +57 -0
  144. package/template/src/stores/uiStore.ts +36 -0
  145. package/template/src/styles/core-variables.css +219 -0
  146. package/template/src/styles/core.css +710 -0
  147. package/template/src/styles/main.css +3164 -0
  148. package/template/src/styles/variables.css +152 -0
  149. package/template/src/types/global.d.ts +47 -0
  150. package/template/src/utils/cacheBuster.ts +20 -0
  151. package/template/src/utils/dom.ts +149 -0
  152. package/template/src/utils/events.ts +203 -0
  153. package/template/src/utils/form.ts +176 -0
  154. package/template/src/utils/formatters.ts +169 -0
  155. package/template/src/utils/helpers.ts +195 -0
  156. package/template/src/utils/markdown.ts +307 -0
  157. package/template/src/utils/sidebar.ts +96 -0
  158. package/template/src/utils/smoothScroll.ts +85 -0
  159. package/template/src/utils/templates.ts +23 -0
  160. package/template/src/utils/validation.ts +73 -0
  161. package/template/src/views/protected/dashboard.html +293 -0
  162. package/template/src/views/public/home.html +150 -0
  163. package/template/src/views/public/login.html +102 -0
  164. package/template/tests/unit/component.test.ts +87 -0
  165. package/template/tests/unit/computed.test.ts +79 -0
  166. package/template/tests/unit/form.test.ts +68 -0
  167. package/template/tests/unit/formatters.test.ts +49 -0
  168. package/template/tests/unit/lazy-components.test.ts +59 -0
  169. package/template/tests/unit/markdown.test.ts +62 -0
  170. package/template/tests/unit/router.test.ts +112 -0
  171. package/template/tests/unit/signals.test.ts +54 -0
  172. package/template/tests/unit/validation.test.ts +50 -0
  173. package/template/tsconfig.build.json +21 -0
  174. package/template/tsconfig.json +51 -0
  175. package/template/vitest.config.ts +36 -0
@@ -0,0 +1,156 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Core Component Removal Script
5
+ * Removes core component file and imports from preloadRegistry.ts
6
+ *
7
+ * Usage:
8
+ * node scripts/remove-core-component.mjs nc-button
9
+ * npm run remove:core-component nc-button
10
+ */
11
+
12
+ import fs from 'fs';
13
+ import path from 'path';
14
+ import { fileURLToPath } from 'url';
15
+
16
+ const __filename = fileURLToPath(import.meta.url);
17
+ const __dirname = path.dirname(__filename);
18
+
19
+ // Get component name from command line
20
+ const componentName = process.argv[2];
21
+
22
+ if (!componentName) {
23
+ console.error('❌ Error: Component name is required');
24
+ console.log('\nUsage:');
25
+ console.log(' npm run remove:core-component <name>');
26
+ console.log('\nExample:');
27
+ console.log(' npm run remove:core-component nc-button');
28
+ process.exit(1);
29
+ }
30
+
31
+ // Validate component name format
32
+ if (!/^[a-z][a-z0-9]*(-[a-z0-9]+)+$/.test(componentName)) {
33
+ console.error('❌ Error: Component name must be in kebab-case with at least one hyphen');
34
+ process.exit(1);
35
+ }
36
+
37
+ // Paths
38
+ const componentsDir = path.resolve(__dirname, '..', 'src', 'components');
39
+ const coreDir = path.join(componentsDir, 'core');
40
+ const componentFile = path.join(coreDir, `${componentName}.ts`);
41
+ const preloadFile = path.join(componentsDir, 'preloadRegistry.ts');
42
+
43
+ console.log(`\n🗑️ Removing core component: ${componentName}\n`);
44
+
45
+ // Step 1: Check if component file exists
46
+ if (!fs.existsSync(componentFile)) {
47
+ console.error(`❌ Error: Core component file "${componentName}.ts" does not exist`);
48
+ console.log(` Expected location: src/components/core/${componentName}.ts`);
49
+ process.exit(1);
50
+ }
51
+
52
+ // Step 2: Remove from preloadRegistry.ts
53
+ let removedFromPreload = false;
54
+ if (fs.existsSync(preloadFile)) {
55
+ let preloadContent = fs.readFileSync(preloadFile, 'utf-8');
56
+ const preloadPattern = new RegExp(`import\\s+['\"]\\./core/${componentName}\\.js['\"];?\\s*\\n`, 'g');
57
+
58
+ if (preloadPattern.test(preloadContent)) {
59
+ preloadContent = preloadContent.replace(preloadPattern, '');
60
+ fs.writeFileSync(preloadFile, preloadContent);
61
+ console.log('✅ Removed from preloadRegistry.ts');
62
+ removedFromPreload = true;
63
+ } else {
64
+ console.log('⚠️ Import not found in preloadRegistry.ts (may have been manually removed)');
65
+ }
66
+ } else {
67
+ console.log('⚠️ preloadRegistry.ts not found');
68
+ }
69
+
70
+ // Step 3: Find and list usages in codebase
71
+ console.log(`\n🔍 Searching for <${componentName}> usage in codebase...`);
72
+
73
+ const usagePattern = new RegExp(`<${componentName}[^>]*>`, 'g');
74
+ const closingPattern = new RegExp(`</${componentName}>`, 'g');
75
+ const usages = [];
76
+
77
+ // Search in specific directories
78
+ const searchDirs = [
79
+ path.resolve(__dirname, '..', 'src', 'views', 'pages'),
80
+ path.resolve(__dirname, '..', 'src', 'components'),
81
+ path.resolve(__dirname, '..', 'src', 'controllers'),
82
+ path.resolve(__dirname, '..', 'index.html'),
83
+ ];
84
+
85
+ function searchDirectory(dirPath) {
86
+ if (!fs.existsSync(dirPath)) return;
87
+
88
+ const stat = fs.statSync(dirPath);
89
+
90
+ if (stat.isDirectory()) {
91
+ const files = fs.readdirSync(dirPath, { withFileTypes: true });
92
+
93
+ for (const file of files) {
94
+ const fullPath = path.join(dirPath, file.name);
95
+
96
+ if (file.isDirectory()) {
97
+ searchDirectory(fullPath);
98
+ } else if (file.name.endsWith('.html') || file.name.endsWith('.ts')) {
99
+ checkFileForUsage(fullPath);
100
+ }
101
+ }
102
+ } else if (stat.isFile()) {
103
+ checkFileForUsage(dirPath);
104
+ }
105
+ }
106
+
107
+ function checkFileForUsage(filePath) {
108
+ // Skip the component file itself
109
+ if (filePath === componentFile) return;
110
+
111
+ const content = fs.readFileSync(filePath, 'utf-8');
112
+ const openingMatches = content.match(usagePattern);
113
+ const closingMatches = content.match(closingPattern);
114
+
115
+ if (openingMatches || closingMatches) {
116
+ const relativePath = path.relative(path.resolve(__dirname, '..'), filePath);
117
+ usages.push({
118
+ file: relativePath,
119
+ count: (openingMatches?.length || 0) + (closingMatches?.length || 0)
120
+ });
121
+ }
122
+ }
123
+
124
+ searchDirs.forEach(searchDirectory);
125
+
126
+ // Step 4: Display usages and warning
127
+ if (usages.length > 0) {
128
+ console.log(`\n⚠️ WARNING: Found usage in ${usages.length} file(s):\n`);
129
+
130
+ for (const usage of usages) {
131
+ console.log(` - ${usage.file} (${usage.count} occurrence${usage.count > 1 ? 's' : ''})`);
132
+ }
133
+
134
+ console.log(`\n⚠️ Core components are framework components used across the app.`);
135
+ console.log(` Removing them may break functionality. Please review usages carefully.\n`);
136
+ console.log(`❌ Aborting removal. Please manually remove usages first.\n`);
137
+ process.exit(1);
138
+ }
139
+
140
+ // Step 5: Delete the component file
141
+ try {
142
+ fs.unlinkSync(componentFile);
143
+ console.log(`✅ Deleted component file: src/components/core/${componentName}.ts`);
144
+ } catch (error) {
145
+ console.error(`❌ Error deleting component file: ${error.message}`);
146
+ process.exit(1);
147
+ }
148
+
149
+ // Summary
150
+ console.log(`\n✅ Core component "${componentName}" removed successfully!\n`);
151
+ console.log('📝 Summary:');
152
+ console.log(` ✓ Deleted: src/components/core/${componentName}.ts`);
153
+ if (removedFromPreload) {
154
+ console.log(` ✓ Removed from: src/components/preloadRegistry.ts`);
155
+ }
156
+ console.log('');
@@ -0,0 +1,13 @@
1
+ // scripts/remove-dev.mjs
2
+ // Remove dev folder from dist for production builds
3
+ import { rmSync, existsSync } from 'fs';
4
+ import { join } from 'path';
5
+
6
+ const devPath = join(process.cwd(), 'dist', 'dev');
7
+
8
+ if (existsSync(devPath)) {
9
+ rmSync(devPath, { recursive: true, force: true });
10
+ console.log('🗑️ Removed dist/dev folder (denc-only files excluded from production)');
11
+ } else {
12
+ console.log('✓ No dist/dev folder found (already clean)');
13
+ }
@@ -0,0 +1,200 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * View Removal Script
5
+ * Removes views (HTML pages) and their associated controllers
6
+ *
7
+ * Usage:
8
+ * node scripts/remove-view.mjs profile
9
+ * npm run remove:view profile
10
+ */
11
+
12
+ import fs from 'fs';
13
+ import path from 'path';
14
+ import readline from 'readline';
15
+ import { fileURLToPath } from 'url';
16
+ import { generateCfRouter } from './generate-cf-router.mjs';
17
+
18
+ const __filename = fileURLToPath(import.meta.url);
19
+ const __dirname = path.dirname(__filename);
20
+
21
+ // Get view name from command line
22
+ const viewName = process.argv[2];
23
+
24
+ if (!viewName) {
25
+ console.error('❌ Error: View name is required');
26
+ console.log('\nUsage:');
27
+ console.log(' npm run remove:view <name>');
28
+ console.log('\nExample:');
29
+ console.log(' npm run remove:view profile');
30
+ process.exit(1);
31
+ }
32
+
33
+ // Create readline interface for prompts
34
+ const rl = readline.createInterface({
35
+ input: process.stdin,
36
+ output: process.stdout
37
+ });
38
+
39
+ // Promisify question
40
+ function question(query) {
41
+ return new Promise(resolve => rl.question(query, resolve));
42
+ }
43
+
44
+ // Generate controller name (camelCase)
45
+ const controllerName = viewName
46
+ .split('-')
47
+ .map((word, index) =>
48
+ index === 0 ? word : word.charAt(0).toUpperCase() + word.slice(1)
49
+ )
50
+ .join('');
51
+
52
+ async function removeView() {
53
+ try {
54
+ // Check for view in both public and protected folders
55
+ const publicViewPath = path.resolve(__dirname, '..', 'src', 'views', 'public', `${viewName}.html`);
56
+ const protectedViewPath = path.resolve(__dirname, '..', 'src', 'views', 'protected', `${viewName}.html`);
57
+
58
+ let viewPath = null;
59
+ let isProtected = false;
60
+
61
+ if (fs.existsSync(publicViewPath)) {
62
+ viewPath = publicViewPath;
63
+ isProtected = false;
64
+ } else if (fs.existsSync(protectedViewPath)) {
65
+ viewPath = protectedViewPath;
66
+ isProtected = true;
67
+ } else {
68
+ console.error(`❌ Error: View "${viewName}.html" not found in public or protected folders`);
69
+ rl.close();
70
+ process.exit(1);
71
+ }
72
+
73
+ // Check for controller
74
+ const controllerPath = path.resolve(__dirname, '..', 'src', 'controllers', `${viewName}.controller.ts`);
75
+ const hasController = fs.existsSync(controllerPath);
76
+
77
+ // Show what will be deleted
78
+ console.log('\n📋 Files to be deleted:');
79
+ console.log(` - ${path.relative(process.cwd(), viewPath)}`);
80
+ if (hasController) {
81
+ console.log(` - ${path.relative(process.cwd(), controllerPath)}`);
82
+ }
83
+ console.log('\n📝 Updates to be made:');
84
+ if (hasController) {
85
+ console.log(' - Remove from src/controllers/index.ts');
86
+ }
87
+ console.log(' - Remove from src/routes/routes.ts');
88
+ if (isProtected) {
89
+ console.log(' - Remove from protected routes array');
90
+ }
91
+
92
+ // Confirm deletion
93
+ const confirm = await question('\n⚠️ Are you sure you want to delete this view? (y/n): ');
94
+
95
+ if (confirm.toLowerCase() !== 'y') {
96
+ console.log('❌ Deletion cancelled');
97
+ rl.close();
98
+ process.exit(0);
99
+ }
100
+
101
+ rl.close();
102
+
103
+ // Delete view file
104
+ fs.unlinkSync(viewPath);
105
+ console.log(`✅ Deleted: ${path.relative(process.cwd(), viewPath)}`);
106
+
107
+ // Delete controller if exists
108
+ if (hasController) {
109
+ fs.unlinkSync(controllerPath);
110
+ console.log(`✅ Deleted: ${path.relative(process.cwd(), controllerPath)}`);
111
+
112
+ // Update controllers/index.ts
113
+ const controllersIndexPath = path.resolve(__dirname, '..', 'src', 'controllers', 'index.ts');
114
+ if (fs.existsSync(controllersIndexPath)) {
115
+ let indexContent = fs.readFileSync(controllersIndexPath, 'utf8');
116
+
117
+ // Remove export line
118
+ const exportPattern = new RegExp(`export \\{ ${controllerName}Controller \\} from '\\.\\/${viewName}\\.controller\\.ts';\\n`, 'g');
119
+ indexContent = indexContent.replace(exportPattern, '');
120
+
121
+ fs.writeFileSync(controllersIndexPath, indexContent);
122
+ console.log('✅ Updated: src/controllers/index.ts');
123
+ }
124
+ }
125
+
126
+ // Update routes.ts
127
+ const routesPath = path.resolve(__dirname, '..', 'src', 'routes', 'routes.ts');
128
+ if (fs.existsSync(routesPath)) {
129
+ let routesContent = fs.readFileSync(routesPath, 'utf8');
130
+
131
+ // No need to remove imports - using lazy loading (no imports at top)
132
+
133
+ // Remove route registration (handles both lazy and non-lazy formats)
134
+ const routePattern = new RegExp(`\\s*\\.register\\('\\/${viewName}'[^\\n]*\\n`, 'g');
135
+ routesContent = routesContent.replace(routePattern, '');
136
+
137
+ // Remove from protected routes array if needed
138
+ if (isProtected) {
139
+ const protectedRoutesRegex = /export const protectedRoutes = \[(.*?)\];/s;
140
+ const match = routesContent.match(protectedRoutesRegex);
141
+
142
+ if (match) {
143
+ const routes = match[1]
144
+ .split(',')
145
+ .map(r => r.trim())
146
+ .filter(r => r && r !== `'/${viewName}'`);
147
+
148
+ routesContent = routesContent.replace(
149
+ protectedRoutesRegex,
150
+ `export const protectedRoutes = [${routes.join(', ')}];`
151
+ );
152
+ }
153
+ }
154
+
155
+ fs.writeFileSync(routesPath, routesContent);
156
+ console.log('✅ Updated: src/routes/routes.ts');
157
+ generateCfRouter();
158
+ }
159
+
160
+ // Remove from navigation menus
161
+ try {
162
+ const indexPath = path.resolve(__dirname, '..', 'index.html');
163
+ let indexContent = fs.readFileSync(indexPath, 'utf-8');
164
+
165
+ // Remove from sidebar (protected) or header (public)
166
+ const sidebarPattern = new RegExp(`<a href="\\/${viewName}"[^>]*class="sidebar-item ${viewName}-link"[^>]*>[\\s\\S]*?<\\/a>\\s*`, 'g');
167
+ const headerPattern = new RegExp(`<a href="\\/${viewName}"[^>]*class="nanc-link"[^>]*>[\\s\\S]*?<\\/a>\\s*`, 'g');
168
+
169
+ indexContent = indexContent.replace(sidebarPattern, '');
170
+ indexContent = indexContent.replace(headerPattern, '');
171
+
172
+ fs.writeFileSync(indexPath, indexContent);
173
+ console.log('✅ Removed from navigation');
174
+
175
+ // Also update app-header.ts for public pages
176
+ if (!isProtected) {
177
+ const headerPath = path.resolve(__dirname, '..', 'src', 'components', 'app-header.ts');
178
+ if (fs.existsSync(headerPath)) {
179
+ let headerContent = fs.readFileSync(headerPath, 'utf-8');
180
+ const headerMobilePattern = new RegExp(`<a href="\\/${viewName}"[^>]*class="nanc-link"[^>]*>[\\s\\S]*?<\\/a>\\s*`, 'g');
181
+ headerContent = headerContent.replace(headerMobilePattern, '');
182
+ fs.writeFileSync(headerPath, headerContent);
183
+ console.log('✅ Removed from header component');
184
+ }
185
+ }
186
+ } catch (e) {
187
+ console.log(`⚠️ Could not remove from navigation (may need manual cleanup)`);
188
+ }
189
+
190
+ console.log('\n✨ View removed successfully!\n');
191
+
192
+ } catch (error) {
193
+ console.error('❌ Error:', error.message);
194
+ rl.close();
195
+ process.exit(1);
196
+ }
197
+ }
198
+
199
+ // Run the removal
200
+ removeView();
@@ -0,0 +1,30 @@
1
+ // scripts/strip-denc-blocks.mjs
2
+ // Removes <!-- DEnc-ONLY-START --> ... <!-- DEnc-ONLY-END --> blocks from HTML files
3
+ import { readFile, writeFile } from 'fs/promises';
4
+ import { resolve } from 'path';
5
+
6
+ const files = [
7
+ 'index.html',
8
+ 'dist/bot/index.html',
9
+ // Add more output HTML files as needed
10
+ ];
11
+
12
+ const DEV_BLOCK_REGEX = /<!-- DEnc-ONLY-START -->(.|\n|\r)*?<!-- DEnc-ONLY-END -->/g;
13
+
14
+ async function stripDevBlocks(file) {
15
+ try {
16
+ const path = resolve(process.cwd(), file);
17
+ let html = await readFile(path, 'utf8');
18
+ const cleaned = html.replace(DEV_BLOCK_REGEX, '');
19
+ if (cleaned !== html) {
20
+ await writeFile(path, cleaned, 'utf8');
21
+ console.log(`Stripped denc-only blocks from ${file}`);
22
+ }
23
+ } catch (err) {
24
+ // Ignore missing files
25
+ }
26
+ }
27
+
28
+ (async () => {
29
+ await Promise.all(files.map(stripDevBlocks));
30
+ })();
@@ -0,0 +1,69 @@
1
+ import { spawn } from 'child_process';
2
+
3
+ const tscArgs = ['tsc', '--watch', '--preserveWatchOutput'];
4
+ let aliasProcess = null;
5
+ let aliasQueued = false;
6
+
7
+ function runAlias() {
8
+ if (aliasProcess) {
9
+ aliasQueued = true;
10
+ return;
11
+ }
12
+
13
+ aliasProcess = spawn('npx', ['tsc-alias'], {
14
+ stdio: ['ignore', 'pipe', 'pipe'],
15
+ shell: true
16
+ });
17
+
18
+ aliasProcess.stdout.on('data', chunk => {
19
+ process.stdout.write(`[alias] ${chunk}`);
20
+ });
21
+
22
+ aliasProcess.stderr.on('data', chunk => {
23
+ process.stderr.write(`[alias] ${chunk}`);
24
+ });
25
+
26
+ aliasProcess.on('exit', code => {
27
+ if (code && code !== 0) {
28
+ process.stderr.write(`[alias] tsc-alias exited with code ${code}\n`);
29
+ }
30
+
31
+ aliasProcess = null;
32
+
33
+ if (aliasQueued) {
34
+ aliasQueued = false;
35
+ runAlias();
36
+ }
37
+ });
38
+ }
39
+
40
+ const tscProcess = spawn('npx', tscArgs, {
41
+ stdio: ['ignore', 'pipe', 'pipe'],
42
+ shell: true
43
+ });
44
+
45
+ function handleTscOutput(chunk, writer) {
46
+ const text = chunk.toString();
47
+ writer.write(text);
48
+
49
+ if (/Found 0 errors?\. Watching for file changes\./.test(text)) {
50
+ runAlias();
51
+ }
52
+ }
53
+
54
+ tscProcess.stdout.on('data', chunk => handleTscOutput(chunk, process.stdout));
55
+ tscProcess.stderr.on('data', chunk => handleTscOutput(chunk, process.stderr));
56
+
57
+ function shutdown(signal) {
58
+ if (aliasProcess) {
59
+ aliasProcess.kill(signal);
60
+ }
61
+ tscProcess.kill(signal);
62
+ }
63
+
64
+ process.on('SIGINT', () => shutdown('SIGINT'));
65
+ process.on('SIGTERM', () => shutdown('SIGTERM'));
66
+
67
+ tscProcess.on('exit', code => {
68
+ process.exit(code ?? 0);
69
+ });