connectbase-client 0.1.4 → 0.1.6

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/README.md CHANGED
@@ -57,77 +57,87 @@ const state = await gameClient.createRoom({
57
57
 
58
58
  Deploy your web application to Connect Base Web Storage with a single command.
59
59
 
60
- ### Basic Usage
60
+ ### Quick Start
61
61
 
62
62
  ```bash
63
- # Deploy a directory
64
- npx connectbase-client deploy ./dist -s <storage-id> -k <api-key>
63
+ # 1. Initialize (one-time setup)
64
+ npx connectbase-client init
65
+
66
+ # 2. Deploy
67
+ npm run deploy
68
+ ```
69
+
70
+ The `init` command will:
71
+ - Ask for your API Key and Storage ID
72
+ - Create a `.connectbaserc` config file
73
+ - Add `.connectbaserc` to `.gitignore`
74
+ - Add a `deploy` script to `package.json`
65
75
 
66
- # Deploy current directory
67
- npx connectbase-client deploy . -s <storage-id> -k <api-key>
76
+ ### Commands
77
+
78
+ | Command | Description |
79
+ |---------|-------------|
80
+ | `init` | Interactive project setup (creates config, adds deploy script) |
81
+ | `deploy <dir>` | Deploy files to web storage |
82
+
83
+ ### Manual Usage
84
+
85
+ If you prefer not to use `init`, you can pass options directly:
86
+
87
+ ```bash
88
+ npx connectbase-client deploy ./dist -s <storage-id> -k <api-key>
68
89
  ```
69
90
 
70
91
  ### Options
71
92
 
72
93
  | Option | Alias | Description |
73
94
  |--------|-------|-------------|
74
- | `--storage <id>` | `-s` | Storage ID (required) |
75
- | `--api-key <key>` | `-k` | API Key (required) |
95
+ | `--storage <id>` | `-s` | Storage ID |
96
+ | `--api-key <key>` | `-k` | API Key |
76
97
  | `--base-url <url>` | `-u` | Custom server URL |
77
98
  | `--help` | `-h` | Show help |
78
99
  | `--version` | `-v` | Show version |
79
100
 
80
- ### Environment Variables
81
-
82
- You can set credentials via environment variables:
83
-
84
- ```bash
85
- export CONNECTBASE_API_KEY=your-api-key
86
- export CONNECTBASE_STORAGE_ID=your-storage-id
87
-
88
- # Then deploy without options
89
- npx connectbase-client deploy ./dist
90
- ```
91
-
92
101
  ### Configuration File
93
102
 
94
- Create a `.connectbaserc` file in your project root:
103
+ The `init` command creates `.connectbaserc` automatically. You can also create it manually:
95
104
 
96
105
  ```json
97
106
  {
98
107
  "apiKey": "your-api-key",
99
- "storageId": "your-storage-id"
108
+ "storageId": "your-storage-id",
109
+ "deployDir": "./dist"
100
110
  }
101
111
  ```
102
112
 
103
- Then deploy:
113
+ ### Environment Variables
104
114
 
105
115
  ```bash
116
+ export CONNECTBASE_API_KEY=your-api-key
117
+ export CONNECTBASE_STORAGE_ID=your-storage-id
106
118
  npx connectbase-client deploy ./dist
107
119
  ```
108
120
 
109
- ### npm Scripts
121
+ ### Requirements
110
122
 
111
- Add to your `package.json`:
123
+ - `index.html` must exist in the root of the deploy directory
124
+ - Supported file types: `.html`, `.css`, `.js`, `.json`, `.svg`, `.png`, `.jpg`, `.gif`, `.webp`, `.woff`, `.woff2`, `.ttf`, `.mp3`, `.mp4`, `.pdf`, `.wasm`, etc.
112
125
 
113
- ```json
114
- {
115
- "scripts": {
116
- "deploy": "connectbase-client deploy ./dist"
117
- }
118
- }
119
- ```
126
+ ### SPA Mode
127
+
128
+ Web Storage supports SPA (Single Page Application) mode, which is **enabled by default**. When enabled, requests to non-existent paths return `index.html` instead of 404, allowing client-side routers (React Router, Vue Router, etc.) to handle routing.
120
129
 
121
- Then run:
130
+ You can toggle SPA mode in the Connect Base Console under **Storage > Security Settings**, or via the API:
122
131
 
123
132
  ```bash
124
- npm run deploy
133
+ # Disable SPA mode (for static sites)
134
+ curl -X PUT "https://api.connectbase.world/v1/apps/{appID}/storages/webs/{storageID}" \
135
+ -H "Authorization: Bearer <TOKEN>" \
136
+ -H "Content-Type: application/json" \
137
+ -d '{"spa_mode": false}'
125
138
  ```
126
139
 
127
- ### Requirements
128
-
129
- - `index.html` must exist in the root of the deploy directory
130
- - Supported file types: `.html`, `.css`, `.js`, `.json`, `.svg`, `.png`, `.jpg`, `.gif`, `.webp`, `.woff`, `.woff2`, `.ttf`, `.mp3`, `.mp4`, `.pdf`, `.wasm`, etc.
140
+ > **Important:** When using SPA mode, ensure all asset paths in your HTML are absolute (`/assets/...`), not relative (`./assets/...`). For Vite projects, set `base: '/'` in `vite.config.ts`.
131
141
 
132
142
  ## API Reference
133
143
 
@@ -339,9 +349,11 @@ const session = await cb.auth.signIn({
339
349
  password: 'password123'
340
350
  })
341
351
 
342
- // OAuth login
343
- const oauthUrl = await cb.oauth.getGoogleAuthUrl()
344
- // Redirect user to oauthUrl
352
+ // OAuth login (리다이렉트 방식)
353
+ await cb.oauth.signIn('google', 'https://myapp.com/oauth/callback')
354
+
355
+ // OAuth login (팝업 방식)
356
+ const result = await cb.oauth.signInWithPopup('google', 'https://myapp.com/oauth/popup-callback')
345
357
 
346
358
  // Get current user
347
359
  const user = await cb.auth.getCurrentUser()
package/dist/cli.js CHANGED
@@ -29,6 +29,7 @@ var fs = __toESM(require("fs"));
29
29
  var path = __toESM(require("path"));
30
30
  var https = __toESM(require("https"));
31
31
  var http = __toESM(require("http"));
32
+ var readline = __toESM(require("readline"));
32
33
  var VERSION = "0.1.3";
33
34
  var DEFAULT_BASE_URL = "https://api.connectbase.world";
34
35
  var colors = {
@@ -123,6 +124,7 @@ function loadConfig() {
123
124
  if (rcContent.apiKey) config.apiKey = rcContent.apiKey;
124
125
  if (rcContent.storageId) config.storageId = rcContent.storageId;
125
126
  if (rcContent.baseUrl) config.baseUrl = rcContent.baseUrl;
127
+ if (rcContent.deployDir) config.deployDir = rcContent.deployDir;
126
128
  } catch {
127
129
  warn(".connectbaserc \uD30C\uC77C\uC744 \uC77D\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4");
128
130
  }
@@ -257,6 +259,107 @@ ${colors.cyan}URL: ${data.url}${colors.reset}
257
259
  process.exit(1);
258
260
  }
259
261
  }
262
+ function prompt(question) {
263
+ const rl = readline.createInterface({
264
+ input: process.stdin,
265
+ output: process.stdout
266
+ });
267
+ return new Promise((resolve2) => {
268
+ rl.question(question, (answer) => {
269
+ rl.close();
270
+ resolve2(answer.trim());
271
+ });
272
+ });
273
+ }
274
+ async function init() {
275
+ log(`
276
+ ${colors.cyan}Connect Base \uD504\uB85C\uC81D\uD2B8 \uCD08\uAE30\uD654${colors.reset}
277
+ `);
278
+ const rcPath = path.join(process.cwd(), ".connectbaserc");
279
+ if (fs.existsSync(rcPath)) {
280
+ const overwrite = await prompt(`${colors.yellow}\u26A0${colors.reset} .connectbaserc\uAC00 \uC774\uBBF8 \uC874\uC7AC\uD569\uB2C8\uB2E4. \uB36E\uC5B4\uC4F0\uC2DC\uACA0\uC2B5\uB2C8\uAE4C? (y/N): `);
281
+ if (overwrite.toLowerCase() !== "y") {
282
+ info("\uCD08\uAE30\uD654\uAC00 \uCDE8\uC18C\uB418\uC5C8\uC2B5\uB2C8\uB2E4");
283
+ return;
284
+ }
285
+ }
286
+ const apiKey = await prompt(`${colors.blue}?${colors.reset} API Key: `);
287
+ if (!apiKey) {
288
+ error("API Key\uB294 \uD544\uC218\uC785\uB2C8\uB2E4");
289
+ process.exit(1);
290
+ }
291
+ const storageId = await prompt(`${colors.blue}?${colors.reset} Storage ID: `);
292
+ if (!storageId) {
293
+ error("Storage ID\uB294 \uD544\uC218\uC785\uB2C8\uB2E4");
294
+ process.exit(1);
295
+ }
296
+ const defaultDir = detectBuildDir();
297
+ const deployDir = await prompt(`${colors.blue}?${colors.reset} \uBC30\uD3EC \uB514\uB809\uD1A0\uB9AC (${defaultDir}): `) || defaultDir;
298
+ const config = {
299
+ apiKey,
300
+ storageId,
301
+ deployDir
302
+ };
303
+ fs.writeFileSync(rcPath, JSON.stringify(config, null, 2) + "\n");
304
+ success(".connectbaserc \uC0DD\uC131 \uC644\uB8CC");
305
+ addToGitignore(".connectbaserc");
306
+ addDeployScript(deployDir);
307
+ log(`
308
+ ${colors.green}\uCD08\uAE30\uD654 \uC644\uB8CC!${colors.reset}
309
+ `);
310
+ log(`${colors.dim}\uBC30\uD3EC\uD558\uB824\uBA74:${colors.reset}`);
311
+ log(` ${colors.cyan}npm run deploy${colors.reset}
312
+ `);
313
+ }
314
+ function detectBuildDir() {
315
+ if (fs.existsSync(path.join(process.cwd(), "dist"))) return "./dist";
316
+ if (fs.existsSync(path.join(process.cwd(), "build"))) return "./build";
317
+ if (fs.existsSync(path.join(process.cwd(), "out"))) return "./out";
318
+ if (fs.existsSync(path.join(process.cwd(), ".next"))) return "./out";
319
+ if (fs.existsSync(path.join(process.cwd(), "vite.config.ts")) || fs.existsSync(path.join(process.cwd(), "vite.config.js"))) return "./dist";
320
+ if (fs.existsSync(path.join(process.cwd(), "next.config.js")) || fs.existsSync(path.join(process.cwd(), "next.config.mjs"))) return "./out";
321
+ return "./dist";
322
+ }
323
+ function addToGitignore(entry) {
324
+ const gitignorePath = path.join(process.cwd(), ".gitignore");
325
+ if (fs.existsSync(gitignorePath)) {
326
+ const content = fs.readFileSync(gitignorePath, "utf-8");
327
+ if (!content.includes(entry)) {
328
+ fs.appendFileSync(gitignorePath, `
329
+ # Connect Base
330
+ ${entry}
331
+ `);
332
+ success(`.gitignore\uC5D0 ${entry} \uCD94\uAC00 \uC644\uB8CC`);
333
+ } else {
334
+ info(`.gitignore\uC5D0 \uC774\uBBF8 ${entry}\uAC00 \uD3EC\uD568\uB418\uC5B4 \uC788\uC2B5\uB2C8\uB2E4`);
335
+ }
336
+ } else {
337
+ fs.writeFileSync(gitignorePath, `# Connect Base
338
+ ${entry}
339
+ `);
340
+ success(".gitignore \uC0DD\uC131 \uC644\uB8CC");
341
+ }
342
+ }
343
+ function addDeployScript(deployDir) {
344
+ const pkgPath = path.join(process.cwd(), "package.json");
345
+ if (!fs.existsSync(pkgPath)) {
346
+ warn("package.json\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC5B4 deploy \uC2A4\uD06C\uB9BD\uD2B8\uB97C \uCD94\uAC00\uD558\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4");
347
+ return;
348
+ }
349
+ try {
350
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
351
+ if (!pkg.scripts) pkg.scripts = {};
352
+ if (pkg.scripts.deploy) {
353
+ info(`package.json\uC5D0 \uC774\uBBF8 deploy \uC2A4\uD06C\uB9BD\uD2B8\uAC00 \uC788\uC2B5\uB2C8\uB2E4: "${pkg.scripts.deploy}"`);
354
+ return;
355
+ }
356
+ pkg.scripts.deploy = `connectbase-client deploy ${deployDir}`;
357
+ fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
358
+ success(`package.json\uC5D0 deploy \uC2A4\uD06C\uB9BD\uD2B8 \uCD94\uAC00 \uC644\uB8CC`);
359
+ } catch {
360
+ warn("package.json \uC218\uC815\uC5D0 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4");
361
+ }
362
+ }
260
363
  function showHelp() {
261
364
  log(`
262
365
  ${colors.cyan}connectbase-client${colors.reset} - Connect Base SDK & CLI
@@ -265,6 +368,7 @@ ${colors.yellow}\uC0AC\uC6A9\uBC95:${colors.reset}
265
368
  npx connectbase-client <command> [options]
266
369
 
267
370
  ${colors.yellow}\uBA85\uB839\uC5B4:${colors.reset}
371
+ init \uD504\uB85C\uC81D\uD2B8 \uCD08\uAE30\uD654 (\uC124\uC815 \uD30C\uC77C \uC0DD\uC131)
268
372
  deploy <directory> \uC6F9 \uC2A4\uD1A0\uB9AC\uC9C0\uC5D0 \uD30C\uC77C \uBC30\uD3EC
269
373
 
270
374
  ${colors.yellow}\uC635\uC158:${colors.reset}
@@ -274,6 +378,13 @@ ${colors.yellow}\uC635\uC158:${colors.reset}
274
378
  -h, --help \uB3C4\uC6C0\uB9D0 \uD45C\uC2DC
275
379
  -v, --version \uBC84\uC804 \uD45C\uC2DC
276
380
 
381
+ ${colors.yellow}\uBE60\uB978 \uC2DC\uC791:${colors.reset}
382
+ ${colors.dim}# 1. \uCD08\uAE30\uD654 (\uCD5C\uCD08 1\uD68C)${colors.reset}
383
+ npx connectbase-client init
384
+
385
+ ${colors.dim}# 2. \uBC30\uD3EC${colors.reset}
386
+ npm run deploy
387
+
277
388
  ${colors.yellow}\uD658\uACBD\uBCC0\uC218:${colors.reset}
278
389
  CONNECTBASE_API_KEY API Key
279
390
  CONNECTBASE_STORAGE_ID \uC2A4\uD1A0\uB9AC\uC9C0 ID
@@ -282,21 +393,8 @@ ${colors.yellow}\uD658\uACBD\uBCC0\uC218:${colors.reset}
282
393
  ${colors.yellow}\uC124\uC815 \uD30C\uC77C (.connectbaserc):${colors.reset}
283
394
  {
284
395
  "apiKey": "your-api-key",
285
- "storageId": "your-storage-id"
286
- }
287
-
288
- ${colors.yellow}\uC608\uC2DC:${colors.reset}
289
- ${colors.dim}# \uAE30\uBCF8 \uBC30\uD3EC${colors.reset}
290
- npx connectbase-client deploy ./dist -s <storage-id> -k <api-key>
291
-
292
- ${colors.dim}# \uD658\uACBD\uBCC0\uC218 \uC0AC\uC6A9${colors.reset}
293
- export CONNECTBASE_API_KEY=your-api-key
294
- export CONNECTBASE_STORAGE_ID=your-storage-id
295
- npx connectbase-client deploy ./dist
296
-
297
- ${colors.dim}# package.json scripts\uC5D0\uC11C \uC0AC\uC6A9${colors.reset}
298
- "scripts": {
299
- "deploy": "connectbase-client deploy ./dist"
396
+ "storageId": "your-storage-id",
397
+ "deployDir": "./dist"
300
398
  }
301
399
  `);
302
400
  }
@@ -345,14 +443,16 @@ async function main() {
345
443
  storageId: parsed.options.storageId || fileConfig.storageId,
346
444
  baseUrl: parsed.options.baseUrl || fileConfig.baseUrl || DEFAULT_BASE_URL
347
445
  };
348
- if (parsed.command === "deploy") {
349
- const directory = parsed.args[0] || ".";
446
+ if (parsed.command === "init") {
447
+ await init();
448
+ } else if (parsed.command === "deploy") {
449
+ const directory = parsed.args[0] || fileConfig.deployDir || ".";
350
450
  if (!config.apiKey) {
351
- error("API Key\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4 (-k \uC635\uC158 \uB610\uB294 CONNECTBASE_API_KEY \uD658\uACBD\uBCC0\uC218)");
451
+ error('API Key\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4. "npx connectbase-client init"\uC73C\uB85C \uC124\uC815\uD558\uAC70\uB098 -k \uC635\uC158\uC744 \uC0AC\uC6A9\uD558\uC138\uC694');
352
452
  process.exit(1);
353
453
  }
354
454
  if (!config.storageId) {
355
- error("\uC2A4\uD1A0\uB9AC\uC9C0 ID\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4 (-s \uC635\uC158 \uB610\uB294 CONNECTBASE_STORAGE_ID \uD658\uACBD\uBCC0\uC218)");
455
+ error('\uC2A4\uD1A0\uB9AC\uC9C0 ID\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4. "npx connectbase-client init"\uC73C\uB85C \uC124\uC815\uD558\uAC70\uB098 -s \uC635\uC158\uC744 \uC0AC\uC6A9\uD558\uC138\uC694');
356
456
  process.exit(1);
357
457
  }
358
458
  await deploy(directory, config);