@lumerahq/cli 0.34.5 → 0.35.2

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.
@@ -148,8 +148,26 @@ var ApiClient = class {
148
148
  }
149
149
  async listCollections() {
150
150
  const result = await this.request("/api/pb/collections");
151
+ return result.items.filter((collection) => collection.type !== "view");
152
+ }
153
+ async listViews() {
154
+ const result = await this.request("/api/pb/views");
151
155
  return result.items;
152
156
  }
157
+ async publishView(project, view, expectedHash) {
158
+ const task = await this.request(`/api/projects/${encodeURIComponent(project)}/views`, { method: "POST", body: JSON.stringify({ config: view.config, query: view.query, expected_definition_hash: expectedHash }) });
159
+ const deadline = Date.now() + 18e4;
160
+ while (Date.now() < deadline) {
161
+ const status = await this.request(task.status_url);
162
+ if (status.terminal) {
163
+ if (status.state !== "completed") throw new Error(`View publishing failed: ${JSON.stringify(status.failure)}. Task: ${task.task_id}`);
164
+ if (status.result?.value?.status === "superseded") throw new Error("View source changed before publishing. Refresh and retry.");
165
+ return;
166
+ }
167
+ await new Promise((resolve2) => setTimeout(resolve2, 1e3));
168
+ }
169
+ throw new Error(`View publishing continues in the background. Task: ${task.task_id}`);
170
+ }
153
171
  async getCollection(id) {
154
172
  return this.request(`/api/pb/collections/${id}`);
155
173
  }
@@ -8,7 +8,7 @@ import {
8
8
  } from "./chunk-2EHJH2QU.js";
9
9
  import {
10
10
  userContextHeaders
11
- } from "./chunk-W57NUJFJ.js";
11
+ } from "./chunk-2A2DSLIE.js";
12
12
  import {
13
13
  fetchWithRetry
14
14
  } from "./chunk-FJFIWC7G.js";
@@ -4,7 +4,7 @@ import {
4
4
  import {
5
5
  createApiClient,
6
6
  isApiErrorStatus
7
- } from "./chunk-W57NUJFJ.js";
7
+ } from "./chunk-2A2DSLIE.js";
8
8
  import {
9
9
  findProjectRoot,
10
10
  getAppName
@@ -16,6 +16,7 @@ import { existsSync, readFileSync, writeFileSync, mkdirSync, readdirSync } from
16
16
  import { join } from "path";
17
17
  var SHARED_COLLECTIONS_DIR = "platform/collections/shared";
18
18
  var SHARED_FUNCTIONS_DIR = "platform/functions/shared";
19
+ var SHARED_VIEWS_DIR = "platform/views/shared";
19
20
  function sharedCollectionsDir(projectRoot) {
20
21
  return join(projectRoot, SHARED_COLLECTIONS_DIR);
21
22
  }
@@ -96,7 +97,7 @@ function declarationForFunctionImport(item, existing) {
96
97
  }
97
98
  async function listIncomingCollectionShares(api, projectExternalId) {
98
99
  const result = await api.listProjectResourceShares(projectExternalId, "incoming");
99
- return (result.shares ?? []).filter((share) => share.object_type === "collection").sort((a, b) => {
100
+ return (result.shares ?? []).filter((share) => share.object_type === "collection" || share.object_type === "view").sort((a, b) => {
100
101
  const bySource = a.source_project.external_id.localeCompare(b.source_project.external_id);
101
102
  if (bySource !== 0) return bySource;
102
103
  return shareCollectionName(a).localeCompare(shareCollectionName(b));
@@ -137,10 +138,12 @@ async function syncResourceShareDeps(projectRoot, api, projectExternalId, opts)
137
138
  }
138
139
  const dir = sharedCollectionsDir(projectRoot);
139
140
  const functionsDir = sharedFunctionsDir(projectRoot);
141
+ const viewsDir = join(projectRoot, SHARED_VIEWS_DIR);
140
142
  const missing = [];
141
143
  if (opts.write) {
142
144
  mkdirSync(dir, { recursive: true });
143
145
  mkdirSync(functionsDir, { recursive: true });
146
+ mkdirSync(viewsDir, { recursive: true });
144
147
  }
145
148
  for (const item of functionImports) {
146
149
  const fileName = functionImportFileName(item);
@@ -159,19 +162,20 @@ async function syncResourceShareDeps(projectRoot, api, projectExternalId, opts)
159
162
  }
160
163
  }
161
164
  for (const share of shares) {
165
+ const isView = share.object_type === "view";
162
166
  const fileName = shareFileName(share);
163
- const filePath = join(dir, fileName);
167
+ const filePath = join(isView ? viewsDir : dir, fileName);
164
168
  const exists = existsSync(filePath);
165
169
  if (!opts.write) {
166
- if (!exists) missing.push(fileName);
170
+ if (!exists) missing.push(`${isView ? "views" : "collections"}/shared/${fileName}`);
167
171
  continue;
168
172
  }
169
173
  const existing = exists ? readSharedCollectionFile(filePath) ?? void 0 : void 0;
170
- const declaration = declarationForShare(share, existing);
174
+ const declaration = isView ? { source_project: share.source_project.external_id, view: shareCollectionName(share), privilege: "view.read", reason: existing?.reason ?? "" } : declarationForShare(share, existing);
171
175
  writeFileSync(filePath, JSON.stringify(declaration, null, 2) + "\n");
172
176
  if (!opts.quiet) {
173
177
  const action = exists ? pc.yellow("\u21BB") : pc.green("+");
174
- console.log(` ${action} collections/shared/${fileName}`);
178
+ console.log(` ${action} ${isView ? "views" : "collections"}/shared/${fileName}`);
175
179
  }
176
180
  }
177
181
  if (!opts.write && missing.length > 0) {
@@ -209,7 +213,7 @@ async function deps(args) {
209
213
  if (sub === "sync") {
210
214
  console.log();
211
215
  console.log(pc.cyan(pc.bold(" Deps Sync")));
212
- console.log(pc.dim(" Syncing incoming resource shares into platform/collections/shared..."));
216
+ console.log(pc.dim(" Syncing incoming resource shares into platform/*/shared..."));
213
217
  console.log();
214
218
  const ok = await syncDeps(projectRoot, { write: true });
215
219
  if (!ok) {
@@ -225,7 +229,9 @@ async function deps(args) {
225
229
  const sharedDeps = loadSharedCollectionDeps(projectRoot);
226
230
  const functionDir = sharedFunctionsDir(projectRoot);
227
231
  const functionFiles = existsSync(functionDir) ? readdirSync(functionDir).filter((entry) => entry.endsWith(".json")).sort() : [];
228
- if (sharedDeps.length === 0 && functionFiles.length === 0) {
232
+ const viewsDir = join(projectRoot, SHARED_VIEWS_DIR);
233
+ const viewFiles = existsSync(viewsDir) ? readdirSync(viewsDir).filter((entry) => entry.endsWith(".json")).sort() : [];
234
+ if (sharedDeps.length === 0 && functionFiles.length === 0 && viewFiles.length === 0) {
229
235
  console.log(pc.dim(" No shared resource declarations in platform/*/shared"));
230
236
  return;
231
237
  }
@@ -246,13 +252,19 @@ async function deps(args) {
246
252
  ` ${dep?.source_project ?? "unknown-source"}/${dep?.function ?? "unknown-function"} ${pc.dim(`(${dep?.alias ?? "unknown-alias"})`)}`
247
253
  );
248
254
  }
255
+ for (const file of viewFiles) {
256
+ const dep = JSON.parse(readFileSync(join(viewsDir, file), "utf8"));
257
+ console.log(` ${pc.bold(file)}`);
258
+ console.log(` ${dep.source_project}/${dep.view} ${pc.dim("(view.read)")}`);
259
+ }
249
260
  console.log();
250
261
  return;
251
262
  }
252
263
  if (sub === "init") {
253
264
  mkdirSync(sharedCollectionsDir(projectRoot), { recursive: true });
254
265
  mkdirSync(sharedFunctionsDir(projectRoot), { recursive: true });
255
- console.log(pc.green(" \u2713"), "Created platform/collections/shared/ and platform/functions/shared/");
266
+ mkdirSync(join(projectRoot, SHARED_VIEWS_DIR), { recursive: true });
267
+ console.log(pc.green(" \u2713"), "Created shared collection, view, and function dependency folders");
256
268
  return;
257
269
  }
258
270
  console.log(`
@@ -263,7 +275,7 @@ async function deps(args) {
263
275
  list Show declared dependencies
264
276
  init Create dependency storage
265
277
 
266
- ${pc.bold("Dependencies:")} platform/collections/shared/*.json and platform/functions/shared/*.json
278
+ ${pc.bold("Dependencies:")} platform/{collections,views,functions}/shared/*.json
267
279
  `);
268
280
  }
269
281
 
@@ -2,9 +2,9 @@ import {
2
2
  deps,
3
3
  syncDeps,
4
4
  syncResourceShareDeps
5
- } from "./chunk-5JNNUIVJ.js";
5
+ } from "./chunk-A27HZEU6.js";
6
6
  import "./chunk-2CR762KB.js";
7
- import "./chunk-W57NUJFJ.js";
7
+ import "./chunk-2A2DSLIE.js";
8
8
  import "./chunk-JLVVHTBY.js";
9
9
  import "./chunk-FJFIWC7G.js";
10
10
  import "./chunk-PNKVD2UK.js";
@@ -1,19 +1,19 @@
1
1
  import {
2
2
  dev
3
- } from "./chunk-P6GDSHYC.js";
3
+ } from "./chunk-5TQ3BQ2X.js";
4
4
  import "./chunk-UGAIWMQV.js";
5
5
  import "./chunk-2EHJH2QU.js";
6
6
  import "./chunk-XZ5VCTGY.js";
7
7
  import "./chunk-5FGDEZSJ.js";
8
8
  import {
9
9
  syncDeps
10
- } from "./chunk-5JNNUIVJ.js";
10
+ } from "./chunk-A27HZEU6.js";
11
11
  import {
12
12
  loadEnv
13
13
  } from "./chunk-2CR762KB.js";
14
14
  import {
15
15
  createApiClient
16
- } from "./chunk-W57NUJFJ.js";
16
+ } from "./chunk-2A2DSLIE.js";
17
17
  import {
18
18
  findProjectRoot,
19
19
  getApiUrl,
package/dist/index.js CHANGED
@@ -197,7 +197,8 @@ ${pc.dim("Resource Types:")}
197
197
  app-api FastAPI application backend
198
198
 
199
199
  ${pc.dim("Examples:")}
200
- lumera apply # Apply all resources
200
+ lumera apply # Apply resources and app (excludes views)
201
+ lumera apply views # Publish views (human source admin)
201
202
  lumera apply collections/users # Apply single collection
202
203
  lumera apply app # Deploy frontend and App API
203
204
  lumera apply app-api # Deploy only the App API
@@ -242,32 +243,32 @@ async function main() {
242
243
  switch (command) {
243
244
  // Resource commands
244
245
  case "plan":
245
- await import("./resources-55CTS5MT.js").then((m) => m.plan(args.slice(1)));
246
+ await import("./resources-E32DYKLL.js").then((m) => m.plan(args.slice(1)));
246
247
  break;
247
248
  case "apply":
248
- await import("./resources-55CTS5MT.js").then((m) => m.apply(args.slice(1)));
249
+ await import("./resources-E32DYKLL.js").then((m) => m.apply(args.slice(1)));
249
250
  break;
250
251
  case "pull":
251
- await import("./resources-55CTS5MT.js").then((m) => m.pull(args.slice(1)));
252
+ await import("./resources-E32DYKLL.js").then((m) => m.pull(args.slice(1)));
252
253
  break;
253
254
  case "destroy":
254
- await import("./resources-55CTS5MT.js").then((m) => m.destroy(args.slice(1)));
255
+ await import("./resources-E32DYKLL.js").then((m) => m.destroy(args.slice(1)));
255
256
  break;
256
257
  case "list":
257
- await import("./resources-55CTS5MT.js").then((m) => m.list(args.slice(1)));
258
+ await import("./resources-E32DYKLL.js").then((m) => m.list(args.slice(1)));
258
259
  break;
259
260
  case "show":
260
- await import("./resources-55CTS5MT.js").then((m) => m.show(args.slice(1)));
261
+ await import("./resources-E32DYKLL.js").then((m) => m.show(args.slice(1)));
261
262
  break;
262
263
  case "diff":
263
- await import("./resources-55CTS5MT.js").then((m) => m.diff(args.slice(1)));
264
+ await import("./resources-E32DYKLL.js").then((m) => m.diff(args.slice(1)));
264
265
  break;
265
266
  // Development
266
267
  case "dev":
267
- await import("./dev-24PCZUAT.js").then((m) => m.dev(args.slice(1)));
268
+ await import("./dev-E2O6R7WW.js").then((m) => m.dev(args.slice(1)));
268
269
  break;
269
270
  case "run":
270
- await import("./run-4XFA5ZDJ.js").then((m) => m.run(args.slice(1)));
271
+ await import("./run-BJ7PXSEH.js").then((m) => m.run(args.slice(1)));
271
272
  break;
272
273
  case "functions":
273
274
  await import("./functions-5OOHGQT7.js").then(
@@ -281,10 +282,10 @@ async function main() {
281
282
  break;
282
283
  // Project
283
284
  case "init":
284
- await import("./init-S42P4A5J.js").then((m) => m.init(args.slice(1)));
285
+ await import("./init-MJEVA5HK.js").then((m) => m.init(args.slice(1)));
285
286
  break;
286
287
  case "register":
287
- await import("./register-GMWA4D4C.js").then((m) => m.register(args.slice(1)));
288
+ await import("./register-RUDM4ITV.js").then((m) => m.register(args.slice(1)));
288
289
  break;
289
290
  case "templates":
290
291
  await import("./templates-LNUOTNLN.js").then((m) => m.templates(subcommand, args.slice(2)));
@@ -301,7 +302,7 @@ async function main() {
301
302
  break;
302
303
  // Dependencies
303
304
  case "deps":
304
- await import("./deps-TNGT6JVD.js").then((m) => m.deps(args.slice(1)));
305
+ await import("./deps-DLJUDFNK.js").then((m) => m.deps(args.slice(1)));
305
306
  break;
306
307
  // Feature flags (read the in-sandbox snapshot)
307
308
  case "flags":
@@ -12,7 +12,7 @@ import {
12
12
  import {
13
13
  createApiClient,
14
14
  validateProjectNameLength
15
- } from "./chunk-W57NUJFJ.js";
15
+ } from "./chunk-2A2DSLIE.js";
16
16
  import {
17
17
  getToken,
18
18
  init_auth,
@@ -7,7 +7,7 @@ import {
7
7
  import {
8
8
  createApiClient,
9
9
  validateProjectExternalId
10
- } from "./chunk-W57NUJFJ.js";
10
+ } from "./chunk-2A2DSLIE.js";
11
11
  import {
12
12
  findProjectRoot,
13
13
  getAppName,