@insforge/cli 0.1.23 → 0.1.25

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/dist/index.js CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  // src/index.ts
4
4
  import { readFileSync as readFileSync6 } from "fs";
5
- import { join as join6, dirname } from "path";
5
+ import { join as join7, dirname } from "path";
6
6
  import { fileURLToPath } from "url";
7
7
  import { Command } from "commander";
8
8
  import * as clack14 from "@clack/prompts";
@@ -360,7 +360,7 @@ async function refreshAccessToken(apiUrl) {
360
360
  }
361
361
 
362
362
  // src/lib/api/platform.ts
363
- async function platformFetch(path3, options = {}, apiUrl) {
363
+ async function platformFetch(path4, options = {}, apiUrl) {
364
364
  const baseUrl = getPlatformApiUrl(apiUrl);
365
365
  const token = getAccessToken();
366
366
  if (!token) {
@@ -371,11 +371,11 @@ async function platformFetch(path3, options = {}, apiUrl) {
371
371
  Authorization: `Bearer ${token}`,
372
372
  ...options.headers ?? {}
373
373
  };
374
- const res = await fetch(`${baseUrl}${path3}`, { ...options, headers });
374
+ const res = await fetch(`${baseUrl}${path4}`, { ...options, headers });
375
375
  if (res.status === 401) {
376
376
  const newToken = await refreshAccessToken(apiUrl);
377
377
  headers.Authorization = `Bearer ${newToken}`;
378
- const retryRes = await fetch(`${baseUrl}${path3}`, { ...options, headers });
378
+ const retryRes = await fetch(`${baseUrl}${path4}`, { ...options, headers });
379
379
  if (!retryRes.ok) {
380
380
  const err = await retryRes.json().catch(() => ({}));
381
381
  throw new CLIError(err.error ?? `Request failed: ${retryRes.status}`, retryRes.status === 403 ? 5 : 1);
@@ -866,14 +866,14 @@ async function getAnonKey() {
866
866
  const data = await res.json();
867
867
  return data.accessToken;
868
868
  }
869
- async function ossFetch(path3, options = {}) {
869
+ async function ossFetch(path4, options = {}) {
870
870
  const config = requireProjectConfig();
871
871
  const headers = {
872
872
  "Content-Type": "application/json",
873
873
  Authorization: `Bearer ${config.api_key}`,
874
874
  ...options.headers ?? {}
875
875
  };
876
- const res = await fetch(`${config.oss_host}${path3}`, { ...options, headers });
876
+ const res = await fetch(`${config.oss_host}${path4}`, { ...options, headers });
877
877
  if (!res.ok) {
878
878
  const err = await res.json().catch(() => ({}));
879
879
  throw new CLIError(err.error ?? `OSS request failed: ${res.status}`);
@@ -1215,8 +1215,8 @@ function registerRecordsCommands(recordsCmd2) {
1215
1215
  if (opts.limit) params.set("limit", String(opts.limit));
1216
1216
  if (opts.offset) params.set("offset", String(opts.offset));
1217
1217
  const query = params.toString();
1218
- const path3 = `/api/database/records/${encodeURIComponent(table)}${query ? `?${query}` : ""}`;
1219
- const res = await ossFetch(path3);
1218
+ const path4 = `/api/database/records/${encodeURIComponent(table)}${query ? `?${query}` : ""}`;
1219
+ const res = await ossFetch(path4);
1220
1220
  const data = await res.json();
1221
1221
  const records = data.data ?? [];
1222
1222
  if (json) {
@@ -1779,13 +1779,41 @@ function registerStorageListObjectsCommand(storageCmd2) {
1779
1779
  import { exec as exec2 } from "child_process";
1780
1780
  import { tmpdir } from "os";
1781
1781
  import { promisify as promisify2 } from "util";
1782
- import * as fs2 from "fs/promises";
1783
- import * as path2 from "path";
1782
+ import * as fs3 from "fs/promises";
1783
+ import * as path3 from "path";
1784
1784
  import * as clack10 from "@clack/prompts";
1785
1785
 
1786
- // src/commands/deployments/deploy.ts
1787
- import * as path from "path";
1786
+ // src/lib/env.ts
1788
1787
  import * as fs from "fs/promises";
1788
+ import * as path from "path";
1789
+ async function readEnvFile(cwd) {
1790
+ const candidates = [".env.local", ".env.production", ".env"];
1791
+ for (const name of candidates) {
1792
+ const filePath = path.join(cwd, name);
1793
+ const exists = await fs.stat(filePath).catch(() => null);
1794
+ if (!exists) continue;
1795
+ const content = await fs.readFile(filePath, "utf-8");
1796
+ const vars = [];
1797
+ for (const line of content.split("\n")) {
1798
+ const trimmed = line.trim();
1799
+ if (!trimmed || trimmed.startsWith("#")) continue;
1800
+ const eqIndex = trimmed.indexOf("=");
1801
+ if (eqIndex === -1) continue;
1802
+ const key = trimmed.slice(0, eqIndex).trim();
1803
+ let value = trimmed.slice(eqIndex + 1).trim();
1804
+ if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
1805
+ value = value.slice(1, -1);
1806
+ }
1807
+ if (key) vars.push({ key, value });
1808
+ }
1809
+ return vars;
1810
+ }
1811
+ return [];
1812
+ }
1813
+
1814
+ // src/commands/deployments/deploy.ts
1815
+ import * as path2 from "path";
1816
+ import * as fs2 from "fs/promises";
1789
1817
  import * as clack9 from "@clack/prompts";
1790
1818
  import archiver from "archiver";
1791
1819
  var POLL_INTERVAL_MS = 5e3;
@@ -1885,8 +1913,8 @@ function registerDeploymentsDeployCommand(deploymentsCmd2) {
1885
1913
  await requireAuth();
1886
1914
  const config = getProjectConfig();
1887
1915
  if (!config) throw new ProjectNotLinkedError();
1888
- const sourceDir = path.resolve(directory ?? ".");
1889
- const stats = await fs.stat(sourceDir).catch(() => null);
1916
+ const sourceDir = path2.resolve(directory ?? ".");
1917
+ const stats = await fs2.stat(sourceDir).catch(() => null);
1890
1918
  if (!stats?.isDirectory()) {
1891
1919
  throw new CLIError(`"${sourceDir}" is not a valid directory.`);
1892
1920
  }
@@ -1955,15 +1983,15 @@ async function waitForProjectActive(projectId, apiUrl, timeoutMs = 12e4) {
1955
1983
  throw new CLIError("Project creation timed out. Check the dashboard for status.");
1956
1984
  }
1957
1985
  async function copyDir(src, dest) {
1958
- const entries = await fs2.readdir(src, { withFileTypes: true });
1986
+ const entries = await fs3.readdir(src, { withFileTypes: true });
1959
1987
  for (const entry of entries) {
1960
- const srcPath = path2.join(src, entry.name);
1961
- const destPath = path2.join(dest, entry.name);
1988
+ const srcPath = path3.join(src, entry.name);
1989
+ const destPath = path3.join(dest, entry.name);
1962
1990
  if (entry.isDirectory()) {
1963
- await fs2.mkdir(destPath, { recursive: true });
1991
+ await fs3.mkdir(destPath, { recursive: true });
1964
1992
  await copyDir(srcPath, destPath);
1965
1993
  } else {
1966
- await fs2.copyFile(srcPath, destPath);
1994
+ await fs3.copyFile(srcPath, destPath);
1967
1995
  }
1968
1996
  }
1969
1997
  }
@@ -2007,7 +2035,11 @@ function registerCreateCommand(program2) {
2007
2035
  if (clack10.isCancel(name)) process.exit(0);
2008
2036
  projectName = name;
2009
2037
  }
2038
+ const validTemplates = ["react", "nextjs", "chatbot", "empty"];
2010
2039
  let template = opts.template;
2040
+ if (template && !validTemplates.includes(template)) {
2041
+ throw new CLIError(`Invalid template "${template}". Valid options: ${validTemplates.join(", ")}`);
2042
+ }
2011
2043
  if (!template) {
2012
2044
  if (json) {
2013
2045
  template = "empty";
@@ -2072,9 +2104,15 @@ function registerCreateCommand(program2) {
2072
2104
  });
2073
2105
  if (!clack10.isCancel(shouldDeploy) && shouldDeploy) {
2074
2106
  try {
2107
+ const envVars = await readEnvFile(process.cwd());
2108
+ const startBody = {};
2109
+ if (envVars.length > 0) {
2110
+ startBody.envVars = envVars;
2111
+ }
2075
2112
  const deploySpinner = clack10.spinner();
2076
2113
  const result = await deployProject({
2077
2114
  sourceDir: process.cwd(),
2115
+ startBody,
2078
2116
  spinner: deploySpinner
2079
2117
  });
2080
2118
  if (result.isReady) {
@@ -2124,9 +2162,9 @@ async function downloadTemplate(framework, projectConfig, projectName, json, _ap
2124
2162
  }
2125
2163
  const tempDir = tmpdir();
2126
2164
  const targetDir = projectName;
2127
- const templatePath = path2.join(tempDir, targetDir);
2165
+ const templatePath = path3.join(tempDir, targetDir);
2128
2166
  try {
2129
- await fs2.rm(templatePath, { recursive: true, force: true });
2167
+ await fs3.rm(templatePath, { recursive: true, force: true });
2130
2168
  } catch {
2131
2169
  }
2132
2170
  const frame = framework === "nextjs" ? "nextjs" : "react";
@@ -2140,7 +2178,7 @@ async function downloadTemplate(framework, projectConfig, projectName, json, _ap
2140
2178
  s?.message("Copying template files...");
2141
2179
  const cwd = process.cwd();
2142
2180
  await copyDir(templatePath, cwd);
2143
- await fs2.rm(templatePath, { recursive: true, force: true }).catch(() => {
2181
+ await fs3.rm(templatePath, { recursive: true, force: true }).catch(() => {
2144
2182
  });
2145
2183
  s?.stop("Template files downloaded");
2146
2184
  } catch (err) {
@@ -2154,28 +2192,28 @@ async function downloadTemplate(framework, projectConfig, projectName, json, _ap
2154
2192
  async function downloadGitHubTemplate(templateName, projectConfig, json) {
2155
2193
  const s = !json ? clack10.spinner() : null;
2156
2194
  s?.start(`Downloading ${templateName} template...`);
2157
- const tempDir = path2.join(tmpdir(), `insforge-template-${Date.now()}`);
2195
+ const tempDir = path3.join(tmpdir(), `insforge-template-${Date.now()}`);
2158
2196
  try {
2159
- await fs2.mkdir(tempDir, { recursive: true });
2197
+ await fs3.mkdir(tempDir, { recursive: true });
2160
2198
  await execAsync2(
2161
2199
  "git clone --depth 1 https://github.com/InsForge/insforge-templates.git .",
2162
2200
  { cwd: tempDir, maxBuffer: 10 * 1024 * 1024, timeout: 6e4 }
2163
2201
  );
2164
- const templateDir = path2.join(tempDir, templateName);
2165
- const stat3 = await fs2.stat(templateDir).catch(() => null);
2166
- if (!stat3?.isDirectory()) {
2202
+ const templateDir = path3.join(tempDir, templateName);
2203
+ const stat4 = await fs3.stat(templateDir).catch(() => null);
2204
+ if (!stat4?.isDirectory()) {
2167
2205
  throw new Error(`Template "${templateName}" not found in repository`);
2168
2206
  }
2169
2207
  s?.message("Copying template files...");
2170
2208
  const cwd = process.cwd();
2171
2209
  await copyDir(templateDir, cwd);
2172
- const envExamplePath = path2.join(cwd, ".env.example");
2173
- const envExampleExists = await fs2.stat(envExamplePath).catch(() => null);
2210
+ const envExamplePath = path3.join(cwd, ".env.example");
2211
+ const envExampleExists = await fs3.stat(envExamplePath).catch(() => null);
2174
2212
  if (envExampleExists) {
2175
2213
  const anonKey = await getAnonKey();
2176
- const envExample = await fs2.readFile(envExamplePath, "utf-8");
2214
+ const envExample = await fs3.readFile(envExamplePath, "utf-8");
2177
2215
  const envContent = envExample.replace(
2178
- /^([A-Z_]+=)(.*)$/gm,
2216
+ /^([A-Z][A-Z0-9_]*=)(.*)$/gm,
2179
2217
  (_, prefix, _value) => {
2180
2218
  const key = prefix.slice(0, -1);
2181
2219
  if (/INSFORGE.*(URL|BASE_URL)$/.test(key)) return `${prefix}${projectConfig.oss_host}`;
@@ -2183,16 +2221,16 @@ async function downloadGitHubTemplate(templateName, projectConfig, json) {
2183
2221
  return `${prefix}${_value}`;
2184
2222
  }
2185
2223
  );
2186
- await fs2.writeFile(path2.join(cwd, ".env.local"), envContent);
2224
+ await fs3.writeFile(path3.join(cwd, ".env.local"), envContent);
2187
2225
  }
2188
2226
  s?.stop(`${templateName} template downloaded`);
2189
- const migrationPath = path2.join(cwd, "migrations", "db_int.sql");
2190
- const migrationExists = await fs2.stat(migrationPath).catch(() => null);
2227
+ const migrationPath = path3.join(cwd, "migrations", "db_int.sql");
2228
+ const migrationExists = await fs3.stat(migrationPath).catch(() => null);
2191
2229
  if (migrationExists) {
2192
2230
  const dbSpinner = !json ? clack10.spinner() : null;
2193
2231
  dbSpinner?.start("Running database migrations...");
2194
2232
  try {
2195
- const sql = await fs2.readFile(migrationPath, "utf-8");
2233
+ const sql = await fs3.readFile(migrationPath, "utf-8");
2196
2234
  await ossFetch("/api/database/advance/rawsql/unrestricted", {
2197
2235
  method: "POST",
2198
2236
  body: JSON.stringify({ query: sql })
@@ -2213,7 +2251,7 @@ async function downloadGitHubTemplate(templateName, projectConfig, json) {
2213
2251
  clack10.log.info("You can manually clone from: https://github.com/InsForge/insforge-templates");
2214
2252
  }
2215
2253
  } finally {
2216
- await fs2.rm(tempDir, { recursive: true, force: true }).catch(() => {
2254
+ await fs3.rm(tempDir, { recursive: true, force: true }).catch(() => {
2217
2255
  });
2218
2256
  }
2219
2257
  }
@@ -2475,8 +2513,8 @@ async function listDocs(json) {
2475
2513
  );
2476
2514
  }
2477
2515
  }
2478
- async function fetchDoc(path3, label, json) {
2479
- const res = await ossFetch(path3);
2516
+ async function fetchDoc(path4, label, json) {
2517
+ const res = await ossFetch(path4);
2480
2518
  const data = await res.json();
2481
2519
  const doc = data.data ?? data;
2482
2520
  if (json) {
@@ -2990,7 +3028,7 @@ function formatSize2(gb) {
2990
3028
 
2991
3029
  // src/index.ts
2992
3030
  var __dirname = dirname(fileURLToPath(import.meta.url));
2993
- var pkg = JSON.parse(readFileSync6(join6(__dirname, "../package.json"), "utf-8"));
3031
+ var pkg = JSON.parse(readFileSync6(join7(__dirname, "../package.json"), "utf-8"));
2994
3032
  var INSFORGE_LOGO = `
2995
3033
  \u2588\u2588\u2557\u2588\u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557
2996
3034
  \u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2554\u2550\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D \u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D