@databricks/appkit 0.5.1 → 0.5.3
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/CLAUDE.md +1 -0
- package/README.md +2 -4
- package/dist/_virtual/{rolldown_runtime.js → _rolldown/runtime.js} +3 -3
- package/dist/appkit/package.js +1 -1
- package/dist/cli/commands/docs.js +1 -1
- package/dist/cli/commands/docs.js.map +1 -1
- package/dist/cli/commands/generate-types.js +5 -0
- package/dist/cli/commands/generate-types.js.map +1 -1
- package/dist/cli/commands/lint.js.map +1 -1
- package/dist/cli/commands/setup.js.map +1 -1
- package/dist/cli/index.js +3 -3
- package/dist/cli/index.js.map +1 -1
- package/dist/connectors/lakebase/client.js +1 -1
- package/dist/context/execution-context.js +1 -1
- package/dist/context/execution-context.js.map +1 -1
- package/dist/context/index.js +2 -2
- package/dist/context/index.js.map +1 -1
- package/dist/context/service-context.js +12 -9
- package/dist/context/service-context.js.map +1 -1
- package/dist/context/user-context.js +1 -1
- package/dist/core/appkit.d.ts +2 -0
- package/dist/core/appkit.d.ts.map +1 -1
- package/dist/core/appkit.js +1 -1
- package/dist/core/appkit.js.map +1 -1
- package/dist/errors/authentication.js +1 -1
- package/dist/errors/base.js +1 -1
- package/dist/errors/configuration.js +1 -1
- package/dist/errors/connection.js +1 -1
- package/dist/errors/execution.js +1 -1
- package/dist/errors/index.js +1 -1
- package/dist/errors/initialization.js +1 -1
- package/dist/errors/server.js +1 -1
- package/dist/errors/tunnel.js +1 -1
- package/dist/errors/validation.js +1 -1
- package/dist/index.d.ts +5 -5
- package/dist/index.js +6 -6
- package/dist/index.js.map +1 -1
- package/dist/plugin/dev-reader.js +1 -1
- package/dist/plugin/dev-reader.js.map +1 -1
- package/dist/plugin/plugin.d.ts +2 -2
- package/dist/plugin/plugin.js +1 -1
- package/dist/{analytics → plugins/analytics}/analytics.d.ts +4 -4
- package/dist/plugins/analytics/analytics.d.ts.map +1 -0
- package/dist/{analytics → plugins/analytics}/analytics.js +9 -9
- package/dist/plugins/analytics/analytics.js.map +1 -0
- package/dist/{analytics → plugins/analytics}/defaults.js +1 -1
- package/dist/plugins/analytics/defaults.js.map +1 -0
- package/dist/{analytics → plugins/analytics}/query.js +6 -6
- package/dist/plugins/analytics/query.js.map +1 -0
- package/dist/plugins/analytics/types.d.ts +9 -0
- package/dist/plugins/analytics/types.d.ts.map +1 -0
- package/dist/plugins/index.js +5 -0
- package/dist/{server → plugins/server}/base-server.js +1 -1
- package/dist/plugins/server/base-server.js.map +1 -0
- package/dist/{server → plugins/server}/index.d.ts +3 -3
- package/dist/plugins/server/index.d.ts.map +1 -0
- package/dist/{server → plugins/server}/index.js +10 -10
- package/dist/plugins/server/index.js.map +1 -0
- package/dist/{server → plugins/server}/remote-tunnel/gate.js +1 -1
- package/dist/plugins/server/remote-tunnel/gate.js.map +1 -0
- package/dist/{server → plugins/server}/remote-tunnel/remote-tunnel-controller.js +2 -2
- package/dist/plugins/server/remote-tunnel/remote-tunnel-controller.js.map +1 -0
- package/dist/{server → plugins/server}/remote-tunnel/remote-tunnel-manager.js +6 -6
- package/dist/plugins/server/remote-tunnel/remote-tunnel-manager.js.map +1 -0
- package/dist/{server → plugins/server}/static-server.js +1 -1
- package/dist/plugins/server/static-server.js.map +1 -0
- package/dist/{server → plugins/server}/types.d.ts +3 -3
- package/dist/plugins/server/types.d.ts.map +1 -0
- package/dist/{server → plugins/server}/utils.js +5 -5
- package/dist/plugins/server/utils.js.map +1 -0
- package/dist/{server → plugins/server}/vite-dev-server.js +6 -6
- package/dist/plugins/server/vite-dev-server.js.map +1 -0
- package/dist/telemetry/telemetry-provider.js.map +1 -1
- package/docs/docs/api/appkit/Class.AppKitError/index.html +4 -4
- package/docs/docs/api/appkit/Class.AuthenticationError/index.html +4 -4
- package/docs/docs/api/appkit/Class.ConfigurationError/index.html +4 -4
- package/docs/docs/api/appkit/Class.ConnectionError/index.html +4 -4
- package/docs/docs/api/appkit/Class.ExecutionError/index.html +4 -4
- package/docs/docs/api/appkit/Class.InitializationError/index.html +4 -4
- package/docs/docs/api/appkit/Class.Plugin/index.html +4 -4
- package/docs/docs/api/appkit/Class.ServerError/index.html +4 -4
- package/docs/docs/api/appkit/Class.TunnelError/index.html +4 -4
- package/docs/docs/api/appkit/Class.ValidationError/index.html +4 -4
- package/docs/docs/api/appkit/Function.appKitTypesPlugin/index.html +4 -4
- package/docs/docs/api/appkit/Function.createApp/index.html +6 -6
- package/docs/docs/api/appkit/Function.createApp.md +8 -6
- package/docs/docs/api/appkit/Function.getExecutionContext/index.html +4 -4
- package/docs/docs/api/appkit/Function.isSQLTypeMarker/index.html +4 -4
- package/docs/docs/api/appkit/Interface.BasePluginConfig/index.html +4 -4
- package/docs/docs/api/appkit/Interface.CacheConfig/index.html +4 -4
- package/docs/docs/api/appkit/Interface.ITelemetry/index.html +4 -4
- package/docs/docs/api/appkit/Interface.StreamExecutionSettings/index.html +4 -4
- package/docs/docs/api/appkit/Interface.TelemetryConfig/index.html +4 -4
- package/docs/docs/api/appkit/TypeAlias.IAppRouter/index.html +4 -4
- package/docs/docs/api/appkit/Variable.sql/index.html +4 -4
- package/docs/docs/api/appkit/index.html +4 -4
- package/docs/docs/api/appkit-ui/data/AreaChart/index.html +4 -4
- package/docs/docs/api/appkit-ui/data/BarChart/index.html +4 -4
- package/docs/docs/api/appkit-ui/data/DataTable/index.html +4 -4
- package/docs/docs/api/appkit-ui/data/DonutChart/index.html +4 -4
- package/docs/docs/api/appkit-ui/data/HeatmapChart/index.html +4 -4
- package/docs/docs/api/appkit-ui/data/LineChart/index.html +4 -4
- package/docs/docs/api/appkit-ui/data/PieChart/index.html +4 -4
- package/docs/docs/api/appkit-ui/data/RadarChart/index.html +4 -4
- package/docs/docs/api/appkit-ui/data/ScatterChart/index.html +5 -5
- package/docs/docs/api/appkit-ui/index.html +4 -4
- package/docs/docs/api/appkit-ui/styling/index.html +5 -5
- package/docs/docs/api/appkit-ui/ui/Accordion/index.html +4 -4
- package/docs/docs/api/appkit-ui/ui/Alert/index.html +4 -4
- package/docs/docs/api/appkit-ui/ui/AlertDialog/index.html +4 -4
- package/docs/docs/api/appkit-ui/ui/AspectRatio/index.html +4 -4
- package/docs/docs/api/appkit-ui/ui/Avatar/index.html +4 -4
- package/docs/docs/api/appkit-ui/ui/Badge/index.html +4 -4
- package/docs/docs/api/appkit-ui/ui/Breadcrumb/index.html +4 -4
- package/docs/docs/api/appkit-ui/ui/Button/index.html +4 -4
- package/docs/docs/api/appkit-ui/ui/ButtonGroup/index.html +4 -4
- package/docs/docs/api/appkit-ui/ui/Calendar/index.html +4 -4
- package/docs/docs/api/appkit-ui/ui/Card/index.html +4 -4
- package/docs/docs/api/appkit-ui/ui/Carousel/index.html +4 -4
- package/docs/docs/api/appkit-ui/ui/ChartContainer/index.html +4 -4
- package/docs/docs/api/appkit-ui/ui/Checkbox/index.html +4 -4
- package/docs/docs/api/appkit-ui/ui/Collapsible/index.html +4 -4
- package/docs/docs/api/appkit-ui/ui/Command/index.html +4 -4
- package/docs/docs/api/appkit-ui/ui/ContextMenu/index.html +4 -4
- package/docs/docs/api/appkit-ui/ui/Dialog/index.html +4 -4
- package/docs/docs/api/appkit-ui/ui/Drawer/index.html +4 -4
- package/docs/docs/api/appkit-ui/ui/DropdownMenu/index.html +4 -4
- package/docs/docs/api/appkit-ui/ui/Empty/index.html +4 -4
- package/docs/docs/api/appkit-ui/ui/Field/index.html +4 -4
- package/docs/docs/api/appkit-ui/ui/FormControl/index.html +4 -4
- package/docs/docs/api/appkit-ui/ui/HoverCard/index.html +4 -4
- package/docs/docs/api/appkit-ui/ui/Input/index.html +4 -4
- package/docs/docs/api/appkit-ui/ui/InputGroup/index.html +4 -4
- package/docs/docs/api/appkit-ui/ui/InputOTP/index.html +4 -4
- package/docs/docs/api/appkit-ui/ui/Item/index.html +4 -4
- package/docs/docs/api/appkit-ui/ui/Kbd/index.html +4 -4
- package/docs/docs/api/appkit-ui/ui/Label/index.html +4 -4
- package/docs/docs/api/appkit-ui/ui/Menubar/index.html +4 -4
- package/docs/docs/api/appkit-ui/ui/NavigationMenu/index.html +4 -4
- package/docs/docs/api/appkit-ui/ui/Pagination/index.html +4 -4
- package/docs/docs/api/appkit-ui/ui/Popover/index.html +4 -4
- package/docs/docs/api/appkit-ui/ui/Progress/index.html +4 -4
- package/docs/docs/api/appkit-ui/ui/RadioGroup/index.html +4 -4
- package/docs/docs/api/appkit-ui/ui/ResizableHandle/index.html +4 -4
- package/docs/docs/api/appkit-ui/ui/ScrollArea/index.html +4 -4
- package/docs/docs/api/appkit-ui/ui/Select/index.html +4 -4
- package/docs/docs/api/appkit-ui/ui/Separator/index.html +4 -4
- package/docs/docs/api/appkit-ui/ui/Sheet/index.html +4 -4
- package/docs/docs/api/appkit-ui/ui/Sidebar/index.html +4 -4
- package/docs/docs/api/appkit-ui/ui/Skeleton/index.html +4 -4
- package/docs/docs/api/appkit-ui/ui/Slider/index.html +4 -4
- package/docs/docs/api/appkit-ui/ui/Spinner/index.html +4 -4
- package/docs/docs/api/appkit-ui/ui/Switch/index.html +4 -4
- package/docs/docs/api/appkit-ui/ui/Table/index.html +4 -4
- package/docs/docs/api/appkit-ui/ui/Tabs/index.html +4 -4
- package/docs/docs/api/appkit-ui/ui/Textarea/index.html +4 -4
- package/docs/docs/api/appkit-ui/ui/Toaster/index.html +4 -4
- package/docs/docs/api/appkit-ui/ui/Toggle/index.html +4 -4
- package/docs/docs/api/appkit-ui/ui/ToggleGroup/index.html +4 -4
- package/docs/docs/api/appkit-ui/ui/Tooltip/index.html +4 -4
- package/docs/docs/api/index.html +4 -4
- package/docs/docs/app-management/index.html +6 -6
- package/docs/docs/app-management.md +2 -2
- package/docs/docs/architecture/index.html +4 -4
- package/docs/docs/category/development/index.html +4 -4
- package/docs/docs/configuration/index.html +4 -4
- package/docs/docs/core-principles/index.html +4 -4
- package/docs/docs/development/ai-assisted-development/index.html +61 -0
- package/docs/docs/development/ai-assisted-development.md +75 -0
- package/docs/docs/development/index.html +8 -7
- package/docs/docs/development/llm-guide/index.html +15 -5
- package/docs/docs/development/llm-guide.md +18 -0
- package/docs/docs/development/local-development/index.html +8 -8
- package/docs/docs/development/local-development.md +3 -3
- package/docs/docs/development/project-setup/index.html +4 -4
- package/docs/docs/development/remote-bridge/index.html +6 -6
- package/docs/docs/development/remote-bridge.md +2 -2
- package/docs/docs/development/type-generation/index.html +4 -4
- package/docs/docs/development.md +4 -3
- package/docs/docs/index.html +22 -7
- package/docs/docs/plugins/index.html +4 -4
- package/docs/docs.md +33 -2
- package/llms.txt +1 -0
- package/package.json +1 -1
- package/dist/analytics/analytics.d.ts.map +0 -1
- package/dist/analytics/analytics.js.map +0 -1
- package/dist/analytics/defaults.js.map +0 -1
- package/dist/analytics/query.js.map +0 -1
- package/dist/analytics/types.d.ts +0 -9
- package/dist/analytics/types.d.ts.map +0 -1
- package/dist/server/base-server.js.map +0 -1
- package/dist/server/index.d.ts.map +0 -1
- package/dist/server/index.js.map +0 -1
- package/dist/server/remote-tunnel/gate.js.map +0 -1
- package/dist/server/remote-tunnel/remote-tunnel-controller.js.map +0 -1
- package/dist/server/remote-tunnel/remote-tunnel-manager.js.map +0 -1
- package/dist/server/static-server.js.map +0 -1
- package/dist/server/types.d.ts.map +0 -1
- package/dist/server/utils.js.map +0 -1
- package/dist/server/vite-dev-server.js.map +0 -1
- /package/dist/{analytics → plugins/analytics}/index.js +0 -0
- /package/dist/{server → plugins/server}/remote-tunnel/denied.html +0 -0
- /package/dist/{server → plugins/server}/remote-tunnel/index.html +0 -0
- /package/dist/{server → plugins/server}/remote-tunnel/wait.html +0 -0
package/CLAUDE.md
CHANGED
|
@@ -117,6 +117,7 @@ The CLI will display the documentation content directly in the terminal.
|
|
|
117
117
|
- [Configuration](./docs/docs/configuration.md): This guide covers environment variables and configuration options for AppKit applications.
|
|
118
118
|
- [Core principles](./docs/docs/core-principles.md): Learn about the fundamental concepts and principles behind AppKit.
|
|
119
119
|
- [Development](./docs/docs/development.md): AppKit provides multiple development workflows to suit different needs: local development with hot reload, AI-assisted development with MCP, and remote tunneling to deployed backends.
|
|
120
|
+
- [AI-Assisted development](./docs/docs/development/ai-assisted-development.md): AppKit integrates with AI coding assistants through the Model Context Protocol (MCP).
|
|
120
121
|
- [LLM Guide](./docs/docs/development/llm-guide.md): This document provides prescriptive guidance for AI coding assistants generating code with Databricks AppKit. It is intentionally opinionated to ensure consistent, production-ready code generation.
|
|
121
122
|
- [Local development](./docs/docs/development/local-development.md): Once your app is bootstrapped according to the Manual quick start guide, you can start the development server with hot reload for both UI and backend code.
|
|
122
123
|
- [Project setup](./docs/docs/development/project-setup.md): This guide covers the recommended project structure and scaffolding for AppKit applications.
|
package/README.md
CHANGED
|
@@ -28,14 +28,12 @@ AppKit simplifies building data applications on Databricks by providing:
|
|
|
28
28
|
|
|
29
29
|
Follow the [Getting Started](https://databricks.github.io/appkit/docs/) guide to get started with AppKit.
|
|
30
30
|
|
|
31
|
+
🤖 For AI/code assistants, see the [AI-assisted development](https://databricks.github.io/appkit/docs/development/ai-assisted-development) guide.
|
|
32
|
+
|
|
31
33
|
## Documentation
|
|
32
34
|
|
|
33
35
|
📖 For full AppKit documentation, visit the [AppKit Documentation](https://databricks.github.io/appkit/) website.
|
|
34
36
|
|
|
35
|
-
👉 For AI/code assistants:
|
|
36
|
-
- Use [llms-compact.txt](./llms-compact.txt) for quick usage patterns.
|
|
37
|
-
- See [llms.txt](./llms.txt) for full guidance and anti-patterns.
|
|
38
|
-
|
|
39
37
|
## Contributing
|
|
40
38
|
|
|
41
39
|
See [CONTRIBUTING.md](CONTRIBUTING.md) for development setup and contribution guidelines.
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import "node:module";
|
|
2
2
|
|
|
3
|
-
//#region
|
|
3
|
+
//#region \0rolldown/runtime.js
|
|
4
4
|
var __defProp = Object.defineProperty;
|
|
5
5
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
6
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
8
|
var __esmMin = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
9
|
-
var __exportAll = (all,
|
|
9
|
+
var __exportAll = (all, no_symbols) => {
|
|
10
10
|
let target = {};
|
|
11
11
|
for (var name in all) {
|
|
12
12
|
__defProp(target, name, {
|
|
@@ -14,7 +14,7 @@ var __exportAll = (all, symbols) => {
|
|
|
14
14
|
enumerable: true
|
|
15
15
|
});
|
|
16
16
|
}
|
|
17
|
-
if (
|
|
17
|
+
if (!no_symbols) {
|
|
18
18
|
__defProp(target, Symbol.toStringTag, { value: "Module" });
|
|
19
19
|
}
|
|
20
20
|
return target;
|
package/dist/appkit/package.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"docs.js","names":[],"sources":["../../../src/cli/commands/docs.ts"],"sourcesContent":["import
|
|
1
|
+
{"version":3,"file":"docs.js","names":[],"sources":["../../../src/cli/commands/docs.ts"],"sourcesContent":["import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { Command } from \"commander\";\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\nfunction findPackageRoot(): string {\n let dir = __dirname;\n while (dir !== path.parse(dir).root) {\n if (fs.existsSync(path.join(dir, \"package.json\"))) {\n return dir;\n }\n dir = path.dirname(dir);\n }\n throw new Error(\"Could not find package root\");\n}\n\nfunction runDocs(docPath?: string) {\n const packageRoot = findPackageRoot();\n\n if (!docPath) {\n // Display llms.txt by default\n const llmsPath = path.join(packageRoot, \"llms.txt\");\n\n if (!fs.existsSync(llmsPath)) {\n console.error(\"Error: llms.txt not found in package\");\n process.exit(1);\n }\n\n const content = fs.readFileSync(llmsPath, \"utf-8\");\n console.log(content);\n return;\n }\n\n // Handle path - remove leading ./ and / first, then strip prefixes\n let normalizedPath = docPath;\n\n // Strip leading ./ or /\n normalizedPath = normalizedPath.replace(/^\\.\\//, \"\");\n normalizedPath = normalizedPath.replace(/^\\//, \"\");\n\n // Remove /appkit/docs/ or docs/ prefix since files are in packageRoot/docs/\n normalizedPath = normalizedPath.replace(/^appkit\\/docs\\//, \"\");\n normalizedPath = normalizedPath.replace(/^docs\\//, \"\");\n\n const fullPath = path.join(packageRoot, \"docs\", normalizedPath);\n\n if (!fs.existsSync(fullPath)) {\n console.error(`Error: Documentation file not found: ${docPath}`);\n console.error(`Tried: ${fullPath}`);\n process.exit(1);\n }\n\n const content = fs.readFileSync(fullPath, \"utf-8\");\n console.log(content);\n}\n\nexport const docsCommand = new Command(\"docs\")\n .description(\"Display embedded documentation\")\n .argument(\n \"[path]\",\n \"Path to specific documentation file (e.g., /appkit/docs/api/appkit-ui/components/Sidebar.md)\",\n )\n .action(runDocs);\n"],"mappings":";;;;;;AAKA,MAAM,aAAa,cAAc,OAAO,KAAK,IAAI;AACjD,MAAM,YAAY,KAAK,QAAQ,WAAW;AAE1C,SAAS,kBAA0B;CACjC,IAAI,MAAM;AACV,QAAO,QAAQ,KAAK,MAAM,IAAI,CAAC,MAAM;AACnC,MAAI,GAAG,WAAW,KAAK,KAAK,KAAK,eAAe,CAAC,CAC/C,QAAO;AAET,QAAM,KAAK,QAAQ,IAAI;;AAEzB,OAAM,IAAI,MAAM,8BAA8B;;AAGhD,SAAS,QAAQ,SAAkB;CACjC,MAAM,cAAc,iBAAiB;AAErC,KAAI,CAAC,SAAS;EAEZ,MAAM,WAAW,KAAK,KAAK,aAAa,WAAW;AAEnD,MAAI,CAAC,GAAG,WAAW,SAAS,EAAE;AAC5B,WAAQ,MAAM,uCAAuC;AACrD,WAAQ,KAAK,EAAE;;EAGjB,MAAM,UAAU,GAAG,aAAa,UAAU,QAAQ;AAClD,UAAQ,IAAI,QAAQ;AACpB;;CAIF,IAAI,iBAAiB;AAGrB,kBAAiB,eAAe,QAAQ,SAAS,GAAG;AACpD,kBAAiB,eAAe,QAAQ,OAAO,GAAG;AAGlD,kBAAiB,eAAe,QAAQ,mBAAmB,GAAG;AAC9D,kBAAiB,eAAe,QAAQ,WAAW,GAAG;CAEtD,MAAM,WAAW,KAAK,KAAK,aAAa,QAAQ,eAAe;AAE/D,KAAI,CAAC,GAAG,WAAW,SAAS,EAAE;AAC5B,UAAQ,MAAM,wCAAwC,UAAU;AAChE,UAAQ,MAAM,UAAU,WAAW;AACnC,UAAQ,KAAK,EAAE;;CAGjB,MAAM,UAAU,GAAG,aAAa,UAAU,QAAQ;AAClD,SAAQ,IAAI,QAAQ;;AAGtB,MAAa,cAAc,IAAI,QAAQ,OAAO,CAC3C,YAAY,iCAAiC,CAC7C,SACC,UACA,+FACD,CACA,OAAO,QAAQ"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
1
2
|
import path from "node:path";
|
|
2
3
|
import { Command } from "commander";
|
|
3
4
|
|
|
@@ -11,6 +12,10 @@ async function runGenerateTypes(rootDir, outFile, warehouseId, options) {
|
|
|
11
12
|
const resolvedRootDir = rootDir || process.cwd();
|
|
12
13
|
const resolvedOutFile = outFile || path.join(process.cwd(), "client/src/appKitTypes.d.ts");
|
|
13
14
|
const queryFolder = path.join(resolvedRootDir, "config/queries");
|
|
15
|
+
if (!fs.existsSync(queryFolder)) {
|
|
16
|
+
console.warn(`Warning: No queries found at ${queryFolder}. Skipping type generation.`);
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
14
19
|
const resolvedWarehouseId = warehouseId || process.env.DATABRICKS_WAREHOUSE_ID;
|
|
15
20
|
if (!resolvedWarehouseId) {
|
|
16
21
|
console.error("Error: DATABRICKS_WAREHOUSE_ID is not set. Please provide it as an argument or environment variable.");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generate-types.js","names":[],"sources":["../../../src/cli/commands/generate-types.ts"],"sourcesContent":["import
|
|
1
|
+
{"version":3,"file":"generate-types.js","names":[],"sources":["../../../src/cli/commands/generate-types.ts"],"sourcesContent":["import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { Command } from \"commander\";\n\n/**\n * Generate types command implementation\n */\nasync function runGenerateTypes(\n rootDir?: string,\n outFile?: string,\n warehouseId?: string,\n options?: { noCache?: boolean },\n) {\n try {\n // Try to import the type generator from @databricks/appkit\n const { generateFromEntryPoint } = await import(\n \"@databricks/appkit/type-generator\"\n );\n\n const resolvedRootDir = rootDir || process.cwd();\n const resolvedOutFile =\n outFile || path.join(process.cwd(), \"client/src/appKitTypes.d.ts\");\n\n const queryFolder = path.join(resolvedRootDir, \"config/queries\");\n if (!fs.existsSync(queryFolder)) {\n console.warn(\n `Warning: No queries found at ${queryFolder}. Skipping type generation.`,\n );\n return;\n }\n\n const resolvedWarehouseId =\n warehouseId || process.env.DATABRICKS_WAREHOUSE_ID;\n if (!resolvedWarehouseId) {\n console.error(\n \"Error: DATABRICKS_WAREHOUSE_ID is not set. Please provide it as an argument or environment variable.\",\n );\n process.exit(1);\n }\n\n await generateFromEntryPoint({\n queryFolder,\n outFile: resolvedOutFile,\n warehouseId: resolvedWarehouseId,\n noCache: options?.noCache || false,\n });\n } catch (error) {\n if (\n error instanceof Error &&\n error.message.includes(\"Cannot find module\")\n ) {\n console.error(\n \"Error: The 'generate-types' command is only available in @databricks/appkit.\",\n );\n console.error(\"Please install @databricks/appkit to use this command.\");\n process.exit(1);\n }\n throw error;\n }\n}\n\nexport const generateTypesCommand = new Command(\"generate-types\")\n .description(\"Generate TypeScript types from SQL queries\")\n .argument(\"[rootDir]\", \"Root directory of the project\", process.cwd())\n .argument(\n \"[outFile]\",\n \"Output file path\",\n path.join(process.cwd(), \"client/src/appKitTypes.d.ts\"),\n )\n .argument(\"[warehouseId]\", \"Databricks warehouse ID\")\n .option(\"--no-cache\", \"Disable caching for type generation\")\n .action(runGenerateTypes);\n"],"mappings":";;;;;;;;AAOA,eAAe,iBACb,SACA,SACA,aACA,SACA;AACA,KAAI;EAEF,MAAM,EAAE,2BAA2B,MAAM,OACvC;EAGF,MAAM,kBAAkB,WAAW,QAAQ,KAAK;EAChD,MAAM,kBACJ,WAAW,KAAK,KAAK,QAAQ,KAAK,EAAE,8BAA8B;EAEpE,MAAM,cAAc,KAAK,KAAK,iBAAiB,iBAAiB;AAChE,MAAI,CAAC,GAAG,WAAW,YAAY,EAAE;AAC/B,WAAQ,KACN,gCAAgC,YAAY,6BAC7C;AACD;;EAGF,MAAM,sBACJ,eAAe,QAAQ,IAAI;AAC7B,MAAI,CAAC,qBAAqB;AACxB,WAAQ,MACN,uGACD;AACD,WAAQ,KAAK,EAAE;;AAGjB,QAAM,uBAAuB;GAC3B;GACA,SAAS;GACT,aAAa;GACb,SAAS,SAAS,WAAW;GAC9B,CAAC;UACK,OAAO;AACd,MACE,iBAAiB,SACjB,MAAM,QAAQ,SAAS,qBAAqB,EAC5C;AACA,WAAQ,MACN,+EACD;AACD,WAAQ,MAAM,yDAAyD;AACvE,WAAQ,KAAK,EAAE;;AAEjB,QAAM;;;AAIV,MAAa,uBAAuB,IAAI,QAAQ,iBAAiB,CAC9D,YAAY,6CAA6C,CACzD,SAAS,aAAa,iCAAiC,QAAQ,KAAK,CAAC,CACrE,SACC,aACA,oBACA,KAAK,KAAK,QAAQ,KAAK,EAAE,8BAA8B,CACxD,CACA,SAAS,iBAAiB,0BAA0B,CACpD,OAAO,cAAc,sCAAsC,CAC3D,OAAO,iBAAiB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lint.js","names":[],"sources":["../../../src/cli/commands/lint.ts"],"sourcesContent":["import
|
|
1
|
+
{"version":3,"file":"lint.js","names":[],"sources":["../../../src/cli/commands/lint.ts"],"sourcesContent":["import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { Lang, parse } from \"@ast-grep/napi\";\nimport { Command } from \"commander\";\n\ninterface Rule {\n id: string;\n pattern: string;\n message: string;\n includeTests?: boolean;\n filter?: (code: string) => boolean;\n}\n\nconst rules: Rule[] = [\n {\n id: \"no-double-type-assertion\",\n pattern: \"$X as unknown as $Y\",\n message:\n \"Avoid double type assertion (as unknown as). Use proper type guards or fix the source type.\",\n },\n {\n id: \"no-as-any\",\n pattern: \"$X as any\",\n message:\n 'Avoid \"as any\" type assertion. Use proper typing or unknown with type guards.',\n includeTests: false, // acceptable in test mocks\n },\n {\n id: \"no-array-index-key\",\n pattern: \"key={$IDX}\",\n message:\n \"Avoid using array index as React key. Use a stable unique identifier.\",\n filter: (code) => /key=\\{(idx|index|i)\\}/.test(code),\n },\n {\n id: \"no-parse-float-without-validation\",\n pattern: \"parseFloat($X).toFixed($Y)\",\n message:\n \"parseFloat can return NaN. Validate input or use toNumber() helper from shared/types.ts.\",\n },\n];\n\nfunction isTestFile(filePath: string): boolean {\n return (\n /\\.(test|spec)\\.(ts|tsx)$/.test(filePath) || filePath.includes(\"/tests/\")\n );\n}\n\nfunction findTsFiles(dir: string, files: string[] = []): string[] {\n const entries = fs.readdirSync(dir, { withFileTypes: true });\n\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name);\n\n if (entry.isDirectory()) {\n if ([\"node_modules\", \"dist\", \"build\", \".git\"].includes(entry.name))\n continue;\n findTsFiles(fullPath, files);\n } else if (entry.isFile() && /\\.(ts|tsx)$/.test(entry.name)) {\n files.push(fullPath);\n }\n }\n\n return files;\n}\n\ninterface Violation {\n file: string;\n line: number;\n column: number;\n rule: string;\n message: string;\n code: string;\n}\n\nfunction lintFile(filePath: string, rules: Rule[]): Violation[] {\n const violations: Violation[] = [];\n const content = fs.readFileSync(filePath, \"utf-8\");\n const lang = filePath.endsWith(\".tsx\") ? Lang.Tsx : Lang.TypeScript;\n const testFile = isTestFile(filePath);\n\n const ast = parse(lang, content);\n const root = ast.root();\n\n for (const rule of rules) {\n // skip rules that don't apply to test files\n if (testFile && rule.includeTests === false) continue;\n\n const matches = root.findAll(rule.pattern);\n\n for (const match of matches) {\n const code = match.text();\n\n if (rule.filter && !rule.filter(code)) continue;\n\n const range = match.range();\n violations.push({\n file: filePath,\n line: range.start.line + 1,\n column: range.start.column + 1,\n rule: rule.id,\n message: rule.message,\n code: code.length > 80 ? `${code.slice(0, 77)}...` : code,\n });\n }\n }\n\n return violations;\n}\n\n/**\n * Lint command implementation\n */\nfunction runLint() {\n const rootDir = process.cwd();\n const files = findTsFiles(rootDir);\n\n console.log(`Scanning ${files.length} TypeScript files...\\n`);\n\n const allViolations: Violation[] = [];\n\n for (const file of files) {\n const violations = lintFile(file, rules);\n allViolations.push(...violations);\n }\n\n if (allViolations.length === 0) {\n console.log(\"No ast-grep lint violations found.\");\n process.exit(0);\n }\n\n console.log(`Found ${allViolations.length} violation(s):\\n`);\n\n for (const v of allViolations) {\n const relPath = path.relative(rootDir, v.file);\n console.log(`${relPath}:${v.line}:${v.column}`);\n console.log(` ${v.rule}: ${v.message}`);\n console.log(` > ${v.code}\\n`);\n }\n\n process.exit(1);\n}\n\nexport const lintCommand = new Command(\"lint\")\n .description(\"Run AST-based linting on TypeScript files\")\n .action(runLint);\n"],"mappings":";;;;;;AAaA,MAAM,QAAgB;CACpB;EACE,IAAI;EACJ,SAAS;EACT,SACE;EACH;CACD;EACE,IAAI;EACJ,SAAS;EACT,SACE;EACF,cAAc;EACf;CACD;EACE,IAAI;EACJ,SAAS;EACT,SACE;EACF,SAAS,SAAS,wBAAwB,KAAK,KAAK;EACrD;CACD;EACE,IAAI;EACJ,SAAS;EACT,SACE;EACH;CACF;AAED,SAAS,WAAW,UAA2B;AAC7C,QACE,2BAA2B,KAAK,SAAS,IAAI,SAAS,SAAS,UAAU;;AAI7E,SAAS,YAAY,KAAa,QAAkB,EAAE,EAAY;CAChE,MAAM,UAAU,GAAG,YAAY,KAAK,EAAE,eAAe,MAAM,CAAC;AAE5D,MAAK,MAAM,SAAS,SAAS;EAC3B,MAAM,WAAW,KAAK,KAAK,KAAK,MAAM,KAAK;AAE3C,MAAI,MAAM,aAAa,EAAE;AACvB,OAAI;IAAC;IAAgB;IAAQ;IAAS;IAAO,CAAC,SAAS,MAAM,KAAK,CAChE;AACF,eAAY,UAAU,MAAM;aACnB,MAAM,QAAQ,IAAI,cAAc,KAAK,MAAM,KAAK,CACzD,OAAM,KAAK,SAAS;;AAIxB,QAAO;;AAYT,SAAS,SAAS,UAAkB,OAA4B;CAC9D,MAAM,aAA0B,EAAE;CAClC,MAAM,UAAU,GAAG,aAAa,UAAU,QAAQ;CAClD,MAAM,OAAO,SAAS,SAAS,OAAO,GAAG,KAAK,MAAM,KAAK;CACzD,MAAM,WAAW,WAAW,SAAS;CAGrC,MAAM,OADM,MAAM,MAAM,QAAQ,CACf,MAAM;AAEvB,MAAK,MAAM,QAAQ,OAAO;AAExB,MAAI,YAAY,KAAK,iBAAiB,MAAO;EAE7C,MAAM,UAAU,KAAK,QAAQ,KAAK,QAAQ;AAE1C,OAAK,MAAM,SAAS,SAAS;GAC3B,MAAM,OAAO,MAAM,MAAM;AAEzB,OAAI,KAAK,UAAU,CAAC,KAAK,OAAO,KAAK,CAAE;GAEvC,MAAM,QAAQ,MAAM,OAAO;AAC3B,cAAW,KAAK;IACd,MAAM;IACN,MAAM,MAAM,MAAM,OAAO;IACzB,QAAQ,MAAM,MAAM,SAAS;IAC7B,MAAM,KAAK;IACX,SAAS,KAAK;IACd,MAAM,KAAK,SAAS,KAAK,GAAG,KAAK,MAAM,GAAG,GAAG,CAAC,OAAO;IACtD,CAAC;;;AAIN,QAAO;;;;;AAMT,SAAS,UAAU;CACjB,MAAM,UAAU,QAAQ,KAAK;CAC7B,MAAM,QAAQ,YAAY,QAAQ;AAElC,SAAQ,IAAI,YAAY,MAAM,OAAO,wBAAwB;CAE7D,MAAM,gBAA6B,EAAE;AAErC,MAAK,MAAM,QAAQ,OAAO;EACxB,MAAM,aAAa,SAAS,MAAM,MAAM;AACxC,gBAAc,KAAK,GAAG,WAAW;;AAGnC,KAAI,cAAc,WAAW,GAAG;AAC9B,UAAQ,IAAI,qCAAqC;AACjD,UAAQ,KAAK,EAAE;;AAGjB,SAAQ,IAAI,SAAS,cAAc,OAAO,kBAAkB;AAE5D,MAAK,MAAM,KAAK,eAAe;EAC7B,MAAM,UAAU,KAAK,SAAS,SAAS,EAAE,KAAK;AAC9C,UAAQ,IAAI,GAAG,QAAQ,GAAG,EAAE,KAAK,GAAG,EAAE,SAAS;AAC/C,UAAQ,IAAI,KAAK,EAAE,KAAK,IAAI,EAAE,UAAU;AACxC,UAAQ,IAAI,OAAO,EAAE,KAAK,IAAI;;AAGhC,SAAQ,KAAK,EAAE;;AAGjB,MAAa,cAAc,IAAI,QAAQ,OAAO,CAC3C,YAAY,4CAA4C,CACxD,OAAO,QAAQ"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"setup.js","names":[],"sources":["../../../src/cli/commands/setup.ts"],"sourcesContent":["import
|
|
1
|
+
{"version":3,"file":"setup.js","names":[],"sources":["../../../src/cli/commands/setup.ts"],"sourcesContent":["import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { Command } from \"commander\";\n\nconst PACKAGES = [\n { name: \"@databricks/appkit\", description: \"Backend SDK\" },\n {\n name: \"@databricks/appkit-ui\",\n description: \"UI Integration, Charts, Tables, SSE, and more.\",\n },\n];\n\nconst SECTION_START = \"<!-- appkit-instructions-start -->\";\nconst SECTION_END = \"<!-- appkit-instructions-end -->\";\n\n/**\n * Find which AppKit packages are installed by checking for package.json\n */\nfunction findInstalledPackages() {\n const cwd = process.cwd();\n const installed = [];\n\n for (const pkg of PACKAGES) {\n const packagePath = path.join(\n cwd,\n \"node_modules\",\n pkg.name,\n \"package.json\",\n );\n if (fs.existsSync(packagePath)) {\n installed.push(pkg);\n }\n }\n\n return installed;\n}\n\n/**\n * Generate the AppKit section content\n */\nfunction generateSection(packages: typeof PACKAGES) {\n const links = packages\n .map((pkg) => {\n const docPath = `./node_modules/${pkg.name}/CLAUDE.md`;\n return `- **${pkg.name}** (${pkg.description}): [${docPath}](${docPath})`;\n })\n .join(\"\\n\");\n\n return `${SECTION_START}\n## Databricks AppKit\n\nThis project uses Databricks AppKit packages. For AI assistant guidance on using these packages, refer to:\n\n${links}\n${SECTION_END}`;\n}\n\n/**\n * Generate standalone CLAUDE.md content (when no existing file)\n */\nfunction generateStandalone(packages: typeof PACKAGES) {\n const links = packages\n .map((pkg) => {\n const docPath = `./node_modules/${pkg.name}/CLAUDE.md`;\n return `- **${pkg.name}** (${pkg.description}): [${docPath}](${docPath})`;\n })\n .join(\"\\n\");\n\n return `# AI Assistant Instructions\n\n${SECTION_START}\n## Databricks AppKit\n\nThis project uses Databricks AppKit packages. For AI assistant guidance on using these packages, refer to:\n\n${links}\n${SECTION_END}\n`;\n}\n\n/**\n * Update existing content with AppKit section\n */\nfunction updateContent(existingContent: string, packages: typeof PACKAGES) {\n const newSection = generateSection(packages);\n\n // Check if AppKit section already exists\n const startIndex = existingContent.indexOf(SECTION_START);\n const endIndex = existingContent.indexOf(SECTION_END);\n\n if (startIndex !== -1 && endIndex !== -1) {\n // Replace existing section\n const before = existingContent.substring(0, startIndex);\n const after = existingContent.substring(endIndex + SECTION_END.length);\n return before + newSection + after;\n }\n\n // Append section to end\n return `${existingContent.trimEnd()}\\n\\n${newSection}\\n`;\n}\n\n/**\n * Setup command implementation\n */\nfunction runSetup(options: { write?: boolean }) {\n const shouldWrite = options.write;\n\n // Find installed packages\n const installed = findInstalledPackages();\n\n if (installed.length === 0) {\n console.log(\"No @databricks/appkit packages found in node_modules.\");\n console.log(\"\\nMake sure you've installed at least one of:\");\n PACKAGES.forEach((pkg) => {\n console.log(` - ${pkg.name}`);\n });\n process.exit(1);\n }\n\n console.log(\"Detected packages:\");\n installed.forEach((pkg) => {\n console.log(` ✓ ${pkg.name}`);\n });\n\n const claudePath = path.join(process.cwd(), \"CLAUDE.md\");\n const existingContent = fs.existsSync(claudePath)\n ? fs.readFileSync(claudePath, \"utf-8\")\n : null;\n\n let finalContent: string;\n let action: string;\n\n if (existingContent) {\n finalContent = updateContent(existingContent, installed);\n action = existingContent.includes(SECTION_START) ? \"Updated\" : \"Added to\";\n } else {\n finalContent = generateStandalone(installed);\n action = \"Created\";\n }\n\n if (shouldWrite) {\n fs.writeFileSync(claudePath, finalContent);\n console.log(`\\n✓ ${action} CLAUDE.md`);\n console.log(` Path: ${claudePath}`);\n } else {\n console.log(\"\\nTo create/update CLAUDE.md, run:\");\n console.log(\" npx appkit setup --write\\n\");\n\n if (existingContent) {\n console.log(\n `This will ${\n existingContent.includes(SECTION_START)\n ? \"update the existing\"\n : \"add a new\"\n } AppKit section.\\n`,\n );\n }\n\n console.log(\"Preview of AppKit section:\\n\");\n console.log(\"─\".repeat(50));\n console.log(generateSection(installed));\n console.log(\"─\".repeat(50));\n }\n}\n\nexport const setupCommand = new Command(\"setup\")\n .description(\"Setup CLAUDE.md with AppKit package references\")\n .option(\"-w, --write\", \"Create or update CLAUDE.md file in current directory\")\n .action(runSetup);\n"],"mappings":"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"}
|
package/dist/cli/index.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
2
|
+
import { docsCommand } from "./commands/docs.js";
|
|
3
3
|
import { generateTypesCommand } from "./commands/generate-types.js";
|
|
4
4
|
import { lintCommand } from "./commands/lint.js";
|
|
5
|
-
import {
|
|
5
|
+
import { setupCommand } from "./commands/setup.js";
|
|
6
6
|
import { readFileSync } from "node:fs";
|
|
7
|
-
import { fileURLToPath } from "node:url";
|
|
8
7
|
import { dirname, join } from "node:path";
|
|
8
|
+
import { fileURLToPath } from "node:url";
|
|
9
9
|
import { Command } from "commander";
|
|
10
10
|
|
|
11
11
|
//#region src/cli/index.ts
|
package/dist/cli/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../src/cli/index.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { readFileSync } from \"node:fs\";\nimport {
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/cli/index.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { readFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { Command } from \"commander\";\nimport { docsCommand } from \"./commands/docs.js\";\nimport { generateTypesCommand } from \"./commands/generate-types.js\";\nimport { lintCommand } from \"./commands/lint.js\";\nimport { setupCommand } from \"./commands/setup.js\";\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\nconst pkgPath = join(__dirname, \"../../package.json\");\nconst pkg = JSON.parse(readFileSync(pkgPath, \"utf-8\"));\n\nconst cmd = new Command();\n\ncmd\n .name(\"appkit\")\n .description(\"CLI tools for Databricks AppKit\")\n .version(pkg.version);\n\ncmd.addCommand(setupCommand);\ncmd.addCommand(generateTypesCommand);\ncmd.addCommand(lintCommand);\ncmd.addCommand(docsCommand);\n\ncmd.parse();\n"],"mappings":";;;;;;;;;;;AAYA,MAAM,UAAU,KADE,QAAQ,cAAc,OAAO,KAAK,IAAI,CAAC,EACzB,qBAAqB;AACrD,MAAM,MAAM,KAAK,MAAM,aAAa,SAAS,QAAQ,CAAC;AAEtD,MAAM,MAAM,IAAI,SAAS;AAEzB,IACG,KAAK,SAAS,CACd,YAAY,kCAAkC,CAC9C,QAAQ,IAAI,QAAQ;AAEvB,IAAI,WAAW,aAAa;AAC5B,IAAI,WAAW,qBAAqB;AACpC,IAAI,WAAW,YAAY;AAC3B,IAAI,WAAW,YAAY;AAE3B,IAAI,OAAO"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { __toCommonJS } from "../../_virtual/
|
|
1
|
+
import { __toCommonJS } from "../../_virtual/_rolldown/runtime.js";
|
|
2
2
|
import { createLogger } from "../../logging/logger.js";
|
|
3
3
|
import { TelemetryManager } from "../../telemetry/telemetry-manager.js";
|
|
4
4
|
import { SpanStatusCode } from "../../telemetry/index.js";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { __esmMin } from "../_virtual/
|
|
1
|
+
import { __esmMin } from "../_virtual/_rolldown/runtime.js";
|
|
2
2
|
import { ServiceContext, init_service_context } from "./service-context.js";
|
|
3
3
|
import { init_user_context, isUserContext } from "./user-context.js";
|
|
4
4
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"execution-context.js","names":[],"sources":["../../src/context/execution-context.ts"],"sourcesContent":["import { AsyncLocalStorage } from \"node:async_hooks\";\nimport { ServiceContext } from \"./service-context\";\nimport {\n
|
|
1
|
+
{"version":3,"file":"execution-context.js","names":[],"sources":["../../src/context/execution-context.ts"],"sourcesContent":["import { AsyncLocalStorage } from \"node:async_hooks\";\nimport { ServiceContext } from \"./service-context\";\nimport {\n type ExecutionContext,\n isUserContext,\n type UserContext,\n} from \"./user-context\";\n\n/**\n * AsyncLocalStorage for execution context.\n * Used to pass user context through the call stack without explicit parameters.\n */\nconst executionContextStorage = new AsyncLocalStorage<UserContext>();\n\n/**\n * Run a function in the context of a user.\n * All calls within the function will have access to the user context.\n *\n * @param userContext - The user context to use\n * @param fn - The function to run\n * @returns The result of the function\n */\nexport function runInUserContext<T>(userContext: UserContext, fn: () => T): T {\n return executionContextStorage.run(userContext, fn);\n}\n\n/**\n * Get the current execution context.\n *\n * - If running inside a user context (via asUser), returns the user context\n * - Otherwise, returns the service context\n *\n * @throws Error if ServiceContext is not initialized\n */\nexport function getExecutionContext(): ExecutionContext {\n const userContext = executionContextStorage.getStore();\n if (userContext) {\n return userContext;\n }\n return ServiceContext.get();\n}\n\n/**\n * Get the current user ID for cache keying and telemetry.\n *\n * Returns the user ID if in user context, otherwise the service user ID.\n */\nexport function getCurrentUserId(): string {\n const ctx = getExecutionContext();\n if (isUserContext(ctx)) {\n return ctx.userId;\n }\n return ctx.serviceUserId;\n}\n\n/**\n * Get the WorkspaceClient for the current execution context.\n */\nexport function getWorkspaceClient() {\n return getExecutionContext().client;\n}\n\n/**\n * Get the warehouse ID promise.\n */\nexport function getWarehouseId(): Promise<string> {\n return getExecutionContext().warehouseId;\n}\n\n/**\n * Get the workspace ID promise.\n */\nexport function getWorkspaceId(): Promise<string> {\n return getExecutionContext().workspaceId;\n}\n\n/**\n * Check if currently running in a user context.\n */\nexport function isInUserContext(): boolean {\n const ctx = executionContextStorage.getStore();\n return ctx !== undefined;\n}\n"],"mappings":";;;;;;;;;;;;;;AAsBA,SAAgB,iBAAoB,aAA0B,IAAgB;AAC5E,QAAO,wBAAwB,IAAI,aAAa,GAAG;;;;;;;;;;AAWrD,SAAgB,sBAAwC;CACtD,MAAM,cAAc,wBAAwB,UAAU;AACtD,KAAI,YACF,QAAO;AAET,QAAO,eAAe,KAAK;;;;;;;AAQ7B,SAAgB,mBAA2B;CACzC,MAAM,MAAM,qBAAqB;AACjC,KAAI,cAAc,IAAI,CACpB,QAAO,IAAI;AAEb,QAAO,IAAI;;;;;AAMb,SAAgB,qBAAqB;AACnC,QAAO,qBAAqB,CAAC;;;;;AAM/B,SAAgB,iBAAkC;AAChD,QAAO,qBAAqB,CAAC;;;;;AAM/B,SAAgB,iBAAkC;AAChD,QAAO,qBAAqB,CAAC;;;;;AAM/B,SAAgB,kBAA2B;AAEzC,QADY,wBAAwB,UAAU,KAC/B;;;;uBAhFkC;oBAK3B;CAMlB,0BAA0B,IAAI,mBAAgC"}
|
package/dist/context/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { __esmMin, __exportAll } from "../_virtual/
|
|
1
|
+
import { __esmMin, __exportAll } from "../_virtual/_rolldown/runtime.js";
|
|
2
2
|
import { ServiceContext, init_service_context } from "./service-context.js";
|
|
3
3
|
import { init_user_context, isUserContext } from "./user-context.js";
|
|
4
4
|
import { getCurrentUserId, getExecutionContext, getWarehouseId, getWorkspaceClient, getWorkspaceId, init_execution_context, isInUserContext, runInUserContext } from "./execution-context.js";
|
|
@@ -16,9 +16,9 @@ var context_exports = /* @__PURE__ */ __exportAll({
|
|
|
16
16
|
runInUserContext: () => runInUserContext
|
|
17
17
|
});
|
|
18
18
|
var init_context = __esmMin((() => {
|
|
19
|
+
init_execution_context();
|
|
19
20
|
init_service_context();
|
|
20
21
|
init_user_context();
|
|
21
|
-
init_execution_context();
|
|
22
22
|
}));
|
|
23
23
|
|
|
24
24
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../src/context/index.ts"],"sourcesContent":["export {
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/context/index.ts"],"sourcesContent":["export {\n getCurrentUserId,\n getExecutionContext,\n getWarehouseId,\n getWorkspaceClient,\n getWorkspaceId,\n isInUserContext,\n runInUserContext,\n} from \"./execution-context\";\nexport { ServiceContext, type ServiceContextState } from \"./service-context\";\nexport {\n type ExecutionContext,\n isUserContext,\n type UserContext,\n} from \"./user-context\";\n"],"mappings":";;;;;;;;;;;;;;;;;;yBAQ6B;uBACgD;oBAKrD"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { __esmMin } from "../_virtual/
|
|
1
|
+
import { __esmMin } from "../_virtual/_rolldown/runtime.js";
|
|
2
2
|
import { AuthenticationError } from "../errors/authentication.js";
|
|
3
3
|
import { ConfigurationError } from "../errors/configuration.js";
|
|
4
4
|
import { InitializationError } from "../errors/initialization.js";
|
|
@@ -25,11 +25,14 @@ var init_service_context = __esmMin((() => {
|
|
|
25
25
|
/**
|
|
26
26
|
* Initialize the service context. Should be called once at app startup.
|
|
27
27
|
* Safe to call multiple times - will return the same instance.
|
|
28
|
+
*
|
|
29
|
+
* @param client - Optional pre-configured WorkspaceClient to use instead
|
|
30
|
+
* of creating one from environment credentials.
|
|
28
31
|
*/
|
|
29
|
-
static async initialize() {
|
|
32
|
+
static async initialize(client) {
|
|
30
33
|
if (ServiceContext.instance) return ServiceContext.instance;
|
|
31
34
|
if (ServiceContext.initPromise) return ServiceContext.initPromise;
|
|
32
|
-
ServiceContext.initPromise = ServiceContext.createContext();
|
|
35
|
+
ServiceContext.initPromise = ServiceContext.createContext(client);
|
|
33
36
|
ServiceContext.instance = await ServiceContext.initPromise;
|
|
34
37
|
return ServiceContext.instance;
|
|
35
38
|
}
|
|
@@ -80,14 +83,14 @@ var init_service_context = __esmMin((() => {
|
|
|
80
83
|
static getClientOptions() {
|
|
81
84
|
return getClientOptions();
|
|
82
85
|
}
|
|
83
|
-
static async createContext() {
|
|
84
|
-
const
|
|
85
|
-
const warehouseId = ServiceContext.getWarehouseId(
|
|
86
|
-
const workspaceId = ServiceContext.getWorkspaceId(
|
|
87
|
-
const currentUser = await
|
|
86
|
+
static async createContext(client) {
|
|
87
|
+
const wsClient = client ?? new WorkspaceClient({}, getClientOptions());
|
|
88
|
+
const warehouseId = ServiceContext.getWarehouseId(wsClient);
|
|
89
|
+
const workspaceId = ServiceContext.getWorkspaceId(wsClient);
|
|
90
|
+
const currentUser = await wsClient.currentUser.me();
|
|
88
91
|
if (!currentUser.id) throw ConfigurationError.resourceNotFound("Service user ID");
|
|
89
92
|
return {
|
|
90
|
-
client,
|
|
93
|
+
client: wsClient,
|
|
91
94
|
serviceUserId: currentUser.id,
|
|
92
95
|
warehouseId,
|
|
93
96
|
workspaceId
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service-context.js","names":["productName","productVersion"],"sources":["../../src/context/service-context.ts"],"sourcesContent":["import {\n type ClientOptions,\n type sql,\n WorkspaceClient,\n} from \"@databricks/sdk-experimental\";\nimport { coerce } from \"semver\";\nimport {\n name as productName,\n version as productVersion,\n} from \"../../package.json\";\nimport {\n AuthenticationError,\n ConfigurationError,\n InitializationError,\n} from \"../errors\";\nimport type { UserContext } from \"./user-context\";\n\n/**\n * Service context holds the service principal client and shared resources.\n * This is initialized once at app startup and shared across all requests.\n */\nexport interface ServiceContextState {\n /** WorkspaceClient authenticated as the service principal */\n client: WorkspaceClient;\n /** The service principal's user ID */\n serviceUserId: string;\n /** Promise that resolves to the warehouse ID */\n warehouseId: Promise<string>;\n /** Promise that resolves to the workspace ID */\n workspaceId: Promise<string>;\n}\n\nfunction getClientOptions(): ClientOptions {\n const isDev = process.env.NODE_ENV === \"development\";\n const semver = coerce(productVersion);\n const normalizedVersion = (semver?.version ??\n productVersion) as ClientOptions[\"productVersion\"];\n\n return {\n product: productName,\n productVersion: normalizedVersion,\n ...(isDev && { userAgentExtra: { mode: \"dev\" } }),\n };\n}\n\n/**\n * ServiceContext is a singleton that manages the service principal's\n * WorkspaceClient and shared resources like warehouse/workspace IDs.\n *\n * It's initialized once at app startup and provides the foundation\n * for both service principal and user context execution.\n */\nexport class ServiceContext {\n private static instance: ServiceContextState | null = null;\n private static initPromise: Promise<ServiceContextState> | null = null;\n\n /**\n * Initialize the service context. Should be called once at app startup.\n * Safe to call multiple times - will return the same instance.\n */\n static async initialize(): Promise<ServiceContextState> {\n if (ServiceContext.instance) {\n return ServiceContext.instance;\n }\n\n if (ServiceContext.initPromise) {\n return ServiceContext.initPromise;\n }\n\n ServiceContext.initPromise = ServiceContext.createContext();\n ServiceContext.instance = await ServiceContext.initPromise;\n return ServiceContext.instance;\n }\n\n /**\n * Get the initialized service context.\n * @throws Error if not initialized\n */\n static get(): ServiceContextState {\n if (!ServiceContext.instance) {\n throw InitializationError.notInitialized(\n \"ServiceContext\",\n \"Call ServiceContext.initialize() first\",\n );\n }\n return ServiceContext.instance;\n }\n\n /**\n * Check if the service context has been initialized.\n */\n static isInitialized(): boolean {\n return ServiceContext.instance !== null;\n }\n\n /**\n * Create a user context from request headers.\n *\n * @param token - The user's access token from x-forwarded-access-token header\n * @param userId - The user's ID from x-forwarded-user header\n * @param userName - Optional user name\n * @throws Error if token is not provided\n */\n static createUserContext(\n token: string,\n userId: string,\n userName?: string,\n ): UserContext {\n if (!token) {\n throw AuthenticationError.missingToken(\"user token\");\n }\n\n const host = process.env.DATABRICKS_HOST;\n if (!host) {\n throw ConfigurationError.missingEnvVar(\"DATABRICKS_HOST\");\n }\n\n const serviceCtx = ServiceContext.get();\n\n // Create user client with the OAuth token from Databricks Apps\n // Note: We use authType: \"pat\" because the token is passed as a Bearer token\n // just like a PAT, even though it's technically an OAuth token\n const userClient = new WorkspaceClient(\n {\n token,\n host,\n authType: \"pat\",\n },\n getClientOptions(),\n );\n\n return {\n client: userClient,\n userId,\n userName,\n warehouseId: serviceCtx.warehouseId,\n workspaceId: serviceCtx.workspaceId,\n isUserContext: true,\n };\n }\n\n /**\n * Get the client options for WorkspaceClient.\n * Exposed for testing purposes.\n */\n static getClientOptions(): ClientOptions {\n return getClientOptions();\n }\n\n private static async createContext(): Promise<ServiceContextState> {\n const client = new WorkspaceClient({}, getClientOptions());\n\n const warehouseId = ServiceContext.getWarehouseId(client);\n const workspaceId = ServiceContext.getWorkspaceId(client);\n const currentUser = await client.currentUser.me();\n\n if (!currentUser.id) {\n throw ConfigurationError.resourceNotFound(\"Service user ID\");\n }\n\n return {\n client,\n serviceUserId: currentUser.id,\n warehouseId,\n workspaceId,\n };\n }\n\n private static async getWorkspaceId(\n client: WorkspaceClient,\n ): Promise<string> {\n if (process.env.DATABRICKS_WORKSPACE_ID) {\n return process.env.DATABRICKS_WORKSPACE_ID;\n }\n\n const response = (await client.apiClient.request({\n path: \"/api/2.0/preview/scim/v2/Me\",\n method: \"GET\",\n headers: new Headers(),\n raw: false,\n query: {},\n responseHeaders: [\"x-databricks-org-id\"],\n })) as { \"x-databricks-org-id\": string };\n\n if (!response[\"x-databricks-org-id\"]) {\n throw ConfigurationError.resourceNotFound(\"Workspace ID\");\n }\n\n return response[\"x-databricks-org-id\"];\n }\n\n private static async getWarehouseId(\n client: WorkspaceClient,\n ): Promise<string> {\n if (process.env.DATABRICKS_WAREHOUSE_ID) {\n return process.env.DATABRICKS_WAREHOUSE_ID;\n }\n\n if (process.env.NODE_ENV === \"development\") {\n const response = (await client.apiClient.request({\n path: \"/api/2.0/sql/warehouses\",\n method: \"GET\",\n headers: new Headers(),\n raw: false,\n query: {\n skip_cannot_use: \"true\",\n },\n })) as { warehouses: sql.EndpointInfo[] };\n\n const priorities: Record<sql.State, number> = {\n RUNNING: 0,\n STOPPED: 1,\n STARTING: 2,\n STOPPING: 3,\n DELETED: 99,\n DELETING: 99,\n };\n\n const warehouses = (response.warehouses || []).sort((a, b) => {\n return (\n priorities[a.state as sql.State] - priorities[b.state as sql.State]\n );\n });\n\n if (response.warehouses.length === 0) {\n throw ConfigurationError.resourceNotFound(\n \"Warehouse ID\",\n \"Please configure the DATABRICKS_WAREHOUSE_ID environment variable\",\n );\n }\n\n const firstWarehouse = warehouses[0];\n if (\n firstWarehouse.state === \"DELETED\" ||\n firstWarehouse.state === \"DELETING\" ||\n !firstWarehouse.id\n ) {\n throw ConfigurationError.resourceNotFound(\n \"Warehouse ID\",\n \"Please configure the DATABRICKS_WAREHOUSE_ID environment variable\",\n );\n }\n\n return firstWarehouse.id;\n }\n\n throw ConfigurationError.resourceNotFound(\n \"Warehouse ID\",\n \"Please configure the DATABRICKS_WAREHOUSE_ID environment variable\",\n );\n }\n\n /**\n * Reset the service context. Only for testing purposes.\n */\n static reset(): void {\n ServiceContext.instance = null;\n ServiceContext.initPromise = null;\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"service-context.js","names":["productName","productVersion"],"sources":["../../src/context/service-context.ts"],"sourcesContent":["import {\n type ClientOptions,\n type sql,\n WorkspaceClient,\n} from \"@databricks/sdk-experimental\";\nimport { coerce } from \"semver\";\nimport {\n name as productName,\n version as productVersion,\n} from \"../../package.json\";\nimport {\n AuthenticationError,\n ConfigurationError,\n InitializationError,\n} from \"../errors\";\nimport type { UserContext } from \"./user-context\";\n\n/**\n * Service context holds the service principal client and shared resources.\n * This is initialized once at app startup and shared across all requests.\n */\nexport interface ServiceContextState {\n /** WorkspaceClient authenticated as the service principal */\n client: WorkspaceClient;\n /** The service principal's user ID */\n serviceUserId: string;\n /** Promise that resolves to the warehouse ID */\n warehouseId: Promise<string>;\n /** Promise that resolves to the workspace ID */\n workspaceId: Promise<string>;\n}\n\nfunction getClientOptions(): ClientOptions {\n const isDev = process.env.NODE_ENV === \"development\";\n const semver = coerce(productVersion);\n const normalizedVersion = (semver?.version ??\n productVersion) as ClientOptions[\"productVersion\"];\n\n return {\n product: productName,\n productVersion: normalizedVersion,\n ...(isDev && { userAgentExtra: { mode: \"dev\" } }),\n };\n}\n\n/**\n * ServiceContext is a singleton that manages the service principal's\n * WorkspaceClient and shared resources like warehouse/workspace IDs.\n *\n * It's initialized once at app startup and provides the foundation\n * for both service principal and user context execution.\n */\nexport class ServiceContext {\n private static instance: ServiceContextState | null = null;\n private static initPromise: Promise<ServiceContextState> | null = null;\n\n /**\n * Initialize the service context. Should be called once at app startup.\n * Safe to call multiple times - will return the same instance.\n *\n * @param client - Optional pre-configured WorkspaceClient to use instead\n * of creating one from environment credentials.\n */\n static async initialize(\n client?: WorkspaceClient,\n ): Promise<ServiceContextState> {\n if (ServiceContext.instance) {\n return ServiceContext.instance;\n }\n\n if (ServiceContext.initPromise) {\n return ServiceContext.initPromise;\n }\n\n ServiceContext.initPromise = ServiceContext.createContext(client);\n ServiceContext.instance = await ServiceContext.initPromise;\n return ServiceContext.instance;\n }\n\n /**\n * Get the initialized service context.\n * @throws Error if not initialized\n */\n static get(): ServiceContextState {\n if (!ServiceContext.instance) {\n throw InitializationError.notInitialized(\n \"ServiceContext\",\n \"Call ServiceContext.initialize() first\",\n );\n }\n return ServiceContext.instance;\n }\n\n /**\n * Check if the service context has been initialized.\n */\n static isInitialized(): boolean {\n return ServiceContext.instance !== null;\n }\n\n /**\n * Create a user context from request headers.\n *\n * @param token - The user's access token from x-forwarded-access-token header\n * @param userId - The user's ID from x-forwarded-user header\n * @param userName - Optional user name\n * @throws Error if token is not provided\n */\n static createUserContext(\n token: string,\n userId: string,\n userName?: string,\n ): UserContext {\n if (!token) {\n throw AuthenticationError.missingToken(\"user token\");\n }\n\n const host = process.env.DATABRICKS_HOST;\n if (!host) {\n throw ConfigurationError.missingEnvVar(\"DATABRICKS_HOST\");\n }\n\n const serviceCtx = ServiceContext.get();\n\n // Create user client with the OAuth token from Databricks Apps\n // Note: We use authType: \"pat\" because the token is passed as a Bearer token\n // just like a PAT, even though it's technically an OAuth token\n const userClient = new WorkspaceClient(\n {\n token,\n host,\n authType: \"pat\",\n },\n getClientOptions(),\n );\n\n return {\n client: userClient,\n userId,\n userName,\n warehouseId: serviceCtx.warehouseId,\n workspaceId: serviceCtx.workspaceId,\n isUserContext: true,\n };\n }\n\n /**\n * Get the client options for WorkspaceClient.\n * Exposed for testing purposes.\n */\n static getClientOptions(): ClientOptions {\n return getClientOptions();\n }\n\n private static async createContext(\n client?: WorkspaceClient,\n ): Promise<ServiceContextState> {\n const wsClient = client ?? new WorkspaceClient({}, getClientOptions());\n\n const warehouseId = ServiceContext.getWarehouseId(wsClient);\n const workspaceId = ServiceContext.getWorkspaceId(wsClient);\n const currentUser = await wsClient.currentUser.me();\n\n if (!currentUser.id) {\n throw ConfigurationError.resourceNotFound(\"Service user ID\");\n }\n\n return {\n client: wsClient,\n serviceUserId: currentUser.id,\n warehouseId,\n workspaceId,\n };\n }\n\n private static async getWorkspaceId(\n client: WorkspaceClient,\n ): Promise<string> {\n if (process.env.DATABRICKS_WORKSPACE_ID) {\n return process.env.DATABRICKS_WORKSPACE_ID;\n }\n\n const response = (await client.apiClient.request({\n path: \"/api/2.0/preview/scim/v2/Me\",\n method: \"GET\",\n headers: new Headers(),\n raw: false,\n query: {},\n responseHeaders: [\"x-databricks-org-id\"],\n })) as { \"x-databricks-org-id\": string };\n\n if (!response[\"x-databricks-org-id\"]) {\n throw ConfigurationError.resourceNotFound(\"Workspace ID\");\n }\n\n return response[\"x-databricks-org-id\"];\n }\n\n private static async getWarehouseId(\n client: WorkspaceClient,\n ): Promise<string> {\n if (process.env.DATABRICKS_WAREHOUSE_ID) {\n return process.env.DATABRICKS_WAREHOUSE_ID;\n }\n\n if (process.env.NODE_ENV === \"development\") {\n const response = (await client.apiClient.request({\n path: \"/api/2.0/sql/warehouses\",\n method: \"GET\",\n headers: new Headers(),\n raw: false,\n query: {\n skip_cannot_use: \"true\",\n },\n })) as { warehouses: sql.EndpointInfo[] };\n\n const priorities: Record<sql.State, number> = {\n RUNNING: 0,\n STOPPED: 1,\n STARTING: 2,\n STOPPING: 3,\n DELETED: 99,\n DELETING: 99,\n };\n\n const warehouses = (response.warehouses || []).sort((a, b) => {\n return (\n priorities[a.state as sql.State] - priorities[b.state as sql.State]\n );\n });\n\n if (response.warehouses.length === 0) {\n throw ConfigurationError.resourceNotFound(\n \"Warehouse ID\",\n \"Please configure the DATABRICKS_WAREHOUSE_ID environment variable\",\n );\n }\n\n const firstWarehouse = warehouses[0];\n if (\n firstWarehouse.state === \"DELETED\" ||\n firstWarehouse.state === \"DELETING\" ||\n !firstWarehouse.id\n ) {\n throw ConfigurationError.resourceNotFound(\n \"Warehouse ID\",\n \"Please configure the DATABRICKS_WAREHOUSE_ID environment variable\",\n );\n }\n\n return firstWarehouse.id;\n }\n\n throw ConfigurationError.resourceNotFound(\n \"Warehouse ID\",\n \"Please configure the DATABRICKS_WAREHOUSE_ID environment variable\",\n );\n }\n\n /**\n * Reset the service context. Only for testing purposes.\n */\n static reset(): void {\n ServiceContext.instance = null;\n ServiceContext.initPromise = null;\n }\n}\n"],"mappings":"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"}
|
package/dist/core/appkit.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { PluginConstructor, PluginData, PluginMap } from "../shared/src/plugin.js";
|
|
2
2
|
import { CacheConfig } from "../shared/src/cache.js";
|
|
3
3
|
import { TelemetryConfig } from "../telemetry/types.js";
|
|
4
|
+
import { WorkspaceClient } from "@databricks/sdk-experimental";
|
|
4
5
|
|
|
5
6
|
//#region src/core/appkit.d.ts
|
|
6
7
|
|
|
@@ -11,6 +12,7 @@ declare function createApp<T extends PluginData<PluginConstructor, unknown, stri
|
|
|
11
12
|
plugins?: T;
|
|
12
13
|
telemetry?: TelemetryConfig;
|
|
13
14
|
cache?: CacheConfig;
|
|
15
|
+
client?: WorkspaceClient;
|
|
14
16
|
}): Promise<PluginMap<T>>;
|
|
15
17
|
//#endregion
|
|
16
18
|
export { createApp };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"appkit.d.ts","names":[],"sources":["../../src/core/appkit.ts"],"sourcesContent":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"appkit.d.ts","names":[],"sources":["../../src/core/appkit.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;iBAyLsB,oBACV,WAAW;YAGT;cACE;UACJ;WACC;IAEV,QAAQ,UAAU"}
|
package/dist/core/appkit.js
CHANGED
|
@@ -69,7 +69,7 @@ var AppKit = class AppKit {
|
|
|
69
69
|
static async _createApp(config = {}) {
|
|
70
70
|
TelemetryManager.initialize(config?.telemetry);
|
|
71
71
|
await CacheManager.getInstance(config?.cache);
|
|
72
|
-
await ServiceContext.initialize();
|
|
72
|
+
await ServiceContext.initialize(config?.client);
|
|
73
73
|
const rawPlugins = config.plugins;
|
|
74
74
|
const instance = new AppKit({ plugins: AppKit.preparePlugins(rawPlugins) });
|
|
75
75
|
await Promise.all(instance.#setupPromises);
|
package/dist/core/appkit.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"appkit.js","names":["#pluginInstances","#setupPromises"],"sources":["../../src/core/appkit.ts"],"sourcesContent":["import type {\n BasePlugin,\n CacheConfig,\n InputPluginMap,\n OptionalConfigPluginDef,\n PluginConstructor,\n PluginData,\n PluginMap,\n} from \"shared\";\nimport { CacheManager } from \"../cache\";\nimport { ServiceContext } from \"../context\";\nimport type { TelemetryConfig } from \"../telemetry\";\nimport { TelemetryManager } from \"../telemetry\";\n\nexport class AppKit<TPlugins extends InputPluginMap> {\n #pluginInstances: Record<string, BasePlugin> = {};\n #setupPromises: Promise<void>[] = [];\n\n private constructor(config: { plugins: TPlugins }) {\n const { plugins, ...globalConfig } = config;\n\n const pluginEntries = Object.entries(plugins);\n\n const corePlugins = pluginEntries.filter(([_, p]) => {\n return (p?.plugin?.phase ?? \"normal\") === \"core\";\n });\n const normalPlugins = pluginEntries.filter(\n ([_, p]) => (p?.plugin?.phase ?? \"normal\") === \"normal\",\n );\n const deferredPlugins = pluginEntries.filter(\n ([_, p]) => (p?.plugin?.phase ?? \"normal\") === \"deferred\",\n );\n\n for (const [name, pluginData] of corePlugins) {\n if (pluginData) {\n this.createAndRegisterPlugin(globalConfig, name, pluginData);\n }\n }\n\n for (const [name, pluginData] of normalPlugins) {\n if (pluginData) {\n this.createAndRegisterPlugin(globalConfig, name, pluginData);\n }\n }\n\n for (const [name, pluginData] of deferredPlugins) {\n if (pluginData) {\n this.createAndRegisterPlugin(globalConfig, name, pluginData, {\n plugins: this.#pluginInstances,\n });\n }\n }\n }\n\n private createAndRegisterPlugin<T extends PluginConstructor>(\n config: Omit<{ plugins: TPlugins }, \"plugins\">,\n name: string,\n pluginData: OptionalConfigPluginDef<T>,\n extraData?: Record<string, unknown>,\n ) {\n const { plugin: Plugin, config: pluginConfig } = pluginData;\n const baseConfig = {\n ...config,\n ...Plugin.DEFAULT_CONFIG,\n ...pluginConfig,\n name,\n ...extraData,\n };\n const pluginInstance = new Plugin(baseConfig);\n\n this.#pluginInstances[name] = pluginInstance;\n\n pluginInstance.validateEnv();\n\n this.#setupPromises.push(pluginInstance.setup());\n\n const self = this;\n\n Object.defineProperty(this, name, {\n get() {\n const plugin = self.#pluginInstances[name];\n return self.wrapWithAsUser(plugin);\n },\n enumerable: true,\n });\n }\n\n /**\n * Binds all function properties in an exports object to the given context.\n */\n private bindExportMethods(\n exports: Record<string, unknown>,\n context: BasePlugin,\n ) {\n for (const key in exports) {\n if (Object.hasOwn(exports, key) && typeof exports[key] === \"function\") {\n exports[key] = (exports[key] as (...args: unknown[]) => unknown).bind(\n context,\n );\n }\n }\n }\n\n /**\n * Wraps a plugin's exports with an `asUser` method that returns\n * a user-scoped version of the exports.\n */\n private wrapWithAsUser<T extends BasePlugin>(plugin: T) {\n // If plugin doesn't implement exports(), return empty object\n const pluginExports = (plugin.exports?.() ?? {}) as Record<string, unknown>;\n this.bindExportMethods(pluginExports, plugin);\n\n // If plugin doesn't support asUser (no asUser method), return exports as-is\n if (typeof (plugin as any).asUser !== \"function\") {\n return pluginExports;\n }\n\n return {\n ...pluginExports,\n /**\n * Execute operations using the user's identity from the request.\n * Returns user-scoped exports where all methods execute with the\n * user's Databricks credentials instead of the service principal.\n */\n asUser: (req: import(\"express\").Request) => {\n const userPlugin = (plugin as any).asUser(req);\n const userExports = (userPlugin.exports?.() ?? {}) as Record<\n string,\n unknown\n >;\n this.bindExportMethods(userExports, userPlugin);\n return userExports;\n },\n };\n }\n\n static async _createApp<\n T extends PluginData<PluginConstructor, unknown, string>[],\n >(\n config: {\n plugins?: T;\n telemetry?: TelemetryConfig;\n cache?: CacheConfig;\n } = {},\n ): Promise<PluginMap<T>> {\n // Initialize core services\n TelemetryManager.initialize(config?.telemetry);\n await CacheManager.getInstance(config?.cache);\n\n // Initialize ServiceContext for Databricks client management\n // This provides the service principal client and shared resources\n await ServiceContext.initialize();\n\n const rawPlugins = config.plugins as T;\n const preparedPlugins = AppKit.preparePlugins(rawPlugins);\n const mergedConfig = {\n plugins: preparedPlugins,\n };\n\n const instance = new AppKit(mergedConfig);\n\n await Promise.all(instance.#setupPromises);\n\n return instance as unknown as PluginMap<T>;\n }\n\n private static preparePlugins(\n plugins: PluginData<PluginConstructor, unknown, string>[],\n ) {\n const result: InputPluginMap = {};\n for (const currentPlugin of plugins) {\n result[currentPlugin.name] = {\n plugin: currentPlugin.plugin,\n config: currentPlugin.config as Record<string, unknown>,\n };\n }\n return result;\n }\n}\n\n/**\n * Bootstraps AppKit with the provided configuration.\n */\nexport async function createApp<\n T extends PluginData<PluginConstructor, unknown, string>[],\n>(\n config: {\n plugins?: T;\n telemetry?: TelemetryConfig;\n cache?: CacheConfig;\n } = {},\n): Promise<PluginMap<T>> {\n return AppKit._createApp(config);\n}\n"],"mappings":";;;;;;;
|
|
1
|
+
{"version":3,"file":"appkit.js","names":["#pluginInstances","#setupPromises"],"sources":["../../src/core/appkit.ts"],"sourcesContent":["import type { WorkspaceClient } from \"@databricks/sdk-experimental\";\nimport type {\n BasePlugin,\n CacheConfig,\n InputPluginMap,\n OptionalConfigPluginDef,\n PluginConstructor,\n PluginData,\n PluginMap,\n} from \"shared\";\nimport { CacheManager } from \"../cache\";\nimport { ServiceContext } from \"../context\";\nimport type { TelemetryConfig } from \"../telemetry\";\nimport { TelemetryManager } from \"../telemetry\";\n\nexport class AppKit<TPlugins extends InputPluginMap> {\n #pluginInstances: Record<string, BasePlugin> = {};\n #setupPromises: Promise<void>[] = [];\n\n private constructor(config: { plugins: TPlugins }) {\n const { plugins, ...globalConfig } = config;\n\n const pluginEntries = Object.entries(plugins);\n\n const corePlugins = pluginEntries.filter(([_, p]) => {\n return (p?.plugin?.phase ?? \"normal\") === \"core\";\n });\n const normalPlugins = pluginEntries.filter(\n ([_, p]) => (p?.plugin?.phase ?? \"normal\") === \"normal\",\n );\n const deferredPlugins = pluginEntries.filter(\n ([_, p]) => (p?.plugin?.phase ?? \"normal\") === \"deferred\",\n );\n\n for (const [name, pluginData] of corePlugins) {\n if (pluginData) {\n this.createAndRegisterPlugin(globalConfig, name, pluginData);\n }\n }\n\n for (const [name, pluginData] of normalPlugins) {\n if (pluginData) {\n this.createAndRegisterPlugin(globalConfig, name, pluginData);\n }\n }\n\n for (const [name, pluginData] of deferredPlugins) {\n if (pluginData) {\n this.createAndRegisterPlugin(globalConfig, name, pluginData, {\n plugins: this.#pluginInstances,\n });\n }\n }\n }\n\n private createAndRegisterPlugin<T extends PluginConstructor>(\n config: Omit<{ plugins: TPlugins }, \"plugins\">,\n name: string,\n pluginData: OptionalConfigPluginDef<T>,\n extraData?: Record<string, unknown>,\n ) {\n const { plugin: Plugin, config: pluginConfig } = pluginData;\n const baseConfig = {\n ...config,\n ...Plugin.DEFAULT_CONFIG,\n ...pluginConfig,\n name,\n ...extraData,\n };\n const pluginInstance = new Plugin(baseConfig);\n\n this.#pluginInstances[name] = pluginInstance;\n\n pluginInstance.validateEnv();\n\n this.#setupPromises.push(pluginInstance.setup());\n\n const self = this;\n\n Object.defineProperty(this, name, {\n get() {\n const plugin = self.#pluginInstances[name];\n return self.wrapWithAsUser(plugin);\n },\n enumerable: true,\n });\n }\n\n /**\n * Binds all function properties in an exports object to the given context.\n */\n private bindExportMethods(\n exports: Record<string, unknown>,\n context: BasePlugin,\n ) {\n for (const key in exports) {\n if (Object.hasOwn(exports, key) && typeof exports[key] === \"function\") {\n exports[key] = (exports[key] as (...args: unknown[]) => unknown).bind(\n context,\n );\n }\n }\n }\n\n /**\n * Wraps a plugin's exports with an `asUser` method that returns\n * a user-scoped version of the exports.\n */\n private wrapWithAsUser<T extends BasePlugin>(plugin: T) {\n // If plugin doesn't implement exports(), return empty object\n const pluginExports = (plugin.exports?.() ?? {}) as Record<string, unknown>;\n this.bindExportMethods(pluginExports, plugin);\n\n // If plugin doesn't support asUser (no asUser method), return exports as-is\n if (typeof (plugin as any).asUser !== \"function\") {\n return pluginExports;\n }\n\n return {\n ...pluginExports,\n /**\n * Execute operations using the user's identity from the request.\n * Returns user-scoped exports where all methods execute with the\n * user's Databricks credentials instead of the service principal.\n */\n asUser: (req: import(\"express\").Request) => {\n const userPlugin = (plugin as any).asUser(req);\n const userExports = (userPlugin.exports?.() ?? {}) as Record<\n string,\n unknown\n >;\n this.bindExportMethods(userExports, userPlugin);\n return userExports;\n },\n };\n }\n\n static async _createApp<\n T extends PluginData<PluginConstructor, unknown, string>[],\n >(\n config: {\n plugins?: T;\n telemetry?: TelemetryConfig;\n cache?: CacheConfig;\n client?: WorkspaceClient;\n } = {},\n ): Promise<PluginMap<T>> {\n // Initialize core services\n TelemetryManager.initialize(config?.telemetry);\n await CacheManager.getInstance(config?.cache);\n\n // Initialize ServiceContext for Databricks client management\n // This provides the service principal client and shared resources\n await ServiceContext.initialize(config?.client);\n\n const rawPlugins = config.plugins as T;\n const preparedPlugins = AppKit.preparePlugins(rawPlugins);\n const mergedConfig = {\n plugins: preparedPlugins,\n };\n\n const instance = new AppKit(mergedConfig);\n\n await Promise.all(instance.#setupPromises);\n\n return instance as unknown as PluginMap<T>;\n }\n\n private static preparePlugins(\n plugins: PluginData<PluginConstructor, unknown, string>[],\n ) {\n const result: InputPluginMap = {};\n for (const currentPlugin of plugins) {\n result[currentPlugin.name] = {\n plugin: currentPlugin.plugin,\n config: currentPlugin.config as Record<string, unknown>,\n };\n }\n return result;\n }\n}\n\n/**\n * Bootstraps AppKit with the provided configuration.\n */\nexport async function createApp<\n T extends PluginData<PluginConstructor, unknown, string>[],\n>(\n config: {\n plugins?: T;\n telemetry?: TelemetryConfig;\n cache?: CacheConfig;\n client?: WorkspaceClient;\n } = {},\n): Promise<PluginMap<T>> {\n return AppKit._createApp(config);\n}\n"],"mappings":";;;;;;;cAW4C;AAI5C,IAAa,SAAb,MAAa,OAAwC;CACnD,mBAA+C,EAAE;CACjD,iBAAkC,EAAE;CAEpC,AAAQ,YAAY,QAA+B;EACjD,MAAM,EAAE,SAAS,GAAG,iBAAiB;EAErC,MAAM,gBAAgB,OAAO,QAAQ,QAAQ;EAE7C,MAAM,cAAc,cAAc,QAAQ,CAAC,GAAG,OAAO;AACnD,WAAQ,GAAG,QAAQ,SAAS,cAAc;IAC1C;EACF,MAAM,gBAAgB,cAAc,QACjC,CAAC,GAAG,QAAQ,GAAG,QAAQ,SAAS,cAAc,SAChD;EACD,MAAM,kBAAkB,cAAc,QACnC,CAAC,GAAG,QAAQ,GAAG,QAAQ,SAAS,cAAc,WAChD;AAED,OAAK,MAAM,CAAC,MAAM,eAAe,YAC/B,KAAI,WACF,MAAK,wBAAwB,cAAc,MAAM,WAAW;AAIhE,OAAK,MAAM,CAAC,MAAM,eAAe,cAC/B,KAAI,WACF,MAAK,wBAAwB,cAAc,MAAM,WAAW;AAIhE,OAAK,MAAM,CAAC,MAAM,eAAe,gBAC/B,KAAI,WACF,MAAK,wBAAwB,cAAc,MAAM,YAAY,EAC3D,SAAS,MAAKA,iBACf,CAAC;;CAKR,AAAQ,wBACN,QACA,MACA,YACA,WACA;EACA,MAAM,EAAE,QAAQ,QAAQ,QAAQ,iBAAiB;EAQjD,MAAM,iBAAiB,IAAI,OAPR;GACjB,GAAG;GACH,GAAG,OAAO;GACV,GAAG;GACH;GACA,GAAG;GACJ,CAC4C;AAE7C,QAAKA,gBAAiB,QAAQ;AAE9B,iBAAe,aAAa;AAE5B,QAAKC,cAAe,KAAK,eAAe,OAAO,CAAC;EAEhD,MAAM,OAAO;AAEb,SAAO,eAAe,MAAM,MAAM;GAChC,MAAM;IACJ,MAAM,SAAS,MAAKD,gBAAiB;AACrC,WAAO,KAAK,eAAe,OAAO;;GAEpC,YAAY;GACb,CAAC;;;;;CAMJ,AAAQ,kBACN,SACA,SACA;AACA,OAAK,MAAM,OAAO,QAChB,KAAI,OAAO,OAAO,SAAS,IAAI,IAAI,OAAO,QAAQ,SAAS,WACzD,SAAQ,OAAQ,QAAQ,KAAyC,KAC/D,QACD;;;;;;CASP,AAAQ,eAAqC,QAAW;EAEtD,MAAM,gBAAiB,OAAO,WAAW,IAAI,EAAE;AAC/C,OAAK,kBAAkB,eAAe,OAAO;AAG7C,MAAI,OAAQ,OAAe,WAAW,WACpC,QAAO;AAGT,SAAO;GACL,GAAG;GAMH,SAAS,QAAmC;IAC1C,MAAM,aAAc,OAAe,OAAO,IAAI;IAC9C,MAAM,cAAe,WAAW,WAAW,IAAI,EAAE;AAIjD,SAAK,kBAAkB,aAAa,WAAW;AAC/C,WAAO;;GAEV;;CAGH,aAAa,WAGX,SAKI,EAAE,EACiB;AAEvB,mBAAiB,WAAW,QAAQ,UAAU;AAC9C,QAAM,aAAa,YAAY,QAAQ,MAAM;AAI7C,QAAM,eAAe,WAAW,QAAQ,OAAO;EAE/C,MAAM,aAAa,OAAO;EAM1B,MAAM,WAAW,IAAI,OAJA,EACnB,SAFsB,OAAO,eAAe,WAAW,EAGxD,CAEwC;AAEzC,QAAM,QAAQ,IAAI,UAASC,cAAe;AAE1C,SAAO;;CAGT,OAAe,eACb,SACA;EACA,MAAM,SAAyB,EAAE;AACjC,OAAK,MAAM,iBAAiB,QAC1B,QAAO,cAAc,QAAQ;GAC3B,QAAQ,cAAc;GACtB,QAAQ,cAAc;GACvB;AAEH,SAAO;;;;;;AAOX,eAAsB,UAGpB,SAKI,EAAE,EACiB;AACvB,QAAO,OAAO,WAAW,OAAO"}
|
package/dist/errors/base.js
CHANGED
package/dist/errors/execution.js
CHANGED
package/dist/errors/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { __esmMin } from "../_virtual/
|
|
1
|
+
import { __esmMin } from "../_virtual/_rolldown/runtime.js";
|
|
2
2
|
import { AppKitError, init_base } from "./base.js";
|
|
3
3
|
import { AuthenticationError, init_authentication } from "./authentication.js";
|
|
4
4
|
import { ConfigurationError, init_configuration } from "./configuration.js";
|
package/dist/errors/server.js
CHANGED
package/dist/errors/tunnel.js
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -3,11 +3,9 @@ import { CacheConfig } from "./shared/src/cache.js";
|
|
|
3
3
|
import { StreamExecutionSettings } from "./shared/src/execute.js";
|
|
4
4
|
import { isSQLTypeMarker, sql } from "./shared/src/sql/helpers.js";
|
|
5
5
|
import { CacheManager } from "./cache/index.js";
|
|
6
|
+
import { getExecutionContext } from "./context/execution-context.js";
|
|
6
7
|
import { ITelemetry, TelemetryConfig } from "./telemetry/types.js";
|
|
7
8
|
import { Counter, Histogram, SeverityNumber, Span, SpanStatusCode } from "./telemetry/index.js";
|
|
8
|
-
import { Plugin } from "./plugin/plugin.js";
|
|
9
|
-
import { toPlugin } from "./plugin/to-plugin.js";
|
|
10
|
-
import { analytics } from "./analytics/analytics.js";
|
|
11
9
|
import { createApp } from "./core/appkit.js";
|
|
12
10
|
import { AppKitError } from "./errors/base.js";
|
|
13
11
|
import { AuthenticationError } from "./errors/authentication.js";
|
|
@@ -18,7 +16,9 @@ import { InitializationError } from "./errors/initialization.js";
|
|
|
18
16
|
import { ServerError } from "./errors/server.js";
|
|
19
17
|
import { TunnelError } from "./errors/tunnel.js";
|
|
20
18
|
import { ValidationError } from "./errors/validation.js";
|
|
21
|
-
import {
|
|
19
|
+
import { Plugin } from "./plugin/plugin.js";
|
|
20
|
+
import { toPlugin } from "./plugin/to-plugin.js";
|
|
21
|
+
import { analytics } from "./plugins/analytics/analytics.js";
|
|
22
|
+
import { server } from "./plugins/server/index.js";
|
|
22
23
|
import { appKitTypesPlugin } from "./type-generator/vite-plugin.js";
|
|
23
|
-
import { getExecutionContext } from "./context/execution-context.js";
|
|
24
24
|
export { AppKitError, AuthenticationError, type BasePluginConfig, type CacheConfig, CacheManager, ConfigurationError, ConnectionError, type Counter, ExecutionError, type Histogram, type IAppRouter, type ITelemetry, InitializationError, Plugin, ServerError, SeverityNumber, type Span, SpanStatusCode, type StreamExecutionSettings, type TelemetryConfig, TunnelError, ValidationError, analytics, appKitTypesPlugin, createApp, getExecutionContext, isSQLTypeMarker, server, sql, toPlugin };
|
package/dist/index.js
CHANGED
|
@@ -13,19 +13,19 @@ import { init_errors } from "./errors/index.js";
|
|
|
13
13
|
import { getExecutionContext } from "./context/execution-context.js";
|
|
14
14
|
import { init_context } from "./context/index.js";
|
|
15
15
|
import { CacheManager } from "./cache/index.js";
|
|
16
|
+
import { createApp } from "./core/appkit.js";
|
|
17
|
+
import "./core/index.js";
|
|
16
18
|
import { Plugin } from "./plugin/plugin.js";
|
|
17
19
|
import { toPlugin } from "./plugin/to-plugin.js";
|
|
18
20
|
import "./plugin/index.js";
|
|
19
|
-
import { analytics } from "./analytics/analytics.js";
|
|
20
|
-
import "./analytics/index.js";
|
|
21
|
-
import { createApp } from "./core/appkit.js";
|
|
22
|
-
import "./core/index.js";
|
|
21
|
+
import { analytics } from "./plugins/analytics/analytics.js";
|
|
23
22
|
import { appKitTypesPlugin } from "./type-generator/vite-plugin.js";
|
|
24
|
-
import { server } from "./server/index.js";
|
|
23
|
+
import { server } from "./plugins/server/index.js";
|
|
24
|
+
import "./plugins/index.js";
|
|
25
25
|
|
|
26
26
|
//#region src/index.ts
|
|
27
|
-
init_errors();
|
|
28
27
|
init_context();
|
|
28
|
+
init_errors();
|
|
29
29
|
|
|
30
30
|
//#endregion
|
|
31
31
|
export { AppKitError, AuthenticationError, CacheManager, ConfigurationError, ConnectionError, ExecutionError, InitializationError, Plugin, ServerError, SeverityNumber, SpanStatusCode, TunnelError, ValidationError, analytics, appKitTypesPlugin, createApp, getExecutionContext, isSQLTypeMarker, server, sql, toPlugin };
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["/**\n * @packageDocumentation\n *\n * Core library for building Databricks applications with type-safe SQL queries,\n * plugin architecture, and React integration.\n */\n\n// Types from shared\nexport type {\n BasePluginConfig,\n CacheConfig,\n IAppRouter,\n StreamExecutionSettings,\n} from \"shared\";\nexport { isSQLTypeMarker, sql } from \"shared\";\nexport {
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["/**\n * @packageDocumentation\n *\n * Core library for building Databricks applications with type-safe SQL queries,\n * plugin architecture, and React integration.\n */\n\n// Types from shared\nexport type {\n BasePluginConfig,\n CacheConfig,\n IAppRouter,\n StreamExecutionSettings,\n} from \"shared\";\nexport { isSQLTypeMarker, sql } from \"shared\";\nexport { CacheManager } from \"./cache\";\nexport { getExecutionContext } from \"./context\";\nexport { createApp } from \"./core\";\n// Errors\nexport {\n AppKitError,\n AuthenticationError,\n ConfigurationError,\n ConnectionError,\n ExecutionError,\n InitializationError,\n ServerError,\n TunnelError,\n ValidationError,\n} from \"./errors\";\n// Plugin authoring\nexport { Plugin, toPlugin } from \"./plugin\";\nexport { analytics, server } from \"./plugins\";\n// Telemetry (for advanced custom telemetry)\nexport {\n type Counter,\n type Histogram,\n type ITelemetry,\n SeverityNumber,\n type Span,\n SpanStatusCode,\n type TelemetryConfig,\n} from \"./telemetry\";\n// Vite plugin and type generation\nexport { appKitTypesPlugin } from \"./type-generator/vite-plugin\";\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;cAgBgD;aAa9B"}
|