@cognite/cli 0.6.0-alpha.6 → 0.6.0-alpha.8
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 +146 -0
- package/_templates/app/new/config/eslint.config.mjs.ejs.t +99 -0
- package/_templates/app/new/config/tsconfig.json.ejs.t +35 -0
- package/_templates/app/new/config/tsconfig.node.json.ejs.t +27 -0
- package/_templates/app/new/config/vite.config.ts.ejs.t +26 -0
- package/_templates/app/new/config/vitest.config.ts.ejs.t +14 -0
- package/_templates/app/new/config/vitest.setup.ts.ejs.t +4 -0
- package/_templates/app/new/cursor/data-modeling.mdc.ejs.t +1996 -0
- package/_templates/app/new/cursor/mcp.json.ejs.t +10 -0
- package/_templates/app/new/cursor/rules.mdc.ejs.t +10 -0
- package/_templates/app/new/github/ci.yml.ejs.t +36 -0
- package/_templates/app/new/prompt.js +49 -0
- package/_templates/app/new/root/.npmrc.ejs.t +4 -0
- package/_templates/app/new/root/AGENTS.md.ejs.t +215 -0
- package/_templates/app/new/root/SPEC.md.ejs.t +77 -0
- package/_templates/app/new/root/app.json.ejs.t +22 -0
- package/_templates/app/new/root/gitignore.ejs.t +21 -0
- package/_templates/app/new/root/index.html.ejs.t +36 -0
- package/_templates/app/new/root/package.json.ejs.t +67 -0
- package/_templates/app/new/src/App.test.tsx.ejs.t +45 -0
- package/_templates/app/new/src/App.tsx.ejs.t +265 -0
- package/_templates/app/new/src/lib/utils.ts.ejs.t +9 -0
- package/_templates/app/new/src/main.tsx.ejs.t +36 -0
- package/_templates/app/new/src/styles.css.ejs.t +12 -0
- package/_vendor/spec-kit/.version +4 -0
- package/_vendor/spec-kit/README.md +39 -0
- package/_vendor/spec-kit/commands/speckit.analyze.md +249 -0
- package/_vendor/spec-kit/commands/speckit.checklist.md +361 -0
- package/_vendor/spec-kit/commands/speckit.clarify.md +247 -0
- package/_vendor/spec-kit/commands/speckit.implement.md +198 -0
- package/_vendor/spec-kit/commands/speckit.plan.md +149 -0
- package/_vendor/spec-kit/commands/speckit.specify.md +327 -0
- package/_vendor/spec-kit/commands/speckit.tasks.md +200 -0
- package/_vendor/spec-kit/scripts/bash/check-prerequisites.sh +190 -0
- package/_vendor/spec-kit/scripts/bash/common.sh +645 -0
- package/_vendor/spec-kit/scripts/bash/setup-plan.sh +75 -0
- package/_vendor/spec-kit/templates/checklist-template.md +40 -0
- package/_vendor/spec-kit/templates/plan-template.md +104 -0
- package/_vendor/spec-kit/templates/spec-template.md +128 -0
- package/_vendor/spec-kit/templates/tasks-template.md +251 -0
- package/dist/chunk-GFMJ4MJZ.js +8 -0
- package/dist/cli/cli.js +293 -73443
- package/dist/skills-4R3OUI44.js +2 -0
- package/package.json +9 -3
- package/dist/chunk-SUXS6HCW.js +0 -3589
- package/dist/skills-HEBDDOC4.js +0 -12
package/README.md
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
# @cognite/cli
|
|
2
|
+
|
|
3
|
+
Build and deploy React apps to [Cognite Data Fusion](https://docs.cognite.com/).
|
|
4
|
+
|
|
5
|
+
## Quick start
|
|
6
|
+
|
|
7
|
+
Scaffold a new app — AI skills are pulled automatically:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npx @cognite/cli apps create
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
This prompts for your app name, org, project, and cluster, then generates a fully configured React + TypeScript project.
|
|
14
|
+
|
|
15
|
+
> Top-level commands (`dune create`, `dune deploy`, `dune deploy:interactive`, `dune skills`) still work as deprecated aliases that print a one-line warning. Migrate to `dune apps <verb>`.
|
|
16
|
+
|
|
17
|
+
## Authentication
|
|
18
|
+
|
|
19
|
+
New apps created with `npx @cognite/cli apps create` depend on [`@cognite/app-sdk`](https://www.npmjs.com/package/@cognite/app-sdk) — **not `@cognite/cli`** — for auth and host integration. `@cognite/cli` is the CLI used to scaffold, develop, and deploy the app; the generated app itself talks to the Fusion app host via `@cognite/app-sdk`'s Comlink handshake. The template wires this up for you.
|
|
20
|
+
|
|
21
|
+
### Legacy apps (`--classic`)
|
|
22
|
+
|
|
23
|
+
Apps created with `--classic` use the older Files API path and wrap their root in `DuneAuthProvider` from `@cognite/dune/auth`:
|
|
24
|
+
|
|
25
|
+
```tsx
|
|
26
|
+
import { DuneAuthProvider, useDune } from '@cognite/dune/auth';
|
|
27
|
+
|
|
28
|
+
function App() {
|
|
29
|
+
const { sdk, isLoading } = useDune();
|
|
30
|
+
if (isLoading) return <div>Loading...</div>;
|
|
31
|
+
return <MyApp sdk={sdk} />;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export default function Root() {
|
|
35
|
+
return (
|
|
36
|
+
<DuneAuthProvider>
|
|
37
|
+
<App />
|
|
38
|
+
</DuneAuthProvider>
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Deployment
|
|
44
|
+
|
|
45
|
+
Deploy interactively via browser OAuth:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
npx @cognite/cli apps deploy --interactive
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
For CI, set your client secret as an environment variable and run:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
pnpm deploy
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Deployment targets are configured in `app.json` at the project root.
|
|
58
|
+
|
|
59
|
+
## AI skills
|
|
60
|
+
|
|
61
|
+
Skills guide your AI agent (Claude Code, Cursor, etc.) through Dune-specific tasks like adding auth, building chat UIs, or reviewing code. They are pulled automatically on `npx @cognite/cli apps create` and can be synced later:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
npx @cognite/cli apps skills pull
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Browse available skills at [cognitedata/builder-skills](https://github.com/cognitedata/builder-skills).
|
|
68
|
+
|
|
69
|
+
## Requirements
|
|
70
|
+
|
|
71
|
+
- Node.js ≥ 20
|
|
72
|
+
- React ≥ 18 (optional peer dependency — only needed for auth components)
|
|
73
|
+
|
|
74
|
+
## Development
|
|
75
|
+
|
|
76
|
+
### Running tests
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
pnpm test # run once
|
|
80
|
+
pnpm test:watch # watch mode
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Testing the CLI against a mock server
|
|
84
|
+
|
|
85
|
+
A local mock of the App Hosting API lets you run the real CLI against a controlled server without hitting a real CDF cluster.
|
|
86
|
+
|
|
87
|
+
**Terminal 1 — start the mock server:**
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
pnpm mock:server
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
**Terminal 2 — run the deploy command against it:**
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
pnpm mock:deploy
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
`mock:deploy` builds and deploys `apps/mock-app` — a minimal workspace app that serves as the standard CLI test target. Under the hood it sets two env vars that work from any app directory too:
|
|
100
|
+
|
|
101
|
+
| Env var | Purpose |
|
|
102
|
+
|---|---|
|
|
103
|
+
| `DUNE_BASE_URL=http://localhost:9090` | Overrides `baseUrl` from `app.json` — all API calls go to the mock |
|
|
104
|
+
| `DUNE_DEPLOY_TOKEN=test-token` | Skips OAuth entirely — no real client secret needed |
|
|
105
|
+
|
|
106
|
+
To test against your own app instead of the fixture:
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
cd apps/my-app
|
|
110
|
+
DUNE_DEPLOY_TOKEN=test-token DUNE_BASE_URL=http://localhost:9090 pnpm exec dune apps deploy --skip-build
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
#### Simulating error scenarios
|
|
114
|
+
|
|
115
|
+
Pass `MOCK_SCENARIO` to the server to force a specific HTTP error:
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
MOCK_SCENARIO=403 pnpm mock:server
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
| `MOCK_SCENARIO` | Step that fails |
|
|
122
|
+
|---|---|
|
|
123
|
+
| `409` | `ensureApp` — app already exists (CLI should recover) |
|
|
124
|
+
| `403` | `ensureApp` — missing `AppHosting:WRITE` capability |
|
|
125
|
+
| `500` | `ensureApp` — internal server error |
|
|
126
|
+
| `upload-409` | `uploadVersion` — version already published, cannot overwrite (hard failure) |
|
|
127
|
+
| `upload-413` | `uploadVersion` — payload too large (50 MB limit) |
|
|
128
|
+
| `upload-403` | `uploadVersion` — missing `AppHosting:WRITE` capability |
|
|
129
|
+
| `upload-500` | `uploadVersion` — internal server error |
|
|
130
|
+
| `publish-403` | `publishAndActivate` — missing `AppHosting:WRITE` capability |
|
|
131
|
+
| `publish-500` | `publishAndActivate` — internal server error |
|
|
132
|
+
| `republish` | `ensureApp` recovers (409), then `uploadVersion` fails (409 — version already published) |
|
|
133
|
+
|
|
134
|
+
The mock server and MSW handlers live in `cli/testing/msw/`. The same handlers are used by the Vitest integration tests in `src/deploy/apphosting-deployer.msw.test.ts`.
|
|
135
|
+
|
|
136
|
+
## Maintenance
|
|
137
|
+
|
|
138
|
+
### Updating the spec-kit vendor snapshot
|
|
139
|
+
|
|
140
|
+
The AI skill commands under `_vendor/spec-kit/` are generated by [spec-kit](https://github.com/github/spec-kit) and checked in. To update to a new release, pass the target tag (requires [`uv`](https://docs.astral.sh/uv/), which provides `uvx`):
|
|
141
|
+
|
|
142
|
+
```bash
|
|
143
|
+
pnpm --filter @cognite/dune refresh-spec-kit v0.9.0
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
The refresh script stages the generated commands, templates, and shell scripts before replacing `_vendor/spec-kit/`. Then review the diff under `_vendor/spec-kit/` and commit it.
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
---
|
|
2
|
+
to: '<%= useCurrentDir ? "" : ((directoryName || name) + "/") %>eslint.config.mjs'
|
|
3
|
+
---
|
|
4
|
+
import { auraEslintPlugin } from '@cognite/aura/eslint';
|
|
5
|
+
import js from '@eslint/js';
|
|
6
|
+
import importPlugin from 'eslint-plugin-import';
|
|
7
|
+
import noOnlyTestsPlugin from 'eslint-plugin-no-only-tests';
|
|
8
|
+
import reactHooks from 'eslint-plugin-react-hooks';
|
|
9
|
+
import reactRefresh from 'eslint-plugin-react-refresh';
|
|
10
|
+
import globals from 'globals';
|
|
11
|
+
import tseslint from 'typescript-eslint';
|
|
12
|
+
|
|
13
|
+
const sharedRules = {
|
|
14
|
+
'import/first': 'error',
|
|
15
|
+
'import/no-duplicates': 'error',
|
|
16
|
+
'import/order': [
|
|
17
|
+
'error',
|
|
18
|
+
{
|
|
19
|
+
groups: ['builtin', 'external', 'internal', 'parent', ['sibling', 'index']],
|
|
20
|
+
'newlines-between': 'always',
|
|
21
|
+
alphabetize: {
|
|
22
|
+
order: 'asc',
|
|
23
|
+
caseInsensitive: true,
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
],
|
|
27
|
+
'no-only-tests/no-only-tests': 'error',
|
|
28
|
+
quotes: ['error', 'single', { avoidEscape: true }],
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const noUnusedVarsOptions = {
|
|
32
|
+
argsIgnorePattern: '^_',
|
|
33
|
+
caughtErrorsIgnorePattern: '^_',
|
|
34
|
+
varsIgnorePattern: '^_',
|
|
35
|
+
ignoreRestSiblings: true,
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export default tseslint.config(
|
|
39
|
+
{
|
|
40
|
+
ignores: ['dist', 'build', '.next', 'coverage', '*.min.js', '.agents', '.cursor', '.claude'],
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
files: ['**/*.{js,mjs,cjs,ts,tsx}'],
|
|
44
|
+
plugins: {
|
|
45
|
+
import: importPlugin,
|
|
46
|
+
'no-only-tests': noOnlyTestsPlugin,
|
|
47
|
+
},
|
|
48
|
+
rules: sharedRules,
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
files: ['**/*.{js,mjs,cjs}'],
|
|
52
|
+
extends: [js.configs.recommended],
|
|
53
|
+
languageOptions: {
|
|
54
|
+
ecmaVersion: 'latest',
|
|
55
|
+
sourceType: 'module',
|
|
56
|
+
globals: {
|
|
57
|
+
...globals.browser,
|
|
58
|
+
...globals.node,
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
rules: {
|
|
62
|
+
'no-unused-vars': ['error', noUnusedVarsOptions],
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
files: ['**/*.cjs'],
|
|
67
|
+
languageOptions: {
|
|
68
|
+
sourceType: 'commonjs',
|
|
69
|
+
globals: {
|
|
70
|
+
...globals.node,
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
files: ['**/*.{ts,tsx}'],
|
|
76
|
+
extends: [js.configs.recommended, ...tseslint.configs.recommended],
|
|
77
|
+
languageOptions: {
|
|
78
|
+
ecmaVersion: 'latest',
|
|
79
|
+
globals: {
|
|
80
|
+
...globals.browser,
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
plugins: {
|
|
84
|
+
aura: auraEslintPlugin,
|
|
85
|
+
'react-hooks': reactHooks,
|
|
86
|
+
'react-refresh': reactRefresh,
|
|
87
|
+
},
|
|
88
|
+
rules: {
|
|
89
|
+
...reactHooks.configs.recommended.rules,
|
|
90
|
+
'@typescript-eslint/consistent-type-imports': 'error',
|
|
91
|
+
'@typescript-eslint/no-explicit-any': 'error',
|
|
92
|
+
'@typescript-eslint/no-non-null-assertion': 'off',
|
|
93
|
+
'@typescript-eslint/no-unused-vars': ['error', noUnusedVarsOptions],
|
|
94
|
+
'aura/no-overriding-styles': 'warn',
|
|
95
|
+
'no-unused-vars': 'off',
|
|
96
|
+
'react-refresh/only-export-components': ['error', { allowConstantExport: true }],
|
|
97
|
+
},
|
|
98
|
+
}
|
|
99
|
+
);
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
---
|
|
2
|
+
to: '<%= useCurrentDir ? "" : ((directoryName || name) + "/") %>tsconfig.json'
|
|
3
|
+
---
|
|
4
|
+
{
|
|
5
|
+
"compilerOptions": {
|
|
6
|
+
"target": "ES2020",
|
|
7
|
+
"useDefineForClassFields": true,
|
|
8
|
+
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
|
9
|
+
"module": "ESNext",
|
|
10
|
+
"skipLibCheck": true,
|
|
11
|
+
|
|
12
|
+
/* Bundler mode */
|
|
13
|
+
"moduleResolution": "bundler",
|
|
14
|
+
"allowImportingTsExtensions": true,
|
|
15
|
+
"isolatedModules": true,
|
|
16
|
+
"moduleDetection": "force",
|
|
17
|
+
"noEmit": true,
|
|
18
|
+
"jsx": "react-jsx",
|
|
19
|
+
|
|
20
|
+
/* Linting */
|
|
21
|
+
"strict": true,
|
|
22
|
+
"noUnusedLocals": true,
|
|
23
|
+
"noUnusedParameters": true,
|
|
24
|
+
"noFallthroughCasesInSwitch": true,
|
|
25
|
+
|
|
26
|
+
/* Testing */
|
|
27
|
+
"types": ["vitest/globals", "@testing-library/jest-dom"],
|
|
28
|
+
"baseUrl": ".",
|
|
29
|
+
"paths": {
|
|
30
|
+
"@/*": ["./src/*"]
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
"include": ["src"]
|
|
34
|
+
}
|
|
35
|
+
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
---
|
|
2
|
+
to: '<%= useCurrentDir ? "" : ((directoryName || name) + "/") %>tsconfig.node.json'
|
|
3
|
+
---
|
|
4
|
+
{
|
|
5
|
+
"compilerOptions": {
|
|
6
|
+
"composite": true,
|
|
7
|
+
"target": "ES2022",
|
|
8
|
+
"lib": ["ES2023"],
|
|
9
|
+
"module": "ESNext",
|
|
10
|
+
"skipLibCheck": true,
|
|
11
|
+
|
|
12
|
+
/* Bundler mode */
|
|
13
|
+
"moduleResolution": "bundler",
|
|
14
|
+
"allowImportingTsExtensions": true,
|
|
15
|
+
"isolatedModules": true,
|
|
16
|
+
"moduleDetection": "force",
|
|
17
|
+
"emitDeclarationOnly": true,
|
|
18
|
+
|
|
19
|
+
/* Linting */
|
|
20
|
+
"strict": true,
|
|
21
|
+
"noUnusedLocals": true,
|
|
22
|
+
"noUnusedParameters": true,
|
|
23
|
+
"noFallthroughCasesInSwitch": true
|
|
24
|
+
},
|
|
25
|
+
"include": ["vite.config.ts", "vitest.config.ts"]
|
|
26
|
+
}
|
|
27
|
+
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
---
|
|
2
|
+
to: '<%= useCurrentDir ? "" : ((directoryName || name) + "/") %>vite.config.ts'
|
|
3
|
+
---
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
|
|
6
|
+
import { fusionOpenPlugin } from '@cognite/dune/vite';
|
|
7
|
+
import tailwindcss from '@tailwindcss/vite';
|
|
8
|
+
import react from '@vitejs/plugin-react';
|
|
9
|
+
import { defineConfig } from 'vite';
|
|
10
|
+
import mkcert from 'vite-plugin-mkcert';
|
|
11
|
+
|
|
12
|
+
export default defineConfig({
|
|
13
|
+
base: './',
|
|
14
|
+
plugins: [react(), mkcert(), fusionOpenPlugin(), tailwindcss()],
|
|
15
|
+
resolve: {
|
|
16
|
+
alias: {
|
|
17
|
+
'@': path.resolve(__dirname, './src'),
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
server: {
|
|
21
|
+
port: 3001,
|
|
22
|
+
},
|
|
23
|
+
worker: {
|
|
24
|
+
format: 'es',
|
|
25
|
+
},
|
|
26
|
+
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
---
|
|
2
|
+
to: '<%= useCurrentDir ? "" : ((directoryName || name) + "/") %>vitest.config.ts'
|
|
3
|
+
---
|
|
4
|
+
import react from '@vitejs/plugin-react';
|
|
5
|
+
import { defineConfig } from 'vitest/config';
|
|
6
|
+
|
|
7
|
+
export default defineConfig({
|
|
8
|
+
plugins: [react()],
|
|
9
|
+
test: {
|
|
10
|
+
globals: true,
|
|
11
|
+
environment: 'happy-dom',
|
|
12
|
+
setupFiles: ['vitest.setup.ts'],
|
|
13
|
+
},
|
|
14
|
+
});
|