@embeddables/cli 0.2.0 → 0.3.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.
- package/.cursor/rules/embeddables-cli.md +679 -0
- package/dist/cli.js +24 -7
- package/dist/commands/dev.d.ts +1 -1
- package/dist/commands/dev.d.ts.map +1 -1
- package/dist/commands/dev.js +44 -5
- package/dist/commands/init.d.ts +0 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +143 -86
- package/dist/commands/pull.d.ts.map +1 -1
- package/dist/commands/pull.js +20 -0
- package/dist/commands/save.d.ts +8 -0
- package/dist/commands/save.d.ts.map +1 -0
- package/dist/commands/save.js +269 -0
- package/dist/compiler/index.d.ts.map +1 -1
- package/dist/compiler/index.js +4 -0
- package/dist/compiler/reverse.d.ts.map +1 -1
- package/dist/compiler/reverse.js +4 -10
- package/dist/config/index.d.ts +2 -0
- package/dist/config/index.d.ts.map +1 -1
- package/dist/constants.d.ts +1 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +2 -0
- package/dist/prompts/projects.d.ts +1 -0
- package/dist/prompts/projects.d.ts.map +1 -1
- package/dist/prompts/projects.js +1 -0
- package/dist/proxy/server.d.ts.map +1 -1
- package/dist/proxy/server.js +10 -4
- package/package.json +2 -1
package/dist/cli.js
CHANGED
|
@@ -8,6 +8,7 @@ import { runInit } from './commands/init.js';
|
|
|
8
8
|
import { runLogin } from './commands/login.js';
|
|
9
9
|
import { runLogout } from './commands/logout.js';
|
|
10
10
|
import { runPull } from './commands/pull.js';
|
|
11
|
+
import { runSave } from './commands/save.js';
|
|
11
12
|
// Make all console.warn output yellow
|
|
12
13
|
const originalWarn = console.warn.bind(console);
|
|
13
14
|
console.warn = (...args) => {
|
|
@@ -22,11 +23,10 @@ program.name('embeddables').description('Embeddables CLI').version('0.1.0');
|
|
|
22
23
|
program
|
|
23
24
|
.command('init')
|
|
24
25
|
.description('Initialize a new Embeddables project')
|
|
25
|
-
.option('--name <name>', 'Project name')
|
|
26
26
|
.option('--project-id <id>', 'Embeddables project ID')
|
|
27
27
|
.option('-y, --yes', 'Skip prompts and use defaults')
|
|
28
28
|
.action(async (opts) => {
|
|
29
|
-
await runInit({
|
|
29
|
+
await runInit({ projectId: opts.projectId, yes: opts.yes });
|
|
30
30
|
});
|
|
31
31
|
program
|
|
32
32
|
.command('build')
|
|
@@ -42,15 +42,15 @@ program
|
|
|
42
42
|
.option('--id <id>', 'Embeddable ID (will prompt if not provided)')
|
|
43
43
|
.option('--pages <glob>', 'Pages glob')
|
|
44
44
|
.option('--out <path>', 'Output json path')
|
|
45
|
-
.option('--
|
|
46
|
-
.option('--engine <url>', 'Engine origin', '
|
|
45
|
+
.option('--local', 'Use local engine (http://localhost:8787)')
|
|
46
|
+
.option('--engine <url>', 'Engine origin', 'https://engine.embeddables.com')
|
|
47
47
|
.option('--port <n>', 'Dev proxy port', '3000')
|
|
48
48
|
.option('--overrideRoute <path>', 'Route to override in proxy (exact match, no wildcards yet)', '/init')
|
|
49
49
|
.option('--pageKeyFrom <mode>', 'filename|export', 'filename')
|
|
50
50
|
.action(async (opts) => {
|
|
51
|
-
// --
|
|
52
|
-
if (opts.
|
|
53
|
-
opts.engine = '
|
|
51
|
+
// --local flag overrides --engine to use local engine
|
|
52
|
+
if (opts.local) {
|
|
53
|
+
opts.engine = 'http://localhost:8787';
|
|
54
54
|
}
|
|
55
55
|
await runDev(opts);
|
|
56
56
|
});
|
|
@@ -76,6 +76,23 @@ program
|
|
|
76
76
|
.action(async (opts) => {
|
|
77
77
|
await runPull(opts);
|
|
78
78
|
});
|
|
79
|
+
program
|
|
80
|
+
.command('save')
|
|
81
|
+
.description('Build and save an embeddable to the cloud')
|
|
82
|
+
.option('--id <id>', 'Embeddable ID (will prompt if not provided)')
|
|
83
|
+
.option('--label <label>', 'Human-readable label for this version')
|
|
84
|
+
.option('--branch <branch_id>', 'Branch ID to save to')
|
|
85
|
+
.option('--skip-build', 'Skip the build step and use existing compiled JSON')
|
|
86
|
+
.option('--from-version <number>', 'Base version number (auto-detected from local files if not provided)')
|
|
87
|
+
.action(async (opts) => {
|
|
88
|
+
await runSave({
|
|
89
|
+
id: opts.id,
|
|
90
|
+
label: opts.label,
|
|
91
|
+
branch: opts.branch,
|
|
92
|
+
skipBuild: opts.skipBuild,
|
|
93
|
+
fromVersion: opts.fromVersion,
|
|
94
|
+
});
|
|
95
|
+
});
|
|
79
96
|
program
|
|
80
97
|
.command('branch')
|
|
81
98
|
.description('Switch to a different branch of an embeddable')
|
package/dist/commands/dev.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../src/commands/dev.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../src/commands/dev.ts"],"names":[],"mappings":"AAmHA,wBAAsB,MAAM,CAAC,IAAI,EAAE;IACjC,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;IACZ,aAAa,EAAE,MAAM,CAAA;IACrB,WAAW,EAAE,UAAU,GAAG,QAAQ,CAAA;CACnC,iBA4GA"}
|
package/dist/commands/dev.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
|
+
import net from 'node:net';
|
|
2
3
|
import path from 'node:path';
|
|
3
4
|
import chokidar from 'chokidar';
|
|
4
5
|
import pc from 'picocolors';
|
|
@@ -6,6 +7,32 @@ import prompts from 'prompts';
|
|
|
6
7
|
import { compileAllPages } from '../compiler/index.js';
|
|
7
8
|
import { startProxyServer } from '../proxy/server.js';
|
|
8
9
|
import { formatError } from '../compiler/errors.js';
|
|
10
|
+
/**
|
|
11
|
+
* Check whether a port is available by attempting to listen on it.
|
|
12
|
+
*/
|
|
13
|
+
function isPortAvailable(port) {
|
|
14
|
+
return new Promise((resolve) => {
|
|
15
|
+
const server = net.createServer();
|
|
16
|
+
server.once('error', () => resolve(false));
|
|
17
|
+
server.once('listening', () => {
|
|
18
|
+
server.close(() => resolve(true));
|
|
19
|
+
});
|
|
20
|
+
server.listen(port);
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Starting from `startPort`, find the first available port.
|
|
25
|
+
* Tries up to `maxAttempts` consecutive ports.
|
|
26
|
+
*/
|
|
27
|
+
async function getAvailablePort(startPort, maxAttempts = 20) {
|
|
28
|
+
for (let i = 0; i < maxAttempts; i++) {
|
|
29
|
+
const port = startPort + i;
|
|
30
|
+
if (await isPortAvailable(port)) {
|
|
31
|
+
return port;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
throw new Error(`Could not find an available port (tried ${startPort}–${startPort + maxAttempts - 1})`);
|
|
35
|
+
}
|
|
9
36
|
async function discoverEmbeddables() {
|
|
10
37
|
const embeddablesDir = 'embeddables';
|
|
11
38
|
if (!fs.existsSync(embeddablesDir)) {
|
|
@@ -96,8 +123,20 @@ export async function runDev(opts) {
|
|
|
96
123
|
console.error(formatError(e));
|
|
97
124
|
process.exit(1);
|
|
98
125
|
}
|
|
99
|
-
// Start proxy
|
|
100
|
-
const
|
|
126
|
+
// Start proxy — find an available port if the requested one is taken
|
|
127
|
+
const requestedPort = Number(opts.port);
|
|
128
|
+
let port;
|
|
129
|
+
try {
|
|
130
|
+
port = await getAvailablePort(requestedPort);
|
|
131
|
+
}
|
|
132
|
+
catch (e) {
|
|
133
|
+
console.error(pc.red(e.message));
|
|
134
|
+
process.exit(1);
|
|
135
|
+
}
|
|
136
|
+
if (port !== requestedPort) {
|
|
137
|
+
console.warn(`Port ${requestedPort} is in use, using ${port} instead.`);
|
|
138
|
+
console.log('');
|
|
139
|
+
}
|
|
101
140
|
const proxy = await startProxyServer({
|
|
102
141
|
port,
|
|
103
142
|
engineOrigin: opts.engine,
|
|
@@ -139,11 +178,11 @@ export async function runDev(opts) {
|
|
|
139
178
|
const separator = '━'.repeat(terminalWidth);
|
|
140
179
|
console.log(`${pc.bold(pc.cyan(separator))}`);
|
|
141
180
|
console.log('');
|
|
142
|
-
if (opts.
|
|
143
|
-
console.log(`${pc.bold(pc.
|
|
181
|
+
if (opts.local) {
|
|
182
|
+
console.log(`${pc.bold(pc.blue('Mode:'))} ${pc.blue('Local')} (using ${opts.engine})`);
|
|
144
183
|
}
|
|
145
184
|
else {
|
|
146
|
-
console.log(`${pc.bold(pc.
|
|
185
|
+
console.log(`${pc.bold(pc.yellow('Mode:'))} ${pc.yellow('Remote')} (using ${opts.engine})`);
|
|
147
186
|
}
|
|
148
187
|
console.log('');
|
|
149
188
|
console.log(`${pc.bold(pc.green('Preview URL:'))} ${pc.underline(pc.cyan(`http://localhost:${port}?id=${embeddableId}&version=latest`))}`);
|
package/dist/commands/init.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAuGA,wBAAsB,OAAO,CAAC,IAAI,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,OAAO,CAAA;CAAE,iBA0KxE"}
|
package/dist/commands/init.js
CHANGED
|
@@ -1,37 +1,112 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
3
4
|
import pc from 'picocolors';
|
|
4
5
|
import prompts from 'prompts';
|
|
5
6
|
import { writeProjectConfig, readProjectConfig } from '../config/index.js';
|
|
6
7
|
import { isLoggedIn } from '../auth/index.js';
|
|
7
8
|
import { promptForProject } from '../prompts/index.js';
|
|
9
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
10
|
+
const __dirname = path.dirname(__filename);
|
|
11
|
+
/** Recursively copy a directory, creating target dirs as needed. */
|
|
12
|
+
function copyDirSync(src, dest) {
|
|
13
|
+
fs.mkdirSync(dest, { recursive: true });
|
|
14
|
+
for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
|
|
15
|
+
const srcPath = path.join(src, entry.name);
|
|
16
|
+
const destPath = path.join(dest, entry.name);
|
|
17
|
+
if (entry.isDirectory()) {
|
|
18
|
+
copyDirSync(srcPath, destPath);
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
fs.copyFileSync(srcPath, destPath);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Generate type declaration stubs in embeddables/.types/ so the editor
|
|
27
|
+
* can resolve imports in generated TSX files without npm install.
|
|
28
|
+
*/
|
|
29
|
+
function writeTypeStubs(embeddablesDir) {
|
|
30
|
+
const typesDir = path.join(embeddablesDir, '.types');
|
|
31
|
+
fs.mkdirSync(typesDir, { recursive: true });
|
|
32
|
+
// React JSX runtime types (needed for "jsx": "react-jsx" in tsconfig)
|
|
33
|
+
fs.writeFileSync(path.join(typesDir, 'react-jsx-runtime.d.ts'), `export namespace JSX {
|
|
34
|
+
type Element = any
|
|
35
|
+
interface IntrinsicElements {
|
|
36
|
+
[elemName: string]: any
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
export function jsx(type: any, props: any, key?: string): JSX.Element
|
|
40
|
+
export function jsxs(type: any, props: any, key?: string): JSX.Element
|
|
41
|
+
export const Fragment: unique symbol
|
|
42
|
+
`, 'utf8');
|
|
43
|
+
// Component primitives
|
|
44
|
+
const componentNames = [
|
|
45
|
+
'BookMeeting',
|
|
46
|
+
'Chart',
|
|
47
|
+
'Container',
|
|
48
|
+
'CustomButton',
|
|
49
|
+
'CustomHTML',
|
|
50
|
+
'FileUpload',
|
|
51
|
+
'InputBox',
|
|
52
|
+
'Lottie',
|
|
53
|
+
'MediaEmbed',
|
|
54
|
+
'MediaImage',
|
|
55
|
+
'OptionSelector',
|
|
56
|
+
'PaypalCheckout',
|
|
57
|
+
'PlainText',
|
|
58
|
+
'ProgressBar',
|
|
59
|
+
'RichText',
|
|
60
|
+
'RichTextMarkdown',
|
|
61
|
+
'Rive',
|
|
62
|
+
'StripeCheckout',
|
|
63
|
+
'StripeCheckout2',
|
|
64
|
+
];
|
|
65
|
+
const componentExports = componentNames
|
|
66
|
+
.map((name) => `export function ${name}(props: Record<string, any>): any`)
|
|
67
|
+
.join('\n');
|
|
68
|
+
fs.writeFileSync(path.join(typesDir, 'components.d.ts'), componentExports + '\n', 'utf8');
|
|
69
|
+
// Embeddables types (OptionSelectorButton, etc.)
|
|
70
|
+
fs.writeFileSync(path.join(typesDir, 'types.d.ts'), `export interface OptionSelectorButton {
|
|
71
|
+
id?: string
|
|
72
|
+
key: string
|
|
73
|
+
text?: string
|
|
74
|
+
description?: string
|
|
75
|
+
icon?: string
|
|
76
|
+
emojiIcon?: string
|
|
77
|
+
imageUrl?: string
|
|
78
|
+
imageAltText?: string
|
|
79
|
+
conditions?: Record<string, any>[]
|
|
80
|
+
triggerEvent?: 'no-action' | 'next-page' | 'open-url'
|
|
81
|
+
openUrlInNewTab?: boolean
|
|
82
|
+
url?: string
|
|
83
|
+
single_select?: boolean
|
|
84
|
+
hide?: boolean
|
|
85
|
+
is_repeatable_button?: boolean
|
|
86
|
+
[key: string]: any
|
|
87
|
+
}
|
|
88
|
+
`, 'utf8');
|
|
89
|
+
}
|
|
8
90
|
export async function runInit(opts) {
|
|
9
91
|
const cwd = process.cwd();
|
|
10
|
-
const packageJsonPath = path.join(cwd, 'package.json');
|
|
11
92
|
const gitignorePath = path.join(cwd, '.gitignore');
|
|
12
93
|
const embeddablesDir = path.join(cwd, 'embeddables');
|
|
13
94
|
console.log('');
|
|
14
95
|
console.log(pc.bold(pc.cyan(' Embeddables Project Setup')));
|
|
15
96
|
console.log('');
|
|
16
|
-
// Check if already initialized
|
|
17
|
-
let existingPackageJson = null;
|
|
18
|
-
if (fs.existsSync(packageJsonPath)) {
|
|
19
|
-
try {
|
|
20
|
-
existingPackageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
|
|
21
|
-
}
|
|
22
|
-
catch {
|
|
23
|
-
// Invalid JSON, we'll overwrite
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
97
|
const existingConfig = readProjectConfig();
|
|
27
|
-
// Step 1: Get Embeddables project
|
|
98
|
+
// Step 1: Get Embeddables project
|
|
28
99
|
let projectId = opts.projectId;
|
|
29
100
|
let selectedProjectTitle;
|
|
101
|
+
let selectedOrgId;
|
|
102
|
+
let selectedOrgTitle;
|
|
30
103
|
if (!projectId && !opts.yes) {
|
|
31
104
|
if (existingConfig?.project_id) {
|
|
32
105
|
console.log(pc.gray(` Using existing project ID: ${existingConfig.project_id}`));
|
|
33
106
|
projectId = existingConfig.project_id;
|
|
34
107
|
selectedProjectTitle = existingConfig.project_name || undefined;
|
|
108
|
+
selectedOrgId = existingConfig.org_id || undefined;
|
|
109
|
+
selectedOrgTitle = existingConfig.org_title || undefined;
|
|
35
110
|
}
|
|
36
111
|
else if (isLoggedIn()) {
|
|
37
112
|
// Fetch and show project list
|
|
@@ -43,6 +118,8 @@ export async function runInit(opts) {
|
|
|
43
118
|
if (selectedProject) {
|
|
44
119
|
projectId = selectedProject.id;
|
|
45
120
|
selectedProjectTitle = selectedProject.title || undefined;
|
|
121
|
+
selectedOrgId = selectedProject.org_id || undefined;
|
|
122
|
+
selectedOrgTitle = selectedProject.org_title || undefined;
|
|
46
123
|
}
|
|
47
124
|
}
|
|
48
125
|
else {
|
|
@@ -62,77 +139,18 @@ export async function runInit(opts) {
|
|
|
62
139
|
projectId = response.projectId || undefined;
|
|
63
140
|
}
|
|
64
141
|
}
|
|
65
|
-
// Step 2: Get project name (default to selected project title, or existing, or directory name)
|
|
66
|
-
let projectName = opts.name;
|
|
67
|
-
if (!projectName) {
|
|
68
|
-
if (existingPackageJson?.name) {
|
|
69
|
-
projectName = existingPackageJson.name;
|
|
70
|
-
console.log(pc.gray(` Using existing project name: ${projectName}`));
|
|
71
|
-
}
|
|
72
|
-
else if (opts.yes) {
|
|
73
|
-
// Use selected project title or directory name as default
|
|
74
|
-
projectName = selectedProjectTitle || path.basename(cwd);
|
|
75
|
-
}
|
|
76
|
-
else {
|
|
77
|
-
// Default to selected project title, then directory name
|
|
78
|
-
const defaultName = selectedProjectTitle || path.basename(cwd);
|
|
79
|
-
const response = await prompts({
|
|
80
|
-
type: 'text',
|
|
81
|
-
name: 'name',
|
|
82
|
-
message: 'Project name:',
|
|
83
|
-
initial: defaultName,
|
|
84
|
-
}, {
|
|
85
|
-
onCancel: () => {
|
|
86
|
-
console.log(pc.gray('\n Cancelled.'));
|
|
87
|
-
process.exit(0);
|
|
88
|
-
},
|
|
89
|
-
});
|
|
90
|
-
projectName = response.name;
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
if (!projectName) {
|
|
94
|
-
console.error('Project name is required.');
|
|
95
|
-
process.exit(1);
|
|
96
|
-
}
|
|
97
|
-
// Create or update package.json
|
|
98
|
-
const packageJson = existingPackageJson || {
|
|
99
|
-
name: projectName,
|
|
100
|
-
version: '1.0.0',
|
|
101
|
-
type: 'module',
|
|
102
|
-
};
|
|
103
|
-
// Ensure name is set
|
|
104
|
-
if (!packageJson.name) {
|
|
105
|
-
packageJson.name = projectName;
|
|
106
|
-
}
|
|
107
|
-
// Ensure type is module
|
|
108
|
-
if (!packageJson.type) {
|
|
109
|
-
packageJson.type = 'module';
|
|
110
|
-
}
|
|
111
|
-
// Add @embeddables/cli as a dependency
|
|
112
|
-
if (!packageJson.dependencies) {
|
|
113
|
-
packageJson.dependencies = {};
|
|
114
|
-
}
|
|
115
|
-
if (!packageJson.dependencies['@embeddables/cli']) {
|
|
116
|
-
packageJson.dependencies['@embeddables/cli'] = '^0.1.0';
|
|
117
|
-
}
|
|
118
|
-
// Write package.json
|
|
119
|
-
fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2) + '\n', 'utf8');
|
|
120
|
-
if (existingPackageJson) {
|
|
121
|
-
console.log(pc.green(' ✓ Updated package.json'));
|
|
122
|
-
}
|
|
123
|
-
else {
|
|
124
|
-
console.log(pc.green(' ✓ Created package.json'));
|
|
125
|
-
}
|
|
126
142
|
// Write embeddables.json config
|
|
127
143
|
if (projectId) {
|
|
128
144
|
writeProjectConfig({
|
|
145
|
+
org_id: selectedOrgId,
|
|
146
|
+
org_title: selectedOrgTitle,
|
|
129
147
|
project_id: projectId,
|
|
130
|
-
project_name: selectedProjectTitle
|
|
148
|
+
project_name: selectedProjectTitle,
|
|
131
149
|
});
|
|
132
150
|
console.log(pc.green(' ✓ Created embeddables.json'));
|
|
133
151
|
}
|
|
134
152
|
// Create or update .gitignore
|
|
135
|
-
const gitignoreEntries = ['
|
|
153
|
+
const gitignoreEntries = ['**/.generated/', '**/.types/', '.DS_Store'];
|
|
136
154
|
let existingGitignore = '';
|
|
137
155
|
if (fs.existsSync(gitignorePath)) {
|
|
138
156
|
existingGitignore = fs.readFileSync(gitignorePath, 'utf8');
|
|
@@ -162,27 +180,66 @@ export async function runInit(opts) {
|
|
|
162
180
|
else {
|
|
163
181
|
console.log(pc.gray(' ✓ embeddables/ directory exists'));
|
|
164
182
|
}
|
|
183
|
+
// Copy .cursor/ folder with Cursor rules
|
|
184
|
+
const packageRoot = path.resolve(__dirname, '..', '..');
|
|
185
|
+
const sourceCursorDir = path.join(packageRoot, '.cursor');
|
|
186
|
+
const targetCursorDir = path.join(cwd, '.cursor');
|
|
187
|
+
if (fs.existsSync(sourceCursorDir)) {
|
|
188
|
+
copyDirSync(sourceCursorDir, targetCursorDir);
|
|
189
|
+
console.log(pc.green(' ✓ Injected .cursor/ rules'));
|
|
190
|
+
}
|
|
191
|
+
// Create tsconfig.json for editor support (JSX, type checking)
|
|
192
|
+
const tsconfigPath = path.join(cwd, 'tsconfig.json');
|
|
193
|
+
if (!fs.existsSync(tsconfigPath)) {
|
|
194
|
+
const tsconfig = {
|
|
195
|
+
compilerOptions: {
|
|
196
|
+
target: 'esnext',
|
|
197
|
+
module: 'esnext',
|
|
198
|
+
moduleResolution: 'bundler',
|
|
199
|
+
jsx: 'react-jsx',
|
|
200
|
+
noEmit: true,
|
|
201
|
+
strict: false,
|
|
202
|
+
skipLibCheck: true,
|
|
203
|
+
esModuleInterop: true,
|
|
204
|
+
baseUrl: '.',
|
|
205
|
+
paths: {
|
|
206
|
+
'react/jsx-runtime': ['./embeddables/.types/react-jsx-runtime'],
|
|
207
|
+
'@embeddables/cli/components': ['./embeddables/.types/components'],
|
|
208
|
+
'@embeddables/cli/types': ['./embeddables/.types/types'],
|
|
209
|
+
},
|
|
210
|
+
},
|
|
211
|
+
include: ['embeddables'],
|
|
212
|
+
};
|
|
213
|
+
fs.writeFileSync(tsconfigPath, JSON.stringify(tsconfig, null, 2) + '\n', 'utf8');
|
|
214
|
+
console.log(pc.green(' ✓ Created tsconfig.json'));
|
|
215
|
+
}
|
|
216
|
+
else {
|
|
217
|
+
console.log(pc.gray(' ✓ tsconfig.json already exists'));
|
|
218
|
+
}
|
|
219
|
+
// Generate type declaration stubs for editor support (no npm install needed)
|
|
220
|
+
writeTypeStubs(embeddablesDir);
|
|
221
|
+
console.log(pc.green(' ✓ Generated type declarations'));
|
|
222
|
+
// Remind user to install dependencies
|
|
223
|
+
console.log('');
|
|
224
|
+
console.log(pc.yellow(' → Run `npm install` to install dependencies'));
|
|
165
225
|
// Print next steps
|
|
166
226
|
console.log('');
|
|
167
227
|
console.log(pc.bold(' Next steps:'));
|
|
168
228
|
console.log('');
|
|
169
|
-
console.log(pc.cyan(' 1.
|
|
170
|
-
console.log(pc.white('
|
|
171
|
-
console.log('');
|
|
172
|
-
console.log(pc.cyan(' 2. Login to Embeddables:'));
|
|
173
|
-
console.log(pc.white(' npx embeddables login'));
|
|
229
|
+
console.log(pc.cyan(' 1. Login to Embeddables:'));
|
|
230
|
+
console.log(pc.white(' embeddables login'));
|
|
174
231
|
console.log('');
|
|
175
232
|
if (projectId) {
|
|
176
|
-
console.log(pc.cyan('
|
|
177
|
-
console.log(pc.white('
|
|
233
|
+
console.log(pc.cyan(' 2. Pull an embeddable:'));
|
|
234
|
+
console.log(pc.white(' embeddables pull'));
|
|
178
235
|
console.log(pc.gray(' (will show a list of embeddables in your project)'));
|
|
179
236
|
}
|
|
180
237
|
else {
|
|
181
|
-
console.log(pc.cyan('
|
|
182
|
-
console.log(pc.white('
|
|
238
|
+
console.log(pc.cyan(' 2. Pull an existing embeddable:'));
|
|
239
|
+
console.log(pc.white(' embeddables pull --id <embeddable-id>'));
|
|
183
240
|
}
|
|
184
241
|
console.log('');
|
|
185
|
-
console.log(pc.cyan('
|
|
186
|
-
console.log(pc.white('
|
|
242
|
+
console.log(pc.cyan(' 3. Start developing:'));
|
|
243
|
+
console.log(pc.white(' embeddables dev'));
|
|
187
244
|
console.log('');
|
|
188
245
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pull.d.ts","sourceRoot":"","sources":["../../src/commands/pull.ts"],"names":[],"mappings":"AAUA,wBAAsB,OAAO,CAAC,IAAI,EAAE;IAAE,EAAE,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,OAAO,CAAA;CAAE,
|
|
1
|
+
{"version":3,"file":"pull.d.ts","sourceRoot":"","sources":["../../src/commands/pull.ts"],"names":[],"mappings":"AAUA,wBAAsB,OAAO,CAAC,IAAI,EAAE;IAAE,EAAE,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,OAAO,CAAA;CAAE,iBAwNhG"}
|
package/dist/commands/pull.js
CHANGED
|
@@ -29,6 +29,8 @@ export async function runPull(opts) {
|
|
|
29
29
|
projectId = selectedProject.id;
|
|
30
30
|
// Save the selected project to config
|
|
31
31
|
writeProjectConfig({
|
|
32
|
+
org_id: selectedProject.org_id || undefined,
|
|
33
|
+
org_title: selectedProject.org_title || undefined,
|
|
32
34
|
project_id: projectId,
|
|
33
35
|
project_name: selectedProject.title || undefined,
|
|
34
36
|
});
|
|
@@ -170,6 +172,24 @@ export async function runPull(opts) {
|
|
|
170
172
|
throw compileError;
|
|
171
173
|
}
|
|
172
174
|
}
|
|
175
|
+
// Store version number in config.json so save knows the base version
|
|
176
|
+
if (version != null) {
|
|
177
|
+
const versionNumber = typeof version === 'number' ? version : parseInt(String(version), 10);
|
|
178
|
+
if (!isNaN(versionNumber)) {
|
|
179
|
+
const configPath = path.join('embeddables', embeddableId, 'config.json');
|
|
180
|
+
if (fs.existsSync(configPath)) {
|
|
181
|
+
try {
|
|
182
|
+
const configContent = fs.readFileSync(configPath, 'utf8');
|
|
183
|
+
const config = JSON.parse(configContent);
|
|
184
|
+
config._version = versionNumber;
|
|
185
|
+
fs.writeFileSync(configPath, JSON.stringify(config, null, 2), 'utf8');
|
|
186
|
+
}
|
|
187
|
+
catch {
|
|
188
|
+
// Ignore errors updating config.json - versioned files are a fallback
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
173
193
|
}
|
|
174
194
|
catch (error) {
|
|
175
195
|
console.error('Error pulling embeddable:', error);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"save.d.ts","sourceRoot":"","sources":["../../src/commands/save.ts"],"names":[],"mappings":"AA+FA,wBAAsB,OAAO,CAAC,IAAI,EAAE;IAClC,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,iBAoPA"}
|