@databricks/appkit-ui 0.23.0 → 0.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CLAUDE.md +9 -1
- package/dist/cli/commands/docs.js +7 -1
- package/dist/cli/commands/docs.js.map +1 -1
- package/dist/cli/commands/generate-types.js +20 -10
- package/dist/cli/commands/generate-types.js.map +1 -1
- package/dist/cli/commands/lint.js +3 -1
- package/dist/cli/commands/lint.js.map +1 -1
- package/dist/cli/commands/plugin/add-resource/add-resource.js +73 -8
- package/dist/cli/commands/plugin/add-resource/add-resource.js.map +1 -1
- package/dist/cli/commands/plugin/create/create.js +164 -20
- package/dist/cli/commands/plugin/create/create.js.map +1 -1
- package/dist/cli/commands/plugin/create/resource-defaults.js +5 -1
- package/dist/cli/commands/plugin/create/resource-defaults.js.map +1 -1
- package/dist/cli/commands/plugin/index.js +7 -1
- package/dist/cli/commands/plugin/index.js.map +1 -1
- package/dist/cli/commands/plugin/list/list.js +7 -1
- package/dist/cli/commands/plugin/list/list.js.map +1 -1
- package/dist/cli/commands/plugin/sync/sync.js +27 -14
- package/dist/cli/commands/plugin/sync/sync.js.map +1 -1
- package/dist/cli/commands/plugin/validate/validate.js +39 -9
- package/dist/cli/commands/plugin/validate/validate.js.map +1 -1
- package/dist/cli/commands/setup.js +6 -5
- package/dist/cli/commands/setup.js.map +1 -1
- package/dist/react/hooks/types.d.ts +1 -1
- package/docs/api/appkit/Class.PolicyDeniedError.md +52 -0
- package/docs/api/appkit/Interface.FilePolicyUser.md +23 -0
- package/docs/api/appkit/Interface.FileResource.md +36 -0
- package/docs/api/appkit/TypeAlias.FileAction.md +18 -0
- package/docs/api/appkit/TypeAlias.FilePolicy.md +20 -0
- package/docs/api/appkit/TypeAlias.ServingFactory.md +9 -5
- package/docs/api/appkit/Variable.READ_ACTIONS.md +8 -0
- package/docs/api/appkit/Variable.WRITE_ACTIONS.md +8 -0
- package/docs/api/appkit.md +19 -12
- package/docs/development/type-generation.md +6 -5
- package/docs/faq.md +8 -8
- package/docs/plugins/analytics.md +1 -1
- package/docs/plugins/custom-plugins.md +4 -0
- package/docs/plugins/execution-context.md +0 -1
- package/docs/plugins/files.md +150 -2
- package/docs/plugins/{serving.md → model-serving.md} +1 -1
- package/docs/plugins/plugin-management.md +22 -6
- package/docs/plugins/vector-search.md +247 -0
- package/llms.txt +9 -1
- package/package.json +1 -1
- package/sbom.cdx.json +1 -1
|
@@ -47,35 +47,65 @@ function resolveManifestPaths(paths, cwd, allowJsManifest) {
|
|
|
47
47
|
async function runPluginValidate(paths, options) {
|
|
48
48
|
const cwd = process.cwd();
|
|
49
49
|
const allowJsManifest = Boolean(options.allowJsManifest);
|
|
50
|
-
if (allowJsManifest) console.warn("Warning: --allow-js-manifest executes manifest.js/manifest.cjs files. Only use with trusted code.");
|
|
50
|
+
if (allowJsManifest && !options.json) console.warn("Warning: --allow-js-manifest executes manifest.js/manifest.cjs files. Only use with trusted code.");
|
|
51
51
|
const manifestPaths = resolveManifestPaths(paths.length > 0 ? paths : ["."], cwd, allowJsManifest);
|
|
52
52
|
if (manifestPaths.length === 0) {
|
|
53
|
-
console.
|
|
53
|
+
if (options.json) console.log("[]");
|
|
54
|
+
else console.error("No manifest files to validate.");
|
|
54
55
|
process.exit(1);
|
|
55
56
|
}
|
|
56
57
|
let hasFailure = false;
|
|
58
|
+
const jsonResults = [];
|
|
57
59
|
for (const { path: manifestPath, type } of manifestPaths) {
|
|
60
|
+
const relativePath = path.relative(cwd, manifestPath);
|
|
58
61
|
let obj;
|
|
59
62
|
try {
|
|
60
63
|
obj = await loadManifestFromFile(manifestPath, type, { allowJsManifest });
|
|
61
64
|
} catch (err) {
|
|
62
|
-
|
|
63
|
-
|
|
65
|
+
const errMsg = err instanceof Error ? err.message : String(err);
|
|
66
|
+
if (options.json) jsonResults.push({
|
|
67
|
+
path: relativePath,
|
|
68
|
+
valid: false,
|
|
69
|
+
errors: [errMsg]
|
|
70
|
+
});
|
|
71
|
+
else {
|
|
72
|
+
console.error(`✗ ${manifestPath}`);
|
|
73
|
+
console.error(` ${errMsg}`);
|
|
74
|
+
}
|
|
64
75
|
hasFailure = true;
|
|
65
76
|
continue;
|
|
66
77
|
}
|
|
67
78
|
const result = detectSchemaType(obj) === "template-plugins" ? validateTemplateManifest(obj) : validateManifest(obj);
|
|
68
|
-
|
|
69
|
-
|
|
79
|
+
if (result.valid) if (options.json) jsonResults.push({
|
|
80
|
+
path: relativePath,
|
|
81
|
+
valid: true
|
|
82
|
+
});
|
|
83
|
+
else console.log(`✓ ${relativePath}`);
|
|
70
84
|
else {
|
|
71
|
-
|
|
72
|
-
|
|
85
|
+
if (options.json) {
|
|
86
|
+
const errors = result.errors?.length ? formatValidationErrors(result.errors, obj).split("\n").filter(Boolean) : [];
|
|
87
|
+
jsonResults.push({
|
|
88
|
+
path: relativePath,
|
|
89
|
+
valid: false,
|
|
90
|
+
...errors.length > 0 && { errors }
|
|
91
|
+
});
|
|
92
|
+
} else {
|
|
93
|
+
console.error(`✗ ${relativePath}`);
|
|
94
|
+
if (result.errors?.length) console.error(formatValidationErrors(result.errors, obj));
|
|
95
|
+
}
|
|
73
96
|
hasFailure = true;
|
|
74
97
|
}
|
|
75
98
|
}
|
|
99
|
+
if (options.json) console.log(JSON.stringify(jsonResults, null, 2));
|
|
76
100
|
process.exit(hasFailure ? 1 : 0);
|
|
77
101
|
}
|
|
78
|
-
const pluginValidateCommand = new Command("validate").description("Validate plugin manifest(s) or template manifests against their JSON schema").argument("[paths...]", "Paths to manifest.json or appkit.plugins.json (or plugin directories); use --allow-js-manifest to include manifest.js").option("--allow-js-manifest", "Allow reading manifest.js/manifest.cjs (executes code; use only with trusted plugins)").
|
|
102
|
+
const pluginValidateCommand = new Command("validate").description("Validate plugin manifest(s) or template manifests against their JSON schema").argument("[paths...]", "Paths to manifest.json or appkit.plugins.json (or plugin directories); use --allow-js-manifest to include manifest.js").option("--allow-js-manifest", "Allow reading manifest.js/manifest.cjs (executes code; use only with trusted plugins)").option("--json", "Output validation results as JSON").addHelpText("after", `
|
|
103
|
+
Examples:
|
|
104
|
+
$ appkit plugin validate
|
|
105
|
+
$ appkit plugin validate plugins/my-plugin
|
|
106
|
+
$ appkit plugin validate plugins/my-plugin plugins/other
|
|
107
|
+
$ appkit plugin validate appkit.plugins.json
|
|
108
|
+
$ appkit plugin validate --json`).action((paths, opts) => runPluginValidate(paths, opts).catch((err) => {
|
|
79
109
|
console.error(err);
|
|
80
110
|
process.exit(1);
|
|
81
111
|
}));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validate.js","names":[],"sources":["../../../../../src/cli/commands/plugin/validate/validate.ts"],"sourcesContent":["import fs from \"node:fs\";\nimport path from \"node:path\";\nimport process from \"node:process\";\nimport { Command } from \"commander\";\nimport {\n loadManifestFromFile,\n type ResolvedManifest,\n resolveManifestInDir,\n} from \"../manifest-resolve\";\nimport {\n detectSchemaType,\n formatValidationErrors,\n validateManifest,\n validateTemplateManifest,\n} from \"./validate-manifest\";\n\nfunction resolveManifestPaths(\n paths: string[],\n cwd: string,\n allowJsManifest: boolean,\n): ResolvedManifest[] {\n const out: ResolvedManifest[] = [];\n for (const p of paths) {\n const resolved = path.resolve(cwd, p);\n if (!fs.existsSync(resolved)) {\n console.error(`Path not found: ${p}`);\n continue;\n }\n const stat = fs.statSync(resolved);\n if (stat.isDirectory()) {\n let found = false;\n const pluginResolved = resolveManifestInDir(resolved, {\n allowJsManifest,\n });\n if (pluginResolved) {\n out.push(pluginResolved);\n found = true;\n }\n const templateManifest = path.join(resolved, \"appkit.plugins.json\");\n if (fs.existsSync(templateManifest)) {\n out.push({ path: templateManifest, type: \"json\" });\n found = true;\n }\n if (!found) {\n console.error(\n `No ${allowJsManifest ? \"manifest.json, manifest.js, or\" : \"manifest.json or\"} appkit.plugins.json in directory: ${p}`,\n );\n }\n } else {\n const ext = path.extname(resolved).toLowerCase();\n if (!allowJsManifest && (ext === \".js\" || ext === \".cjs\")) {\n console.error(\n `JS manifest provided but disabled by default: ${p}. Re-run with --allow-js-manifest to opt in.`,\n );\n continue;\n }\n out.push({\n path: resolved,\n type: ext === \".js\" || ext === \".cjs\" ? \"js\" : \"json\",\n });\n }\n }\n return out;\n}\n\nasync function runPluginValidate(\n paths: string[],\n options:
|
|
1
|
+
{"version":3,"file":"validate.js","names":[],"sources":["../../../../../src/cli/commands/plugin/validate/validate.ts"],"sourcesContent":["import fs from \"node:fs\";\nimport path from \"node:path\";\nimport process from \"node:process\";\nimport { Command } from \"commander\";\nimport {\n loadManifestFromFile,\n type ResolvedManifest,\n resolveManifestInDir,\n} from \"../manifest-resolve\";\nimport {\n detectSchemaType,\n formatValidationErrors,\n validateManifest,\n validateTemplateManifest,\n} from \"./validate-manifest\";\n\nfunction resolveManifestPaths(\n paths: string[],\n cwd: string,\n allowJsManifest: boolean,\n): ResolvedManifest[] {\n const out: ResolvedManifest[] = [];\n for (const p of paths) {\n const resolved = path.resolve(cwd, p);\n if (!fs.existsSync(resolved)) {\n console.error(`Path not found: ${p}`);\n continue;\n }\n const stat = fs.statSync(resolved);\n if (stat.isDirectory()) {\n let found = false;\n const pluginResolved = resolveManifestInDir(resolved, {\n allowJsManifest,\n });\n if (pluginResolved) {\n out.push(pluginResolved);\n found = true;\n }\n const templateManifest = path.join(resolved, \"appkit.plugins.json\");\n if (fs.existsSync(templateManifest)) {\n out.push({ path: templateManifest, type: \"json\" });\n found = true;\n }\n if (!found) {\n console.error(\n `No ${allowJsManifest ? \"manifest.json, manifest.js, or\" : \"manifest.json or\"} appkit.plugins.json in directory: ${p}`,\n );\n }\n } else {\n const ext = path.extname(resolved).toLowerCase();\n if (!allowJsManifest && (ext === \".js\" || ext === \".cjs\")) {\n console.error(\n `JS manifest provided but disabled by default: ${p}. Re-run with --allow-js-manifest to opt in.`,\n );\n continue;\n }\n out.push({\n path: resolved,\n type: ext === \".js\" || ext === \".cjs\" ? \"js\" : \"json\",\n });\n }\n }\n return out;\n}\n\ninterface ValidateOptions {\n allowJsManifest?: boolean;\n json?: boolean;\n}\n\nasync function runPluginValidate(\n paths: string[],\n options: ValidateOptions,\n): Promise<void> {\n const cwd = process.cwd();\n const allowJsManifest = Boolean(options.allowJsManifest);\n if (allowJsManifest && !options.json) {\n console.warn(\n \"Warning: --allow-js-manifest executes manifest.js/manifest.cjs files. Only use with trusted code.\",\n );\n }\n const toValidate = paths.length > 0 ? paths : [\".\"];\n const manifestPaths = resolveManifestPaths(toValidate, cwd, allowJsManifest);\n\n if (manifestPaths.length === 0) {\n if (options.json) {\n console.log(\"[]\");\n } else {\n console.error(\"No manifest files to validate.\");\n }\n process.exit(1);\n }\n\n let hasFailure = false;\n const jsonResults: { path: string; valid: boolean; errors?: string[] }[] = [];\n\n for (const { path: manifestPath, type } of manifestPaths) {\n const relativePath = path.relative(cwd, manifestPath);\n let obj: unknown;\n try {\n obj = await loadManifestFromFile(manifestPath, type, { allowJsManifest });\n } catch (err) {\n const errMsg = err instanceof Error ? err.message : String(err);\n if (options.json) {\n jsonResults.push({\n path: relativePath,\n valid: false,\n errors: [errMsg],\n });\n } else {\n console.error(`✗ ${manifestPath}`);\n console.error(` ${errMsg}`);\n }\n hasFailure = true;\n continue;\n }\n\n const schemaType = detectSchemaType(obj);\n const result =\n schemaType === \"template-plugins\"\n ? validateTemplateManifest(obj)\n : validateManifest(obj);\n\n if (result.valid) {\n if (options.json) {\n jsonResults.push({ path: relativePath, valid: true });\n } else {\n console.log(`✓ ${relativePath}`);\n }\n } else {\n if (options.json) {\n const errors = result.errors?.length\n ? formatValidationErrors(result.errors, obj)\n .split(\"\\n\")\n .filter(Boolean)\n : [];\n jsonResults.push({\n path: relativePath,\n valid: false,\n ...(errors.length > 0 && { errors }),\n });\n } else {\n console.error(`✗ ${relativePath}`);\n if (result.errors?.length) {\n console.error(formatValidationErrors(result.errors, obj));\n }\n }\n hasFailure = true;\n }\n }\n\n if (options.json) {\n console.log(JSON.stringify(jsonResults, null, 2));\n }\n\n process.exit(hasFailure ? 1 : 0);\n}\n\nexport const pluginValidateCommand = new Command(\"validate\")\n .description(\n \"Validate plugin manifest(s) or template manifests against their JSON schema\",\n )\n .argument(\n \"[paths...]\",\n \"Paths to manifest.json or appkit.plugins.json (or plugin directories); use --allow-js-manifest to include manifest.js\",\n )\n .option(\n \"--allow-js-manifest\",\n \"Allow reading manifest.js/manifest.cjs (executes code; use only with trusted plugins)\",\n )\n .option(\"--json\", \"Output validation results as JSON\")\n .addHelpText(\n \"after\",\n `\nExamples:\n $ appkit plugin validate\n $ appkit plugin validate plugins/my-plugin\n $ appkit plugin validate plugins/my-plugin plugins/other\n $ appkit plugin validate appkit.plugins.json\n $ appkit plugin validate --json`,\n )\n .action((paths: string[], opts: ValidateOptions) =>\n runPluginValidate(paths, opts).catch((err) => {\n console.error(err);\n process.exit(1);\n }),\n );\n"],"mappings":"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"}
|
|
@@ -95,10 +95,8 @@ function runSetup(options) {
|
|
|
95
95
|
const installed = findInstalledPackages();
|
|
96
96
|
if (installed.length === 0) {
|
|
97
97
|
console.log("No @databricks/appkit packages found in node_modules.");
|
|
98
|
-
console.log("\
|
|
99
|
-
|
|
100
|
-
console.log(` - ${pkg.name}`);
|
|
101
|
-
});
|
|
98
|
+
console.log("\nInstall at least one of:");
|
|
99
|
+
for (const pkg of PACKAGES) console.log(` npm install ${pkg.name}`);
|
|
102
100
|
process.exit(1);
|
|
103
101
|
}
|
|
104
102
|
console.log("Detected packages:");
|
|
@@ -130,7 +128,10 @@ function runSetup(options) {
|
|
|
130
128
|
console.log("─".repeat(50));
|
|
131
129
|
}
|
|
132
130
|
}
|
|
133
|
-
const setupCommand = new Command("setup").description("Setup CLAUDE.md with AppKit package references").option("-w, --write", "Create or update CLAUDE.md file in current directory").
|
|
131
|
+
const setupCommand = new Command("setup").description("Setup CLAUDE.md with AppKit package references").option("-w, --write", "Create or update CLAUDE.md file in current directory").addHelpText("after", `
|
|
132
|
+
Examples:
|
|
133
|
+
$ appkit setup
|
|
134
|
+
$ appkit setup --write`).action(runSetup);
|
|
134
135
|
|
|
135
136
|
//#endregion
|
|
136
137
|
export { setupCommand };
|
|
@@ -1 +1 @@
|
|
|
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\n### Databricks Skills\n\nFor enhanced AI assistance with Databricks CLI operations, authentication, data exploration, and app development, install the Databricks skills:\n\n\\`\\`\\`bash\ndatabricks experimental aitools install\n\\`\\`\\`\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\n### Databricks Skills\n\nFor enhanced AI assistance with Databricks CLI operations, authentication, data exploration, and app development, install the Databricks skills:\n\n\\`\\`\\`bash\ndatabricks experimental aitools install\n\\`\\`\\`\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(\"\\
|
|
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\n### Databricks Skills\n\nFor enhanced AI assistance with Databricks CLI operations, authentication, data exploration, and app development, install the Databricks skills:\n\n\\`\\`\\`bash\ndatabricks experimental aitools install\n\\`\\`\\`\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\n### Databricks Skills\n\nFor enhanced AI assistance with Databricks CLI operations, authentication, data exploration, and app development, install the Databricks skills:\n\n\\`\\`\\`bash\ndatabricks experimental aitools install\n\\`\\`\\`\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(\"\\nInstall at least one of:\");\n for (const pkg of PACKAGES) {\n console.log(` npm install ${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 .addHelpText(\n \"after\",\n `\nExamples:\n $ appkit setup\n $ appkit setup --write`,\n )\n .action(runSetup);\n"],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Class: PolicyDeniedError
|
|
2
|
+
|
|
3
|
+
Thrown when a policy denies an action.
|
|
4
|
+
|
|
5
|
+
## Extends[](#extends "Direct link to Extends")
|
|
6
|
+
|
|
7
|
+
* `Error`
|
|
8
|
+
|
|
9
|
+
## Constructors[](#constructors "Direct link to Constructors")
|
|
10
|
+
|
|
11
|
+
### Constructor[](#constructor "Direct link to Constructor")
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
new PolicyDeniedError(action: FileAction, volumeKey: string): PolicyDeniedError;
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
#### Parameters[](#parameters "Direct link to Parameters")
|
|
19
|
+
|
|
20
|
+
| Parameter | Type |
|
|
21
|
+
| ----------- | --------------------------------------------------------------- |
|
|
22
|
+
| `action` | [`FileAction`](./docs/api/appkit/TypeAlias.FileAction.md) |
|
|
23
|
+
| `volumeKey` | `string` |
|
|
24
|
+
|
|
25
|
+
#### Returns[](#returns "Direct link to Returns")
|
|
26
|
+
|
|
27
|
+
`PolicyDeniedError`
|
|
28
|
+
|
|
29
|
+
#### Overrides[](#overrides "Direct link to Overrides")
|
|
30
|
+
|
|
31
|
+
```ts
|
|
32
|
+
Error.constructor
|
|
33
|
+
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Properties[](#properties "Direct link to Properties")
|
|
37
|
+
|
|
38
|
+
### action[](#action "Direct link to action")
|
|
39
|
+
|
|
40
|
+
```ts
|
|
41
|
+
readonly action: FileAction;
|
|
42
|
+
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
***
|
|
46
|
+
|
|
47
|
+
### volumeKey[](#volumekey "Direct link to volumeKey")
|
|
48
|
+
|
|
49
|
+
```ts
|
|
50
|
+
readonly volumeKey: string;
|
|
51
|
+
|
|
52
|
+
```
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Interface: FilePolicyUser
|
|
2
|
+
|
|
3
|
+
Minimal user identity passed to the policy function.
|
|
4
|
+
|
|
5
|
+
## Properties[](#properties "Direct link to Properties")
|
|
6
|
+
|
|
7
|
+
### id[](#id "Direct link to id")
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
id: string;
|
|
11
|
+
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
***
|
|
15
|
+
|
|
16
|
+
### isServicePrincipal?[](#isserviceprincipal "Direct link to isServicePrincipal?")
|
|
17
|
+
|
|
18
|
+
```ts
|
|
19
|
+
optional isServicePrincipal: boolean;
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
`true` when the caller is the service principal (direct SDK call, not `asUser`).
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Interface: FileResource
|
|
2
|
+
|
|
3
|
+
Describes the file or directory being acted upon.
|
|
4
|
+
|
|
5
|
+
## Properties[](#properties "Direct link to Properties")
|
|
6
|
+
|
|
7
|
+
### path[](#path "Direct link to path")
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
path: string;
|
|
11
|
+
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Relative path within the volume.
|
|
15
|
+
|
|
16
|
+
***
|
|
17
|
+
|
|
18
|
+
### size?[](#size "Direct link to size?")
|
|
19
|
+
|
|
20
|
+
```ts
|
|
21
|
+
optional size: number;
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Content length in bytes — only present for uploads.
|
|
26
|
+
|
|
27
|
+
***
|
|
28
|
+
|
|
29
|
+
### volume[](#volume "Direct link to volume")
|
|
30
|
+
|
|
31
|
+
```ts
|
|
32
|
+
volume: string;
|
|
33
|
+
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
The volume key (e.g. `"uploads"`).
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Type Alias: FileAction
|
|
2
|
+
|
|
3
|
+
```ts
|
|
4
|
+
type FileAction =
|
|
5
|
+
| "list"
|
|
6
|
+
| "read"
|
|
7
|
+
| "download"
|
|
8
|
+
| "raw"
|
|
9
|
+
| "exists"
|
|
10
|
+
| "metadata"
|
|
11
|
+
| "preview"
|
|
12
|
+
| "upload"
|
|
13
|
+
| "mkdir"
|
|
14
|
+
| "delete";
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Every action the files plugin can perform.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Type Alias: FilePolicy()
|
|
2
|
+
|
|
3
|
+
```ts
|
|
4
|
+
type FilePolicy = (action: FileAction, resource: FileResource, user: FilePolicyUser) => boolean | Promise<boolean>;
|
|
5
|
+
|
|
6
|
+
```
|
|
7
|
+
|
|
8
|
+
A policy function that decides whether `user` may perform `action` on `resource`. Return `true` to allow, `false` to deny.
|
|
9
|
+
|
|
10
|
+
## Parameters[](#parameters "Direct link to Parameters")
|
|
11
|
+
|
|
12
|
+
| Parameter | Type |
|
|
13
|
+
| ---------- | ----------------------------------------------------------------------- |
|
|
14
|
+
| `action` | [`FileAction`](./docs/api/appkit/TypeAlias.FileAction.md) |
|
|
15
|
+
| `resource` | [`FileResource`](./docs/api/appkit/Interface.FileResource.md) |
|
|
16
|
+
| `user` | [`FilePolicyUser`](./docs/api/appkit/Interface.FilePolicyUser.md) |
|
|
17
|
+
|
|
18
|
+
## Returns[](#returns "Direct link to Returns")
|
|
19
|
+
|
|
20
|
+
`boolean` | `Promise`<`boolean`>
|
|
@@ -1,15 +1,19 @@
|
|
|
1
1
|
# Type Alias: ServingFactory
|
|
2
2
|
|
|
3
3
|
```ts
|
|
4
|
-
type ServingFactory = keyof ServingEndpointRegistry extends never ? (alias?: string) => ServingEndpointHandle : <K>(alias: K) => ServingEndpointHandle<ServingEndpointRegistry[K]["request"], ServingEndpointRegistry[K]["response"]
|
|
4
|
+
type ServingFactory = keyof ServingEndpointRegistry extends never ? (alias?: string) => ServingEndpointHandle : true extends IsUnion<keyof ServingEndpointRegistry> ? <K>(alias: K) => ServingEndpointHandle<ServingEndpointRegistry[K]["request"], ServingEndpointRegistry[K]["response"]> : {
|
|
5
|
+
<K> (alias: K): ServingEndpointHandle<ServingEndpointRegistry[K]["request"], ServingEndpointRegistry[K]["response"]>;
|
|
6
|
+
(): ServingEndpointHandle<never, never>;
|
|
7
|
+
};
|
|
5
8
|
|
|
6
9
|
```
|
|
7
10
|
|
|
8
11
|
Factory function returned by `AppKit.serving`.
|
|
9
12
|
|
|
10
|
-
|
|
13
|
+
Adapts based on the `ServingEndpointRegistry` state:
|
|
11
14
|
|
|
12
|
-
* **
|
|
13
|
-
* **
|
|
15
|
+
* **Empty (default):** `(alias?: string) => ServingEndpointHandle` — any string, untyped.
|
|
16
|
+
* **Single key:** alias optional — `serving()` returns the typed handle for the only endpoint.
|
|
17
|
+
* **Multiple keys:** alias required — must specify which endpoint.
|
|
14
18
|
|
|
15
|
-
Run `
|
|
19
|
+
Run `npx appkit generate-types` or start the dev server to generate the registry.
|
package/docs/api/appkit.md
CHANGED
|
@@ -20,6 +20,7 @@ Core library for building Databricks applications with type-safe SQL queries, pl
|
|
|
20
20
|
| [ExecutionError](./docs/api/appkit/Class.ExecutionError.md) | Error thrown when an operation execution fails. Use for statement failures, canceled operations, or unexpected states. |
|
|
21
21
|
| [InitializationError](./docs/api/appkit/Class.InitializationError.md) | Error thrown when a service or component is not properly initialized. Use when accessing services before they are ready. |
|
|
22
22
|
| [Plugin](./docs/api/appkit/Class.Plugin.md) | Base abstract class for creating AppKit plugins. |
|
|
23
|
+
| [PolicyDeniedError](./docs/api/appkit/Class.PolicyDeniedError.md) | Thrown when a policy denies an action. |
|
|
23
24
|
| [ResourceRegistry](./docs/api/appkit/Class.ResourceRegistry.md) | Central registry for tracking plugin resource requirements. Deduplication uses type + resourceKey (machine-stable); alias is for display only. |
|
|
24
25
|
| [ServerError](./docs/api/appkit/Class.ServerError.md) | Error thrown when server lifecycle operations fail. Use for server start/stop issues, configuration conflicts, etc. |
|
|
25
26
|
| [TunnelError](./docs/api/appkit/Class.TunnelError.md) | Error thrown when remote tunnel operations fail. Use for tunnel connection issues, message parsing failures, etc. |
|
|
@@ -33,6 +34,8 @@ Core library for building Databricks applications with type-safe SQL queries, pl
|
|
|
33
34
|
| [CacheConfig](./docs/api/appkit/Interface.CacheConfig.md) | Configuration for the CacheInterceptor. Controls TTL, size limits, storage backend, and probabilistic cleanup. |
|
|
34
35
|
| [DatabaseCredential](./docs/api/appkit/Interface.DatabaseCredential.md) | Database credentials with OAuth token for Postgres connection |
|
|
35
36
|
| [EndpointConfig](./docs/api/appkit/Interface.EndpointConfig.md) | - |
|
|
37
|
+
| [FilePolicyUser](./docs/api/appkit/Interface.FilePolicyUser.md) | Minimal user identity passed to the policy function. |
|
|
38
|
+
| [FileResource](./docs/api/appkit/Interface.FileResource.md) | Describes the file or directory being acted upon. |
|
|
36
39
|
| [GenerateDatabaseCredentialRequest](./docs/api/appkit/Interface.GenerateDatabaseCredentialRequest.md) | Request parameters for generating database OAuth credentials |
|
|
37
40
|
| [ITelemetry](./docs/api/appkit/Interface.ITelemetry.md) | Plugin-facing interface for OpenTelemetry instrumentation. Provides a thin abstraction over OpenTelemetry APIs for plugins. |
|
|
38
41
|
| [LakebasePoolConfig](./docs/api/appkit/Interface.LakebasePoolConfig.md) | Configuration for creating a Lakebase connection pool |
|
|
@@ -50,21 +53,25 @@ Core library for building Databricks applications with type-safe SQL queries, pl
|
|
|
50
53
|
|
|
51
54
|
## Type Aliases[](#type-aliases "Direct link to Type Aliases")
|
|
52
55
|
|
|
53
|
-
| Type Alias | Description
|
|
54
|
-
| ----------------------------------------------------------------------------- |
|
|
55
|
-
| [ConfigSchema](./docs/api/appkit/TypeAlias.ConfigSchema.md) | Configuration schema definition for plugin config. Re-exported from the standard JSON Schema Draft 7 types.
|
|
56
|
-
| [ExecutionResult](./docs/api/appkit/TypeAlias.ExecutionResult.md) | Discriminated union for plugin execution results.
|
|
57
|
-
| [
|
|
58
|
-
| [
|
|
59
|
-
| [
|
|
60
|
-
| [
|
|
61
|
-
| [
|
|
56
|
+
| Type Alias | Description |
|
|
57
|
+
| ----------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
|
|
58
|
+
| [ConfigSchema](./docs/api/appkit/TypeAlias.ConfigSchema.md) | Configuration schema definition for plugin config. Re-exported from the standard JSON Schema Draft 7 types. |
|
|
59
|
+
| [ExecutionResult](./docs/api/appkit/TypeAlias.ExecutionResult.md) | Discriminated union for plugin execution results. |
|
|
60
|
+
| [FileAction](./docs/api/appkit/TypeAlias.FileAction.md) | Every action the files plugin can perform. |
|
|
61
|
+
| [FilePolicy](./docs/api/appkit/TypeAlias.FilePolicy.md) | A policy function that decides whether `user` may perform `action` on `resource`. Return `true` to allow, `false` to deny. |
|
|
62
|
+
| [IAppRouter](./docs/api/appkit/TypeAlias.IAppRouter.md) | Express router type for plugin route registration |
|
|
63
|
+
| [PluginData](./docs/api/appkit/TypeAlias.PluginData.md) | Tuple of plugin class, config, and name. Created by `toPlugin()` and passed to `createApp()`. |
|
|
64
|
+
| [ResourcePermission](./docs/api/appkit/TypeAlias.ResourcePermission.md) | Union of all possible permission levels across all resource types. |
|
|
65
|
+
| [ServingFactory](./docs/api/appkit/TypeAlias.ServingFactory.md) | Factory function returned by `AppKit.serving`. |
|
|
66
|
+
| [ToPlugin](./docs/api/appkit/TypeAlias.ToPlugin.md) | Factory function type returned by `toPlugin()`. Accepts optional config and returns a PluginData tuple. |
|
|
62
67
|
|
|
63
68
|
## Variables[](#variables "Direct link to Variables")
|
|
64
69
|
|
|
65
|
-
| Variable
|
|
66
|
-
|
|
|
67
|
-
| [
|
|
70
|
+
| Variable | Description |
|
|
71
|
+
| ------------------------------------------------------------------- | ---------------------------- |
|
|
72
|
+
| [READ\_ACTIONS](./docs/api/appkit/Variable.READ_ACTIONS.md) | Actions that only read data. |
|
|
73
|
+
| [sql](./docs/api/appkit/Variable.sql.md) | SQL helper namespace |
|
|
74
|
+
| [WRITE\_ACTIONS](./docs/api/appkit/Variable.WRITE_ACTIONS.md) | Actions that mutate data. |
|
|
68
75
|
|
|
69
76
|
## Functions[](#functions "Direct link to Functions")
|
|
70
77
|
|
|
@@ -4,7 +4,9 @@ AppKit can automatically generate TypeScript types for your SQL queries, providi
|
|
|
4
4
|
|
|
5
5
|
## Goal[](#goal "Direct link to Goal")
|
|
6
6
|
|
|
7
|
-
Generate
|
|
7
|
+
Generate type-safe TypeScript declarations for query keys, parameters, and result rows.
|
|
8
|
+
|
|
9
|
+
All generated files live in `shared/appkit-types/`, one per plugin (e.g. `analytics.d.ts`). They use [`declare module`](https://www.typescriptlang.org/docs/handbook/declaration-merging.html#module-augmentation) to augment existing interfaces, so the types apply globally — you never need to import them. TypeScript auto-discovers them through `"include": ["shared/appkit-types"]` in your tsconfig.
|
|
8
10
|
|
|
9
11
|
## Vite plugin: `appKitTypesPlugin`[](#vite-plugin-appkittypesplugin "Direct link to vite-plugin-appkittypesplugin")
|
|
10
12
|
|
|
@@ -12,7 +14,7 @@ The recommended approach is to use the Vite plugin, which watches your SQL files
|
|
|
12
14
|
|
|
13
15
|
### Configuration[](#configuration "Direct link to Configuration")
|
|
14
16
|
|
|
15
|
-
* `outFile?: string` - Output file path (default: `
|
|
17
|
+
* `outFile?: string` - Output file path (default: `shared/appkit-types/analytics.d.ts`)
|
|
16
18
|
* `watchFolders?: string[]` - Folders to watch for SQL files (default: `["../config/queries"]`)
|
|
17
19
|
|
|
18
20
|
### Example[](#example "Direct link to Example")
|
|
@@ -27,7 +29,6 @@ export default defineConfig({
|
|
|
27
29
|
plugins: [
|
|
28
30
|
react(),
|
|
29
31
|
appKitTypesPlugin({
|
|
30
|
-
outFile: "src/appKitTypes.d.ts",
|
|
31
32
|
watchFolders: ["../config/queries"],
|
|
32
33
|
}),
|
|
33
34
|
],
|
|
@@ -54,14 +55,14 @@ npx @databricks/appkit generate-types [rootDir] [outFile] [warehouseId]
|
|
|
54
55
|
* Generate types using warehouse ID from environment
|
|
55
56
|
|
|
56
57
|
```bash
|
|
57
|
-
npx @databricks/appkit generate-types .
|
|
58
|
+
npx @databricks/appkit generate-types . shared/appkit-types/analytics.d.ts
|
|
58
59
|
|
|
59
60
|
```
|
|
60
61
|
|
|
61
62
|
* Generate types using warehouse ID explicitly
|
|
62
63
|
|
|
63
64
|
```bash
|
|
64
|
-
npx @databricks/appkit generate-types .
|
|
65
|
+
npx @databricks/appkit generate-types . shared/appkit-types/analytics.d.ts abc123...
|
|
65
66
|
|
|
66
67
|
```
|
|
67
68
|
|
package/docs/faq.md
CHANGED
|
@@ -6,14 +6,14 @@
|
|
|
6
6
|
|
|
7
7
|
AppKit provides built-in integrations with the following Databricks services via its [plugin system](./docs/plugins.md):
|
|
8
8
|
|
|
9
|
-
| Plugin
|
|
10
|
-
|
|
|
11
|
-
| [Analytics](./docs/plugins/analytics.md)
|
|
12
|
-
| [Lakebase](./docs/plugins/lakebase.md)
|
|
13
|
-
| [Genie](./docs/plugins/genie.md)
|
|
14
|
-
| [Files](./docs/plugins/files.md)
|
|
15
|
-
| [Serving](./docs/plugins/serving.md)
|
|
16
|
-
| [Server](./docs/plugins/server.md)
|
|
9
|
+
| Plugin | Databricks Service | What It Does |
|
|
10
|
+
| ------------------------------------------------------ | --------------------------------- | --------------------------------------------------------------------------------------- |
|
|
11
|
+
| [Analytics](./docs/plugins/analytics.md) | SQL Warehouses | Execute parameterized SQL queries with built-in caching, retry, and Arrow support |
|
|
12
|
+
| [Lakebase](./docs/plugins/lakebase.md) | Lakebase Autoscaling (PostgreSQL) | Relational database access via standard pg.Pool with automatic OAuth token refresh |
|
|
13
|
+
| [Genie](./docs/plugins/genie.md) | AI/BI Genie Spaces | Natural language data queries with conversation management and streaming |
|
|
14
|
+
| [Files](./docs/plugins/files.md) | Unity Catalog Volumes | Multi-volume file operations (list, read, upload, download, delete, preview) |
|
|
15
|
+
| [Model Serving](./docs/plugins/model-serving.md) | Model Serving | Authenticated proxy to Model Serving endpoints with invoke and streaming support |
|
|
16
|
+
| [Server](./docs/plugins/server.md) | N/A | Express HTTP server with static file serving, Vite dev mode, and plugin route injection |
|
|
17
17
|
|
|
18
18
|
Stay tuned for new plugins as we constantly expand integrations!
|
|
19
19
|
|
|
@@ -139,7 +139,7 @@ function SpendTable() {
|
|
|
139
139
|
Augment the `QueryRegistry` interface to get full type inference on parameters and results:
|
|
140
140
|
|
|
141
141
|
```ts
|
|
142
|
-
//
|
|
142
|
+
// shared/appkit-types/analytics.d.ts
|
|
143
143
|
declare module "@databricks/appkit-ui/react" {
|
|
144
144
|
interface QueryRegistry {
|
|
145
145
|
spend_summary: {
|
|
@@ -3,8 +3,12 @@
|
|
|
3
3
|
If you need custom API routes or background logic, implement an AppKit plugin. The fastest way is to use the CLI:
|
|
4
4
|
|
|
5
5
|
```bash
|
|
6
|
+
# Interactive
|
|
6
7
|
npx @databricks/appkit plugin create
|
|
7
8
|
|
|
9
|
+
# Non-interactive
|
|
10
|
+
npx @databricks/appkit plugin create --placement in-repo --path plugins/my-plugin --name my-plugin --description "My plugin" --force
|
|
11
|
+
|
|
8
12
|
```
|
|
9
13
|
|
|
10
14
|
For a deeper understanding of the plugin structure, read on.
|
|
@@ -38,7 +38,6 @@ Exported from `@databricks/appkit`:
|
|
|
38
38
|
* `getWorkspaceClient()`: Returns the appropriate WorkspaceClient for current context
|
|
39
39
|
* `getWarehouseId()`: `Promise<string>` (from `DATABRICKS_WAREHOUSE_ID` or auto-selected in dev)
|
|
40
40
|
* `getWorkspaceId()`: `Promise<string>` (from `DATABRICKS_WORKSPACE_ID` or fetched)
|
|
41
|
-
* `isInUserContext()`: Returns `true` if currently executing in user context
|
|
42
41
|
|
|
43
42
|
## Development mode behavior[](#development-mode-behavior "Direct link to Development mode behavior")
|
|
44
43
|
|