@lumerahq/cli 0.19.16-dev.0 → 0.19.17-dev.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.
@@ -4,7 +4,7 @@ import {
4
4
  import {
5
5
  createApiClient,
6
6
  isApiErrorStatus
7
- } from "./chunk-WIX3DUD5.js";
7
+ } from "./chunk-MDCAEFUH.js";
8
8
  import {
9
9
  findProjectRoot,
10
10
  getAppName
@@ -25,12 +25,6 @@ while (__pkgDir !== "/") {
25
25
  }
26
26
  var pkg = JSON.parse(readFileSync(resolve(__pkgDir, "package.json"), "utf-8"));
27
27
  var CLI_USER_AGENT = `lumera-cli/${pkg.version}`;
28
- var USER_CONTEXT_ENV = "LUMERA_USER_ID";
29
- var USER_CONTEXT_HEADER = "X-Lumera-User-Id";
30
- function userContextHeaders() {
31
- const userID = process.env[USER_CONTEXT_ENV]?.trim();
32
- return userID ? { [USER_CONTEXT_HEADER]: userID } : {};
33
- }
34
28
  var ApiError = class extends Error {
35
29
  status;
36
30
  body;
@@ -73,7 +67,6 @@ var ApiClient = class {
73
67
  "User-Agent": CLI_USER_AGENT,
74
68
  "X-Lumera-Client": "lumera-cli",
75
69
  ...this.projectExternalId ? { "X-Lumera-Project": this.projectExternalId } : {},
76
- ...userContextHeaders(),
77
70
  ...options.headers
78
71
  };
79
72
  const method = (options.method || "GET").toUpperCase();
@@ -9,12 +9,6 @@ import { existsSync, readFileSync } from "fs";
9
9
  import { resolve, dirname } from "path";
10
10
  import archiver from "archiver";
11
11
  import pc from "picocolors";
12
- var USER_CONTEXT_ENV = "LUMERA_USER_ID";
13
- var USER_CONTEXT_HEADER = "X-Lumera-User-Id";
14
- function userContextHeaders() {
15
- const userID = process.env[USER_CONTEXT_ENV]?.trim();
16
- return userID ? { [USER_CONTEXT_HEADER]: userID } : {};
17
- }
18
12
  function formatTimestampVersion(date = /* @__PURE__ */ new Date()) {
19
13
  const pad = (value) => String(value).padStart(2, "0");
20
14
  return [
@@ -62,8 +56,7 @@ async function ensureAppRecord(apiBase, token, appName, appTitle) {
62
56
  {
63
57
  headers: {
64
58
  Authorization: `Bearer ${token}`,
65
- "X-Lumera-Client": "lumera-cli",
66
- ...userContextHeaders()
59
+ "X-Lumera-Client": "lumera-cli"
67
60
  }
68
61
  }
69
62
  );
@@ -82,8 +75,7 @@ async function ensureAppRecord(apiBase, token, appName, appTitle) {
82
75
  headers: {
83
76
  Authorization: `Bearer ${token}`,
84
77
  "Content-Type": "application/json",
85
- "X-Lumera-Client": "lumera-cli",
86
- ...userContextHeaders()
78
+ "X-Lumera-Client": "lumera-cli"
87
79
  },
88
80
  body: JSON.stringify(appData)
89
81
  });
@@ -116,8 +108,7 @@ async function deploy(options) {
116
108
  method: "POST",
117
109
  headers: {
118
110
  Authorization: `Bearer ${token}`,
119
- "X-Lumera-Client": "lumera-cli",
120
- ...userContextHeaders()
111
+ "X-Lumera-Client": "lumera-cli"
121
112
  },
122
113
  body: formData
123
114
  });
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  deps,
3
3
  syncDeps
4
- } from "./chunk-TPQGGLSD.js";
4
+ } from "./chunk-4WZMUFC7.js";
5
5
  import "./chunk-2CR762KB.js";
6
- import "./chunk-WIX3DUD5.js";
6
+ import "./chunk-MDCAEFUH.js";
7
7
  import "./chunk-ZH3NVYEQ.js";
8
8
  import "./chunk-FJFIWC7G.js";
9
9
  import "./chunk-PNKVD2UK.js";
@@ -1,15 +1,15 @@
1
1
  import {
2
2
  dev
3
- } from "./chunk-VM5YR3HF.js";
3
+ } from "./chunk-VOIZWYZD.js";
4
4
  import {
5
5
  syncDeps
6
- } from "./chunk-TPQGGLSD.js";
6
+ } from "./chunk-4WZMUFC7.js";
7
7
  import {
8
8
  loadEnv
9
9
  } from "./chunk-2CR762KB.js";
10
10
  import {
11
11
  createApiClient
12
- } from "./chunk-WIX3DUD5.js";
12
+ } from "./chunk-MDCAEFUH.js";
13
13
  import {
14
14
  findProjectRoot,
15
15
  getApiUrl,
package/dist/index.js CHANGED
@@ -219,39 +219,39 @@ async function main() {
219
219
  switch (command) {
220
220
  // Resource commands
221
221
  case "plan":
222
- await import("./resources-EZQGSI5L.js").then((m) => m.plan(args.slice(1)));
222
+ await import("./resources-M6R2RFSW.js").then((m) => m.plan(args.slice(1)));
223
223
  break;
224
224
  case "apply":
225
- await import("./resources-EZQGSI5L.js").then((m) => m.apply(args.slice(1)));
225
+ await import("./resources-M6R2RFSW.js").then((m) => m.apply(args.slice(1)));
226
226
  break;
227
227
  case "pull":
228
- await import("./resources-EZQGSI5L.js").then((m) => m.pull(args.slice(1)));
228
+ await import("./resources-M6R2RFSW.js").then((m) => m.pull(args.slice(1)));
229
229
  break;
230
230
  case "destroy":
231
- await import("./resources-EZQGSI5L.js").then((m) => m.destroy(args.slice(1)));
231
+ await import("./resources-M6R2RFSW.js").then((m) => m.destroy(args.slice(1)));
232
232
  break;
233
233
  case "list":
234
- await import("./resources-EZQGSI5L.js").then((m) => m.list(args.slice(1)));
234
+ await import("./resources-M6R2RFSW.js").then((m) => m.list(args.slice(1)));
235
235
  break;
236
236
  case "show":
237
- await import("./resources-EZQGSI5L.js").then((m) => m.show(args.slice(1)));
237
+ await import("./resources-M6R2RFSW.js").then((m) => m.show(args.slice(1)));
238
238
  break;
239
239
  case "diff":
240
- await import("./resources-EZQGSI5L.js").then((m) => m.diff(args.slice(1)));
240
+ await import("./resources-M6R2RFSW.js").then((m) => m.diff(args.slice(1)));
241
241
  break;
242
242
  // Development
243
243
  case "dev":
244
- await import("./dev-33OLPWUK.js").then((m) => m.dev(args.slice(1)));
244
+ await import("./dev-PONRO7VN.js").then((m) => m.dev(args.slice(1)));
245
245
  break;
246
246
  case "run":
247
- await import("./run-BQPH6BIK.js").then((m) => m.run(args.slice(1)));
247
+ await import("./run-R6MO23U7.js").then((m) => m.run(args.slice(1)));
248
248
  break;
249
249
  // Project
250
250
  case "init":
251
- await import("./init-EBNELAZA.js").then((m) => m.init(args.slice(1)));
251
+ await import("./init-KJOWD2KQ.js").then((m) => m.init(args.slice(1)));
252
252
  break;
253
253
  case "register":
254
- await import("./register-EQ5KYVLV.js").then((m) => m.register(args.slice(1)));
254
+ await import("./register-QBRKXWNX.js").then((m) => m.register(args.slice(1)));
255
255
  break;
256
256
  case "templates":
257
257
  await import("./templates-LNUOTNLN.js").then((m) => m.templates(subcommand, args.slice(2)));
@@ -268,7 +268,7 @@ async function main() {
268
268
  break;
269
269
  // Dependencies
270
270
  case "deps":
271
- await import("./deps-ALKBN6UT.js").then((m) => m.deps(args.slice(1)));
271
+ await import("./deps-KVHWZARX.js").then((m) => m.deps(args.slice(1)));
272
272
  break;
273
273
  // Auth
274
274
  case "login":
@@ -7,7 +7,7 @@ import {
7
7
  } from "./chunk-BHYDYR75.js";
8
8
  import {
9
9
  createApiClient
10
- } from "./chunk-WIX3DUD5.js";
10
+ } from "./chunk-MDCAEFUH.js";
11
11
  import {
12
12
  getToken,
13
13
  init_auth,
@@ -6,7 +6,7 @@ import {
6
6
  } from "./chunk-BHYDYR75.js";
7
7
  import {
8
8
  createApiClient
9
- } from "./chunk-WIX3DUD5.js";
9
+ } from "./chunk-MDCAEFUH.js";
10
10
  import {
11
11
  findProjectRoot,
12
12
  getAppName,
@@ -1,16 +1,16 @@
1
1
  import {
2
2
  deploy
3
- } from "./chunk-VM5YR3HF.js";
3
+ } from "./chunk-VOIZWYZD.js";
4
4
  import {
5
5
  syncDeps
6
- } from "./chunk-TPQGGLSD.js";
6
+ } from "./chunk-4WZMUFC7.js";
7
7
  import {
8
8
  loadEnv
9
9
  } from "./chunk-2CR762KB.js";
10
10
  import {
11
11
  ApiError,
12
12
  createApiClient
13
- } from "./chunk-WIX3DUD5.js";
13
+ } from "./chunk-MDCAEFUH.js";
14
14
  import {
15
15
  findProjectRoot,
16
16
  getApiUrl,
@@ -3073,7 +3073,7 @@ async function plan(args) {
3073
3073
  showPlanHelp();
3074
3074
  return;
3075
3075
  }
3076
- const jsonOutput = args.includes("--json");
3076
+ const jsonOutput = process.env.LUMERA_JSON === "1";
3077
3077
  const projectRoot = findProjectRoot();
3078
3078
  loadEnv(projectRoot);
3079
3079
  const platformDir = getPlatformDir();
@@ -3081,7 +3081,7 @@ async function plan(args) {
3081
3081
  const api = createApiClient(void 0, void 0, appName);
3082
3082
  const projectId = getProjectId(projectRoot);
3083
3083
  const positionalArgs = args.filter((a) => !a.startsWith("-"));
3084
- const { type, name } = parseResource(positionalArgs.filter((a) => a !== "--json")[0]);
3084
+ const { type, name } = parseResource(positionalArgs[0]);
3085
3085
  console.log();
3086
3086
  console.log(pc2.cyan(pc2.bold(" Plan")));
3087
3087
  console.log(pc2.dim(" Comparing local files to remote state..."));
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-2CR762KB.js";
4
4
  import {
5
5
  createApiClient
6
- } from "./chunk-WIX3DUD5.js";
6
+ } from "./chunk-MDCAEFUH.js";
7
7
  import {
8
8
  findProjectRoot,
9
9
  getApiUrl,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lumerahq/cli",
3
- "version": "0.19.16-dev.0",
3
+ "version": "0.19.17-dev.0",
4
4
  "description": "CLI for building and deploying Lumera apps",
5
5
  "type": "module",
6
6
  "engines": {
@@ -41,9 +41,9 @@ All resources use **external IDs** in the format `<app-name>:<resource-name>` (a
41
41
  **All collection names are automatically namespaced by project.** Always use bare names (e.g. `orders`, not `myproject__orders`) everywhere — in collection JSON files, Python SDK calls, JavaScript hooks, and frontend queries. The platform resolves bare names to the project-scoped version transparently.
42
42
 
43
43
  - `pb.ensure_collection("orders", ...)` → stored as `{project}__orders`
44
- - `pb.search("orders", ...)` → resolves to `{project}__orders`
44
+ - `query_sql("SELECT id FROM orders")` → resolves to `{project}__orders`
45
45
  - `ctx.dao.find("orders", ...)` → resolves to `{project}__orders`
46
- - `pbList("orders", ...)` in frontend → resolves via `X-Lumera-Project` header
46
+ - `pbSql({ sql: "SELECT id FROM orders" })` in frontend → resolves via `X-Lumera-Project` header
47
47
 
48
48
  **Never manually prefix collection names with `{project}__`.** Two projects can each have an `orders` collection — they are fully isolated.
49
49
 
@@ -96,10 +96,16 @@ Custom apps run in an **iframe**. **Always use the `@lumerahq/ui` bridge for API
96
96
 
97
97
  ```ts
98
98
  // ✅ Correct — uses postMessage bridge, no CORS issues
99
- import { pbSql, pbList, pbCreate, pbUpdate, pbDelete } from '@lumerahq/ui/lib';
99
+ import { pbSql, pbCreate, pbUpdate, pbDelete } from '@lumerahq/ui/lib';
100
+
101
+ // New read queries: use SQL for collection access, including lookups, lists, reports, joins, ordering, and filters
102
+ const result = await pbSql<{ id: string; amount: number }>({
103
+ sql: 'SELECT id, amount FROM orders WHERE status = {:status} ORDER BY updated DESC LIMIT 100',
104
+ params: { status: 'pending' },
105
+ });
106
+ const records = result.rows;
100
107
 
101
108
  // CRUD
102
- const records = await pbList('orders', { filter: JSON.stringify({ status: "pending" }) });
103
109
  await pbCreate('orders', { amount: 100 });
104
110
  await pbUpdate('orders', recordId, { status: 'done' });
105
111
  await pbDelete('orders', recordId);
@@ -113,6 +119,9 @@ fetch('https://app.lumerahq.com/api/pb/sql', ...);
113
119
 
114
120
  **Rules:**
115
121
  - Always import from `@lumerahq/ui/lib` — never write a custom `apiFetch` with raw `fetch()`
122
+ - Use `pbSql()` for new read-only collection access
123
+ - Existing `pbList()` / `pbSearch()` filter code remains supported for simple existing list/search reads; do not rewrite working code just because SQL exists
124
+ - Use record helpers such as `pbCreate()`, `pbUpdate()`, and `pbDelete()` for mutations
116
125
  - Token is not needed — the bridge handles auth via the parent session
117
126
  - `X-Lumera-Project` header is not needed — the parent adds it automatically
118
127