railcode 0.1.0 → 0.1.1

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
@@ -2,6 +2,33 @@
2
2
 
3
3
  TypeScript CLI for app builders working on static Railcode apps.
4
4
 
5
+ ## Install
6
+
7
+ Install the CLI globally from npm:
8
+
9
+ ```bash
10
+ npm install -g railcode
11
+ railcode --version
12
+ ```
13
+
14
+ On first install, log in from a terminal:
15
+
16
+ ```bash
17
+ railcode login
18
+ ```
19
+
20
+ If the CLI prompts for `Railcode auth/API domain`, enter your Railcode domain.
21
+ Bare domains are treated as HTTPS, so `railcode.example.com` becomes
22
+ `https://railcode.example.com`. Full `https://...` URLs and trailing slashes are
23
+ also accepted. To skip the prompt, pass the domain up front:
24
+
25
+ ```bash
26
+ railcode login --api-url railcode.example.com
27
+ ```
28
+
29
+ The login flow opens a browser authorization link and saves the resulting API
30
+ token under `~/.railcode/config.json`.
31
+
5
32
  ## Build
6
33
 
7
34
  ```bash
@@ -13,11 +40,12 @@ npm link
13
40
  ## Common Flow
14
41
 
15
42
  ```bash
43
+ npm install -g railcode
44
+ railcode login
16
45
  mkdir my-app
17
46
  cd my-app
18
47
  railcode init my-app
19
48
  railcode dev
20
- railcode login
21
49
  railcode design-system pull design-system.md
22
50
  railcode deploy
23
51
  ```
package/dist/index.js CHANGED
@@ -8,7 +8,7 @@ import { basename, dirname, join, relative, resolve, sep } from "node:path";
8
8
  import process from "node:process";
9
9
  import { createInterface } from "node:readline/promises";
10
10
  import { fileURLToPath } from "node:url";
11
- const VERSION = "0.1.0";
11
+ const VERSION = "0.1.1";
12
12
  const CLI_PACKAGE_NAME = "railcode";
13
13
  const SKILL_NAME = "create-railcode-app";
14
14
  const RAILCODE_HOME = process.env.RAILCODE_HOME || join(homedir(), ".railcode");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "railcode",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "CLI for building, testing, and deploying Railcode apps.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -378,20 +378,20 @@ function SqlPanel() {
378
378
  return (
379
379
  <Panel
380
380
  title="Read-only SQL"
381
- code="await postgres(name).runSQL(query, params)"
381
+ code="await dataConnectors(); await postgres(name).runSQL(query, params)"
382
382
  icon={<Database className="size-4" />}
383
383
  actions={
384
384
  <Button
385
385
  icon={<RefreshCcw className="size-4" />}
386
386
  onClick={() => void refreshConnections()}
387
387
  >
388
- Connections
388
+ Connectors
389
389
  </Button>
390
390
  }
391
391
  >
392
392
  <form className="grid gap-3" onSubmit={submit}>
393
393
  <label className="grid gap-1.5 text-sm">
394
- <span className="font-medium">Global connection</span>
394
+ <span className="font-medium">Data connector</span>
395
395
  <select
396
396
  className="h-9 rounded-md border border-input bg-canvas px-3 outline-none focus:border-rail focus:ring-2 focus:ring-rail/20"
397
397
  disabled={!hasConnections}
@@ -408,7 +408,7 @@ function SqlPanel() {
408
408
  </label>
409
409
  {!hasConnections ? (
410
410
  <div className="rounded-md border border-line bg-muted px-3 py-2 text-sm text-dim">
411
- No global SQL connections are configured.
411
+ No data connectors are configured.
412
412
  </div>
413
413
  ) : null}
414
414
  <label className="grid gap-1.5 text-sm">
@@ -100,11 +100,13 @@ export type SqlRows = Array<Record<string, unknown>> & {
100
100
  truncated?: boolean;
101
101
  };
102
102
 
103
- export type DatabaseConnectorInfo = {
103
+ export type DataConnectorInfo = {
104
104
  engine: "postgres" | "mysql" | string;
105
105
  name: string;
106
106
  };
107
107
 
108
+ export type DatabaseConnectorInfo = DataConnectorInfo;
109
+
108
110
  export type DatabaseHandle = {
109
111
  runSQL(query: string, params?: unknown[]): Promise<SqlRows>;
110
112
  };
@@ -182,6 +184,7 @@ declare global {
182
184
  };
183
185
  postgres?: DatabaseNamespace;
184
186
  mysql?: DatabaseNamespace;
187
+ dataConnectors?: () => Promise<DataConnectorInfo[]>;
185
188
  databaseConnectors?: () => Promise<DatabaseConnectorInfo[]>;
186
189
  llm?: {
187
190
  generate(
@@ -233,11 +236,23 @@ export const fileStore = {
233
236
  },
234
237
  };
235
238
 
239
+ function requireDataConnectors(): () => Promise<DataConnectorInfo[]> {
240
+ const value = window.dataConnectors ?? window.databaseConnectors;
241
+ if (!value) {
242
+ throw new Error(
243
+ "Railcode SDK global 'dataConnectors' is not available. Make sure /_api/sdk.js loads before the app bundle.",
244
+ );
245
+ }
246
+ return value;
247
+ }
248
+
236
249
  // -> [{ engine, name }, ...] every configured connection this app can query.
237
- export function databaseConnectors(): Promise<DatabaseConnectorInfo[]> {
238
- return requireSdk("databaseConnectors")();
250
+ export function dataConnectors(): Promise<DataConnectorInfo[]> {
251
+ return requireDataConnectors()();
239
252
  }
240
253
 
254
+ export const databaseConnectors = dataConnectors;
255
+
241
256
  // Per-engine namespaces: `postgres('orders').runSQL(q, p)` targets a named
242
257
  // connection; `postgres.runSQL(q, p)` uses the connection named "default".
243
258
  function databaseNamespace(engine: "postgres" | "mysql"): DatabaseNamespace {
@@ -2,7 +2,7 @@ import { create } from "zustand";
2
2
 
3
3
  import { cleanError } from "@/lib/format";
4
4
  import {
5
- DatabaseConnectorInfo,
5
+ DataConnectorInfo,
6
6
  FileEntry,
7
7
  Identity,
8
8
  KvRow,
@@ -10,7 +10,7 @@ import {
10
10
  SqlRows,
11
11
  AppUsers,
12
12
  collection,
13
- databaseConnectors,
13
+ dataConnectors,
14
14
  fileStore,
15
15
  getIdentity,
16
16
  getAppUsers,
@@ -34,7 +34,7 @@ type AppState = {
34
34
  appUsers?: AppUsers;
35
35
  kvRows: KvRow<StarterDoc>[];
36
36
  files: FileEntry[];
37
- connections: DatabaseConnectorInfo[];
37
+ connections: DataConnectorInfo[];
38
38
  sqlRows?: SqlRows;
39
39
  llmResult?: LlmResult;
40
40
  streamText: string;
@@ -51,7 +51,7 @@ type AppState = {
51
51
  querySql: (
52
52
  query: string,
53
53
  params: unknown[],
54
- connector?: DatabaseConnectorInfo,
54
+ connector?: DataConnectorInfo,
55
55
  ) => Promise<void>;
56
56
  generateText: (prompt: string) => Promise<void>;
57
57
  streamTextResponse: (prompt: string) => Promise<void>;
@@ -81,6 +81,13 @@ function withError(error: unknown, area: ApiArea) {
81
81
  });
82
82
  }
83
83
 
84
+ function namespaceFor(connector?: DataConnectorInfo) {
85
+ const engine = connector?.engine ?? "postgres";
86
+ if (engine === "postgres") return postgres;
87
+ if (engine === "mysql") return mysql;
88
+ throw new Error(`Unsupported data connector engine: ${engine}`);
89
+ }
90
+
84
91
  export const useAppStore = create<AppState>((set, get) => ({
85
92
  kvRows: [],
86
93
  files: [],
@@ -106,7 +113,7 @@ export const useAppStore = create<AppState>((set, get) => ({
106
113
  getAppUsers(),
107
114
  starterCollection().list(),
108
115
  fileStore.list(),
109
- databaseConnectors(),
116
+ dataConnectors(),
110
117
  ]);
111
118
  set((state) => ({
112
119
  identity,
@@ -210,7 +217,7 @@ export const useAppStore = create<AppState>((set, get) => ({
210
217
  async refreshConnections() {
211
218
  set(patchStatus("sql", "loading"));
212
219
  try {
213
- const connections = await databaseConnectors();
220
+ const connections = await dataConnectors();
214
221
  set((state) => ({
215
222
  connections,
216
223
  status: { ...state.status, sql: "ready" },
@@ -223,10 +230,8 @@ export const useAppStore = create<AppState>((set, get) => ({
223
230
  async querySql(query, params, connector) {
224
231
  set(patchStatus("sql", "loading"));
225
232
  try {
226
- const engine = connector?.engine ?? "postgres";
227
233
  const name = connector?.name ?? "default";
228
- const ns = engine === "mysql" ? mysql : postgres;
229
- const sqlRows = await ns(name).runSQL(query, params);
234
+ const sqlRows = await namespaceFor(connector)(name).runSQL(query, params);
230
235
  set((state) => ({
231
236
  sqlRows,
232
237
  status: { ...state.status, sql: "ready" },
package/static/sdk.js CHANGED
@@ -12,7 +12,7 @@
12
12
  * await files.upload('logo.png', blob, 'image/png');
13
13
  *
14
14
  * // query an external database an admin configured for this app (read-only):
15
- * const rows = await sql('select * from orders where id = $1', [orderId]);
15
+ * const rows = await postgres('analytics').runSQL('select * from orders where id = $1', [orderId]);
16
16
  * </script>
17
17
  *
18
18
  * Everything is scoped to THIS app automatically (derived from the hostname
@@ -75,7 +75,7 @@
75
75
  <button id="collapse">Hide \u203A</button>
76
76
  </header>
77
77
  <div class="log" id="log"></div>
78
- <footer>Calls made via <code>sql()</code>, <code>llm</code>, <code>db</code>, <code>files</code>, <code>me()</code>, <code>appUsers()</code></footer>
78
+ <footer>Calls made via <code>postgres()</code>, <code>mysql()</code>, <code>llm</code>, <code>db</code>, <code>files</code>, <code>me()</code>, <code>appUsers()</code></footer>
79
79
  </div>`;
80
80
  function mount() {
81
81
  (document.body || document.documentElement).appendChild(host);
@@ -368,7 +368,8 @@
368
368
  };
369
369
  var postgres = namespace("postgres");
370
370
  var mysql = namespace("mysql");
371
- var databaseConnectors = () => track("connections", "databaseConnectors()", () => call("GET", "/connections"));
371
+ var dataConnectors = () => track("connections", "dataConnectors()", () => call("GET", "/connections"));
372
+ var databaseConnectors = dataConnectors;
372
373
 
373
374
  // src/design-system.ts
374
375
  var designSystem = () => track("design-system", "designSystem()", () => call("GET", "/config/design-system"));
@@ -425,6 +426,7 @@
425
426
  window.llm = llm;
426
427
  window.postgres = postgres;
427
428
  window.mysql = mysql;
429
+ window.dataConnectors = dataConnectors;
428
430
  window.databaseConnectors = databaseConnectors;
429
431
  window.designSystem = designSystem;
430
432
  window.me = me;