@nitrostack/cli 1.0.14 → 1.0.15

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 (49) hide show
  1. package/assets/canonical.gitignore +57 -0
  2. package/dist/commands/init.d.ts.map +1 -1
  3. package/dist/commands/init.js +8 -7
  4. package/dist/commands/pack.d.ts +10 -0
  5. package/dist/commands/pack.d.ts.map +1 -0
  6. package/dist/commands/pack.js +82 -0
  7. package/dist/index.d.ts +2 -0
  8. package/dist/index.d.ts.map +1 -1
  9. package/dist/index.js +12 -0
  10. package/dist/pack/canonical-gitignore.d.ts +14 -0
  11. package/dist/pack/canonical-gitignore.d.ts.map +1 -0
  12. package/dist/pack/canonical-gitignore.js +28 -0
  13. package/dist/pack/exclusions.d.ts +8 -0
  14. package/dist/pack/exclusions.d.ts.map +1 -0
  15. package/dist/pack/exclusions.js +84 -0
  16. package/dist/pack/gitignore.d.ts +21 -0
  17. package/dist/pack/gitignore.d.ts.map +1 -0
  18. package/dist/pack/gitignore.js +123 -0
  19. package/dist/pack/ignore-matcher.d.ts +19 -0
  20. package/dist/pack/ignore-matcher.d.ts.map +1 -0
  21. package/dist/pack/ignore-matcher.js +149 -0
  22. package/dist/pack/index.d.ts +11 -0
  23. package/dist/pack/index.d.ts.map +1 -0
  24. package/dist/pack/index.js +8 -0
  25. package/dist/pack/pack-project.d.ts +6 -0
  26. package/dist/pack/pack-project.d.ts.map +1 -0
  27. package/dist/pack/pack-project.js +59 -0
  28. package/dist/pack/standalone.d.ts +3 -0
  29. package/dist/pack/standalone.d.ts.map +1 -0
  30. package/dist/pack/standalone.js +95 -0
  31. package/dist/pack/tree.d.ts +5 -0
  32. package/dist/pack/tree.d.ts.map +1 -0
  33. package/dist/pack/tree.js +70 -0
  34. package/dist/pack/types.d.ts +35 -0
  35. package/dist/pack/types.d.ts.map +1 -0
  36. package/dist/pack/types.js +1 -0
  37. package/dist/pack/validate-project.d.ts +9 -0
  38. package/dist/pack/validate-project.d.ts.map +1 -0
  39. package/dist/pack/validate-project.js +44 -0
  40. package/dist/pack/zipper.d.ts +20 -0
  41. package/dist/pack/zipper.d.ts.map +1 -0
  42. package/dist/pack/zipper.js +121 -0
  43. package/package.json +6 -3
  44. package/templates/typescript-oauth/.env.example +1 -1
  45. package/templates/typescript-oauth/_gitignore +57 -0
  46. package/templates/typescript-pizzaz/.env.example +1 -1
  47. package/templates/typescript-pizzaz/_gitignore +57 -0
  48. package/templates/typescript-starter/.env.example +1 -1
  49. package/templates/typescript-starter/_gitignore +57 -0
@@ -0,0 +1,121 @@
1
+ import path from 'path';
2
+ import fs from 'fs';
3
+ import { createWriteStream } from 'fs';
4
+ import archiver from 'archiver';
5
+ import { isPathIgnored } from './gitignore.js';
6
+ /** True when realPath is the root or a descendant of rootReal. */
7
+ function isInsideRoot(realPath, rootReal) {
8
+ const relative = path.relative(rootReal, realPath);
9
+ return relative === '' || (!relative.startsWith('..') && !path.isAbsolute(relative));
10
+ }
11
+ /**
12
+ * Collect relative file paths that should be included, and pruned excluded roots.
13
+ * Excluded directories are recorded once and not descended into.
14
+ * Symlinks are resolved via stat/realpath so:
15
+ * - symlink-to-directory is walked (not archived as a file)
16
+ * - cycles and targets outside the project root are skipped
17
+ */
18
+ export async function collectFilesToPack(projectRoot, matcher) {
19
+ const includedPaths = [];
20
+ const excludedPaths = [];
21
+ const visitedDirs = new Set();
22
+ let projectRootReal;
23
+ try {
24
+ projectRootReal = await fs.promises.realpath(projectRoot);
25
+ }
26
+ catch {
27
+ projectRootReal = path.resolve(projectRoot);
28
+ }
29
+ async function walk(currentDir) {
30
+ let currentReal;
31
+ try {
32
+ currentReal = await fs.promises.realpath(currentDir);
33
+ }
34
+ catch {
35
+ return;
36
+ }
37
+ if (visitedDirs.has(currentReal)) {
38
+ return;
39
+ }
40
+ if (!isInsideRoot(currentReal, projectRootReal)) {
41
+ return;
42
+ }
43
+ visitedDirs.add(currentReal);
44
+ let entries;
45
+ try {
46
+ entries = await fs.promises.readdir(currentDir, { withFileTypes: true });
47
+ }
48
+ catch {
49
+ return;
50
+ }
51
+ entries.sort((a, b) => a.name.localeCompare(b.name));
52
+ for (const entry of entries) {
53
+ const absolutePath = path.join(currentDir, entry.name);
54
+ const relativePath = path.relative(projectRoot, absolutePath).split(path.sep).join('/');
55
+ let isDirectory = entry.isDirectory();
56
+ let isFile = entry.isFile();
57
+ if (entry.isSymbolicLink()) {
58
+ try {
59
+ const realTarget = await fs.promises.realpath(absolutePath);
60
+ if (!isInsideRoot(realTarget, projectRootReal)) {
61
+ // Symlink escapes the project — skip
62
+ continue;
63
+ }
64
+ const stats = await fs.promises.stat(absolutePath);
65
+ isDirectory = stats.isDirectory();
66
+ isFile = stats.isFile();
67
+ }
68
+ catch {
69
+ // Broken symlink — skip
70
+ continue;
71
+ }
72
+ }
73
+ if (isPathIgnored(matcher, projectRoot, absolutePath, isDirectory)) {
74
+ const displayPath = isDirectory ? `${relativePath}/` : relativePath;
75
+ excludedPaths.push(displayPath);
76
+ continue;
77
+ }
78
+ if (isDirectory) {
79
+ await walk(absolutePath);
80
+ continue;
81
+ }
82
+ if (isFile) {
83
+ includedPaths.push(relativePath);
84
+ }
85
+ }
86
+ }
87
+ await walk(projectRoot);
88
+ includedPaths.sort();
89
+ excludedPaths.sort();
90
+ return {
91
+ filesIncluded: includedPaths.length,
92
+ includedPaths,
93
+ excludedPaths,
94
+ };
95
+ }
96
+ /**
97
+ * Create an optimized zip archive from the project directory.
98
+ */
99
+ export async function createOptimizedZip(projectRoot, outputPath, matcher) {
100
+ const collection = await collectFilesToPack(projectRoot, matcher);
101
+ const outputDir = path.dirname(outputPath);
102
+ await fs.promises.mkdir(outputDir, { recursive: true });
103
+ await new Promise((resolve, reject) => {
104
+ const output = createWriteStream(outputPath);
105
+ const archive = archiver('zip', { zlib: { level: 9 } });
106
+ output.on('close', () => resolve());
107
+ output.on('error', reject);
108
+ archive.on('error', reject);
109
+ archive.pipe(output);
110
+ for (const relativePath of collection.includedPaths) {
111
+ const absolutePath = path.join(projectRoot, relativePath);
112
+ archive.file(absolutePath, { name: relativePath });
113
+ }
114
+ void archive.finalize();
115
+ });
116
+ return collection;
117
+ }
118
+ export async function getZipSizeBytes(outputPath) {
119
+ const stats = await fs.promises.stat(outputPath);
120
+ return stats.size;
121
+ }
package/package.json CHANGED
@@ -1,13 +1,14 @@
1
1
  {
2
2
  "name": "@nitrostack/cli",
3
- "version": "1.0.14",
3
+ "version": "1.0.15",
4
4
  "description": "CLI for NitroStack - Create and manage MCP server projects",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",
8
8
  "bin": {
9
9
  "nitrostack-cli": "dist/index.js",
10
- "@nitrostack/cli": "dist/index.js"
10
+ "@nitrostack/cli": "dist/index.js",
11
+ "nitrostack-pack": "dist/pack/standalone.js"
11
12
  },
12
13
  "exports": {
13
14
  ".": {
@@ -23,7 +24,7 @@
23
24
  "assets"
24
25
  ],
25
26
  "scripts": {
26
- "build": "tsc && chmod +x dist/index.js",
27
+ "build": "tsc && chmod +x dist/index.js dist/pack/standalone.js",
27
28
  "dev": "tsc --watch",
28
29
  "test": "NODE_OPTIONS=--experimental-vm-modules jest",
29
30
  "test:coverage": "NODE_OPTIONS=--experimental-vm-modules jest --coverage",
@@ -40,6 +41,7 @@
40
41
  "author": "Nitrostack Inc <hello@nitrostack.ai>",
41
42
  "license": "Apache-2.0",
42
43
  "dependencies": {
44
+ "archiver": "^7.0.1",
43
45
  "chalk": "^5.3.0",
44
46
  "chokidar": "^3.6.0",
45
47
  "commander": "^12.1.0",
@@ -51,6 +53,7 @@
51
53
  "posthog-node": "^5.21.2"
52
54
  },
53
55
  "devDependencies": {
56
+ "@types/archiver": "^6.0.3",
54
57
  "@types/fs-extra": "^11.0.4",
55
58
  "@types/inquirer": "^9.0.9",
56
59
  "@types/jest": "^29.5.14",
@@ -1,6 +1,6 @@
1
1
  # NitroStack Configuration
2
2
  NITRO_LOG_LEVEL=info
3
- NITROSTACK_APP_MODE=openai
3
+ NITROSTACK_APP_MODE=universal
4
4
 
5
5
  # Server Transport Configuration (Optional)
6
6
  # =============================================================================
@@ -0,0 +1,57 @@
1
+ # Dependencies
2
+ node_modules/
3
+ src/widgets/node_modules/
4
+
5
+ # Build outputs
6
+ dist/
7
+ src/widgets/.next/
8
+ src/widgets/out/
9
+
10
+ # Environment files
11
+ .env
12
+ .env.local
13
+ .env.*.local
14
+
15
+ # IDE
16
+ .idea/
17
+ .vscode/
18
+ *.swp
19
+ *.swo
20
+ *~
21
+
22
+ # OS files
23
+ .DS_Store
24
+ Thumbs.db
25
+
26
+ # Logs
27
+ *.log
28
+ npm-debug.log*
29
+ yarn-debug.log*
30
+ yarn-error.log*
31
+
32
+ # Runtime data
33
+ pids/
34
+ *.pid
35
+ *.seed
36
+ *.pid.lock
37
+
38
+ # Coverage
39
+ coverage/
40
+ .nyc_output/
41
+
42
+ # Uploads
43
+ uploads/
44
+
45
+ # TypeScript cache
46
+ *.tsbuildinfo
47
+
48
+ # Optional npm cache
49
+ .npm/
50
+
51
+ # Optional eslint cache
52
+ .eslintcache
53
+
54
+ # OAuth tokens/secrets (never commit these!)
55
+ *.pem
56
+ *.key
57
+ tokens.json
@@ -1,6 +1,6 @@
1
1
  # NitroStack Configuration
2
2
  NITRO_LOG_LEVEL=info
3
- NITROSTACK_APP_MODE=openai
3
+ NITROSTACK_APP_MODE=universal
4
4
 
5
5
  # Server Transport Configuration (Optional)
6
6
  # =============================================================================
@@ -0,0 +1,57 @@
1
+ # Dependencies
2
+ node_modules/
3
+ src/widgets/node_modules/
4
+
5
+ # Build outputs
6
+ dist/
7
+ src/widgets/.next/
8
+ src/widgets/out/
9
+
10
+ # Environment files
11
+ .env
12
+ .env.local
13
+ .env.*.local
14
+
15
+ # IDE
16
+ .idea/
17
+ .vscode/
18
+ *.swp
19
+ *.swo
20
+ *~
21
+
22
+ # OS files
23
+ .DS_Store
24
+ Thumbs.db
25
+
26
+ # Logs
27
+ *.log
28
+ npm-debug.log*
29
+ yarn-debug.log*
30
+ yarn-error.log*
31
+
32
+ # Runtime data
33
+ pids/
34
+ *.pid
35
+ *.seed
36
+ *.pid.lock
37
+
38
+ # Coverage
39
+ coverage/
40
+ .nyc_output/
41
+
42
+ # Uploads
43
+ uploads/
44
+
45
+ # TypeScript cache
46
+ *.tsbuildinfo
47
+
48
+ # Optional npm cache
49
+ .npm/
50
+
51
+ # Optional eslint cache
52
+ .eslintcache
53
+
54
+ # OAuth tokens/secrets (never commit these!)
55
+ *.pem
56
+ *.key
57
+ tokens.json
@@ -1,6 +1,6 @@
1
1
  # NitroStack Configuration
2
2
  NITRO_LOG_LEVEL=info
3
- NITROSTACK_APP_MODE=openai
3
+ NITROSTACK_APP_MODE=universal
4
4
 
5
5
  # Server Transport Configuration (Optional)
6
6
  # =============================================================================
@@ -0,0 +1,57 @@
1
+ # Dependencies
2
+ node_modules/
3
+ src/widgets/node_modules/
4
+
5
+ # Build outputs
6
+ dist/
7
+ src/widgets/.next/
8
+ src/widgets/out/
9
+
10
+ # Environment files
11
+ .env
12
+ .env.local
13
+ .env.*.local
14
+
15
+ # IDE
16
+ .idea/
17
+ .vscode/
18
+ *.swp
19
+ *.swo
20
+ *~
21
+
22
+ # OS files
23
+ .DS_Store
24
+ Thumbs.db
25
+
26
+ # Logs
27
+ *.log
28
+ npm-debug.log*
29
+ yarn-debug.log*
30
+ yarn-error.log*
31
+
32
+ # Runtime data
33
+ pids/
34
+ *.pid
35
+ *.seed
36
+ *.pid.lock
37
+
38
+ # Coverage
39
+ coverage/
40
+ .nyc_output/
41
+
42
+ # Uploads
43
+ uploads/
44
+
45
+ # TypeScript cache
46
+ *.tsbuildinfo
47
+
48
+ # Optional npm cache
49
+ .npm/
50
+
51
+ # Optional eslint cache
52
+ .eslintcache
53
+
54
+ # OAuth tokens/secrets (never commit these!)
55
+ *.pem
56
+ *.key
57
+ tokens.json