@papercraneai/cli 1.8.0 → 1.8.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.
- package/bin/papercrane.js +37 -33
- package/lib/dev-server.js +7 -4
- package/package.json +1 -1
package/bin/papercrane.js
CHANGED
|
@@ -8,7 +8,7 @@ import path from 'path';
|
|
|
8
8
|
import os from 'os';
|
|
9
9
|
import http from 'http';
|
|
10
10
|
import { http as httpClient } from '../lib/axios-client.js';
|
|
11
|
-
import { setApiKey, clearConfig, isLoggedIn,
|
|
11
|
+
import { setApiKey, clearConfig, isLoggedIn, setOrgId, getOrgId } from '../lib/config.js';
|
|
12
12
|
import { validateApiKey } from '../lib/cloud-client.js';
|
|
13
13
|
import { listFunctions, getFunction, runFunction, formatDescribe, formatDescribeRoot, formatFlat, formatResult, formatUnconnected } from '../lib/function-client.js';
|
|
14
14
|
import { listWorkspaces, resolveWorkspaceId, getLocalWorkspacePath, pullWorkspace, pushWorkspace } from '../lib/environment-client.js';
|
|
@@ -22,15 +22,18 @@ async function requireWorkspace() {
|
|
|
22
22
|
console.error(chalk.red('Not logged in. Run: papercrane login'));
|
|
23
23
|
process.exit(1);
|
|
24
24
|
}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
25
|
+
// Resolve current workspace from ~/.papercrane/current symlink
|
|
26
|
+
const currentLink = path.join(os.homedir(), '.papercrane', 'current');
|
|
27
|
+
try {
|
|
28
|
+
const target = await fs.readlink(currentLink);
|
|
29
|
+
const match = target.match(/workspaces\/(\d+)/);
|
|
30
|
+
if (match) return parseInt(match[1], 10);
|
|
31
|
+
} catch {}
|
|
32
|
+
console.error(chalk.red('No workspace selected.'));
|
|
33
|
+
console.error(chalk.dim('\nRun these commands first:'));
|
|
34
|
+
console.error(chalk.dim(' papercrane workspaces list'));
|
|
35
|
+
console.error(chalk.dim(' papercrane workspaces use <id>'));
|
|
36
|
+
process.exit(1);
|
|
34
37
|
}
|
|
35
38
|
|
|
36
39
|
/**
|
|
@@ -47,7 +50,6 @@ async function showPostLoginHelp() {
|
|
|
47
50
|
if (workspaces.length === 1) {
|
|
48
51
|
// Auto-select the only workspace
|
|
49
52
|
const ws = workspaces[0];
|
|
50
|
-
await setDefaultWorkspace(ws.id);
|
|
51
53
|
|
|
52
54
|
const workspaceDir = getLocalWorkspacePath(ws.id);
|
|
53
55
|
const { generateScaffolding } = await import('../lib/dev-server.js');
|
|
@@ -451,7 +453,7 @@ program
|
|
|
451
453
|
console.log(chalk.cyan(`Scaffolding workspace in ${dir}...`));
|
|
452
454
|
|
|
453
455
|
const { generateScaffolding } = await import('../lib/dev-server.js');
|
|
454
|
-
await generateScaffolding(dir, {
|
|
456
|
+
await generateScaffolding(dir, { npmInstall: options.npmInstall });
|
|
455
457
|
|
|
456
458
|
// Set ~/.papercrane/current symlink → scaffolded dir
|
|
457
459
|
const currentLink = path.join(os.homedir(), '.papercrane', 'current');
|
|
@@ -800,7 +802,15 @@ workspacesCmd
|
|
|
800
802
|
}
|
|
801
803
|
|
|
802
804
|
const workspaces = await listWorkspaces();
|
|
803
|
-
|
|
805
|
+
|
|
806
|
+
// Resolve current workspace from ~/.papercrane/current symlink
|
|
807
|
+
let currentWsId = null;
|
|
808
|
+
try {
|
|
809
|
+
const currentLink = path.join(os.homedir(), '.papercrane', 'current');
|
|
810
|
+
const target = await fs.readlink(currentLink);
|
|
811
|
+
const match = target.match(/workspaces\/(\d+)/);
|
|
812
|
+
if (match) currentWsId = parseInt(match[1], 10);
|
|
813
|
+
} catch {}
|
|
804
814
|
|
|
805
815
|
if (!workspaces || workspaces.length === 0) {
|
|
806
816
|
console.log(chalk.yellow('No workspaces found.'));
|
|
@@ -809,12 +819,12 @@ workspacesCmd
|
|
|
809
819
|
|
|
810
820
|
console.log(chalk.bold('\nWorkspaces:\n'));
|
|
811
821
|
for (const ws of workspaces) {
|
|
812
|
-
const
|
|
822
|
+
const isCurrent = ws.id === currentWsId;
|
|
813
823
|
const status = ws.status === 'ready' ? chalk.green('ready') : chalk.yellow(ws.status);
|
|
814
|
-
const
|
|
824
|
+
const currentMarker = isCurrent ? chalk.cyan(' (current)') : '';
|
|
815
825
|
const typeLabel = ws.type === 'external' ? chalk.dim('external') : chalk.dim('managed');
|
|
816
826
|
const createdDate = ws.createdAt ? new Date(ws.createdAt).toLocaleDateString() : '';
|
|
817
|
-
console.log(` ${chalk.bold(ws.id)} ${ws.name || '(unnamed)'} ${typeLabel} ${status} ${chalk.dim(createdDate)}${
|
|
827
|
+
console.log(` ${chalk.bold(ws.id)} ${ws.name || '(unnamed)'} ${typeLabel} ${status} ${chalk.dim(createdDate)}${currentMarker}`);
|
|
818
828
|
}
|
|
819
829
|
console.log();
|
|
820
830
|
} catch (error) {
|
|
@@ -825,7 +835,7 @@ workspacesCmd
|
|
|
825
835
|
|
|
826
836
|
workspacesCmd
|
|
827
837
|
.command('use <id>')
|
|
828
|
-
.description('Set the
|
|
838
|
+
.description('Set the current workspace')
|
|
829
839
|
.option('--reset-scaffolding', 'Regenerate scaffolding files (layout.tsx, globals.css, configs)')
|
|
830
840
|
.action(async (id, options) => {
|
|
831
841
|
try {
|
|
@@ -841,8 +851,6 @@ workspacesCmd
|
|
|
841
851
|
process.exit(1);
|
|
842
852
|
}
|
|
843
853
|
|
|
844
|
-
await setDefaultWorkspace(wsId);
|
|
845
|
-
|
|
846
854
|
const { generateScaffolding, resetScaffolding } = await import('../lib/dev-server.js');
|
|
847
855
|
const workspaceDir = getLocalWorkspacePath(wsId);
|
|
848
856
|
|
|
@@ -884,7 +892,7 @@ workspacesCmd
|
|
|
884
892
|
await fs.symlink(workspaceDir, currentLink);
|
|
885
893
|
}
|
|
886
894
|
|
|
887
|
-
console.log(chalk.green(`✓
|
|
895
|
+
console.log(chalk.green(`✓ Current workspace set to ${wsId}`));
|
|
888
896
|
console.log(chalk.dim(` ${currentLink} → ${workspaceDir}`));
|
|
889
897
|
console.log(chalk.dim(` Dashboards: ${workspaceDir}/app/\n`));
|
|
890
898
|
} catch (error) {
|
|
@@ -919,7 +927,7 @@ program
|
|
|
919
927
|
const currentLink = path.join(os.homedir(), '.papercrane', 'current');
|
|
920
928
|
try {
|
|
921
929
|
await fs.readlink(currentLink);
|
|
922
|
-
workspaceDir = currentLink;
|
|
930
|
+
workspaceDir = await fs.realpath(currentLink);
|
|
923
931
|
} catch {
|
|
924
932
|
console.error(chalk.red('No workspace set up.'));
|
|
925
933
|
console.error(chalk.dim('\nRun one of:'));
|
|
@@ -940,20 +948,16 @@ program
|
|
|
940
948
|
console.log(chalk.dim('Build cache cleared.'));
|
|
941
949
|
}
|
|
942
950
|
|
|
943
|
-
await generateScaffolding(workspaceDir, {
|
|
951
|
+
await generateScaffolding(workspaceDir, { npmInstall: options.npmInstall });
|
|
944
952
|
|
|
945
|
-
//
|
|
953
|
+
// Check node_modules exists — fail fast if missing
|
|
946
954
|
const nmDir = path.join(workspaceDir, 'node_modules');
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
} catch {
|
|
954
|
-
console.log(chalk.dim('node_modules not found, running npm install...'));
|
|
955
|
-
execSync('npm install --prefer-offline', { cwd: workspaceDir, stdio: 'inherit' });
|
|
956
|
-
}
|
|
955
|
+
try {
|
|
956
|
+
await fs.access(nmDir);
|
|
957
|
+
} catch {
|
|
958
|
+
console.error(chalk.red('Error: node_modules not found.'));
|
|
959
|
+
console.error(chalk.dim('Run: papercrane dev --npm-install'));
|
|
960
|
+
process.exit(1);
|
|
957
961
|
}
|
|
958
962
|
|
|
959
963
|
const port = parseInt(options.port, 10);
|
package/lib/dev-server.js
CHANGED
|
@@ -257,9 +257,9 @@ export async function resetScaffolding(workspaceDir) {
|
|
|
257
257
|
/**
|
|
258
258
|
* Generate the project structure inside the workspace.
|
|
259
259
|
* Creates package.json, tsconfig.json, postcss.config.mjs, app/layout.tsx, app/globals.css.
|
|
260
|
-
*
|
|
260
|
+
* Pass { npmInstall: true } to also run npm install if node_modules doesn't exist.
|
|
261
261
|
*/
|
|
262
|
-
export async function generateScaffolding(workspaceDir, {
|
|
262
|
+
export async function generateScaffolding(workspaceDir, { npmInstall = false } = {}) {
|
|
263
263
|
const appDir = path.join(workspaceDir, 'app');
|
|
264
264
|
await fs.mkdir(appDir, { recursive: true });
|
|
265
265
|
|
|
@@ -340,13 +340,16 @@ const nextConfig = {
|
|
|
340
340
|
turbopack: {
|
|
341
341
|
root: ${JSON.stringify(workspaceDir)},
|
|
342
342
|
},
|
|
343
|
+
experimental: {
|
|
344
|
+
turbopackFileSystemCacheForDev: false,
|
|
345
|
+
},
|
|
343
346
|
};
|
|
344
347
|
export default nextConfig;
|
|
345
348
|
`;
|
|
346
349
|
await fs.writeFile(nextConfigPath, nextConfig, 'utf-8');
|
|
347
350
|
|
|
348
|
-
// npm install — only
|
|
349
|
-
if (
|
|
351
|
+
// npm install — only when explicitly requested and node_modules doesn't exist
|
|
352
|
+
if (npmInstall) {
|
|
350
353
|
const nmDir = path.join(workspaceDir, 'node_modules');
|
|
351
354
|
if (!fsSync.existsSync(nmDir)) {
|
|
352
355
|
console.log('Installing dependencies...');
|