@cognite/dune 0.1.2 → 0.2.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.
Files changed (37) hide show
  1. package/_templates/app/new/config/biome.json.ejs.t +54 -0
  2. package/_templates/app/new/config/components.json.ejs.t +28 -0
  3. package/_templates/app/new/config/tailwind.config.js.ejs.t +15 -0
  4. package/_templates/app/new/{tsconfig.json.ejs.t → config/tsconfig.json.ejs.t} +4 -1
  5. package/_templates/app/new/config/vite.config.ts.ejs.t +27 -0
  6. package/_templates/app/new/cursor/data-modeling.mdc.ejs.t +1994 -0
  7. package/_templates/app/new/cursor/mcp.json.ejs.t +15 -0
  8. package/_templates/app/new/cursor/rules.mdc.ejs.t +12 -0
  9. package/_templates/app/new/root/PRD.md.ejs.t +5 -0
  10. package/_templates/app/new/{package.json.ejs.t → root/package.json.ejs.t} +11 -2
  11. package/_templates/app/new/{App.test.tsx.ejs.t → src/App.test.tsx.ejs.t} +5 -5
  12. package/_templates/app/new/{App.tsx.ejs.t → src/App.tsx.ejs.t} +2 -3
  13. package/_templates/app/new/src/lib/utils.ts.ejs.t +10 -0
  14. package/_templates/app/new/{main.tsx.ejs.t → src/main.tsx.ejs.t} +2 -0
  15. package/_templates/app/new/src/styles.css.ejs.t +25 -0
  16. package/bin/auth/authentication-flow.js +89 -0
  17. package/bin/auth/callback-server.js +181 -0
  18. package/bin/auth/certificate-manager.js +81 -0
  19. package/bin/auth/client-credentials.js +240 -0
  20. package/bin/auth/oauth-client.js +92 -0
  21. package/bin/cli.js +45 -5
  22. package/bin/deploy-command.js +246 -0
  23. package/bin/deploy-interactive-command.js +382 -0
  24. package/bin/utils/crypto.js +35 -0
  25. package/dist/deploy/index.d.ts +7 -0
  26. package/dist/deploy/index.js +43 -1
  27. package/package.json +3 -2
  28. package/src/deploy/application-deployer.ts +38 -0
  29. package/src/deploy/deploy.ts +8 -0
  30. package/_templates/app/new/biome.json.ejs.t +0 -25
  31. package/_templates/app/new/vite.config.ts.ejs.t +0 -15
  32. /package/_templates/app/new/{tsconfig.node.json.ejs.t → config/tsconfig.node.json.ejs.t} +0 -0
  33. /package/_templates/app/new/{vitest.config.ts.ejs.t → config/vitest.config.ts.ejs.t} +0 -0
  34. /package/_templates/app/new/{vitest.setup.ts.ejs.t → config/vitest.setup.ts.ejs.t} +0 -0
  35. /package/_templates/app/new/{app.json.ejs.t → root/app.json.ejs.t} +0 -0
  36. /package/_templates/app/new/{gitignore.ejs.t → root/gitignore.ejs.t} +0 -0
  37. /package/_templates/app/new/{index.html.ejs.t → root/index.html.ejs.t} +0 -0
@@ -0,0 +1,382 @@
1
+ /**
2
+ * Interactive Deploy Command
3
+ *
4
+ * Handles deployment with browser-based OAuth login instead of environment variables.
5
+ */
6
+
7
+ import { execSync } from "node:child_process";
8
+ import { existsSync, readFileSync, unlinkSync } from "node:fs";
9
+ import os from "node:os";
10
+ import path from "node:path";
11
+ import { resolve } from "node:path";
12
+ import { AuthenticationFlow } from "./auth/authentication-flow.js";
13
+
14
+ /**
15
+ * Generate Fusion app URL
16
+ */
17
+ function generateFusionUrl(deployment, appExternalId, versionTag) {
18
+ const { org, project, baseUrl } = deployment;
19
+ const cluster = baseUrl?.split("//")[1];
20
+
21
+ if (!org || !project || !cluster) {
22
+ return null;
23
+ }
24
+
25
+ return `https://${org}.fusion.cognite.com/${project}/streamlit-apps/dune/${appExternalId}-${versionTag}?cluster=${cluster}&workspace=industrial-tools`;
26
+ }
27
+
28
+ // Default OAuth configuration for CDF
29
+ const DEFAULT_CONFIG = {
30
+ authority: "https://auth.cognite.com",
31
+ clientId: "c6f97d29-79a5-48ac-85de-1de8229226cb", // CDF CLI public client ID
32
+ redirectUri: "https://localhost:3000",
33
+ port: 3000,
34
+ loginTimeout: 5 * 60 * 1000, // 5 minutes
35
+ certDir: path.join(os.homedir(), ".cdf-login"),
36
+ };
37
+
38
+ /**
39
+ * Load app.json from a directory
40
+ */
41
+ function loadAppConfig(appDir) {
42
+ const configPath = resolve(appDir, "app.json");
43
+ if (!existsSync(configPath)) {
44
+ return null;
45
+ }
46
+ try {
47
+ return JSON.parse(readFileSync(configPath, "utf-8"));
48
+ } catch (error) {
49
+ console.error(`Error parsing app.json: ${error.message}`);
50
+ return null;
51
+ }
52
+ }
53
+
54
+ /**
55
+ * Detect the package manager being used
56
+ */
57
+ function detectPackageManager(appDir) {
58
+ if (existsSync(resolve(appDir, "pnpm-lock.yaml"))) return "pnpm";
59
+ if (existsSync(resolve(appDir, "yarn.lock"))) return "yarn";
60
+ if (existsSync(resolve(appDir, "bun.lockb"))) return "bun";
61
+ return "npm";
62
+ }
63
+
64
+ /**
65
+ * Build the app
66
+ */
67
+ function buildApp(appDir, verbose = true) {
68
+ const pm = detectPackageManager(appDir);
69
+ console.log(`📦 Building app with ${pm}...`);
70
+
71
+ execSync(`${pm} run build`, {
72
+ cwd: appDir,
73
+ stdio: verbose ? "inherit" : "pipe",
74
+ });
75
+
76
+ console.log("✅ Build successful");
77
+ }
78
+
79
+ /**
80
+ * Print help message
81
+ */
82
+ function printHelp() {
83
+ console.log(`
84
+ Deploy your Dune app to Cognite Data Fusion (Interactive Login)
85
+
86
+ Usage:
87
+ npx @cognite/dune deploy:interactive [options]
88
+
89
+ Options:
90
+ --base-url <url> CDF base URL (e.g., https://api.cognitedata.com)
91
+ --project <project> CDF project name
92
+ --org <organization> Organization hint for login
93
+ --deployment, -d <target> Deployment target from app.json (index or name)
94
+ --skip-build Skip the build step
95
+ --published Deploy as published (default: draft)
96
+ --help, -h Show this help message
97
+
98
+ Description:
99
+ This command opens a browser window for you to log in to CDF.
100
+ No environment variables or secrets are required - authentication
101
+ is handled through your browser session.
102
+
103
+ If no options are provided, you'll be prompted to select a deployment
104
+ target from app.json or enter custom values.
105
+
106
+ Examples:
107
+ npx @cognite/dune deploy:interactive # Interactive prompts
108
+ npx @cognite/dune deploy:interactive -d 0 # Use first deployment
109
+ npx @cognite/dune deploy:interactive --base-url https://api.cognitedata.com --project my-project
110
+ `);
111
+ }
112
+
113
+ /**
114
+ * Interactive deploy command handler
115
+ */
116
+ export async function handleDeployInteractive(args) {
117
+ // Check for help first
118
+ if (args.includes("--help") || args.includes("-h")) {
119
+ printHelp();
120
+ process.exit(0);
121
+ }
122
+
123
+ const cwd = process.cwd();
124
+
125
+ // Load app.json
126
+ const appConfig = loadAppConfig(cwd);
127
+ if (!appConfig) {
128
+ console.error("❌ No app.json found in current directory");
129
+ console.error("Make sure you're running this command from your app's root directory.");
130
+ process.exit(1);
131
+ }
132
+
133
+ // Parse arguments
134
+ let baseUrl = null;
135
+ let project = null;
136
+ let organization = null;
137
+ let deploymentIndex = null;
138
+ let skipBuild = false;
139
+ let published = false;
140
+
141
+ for (let i = 0; i < args.length; i++) {
142
+ const arg = args[i];
143
+ if (arg === "--base-url") {
144
+ baseUrl = args[++i];
145
+ } else if (arg === "--project") {
146
+ project = args[++i];
147
+ } else if (arg === "--org") {
148
+ organization = args[++i];
149
+ } else if (arg === "--deployment" || arg === "-d") {
150
+ const value = args[++i];
151
+ if (value === undefined) {
152
+ console.error("❌ --deployment requires a value (index or project name)");
153
+ process.exit(1);
154
+ }
155
+ const idx = Number.parseInt(value, 10);
156
+ if (!Number.isNaN(idx)) {
157
+ deploymentIndex = idx;
158
+ } else if (appConfig.deployments) {
159
+ const found = appConfig.deployments.findIndex(
160
+ (d) => d.project === value || `${d.org}/${d.project}` === value
161
+ );
162
+ if (found === -1) {
163
+ console.error(`❌ No deployment found for project: ${value}`);
164
+ console.log("Available deployments:");
165
+ appConfig.deployments.forEach((d, i) => {
166
+ console.log(` ${i}: ${d.org}/${d.project}`);
167
+ });
168
+ process.exit(1);
169
+ }
170
+ deploymentIndex = found;
171
+ }
172
+ } else if (arg === "--skip-build") {
173
+ skipBuild = true;
174
+ } else if (arg === "--published") {
175
+ published = true;
176
+ }
177
+ }
178
+
179
+ // Determine deployment target
180
+ let deployment;
181
+ const enquirer = await import("enquirer");
182
+
183
+ if (baseUrl && project) {
184
+ // Use CLI-provided values
185
+ deployment = {
186
+ baseUrl,
187
+ project,
188
+ org: organization || "unknown",
189
+ published,
190
+ };
191
+ } else if (deploymentIndex !== null) {
192
+ // Use deployment from app.json by index
193
+ if (
194
+ !appConfig.deployments ||
195
+ deploymentIndex < 0 ||
196
+ deploymentIndex >= appConfig.deployments.length
197
+ ) {
198
+ console.error(`❌ Invalid deployment index: ${deploymentIndex}`);
199
+ if (appConfig.deployments) {
200
+ console.log(`Available deployments (0-${appConfig.deployments.length - 1}):`);
201
+ appConfig.deployments.forEach((d, i) => {
202
+ console.log(` ${i}: ${d.org}/${d.project}`);
203
+ });
204
+ }
205
+ process.exit(1);
206
+ }
207
+ deployment = appConfig.deployments[deploymentIndex];
208
+ } else if (appConfig.deployments && appConfig.deployments.length > 0) {
209
+ // Prompt user to select from existing deployments or enter custom
210
+ const choices = [
211
+ ...appConfig.deployments.map((d) => `${d.org}/${d.project}`),
212
+ "Enter custom target...",
213
+ ];
214
+
215
+ const { selected } = await enquirer.default.prompt({
216
+ type: "select",
217
+ name: "selected",
218
+ message: "Select deployment target",
219
+ choices,
220
+ });
221
+
222
+ if (selected === "Enter custom target...") {
223
+ const answers = await enquirer.default.prompt([
224
+ {
225
+ type: "input",
226
+ name: "baseUrl",
227
+ message: "CDF Base URL",
228
+ initial: "https://api.cognitedata.com",
229
+ },
230
+ {
231
+ type: "input",
232
+ name: "project",
233
+ message: "CDF Project",
234
+ },
235
+ {
236
+ type: "input",
237
+ name: "org",
238
+ message: "Organization (for login hint)",
239
+ initial: "",
240
+ },
241
+ ]);
242
+ deployment = {
243
+ baseUrl: answers.baseUrl,
244
+ project: answers.project,
245
+ org: answers.org || null,
246
+ published,
247
+ };
248
+ if (answers.org) {
249
+ organization = answers.org;
250
+ }
251
+ } else {
252
+ // Find the deployment by matching the selected name
253
+ deployment = appConfig.deployments.find((d) => `${d.org}/${d.project}` === selected);
254
+ }
255
+ } else {
256
+ // No deployments in app.json - prompt for values
257
+ console.log("No deployments configured in app.json. Enter target details:\n");
258
+
259
+ const answers = await enquirer.default.prompt([
260
+ {
261
+ type: "input",
262
+ name: "baseUrl",
263
+ message: "CDF Base URL",
264
+ initial: "https://api.cognitedata.com",
265
+ },
266
+ {
267
+ type: "input",
268
+ name: "project",
269
+ message: "CDF Project",
270
+ validate: (v) => (v ? true : "Project is required"),
271
+ },
272
+ {
273
+ type: "input",
274
+ name: "org",
275
+ message: "Organization (for login hint)",
276
+ initial: "",
277
+ },
278
+ ]);
279
+
280
+ deployment = {
281
+ baseUrl: answers.baseUrl,
282
+ project: answers.project,
283
+ org: answers.org || null,
284
+ published,
285
+ };
286
+ if (answers.org) {
287
+ organization = answers.org;
288
+ }
289
+ }
290
+
291
+ console.log("\n🚀 Dune Deploy (Interactive)");
292
+ console.log("=============================");
293
+ console.log(`App: ${appConfig.name} (${appConfig.externalId})`);
294
+ console.log(`Version: ${appConfig.versionTag}`);
295
+ console.log(`Target: ${deployment.project} @ ${deployment.baseUrl}`);
296
+ console.log();
297
+
298
+ // Build the app first
299
+ if (!skipBuild) {
300
+ try {
301
+ buildApp(cwd);
302
+ } catch (error) {
303
+ console.error("❌ Build failed:", error.message);
304
+ process.exit(1);
305
+ }
306
+ }
307
+
308
+ // Start interactive login flow
309
+ try {
310
+ const authFlow = new AuthenticationFlow(DEFAULT_CONFIG);
311
+
312
+ // Use org from CLI, then deployment, then null
313
+ const orgHint = organization || deployment.org || null;
314
+
315
+ console.log("\n🔐 Starting browser authentication...");
316
+ console.log("A browser window will open for you to log in.\n");
317
+
318
+ const tokens = await authFlow.login(orgHint);
319
+
320
+ if (!tokens || !tokens.access_token) {
321
+ throw new Error("No access token received from authentication");
322
+ }
323
+
324
+ console.log("\n✅ Authentication successful!");
325
+ console.log(`\n📤 Deploying to ${deployment.project}...`);
326
+
327
+ // Import CogniteClient and deployer classes
328
+ const { CogniteClient } = await import("@cognite/sdk");
329
+ const { CdfApplicationDeployer, ApplicationPackager } = await import("../dist/deploy/index.js");
330
+
331
+ // Create SDK with the obtained token
332
+ const sdk = new CogniteClient({
333
+ appId: appConfig.externalId,
334
+ project: deployment.project,
335
+ baseUrl: deployment.baseUrl,
336
+ getToken: async () => tokens.access_token,
337
+ });
338
+ await sdk.authenticate();
339
+
340
+ // Package the application
341
+ const distPath = `${cwd}/dist`;
342
+ const packager = new ApplicationPackager(distPath);
343
+ const zipFilename = await packager.createZip("app.zip", true);
344
+
345
+ // Deploy to CDF
346
+ const deployer = new CdfApplicationDeployer(sdk);
347
+ await deployer.deploy(
348
+ appConfig.externalId,
349
+ appConfig.name,
350
+ appConfig.description,
351
+ appConfig.versionTag,
352
+ zipFilename,
353
+ deployment.published
354
+ );
355
+
356
+ // Clean up zip file
357
+ try {
358
+ unlinkSync(zipFilename);
359
+ } catch {
360
+ // Ignore cleanup errors
361
+ }
362
+
363
+ console.log(`\n✅ Successfully deployed ${appConfig.name} to ${deployment.project}`);
364
+
365
+ if (deployment.published || published) {
366
+ console.log("🌐 App is published and available to all users");
367
+ } else {
368
+ console.log("🔒 App is deployed in draft mode");
369
+ }
370
+
371
+ // Generate and display the app URL
372
+ const appUrl = generateFusionUrl(deployment, appConfig.externalId, appConfig.versionTag);
373
+ if (appUrl) {
374
+ console.log(`\n🔗 Open your app:\n ${appUrl}`);
375
+ }
376
+
377
+ process.exit(0);
378
+ } catch (error) {
379
+ console.error("\n❌ Deployment failed:", error.message);
380
+ process.exit(1);
381
+ }
382
+ }
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Cryptographic Utilities for OAuth 2.0 PKCE
3
+ *
4
+ * Provides functions for generating secure random strings and PKCE code challenges.
5
+ */
6
+
7
+ import crypto from "node:crypto";
8
+
9
+ // biome-ignore lint/complexity/noStaticOnlyClass: Utility class pattern
10
+ export class CryptoUtils {
11
+ /**
12
+ * Generate a cryptographically secure random string
13
+ * @param {number} length - Desired length of the string
14
+ * @returns {string} Random string using URL-safe base64 characters
15
+ */
16
+ static generateRandomString(length) {
17
+ const bytes = crypto.randomBytes(length);
18
+ return bytes
19
+ .toString("base64")
20
+ .replace(/\+/g, "-")
21
+ .replace(/\//g, "_")
22
+ .replace(/=/g, "")
23
+ .slice(0, length);
24
+ }
25
+
26
+ /**
27
+ * Generate PKCE code challenge from verifier
28
+ * @param {string} verifier - The code verifier string
29
+ * @returns {string} Base64url-encoded SHA256 hash of the verifier
30
+ */
31
+ static generateCodeChallenge(verifier) {
32
+ const hash = crypto.createHash("sha256").update(verifier).digest();
33
+ return hash.toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
34
+ }
35
+ }
@@ -29,6 +29,13 @@ declare class CdfApplicationDeployer {
29
29
  * @param {CogniteClient} client - Cognite SDK client
30
30
  */
31
31
  constructor(client: CogniteClient);
32
+ private DATA_SET_EXTERNAL_ID;
33
+ /**
34
+ * Validate that the required data set exists and is accessible
35
+ * @returns {Promise<number>} Data set ID (numerical)
36
+ * @throws {Error} If data set doesn't exist or user doesn't have access
37
+ */
38
+ validateDataSet(): Promise<number | undefined>;
32
39
  /**
33
40
  * Upload application package to CDF Files API
34
41
  * @param {string} appExternalId - Application external ID
@@ -1,3 +1,6 @@
1
+ // src/deploy/deploy.ts
2
+ import fs3 from "fs";
3
+
1
4
  // src/deploy/application-deployer.ts
2
5
  import fs from "fs";
3
6
  var CdfApplicationDeployer = class {
@@ -5,8 +8,38 @@ var CdfApplicationDeployer = class {
5
8
  * @param {CogniteClient} client - Cognite SDK client
6
9
  */
7
10
  constructor(client) {
11
+ this.DATA_SET_EXTERNAL_ID = "published-custom-apps";
8
12
  this.client = client;
9
13
  }
14
+ /**
15
+ * Validate that the required data set exists and is accessible
16
+ * @returns {Promise<number>} Data set ID (numerical)
17
+ * @throws {Error} If data set doesn't exist or user doesn't have access
18
+ */
19
+ async validateDataSet() {
20
+ try {
21
+ const dataSets = await this.client.datasets.retrieve([
22
+ { externalId: this.DATA_SET_EXTERNAL_ID }
23
+ ]);
24
+ return dataSets[0].id;
25
+ } catch (error) {
26
+ try {
27
+ this.client.datasets.create([
28
+ {
29
+ externalId: this.DATA_SET_EXTERNAL_ID,
30
+ name: "Published Custom Apps",
31
+ description: "Published Custom Apps",
32
+ writeProtected: false
33
+ }
34
+ ]);
35
+ console.log(`\u2705 Data set '${this.DATA_SET_EXTERNAL_ID}' created`);
36
+ } catch (error2) {
37
+ throw new Error(
38
+ `Failed to create data set '${this.DATA_SET_EXTERNAL_ID}'. Please ask your IT admin to create it or grant access.`
39
+ );
40
+ }
41
+ }
42
+ }
10
43
  /**
11
44
  * Upload application package to CDF Files API
12
45
  * @param {string} appExternalId - Application external ID
@@ -17,6 +50,10 @@ var CdfApplicationDeployer = class {
17
50
  * @param {boolean} published - Whether the application should be published
18
51
  */
19
52
  async uploadToFilesApi(appExternalId, name, description, versionTag, zipFilename, published = false) {
53
+ console.log("\u{1F50D} Validating data set access...");
54
+ const dataSetId = await this.validateDataSet();
55
+ console.log(`\u2705 Data set '${this.DATA_SET_EXTERNAL_ID}' validated (ID: ${dataSetId})
56
+ `);
20
57
  console.log("\u{1F4C1} Creating file record...");
21
58
  const fileContent = fs.readFileSync(zipFilename);
22
59
  const metadata = {
@@ -31,7 +68,8 @@ var CdfApplicationDeployer = class {
31
68
  name: `${appExternalId}-${versionTag}.zip`,
32
69
  externalId: `${appExternalId}-${versionTag}`,
33
70
  directory: "/dune-apps",
34
- metadata
71
+ metadata,
72
+ dataSetId
35
73
  },
36
74
  fileContent,
37
75
  true,
@@ -209,6 +247,10 @@ var deploy = async (deployment, app, folder) => {
209
247
  zipFilename,
210
248
  deployment.published
211
249
  );
250
+ try {
251
+ fs3.unlinkSync(zipFilename);
252
+ } catch {
253
+ }
212
254
  };
213
255
  export {
214
256
  ApplicationPackager,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cognite/dune",
3
- "version": "0.1.2",
3
+ "version": "0.2.0",
4
4
  "description": "Build and deploy React apps to Cognite Data Fusion",
5
5
  "keywords": [
6
6
  "cognite",
@@ -59,7 +59,8 @@
59
59
  "archiver": "^7.0.1",
60
60
  "enquirer": "^2.4.1",
61
61
  "execa": "^5.1.1",
62
- "hygen": "^6.2.11"
62
+ "hygen": "^6.2.11",
63
+ "open": "^10.1.0"
63
64
  },
64
65
  "peerDependencies": {
65
66
  "@cognite/sdk": ">=9.0.0",
@@ -17,6 +17,38 @@ export class CdfApplicationDeployer {
17
17
  this.client = client;
18
18
  }
19
19
 
20
+ private DATA_SET_EXTERNAL_ID = "published-custom-apps";
21
+
22
+ /**
23
+ * Validate that the required data set exists and is accessible
24
+ * @returns {Promise<number>} Data set ID (numerical)
25
+ * @throws {Error} If data set doesn't exist or user doesn't have access
26
+ */
27
+ async validateDataSet() {
28
+ try {
29
+ const dataSets = await this.client.datasets.retrieve([
30
+ { externalId: this.DATA_SET_EXTERNAL_ID },
31
+ ]);
32
+ return dataSets[0].id;
33
+ } catch (error) {
34
+ try {
35
+ this.client.datasets.create([
36
+ {
37
+ externalId: this.DATA_SET_EXTERNAL_ID,
38
+ name: "Published Custom Apps",
39
+ description: "Published Custom Apps",
40
+ writeProtected: false,
41
+ },
42
+ ]);
43
+ console.log(`✅ Data set '${this.DATA_SET_EXTERNAL_ID}' created`);
44
+ } catch (error) {
45
+ throw new Error(
46
+ `Failed to create data set '${this.DATA_SET_EXTERNAL_ID}'. Please ask your IT admin to create it or grant access.`
47
+ );
48
+ }
49
+ }
50
+ }
51
+
20
52
  /**
21
53
  * Upload application package to CDF Files API
22
54
  * @param {string} appExternalId - Application external ID
@@ -34,6 +66,11 @@ export class CdfApplicationDeployer {
34
66
  zipFilename: string,
35
67
  published = false
36
68
  ): Promise<void> {
69
+ // Validate data set exists and get its ID
70
+ console.log("🔍 Validating data set access...");
71
+ const dataSetId = await this.validateDataSet();
72
+ console.log(`✅ Data set '${this.DATA_SET_EXTERNAL_ID}' validated (ID: ${dataSetId})\n`);
73
+
37
74
  console.log("📁 Creating file record...");
38
75
 
39
76
  const fileContent = fs.readFileSync(zipFilename);
@@ -51,6 +88,7 @@ export class CdfApplicationDeployer {
51
88
  externalId: `${appExternalId}-${versionTag}`,
52
89
  directory: "/dune-apps",
53
90
  metadata: metadata,
91
+ dataSetId: dataSetId,
54
92
  },
55
93
  fileContent,
56
94
  true, // overwrite
@@ -1,3 +1,4 @@
1
+ import fs from "node:fs";
1
2
  import { CdfApplicationDeployer } from "./application-deployer";
2
3
  import { ApplicationPackager } from "./application-packager";
3
4
  import { getSdk } from "./get-sdk";
@@ -22,4 +23,11 @@ export const deploy = async (deployment: Deployment, app: App, folder: string) =
22
23
  zipFilename,
23
24
  deployment.published
24
25
  );
26
+
27
+ // Step 4: Clean up zip file
28
+ try {
29
+ fs.unlinkSync(zipFilename);
30
+ } catch {
31
+ // Ignore cleanup errors
32
+ }
25
33
  };
@@ -1,25 +0,0 @@
1
- ---
2
- to: <%= name %>/biome.json
3
- ---
4
- {
5
- "$schema": "https://biomejs.dev/schemas/1.9.4/schema.json",
6
- "vcs": {
7
- "enabled": true,
8
- "clientKind": "git",
9
- "useIgnoreFile": true
10
- },
11
- "organizeImports": {
12
- "enabled": true
13
- },
14
- "linter": {
15
- "enabled": true,
16
- "rules": {
17
- "recommended": true
18
- }
19
- },
20
- "formatter": {
21
- "enabled": true,
22
- "indentStyle": "tab"
23
- }
24
- }
25
-
@@ -1,15 +0,0 @@
1
- ---
2
- to: <%= name %>/vite.config.ts
3
- ---
4
- import react from "@vitejs/plugin-react";
5
- import { defineConfig } from "vite";
6
- import mkcert from "vite-plugin-mkcert";
7
-
8
- export default defineConfig({
9
- plugins: [react(), mkcert()],
10
- server: {
11
- https: true,
12
- port: 3000,
13
- },
14
- });
15
-