@databricks/appkit 0.11.0 → 0.11.1
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/dist/appkit/package.js +1 -1
- package/dist/cli/commands/plugin/sync/sync.js +13 -10
- package/dist/cli/commands/plugin/sync/sync.js.map +1 -1
- package/dist/plugins/lakebase/manifest.json +1 -0
- package/dist/registry/types.d.ts +4 -0
- package/dist/registry/types.js.map +1 -1
- package/dist/schemas/plugin-manifest.schema.json +5 -0
- package/dist/shared/src/plugin.d.ts +1 -0
- package/dist/shared/src/plugin.d.ts.map +1 -1
- package/dist/utils/vite-config-merge.js +4 -1
- package/dist/utils/vite-config-merge.js.map +1 -1
- package/docs/docs/api/appkit/Class.AppKitError/index.html +2 -2
- package/docs/docs/api/appkit/Class.AuthenticationError/index.html +2 -2
- package/docs/docs/api/appkit/Class.ConfigurationError/index.html +2 -2
- package/docs/docs/api/appkit/Class.ConnectionError/index.html +2 -2
- package/docs/docs/api/appkit/Class.ExecutionError/index.html +2 -2
- package/docs/docs/api/appkit/Class.InitializationError/index.html +2 -2
- package/docs/docs/api/appkit/Class.Plugin/index.html +2 -2
- package/docs/docs/api/appkit/Class.ResourceRegistry/index.html +2 -2
- package/docs/docs/api/appkit/Class.ServerError/index.html +2 -2
- package/docs/docs/api/appkit/Class.TunnelError/index.html +2 -2
- package/docs/docs/api/appkit/Class.ValidationError/index.html +2 -2
- package/docs/docs/api/appkit/Enumeration.RequestedClaimsPermissionSet/index.html +2 -2
- package/docs/docs/api/appkit/Enumeration.ResourceType/index.html +2 -2
- package/docs/docs/api/appkit/Function.appKitTypesPlugin/index.html +2 -2
- package/docs/docs/api/appkit/Function.createApp/index.html +2 -2
- package/docs/docs/api/appkit/Function.createLakebasePool/index.html +2 -2
- package/docs/docs/api/appkit/Function.generateDatabaseCredential/index.html +2 -2
- package/docs/docs/api/appkit/Function.getExecutionContext/index.html +2 -2
- package/docs/docs/api/appkit/Function.getLakebaseOrmConfig/index.html +2 -2
- package/docs/docs/api/appkit/Function.getLakebasePgConfig/index.html +2 -2
- package/docs/docs/api/appkit/Function.getPluginManifest/index.html +2 -2
- package/docs/docs/api/appkit/Function.getResourceRequirements/index.html +2 -2
- package/docs/docs/api/appkit/Function.getUsernameWithApiLookup/index.html +2 -2
- package/docs/docs/api/appkit/Function.getWorkspaceClient/index.html +2 -2
- package/docs/docs/api/appkit/Function.isSQLTypeMarker/index.html +2 -2
- package/docs/docs/api/appkit/Interface.BasePluginConfig/index.html +2 -2
- package/docs/docs/api/appkit/Interface.CacheConfig/index.html +2 -2
- package/docs/docs/api/appkit/Interface.DatabaseCredential/index.html +2 -2
- package/docs/docs/api/appkit/Interface.GenerateDatabaseCredentialRequest/index.html +2 -2
- package/docs/docs/api/appkit/Interface.ITelemetry/index.html +2 -2
- package/docs/docs/api/appkit/Interface.LakebasePoolConfig/index.html +2 -2
- package/docs/docs/api/appkit/Interface.PluginManifest/index.html +7 -3
- package/docs/docs/api/appkit/Interface.PluginManifest.md +11 -0
- package/docs/docs/api/appkit/Interface.RequestedClaims/index.html +2 -2
- package/docs/docs/api/appkit/Interface.RequestedResource/index.html +2 -2
- package/docs/docs/api/appkit/Interface.ResourceEntry/index.html +2 -2
- package/docs/docs/api/appkit/Interface.ResourceFieldEntry/index.html +2 -2
- package/docs/docs/api/appkit/Interface.ResourceRequirement/index.html +2 -2
- package/docs/docs/api/appkit/Interface.StreamExecutionSettings/index.html +2 -2
- package/docs/docs/api/appkit/Interface.TelemetryConfig/index.html +2 -2
- package/docs/docs/api/appkit/Interface.ValidationResult/index.html +2 -2
- package/docs/docs/api/appkit/TypeAlias.ConfigSchema/index.html +2 -2
- package/docs/docs/api/appkit/TypeAlias.IAppRouter/index.html +2 -2
- package/docs/docs/api/appkit/TypeAlias.ResourcePermission/index.html +2 -2
- package/docs/docs/api/appkit/TypeAlias.ToPlugin/index.html +2 -2
- package/docs/docs/api/appkit/Variable.sql/index.html +2 -2
- package/docs/docs/api/appkit/index.html +2 -2
- package/docs/docs/api/appkit-ui/data/AreaChart/index.html +2 -2
- package/docs/docs/api/appkit-ui/data/BarChart/index.html +2 -2
- package/docs/docs/api/appkit-ui/data/DataTable/index.html +2 -2
- package/docs/docs/api/appkit-ui/data/DonutChart/index.html +2 -2
- package/docs/docs/api/appkit-ui/data/HeatmapChart/index.html +2 -2
- package/docs/docs/api/appkit-ui/data/LineChart/index.html +2 -2
- package/docs/docs/api/appkit-ui/data/PieChart/index.html +2 -2
- package/docs/docs/api/appkit-ui/data/RadarChart/index.html +2 -2
- package/docs/docs/api/appkit-ui/data/ScatterChart/index.html +2 -2
- package/docs/docs/api/appkit-ui/index.html +2 -2
- package/docs/docs/api/appkit-ui/styling/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/Accordion/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/Alert/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/AlertDialog/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/AspectRatio/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/Avatar/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/Badge/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/Breadcrumb/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/Button/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/ButtonGroup/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/Calendar/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/Card/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/Carousel/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/ChartContainer/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/Checkbox/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/Collapsible/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/Command/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/ContextMenu/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/Dialog/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/Drawer/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/DropdownMenu/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/Empty/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/Field/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/FormControl/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/HoverCard/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/Input/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/InputGroup/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/InputOTP/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/Item/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/Kbd/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/Label/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/Menubar/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/NavigationMenu/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/Pagination/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/Popover/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/Progress/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/RadioGroup/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/ResizableHandle/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/ScrollArea/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/Select/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/Separator/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/Sheet/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/Sidebar/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/Skeleton/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/Slider/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/Spinner/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/Switch/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/Table/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/Tabs/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/Textarea/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/Toaster/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/Toggle/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/ToggleGroup/index.html +2 -2
- package/docs/docs/api/appkit-ui/ui/Tooltip/index.html +2 -2
- package/docs/docs/api/index.html +2 -2
- package/docs/docs/app-management/index.html +2 -2
- package/docs/docs/architecture/index.html +2 -2
- package/docs/docs/category/development/index.html +2 -2
- package/docs/docs/configuration/index.html +2 -2
- package/docs/docs/core-principles/index.html +2 -2
- package/docs/docs/development/ai-assisted-development/index.html +2 -2
- package/docs/docs/development/index.html +2 -2
- package/docs/docs/development/llm-guide/index.html +2 -2
- package/docs/docs/development/local-development/index.html +2 -2
- package/docs/docs/development/project-setup/index.html +2 -2
- package/docs/docs/development/remote-bridge/index.html +2 -2
- package/docs/docs/development/type-generation/index.html +2 -2
- package/docs/docs/index.html +2 -2
- package/docs/docs/plugins/analytics/index.html +2 -2
- package/docs/docs/plugins/caching/index.html +2 -2
- package/docs/docs/plugins/custom-plugins/index.html +2 -2
- package/docs/docs/plugins/execution-context/index.html +2 -2
- package/docs/docs/plugins/index.html +2 -2
- package/docs/docs/plugins/lakebase/index.html +2 -2
- package/docs/docs/plugins/plugin-management/index.html +2 -2
- package/docs/docs/plugins/server/index.html +2 -2
- package/package.json +1 -1
package/dist/appkit/package.js
CHANGED
|
@@ -181,7 +181,7 @@ function discoverLocalPlugins(relativeImports, serverFileDir, cwd) {
|
|
|
181
181
|
try {
|
|
182
182
|
const content = fs.readFileSync(manifestPath, "utf-8");
|
|
183
183
|
const manifest = validateManifestWithSchema(JSON.parse(content), manifestPath);
|
|
184
|
-
if (!manifest) continue;
|
|
184
|
+
if (!manifest || manifest.hidden) continue;
|
|
185
185
|
const relativePath = path.relative(cwd, path.dirname(manifestPath));
|
|
186
186
|
plugins[manifest.name] = {
|
|
187
187
|
name: manifest.name,
|
|
@@ -234,14 +234,17 @@ function scanForPlugins(cwd, packages) {
|
|
|
234
234
|
const packagePath = path.join(cwd, "node_modules", packageName);
|
|
235
235
|
if (!fs.existsSync(packagePath)) continue;
|
|
236
236
|
const manifests = discoverPluginManifests(packagePath);
|
|
237
|
-
for (const manifest of manifests)
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
237
|
+
for (const manifest of manifests) {
|
|
238
|
+
if (manifest.hidden) continue;
|
|
239
|
+
plugins[manifest.name] = {
|
|
240
|
+
name: manifest.name,
|
|
241
|
+
displayName: manifest.displayName,
|
|
242
|
+
description: manifest.description,
|
|
243
|
+
package: packageName,
|
|
244
|
+
resources: manifest.resources,
|
|
245
|
+
...manifest.onSetupMessage && { onSetupMessage: manifest.onSetupMessage }
|
|
246
|
+
};
|
|
247
|
+
}
|
|
245
248
|
}
|
|
246
249
|
return plugins;
|
|
247
250
|
}
|
|
@@ -265,7 +268,7 @@ function scanPluginsDir(dir, packageName) {
|
|
|
265
268
|
try {
|
|
266
269
|
const content = fs.readFileSync(manifestPath, "utf-8");
|
|
267
270
|
const manifest = validateManifestWithSchema(JSON.parse(content), manifestPath);
|
|
268
|
-
if (manifest) plugins[manifest.name] = {
|
|
271
|
+
if (manifest && !manifest.hidden) plugins[manifest.name] = {
|
|
269
272
|
name: manifest.name,
|
|
270
273
|
displayName: manifest.displayName,
|
|
271
274
|
description: manifest.description,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sync.js","names":[],"sources":["../../../../../src/cli/commands/plugin/sync/sync.ts"],"sourcesContent":["import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { Lang, parse, type SgNode } from \"@ast-grep/napi\";\nimport { Command } from \"commander\";\nimport type {\n PluginManifest,\n TemplatePlugin,\n TemplatePluginsManifest,\n} from \"../manifest-types\";\nimport {\n formatValidationErrors,\n validateManifest,\n} from \"../validate/validate-manifest\";\n\n/**\n * Checks whether a resolved file path is within a given directory boundary.\n * Uses path.resolve + startsWith to prevent directory traversal.\n *\n * @param filePath - The path to check (will be resolved to absolute)\n * @param boundary - The directory that must contain filePath\n * @returns true if filePath is inside boundary (or equal to it)\n */\nfunction isWithinDirectory(filePath: string, boundary: string): boolean {\n const resolvedPath = path.resolve(filePath);\n const resolvedBoundary = path.resolve(boundary);\n // Append separator to avoid prefix false-positives (e.g. /foo-bar matching /foo)\n return (\n resolvedPath === resolvedBoundary ||\n resolvedPath.startsWith(`${resolvedBoundary}${path.sep}`)\n );\n}\n\n/**\n * Validates a parsed JSON object against the plugin-manifest JSON schema.\n * Returns the manifest if valid, or null and logs schema errors.\n */\nfunction validateManifestWithSchema(\n obj: unknown,\n sourcePath: string,\n): PluginManifest | null {\n const result = validateManifest(obj);\n if (result.valid && result.manifest) return result.manifest;\n if (result.errors?.length) {\n console.warn(\n `Warning: Manifest at ${sourcePath} failed schema validation:\\n${formatValidationErrors(result.errors, obj)}`,\n );\n }\n return null;\n}\n\n/**\n * Known packages that may contain AppKit plugins.\n * Always scanned for manifests, even if not imported in the server file.\n */\nconst KNOWN_PLUGIN_PACKAGES = [\"@databricks/appkit\"];\n\n/**\n * Candidate paths for the server entry file, relative to cwd.\n * Checked in order; the first that exists is used.\n */\nconst SERVER_FILE_CANDIDATES = [\"server/server.ts\", \"server/index.ts\"];\n\n/**\n * Find the server entry file by checking candidate paths in order.\n *\n * @param cwd - Current working directory\n * @returns Absolute path to the server file, or null if none found\n */\nfunction findServerFile(cwd: string): string | null {\n for (const candidate of SERVER_FILE_CANDIDATES) {\n const fullPath = path.join(cwd, candidate);\n if (fs.existsSync(fullPath)) {\n return fullPath;\n }\n }\n return null;\n}\n\n/**\n * Represents a single named import extracted from the server file.\n */\ninterface ParsedImport {\n /** The imported name (or local alias if renamed) */\n name: string;\n /** The original exported name (differs from name when using `import { foo as bar }`) */\n originalName: string;\n /** The module specifier (package name or relative path) */\n source: string;\n}\n\n/**\n * Extract all named imports from the AST root using structural node traversal.\n * Handles single/double quotes, multiline imports, and aliased imports.\n *\n * @param root - AST root node\n * @returns Array of parsed imports with name, original name, and source\n */\nfunction parseImports(root: SgNode): ParsedImport[] {\n const imports: ParsedImport[] = [];\n\n // Find all import_statement nodes in the AST\n const importStatements = root.findAll({\n rule: { kind: \"import_statement\" },\n });\n\n for (const stmt of importStatements) {\n // Extract the module specifier (the string node, e.g. '@databricks/appkit')\n const sourceNode = stmt.find({ rule: { kind: \"string\" } });\n if (!sourceNode) continue;\n\n // Strip surrounding quotes from the string node text\n const source = sourceNode.text().replace(/^['\"]|['\"]$/g, \"\");\n\n // Find named_imports block: { createApp, analytics, server }\n const namedImports = stmt.find({ rule: { kind: \"named_imports\" } });\n if (!namedImports) continue;\n\n // Extract each import_specifier\n const specifiers = namedImports.findAll({\n rule: { kind: \"import_specifier\" },\n });\n\n for (const specifier of specifiers) {\n const children = specifier.children();\n if (children.length >= 3) {\n // Aliased import: `foo as bar` — children are [name, \"as\", alias]\n const originalName = children[0].text();\n const localName = children[children.length - 1].text();\n imports.push({ name: localName, originalName, source });\n } else {\n // Simple import: `foo`\n const name = specifier.text();\n imports.push({ name, originalName: name, source });\n }\n }\n }\n\n return imports;\n}\n\n/**\n * Extract local names of plugins actually used in the `plugins: [...]` array\n * passed to `createApp()`. Uses structural AST traversal to find `pair` nodes\n * with key \"plugins\" and array values containing call expressions.\n *\n * @param root - AST root node\n * @returns Set of local variable names used as plugin calls in the plugins array\n */\nfunction parsePluginUsages(root: SgNode): Set<string> {\n const usedNames = new Set<string>();\n\n // Find all property pairs in the AST\n const pairs = root.findAll({ rule: { kind: \"pair\" } });\n\n for (const pair of pairs) {\n // Check if the property key is \"plugins\"\n const key = pair.find({ rule: { kind: \"property_identifier\" } });\n if (!key || key.text() !== \"plugins\") continue;\n\n // Find the array value\n const arrayNode = pair.find({ rule: { kind: \"array\" } });\n if (!arrayNode) continue;\n\n // Iterate direct children of the array to find call expressions\n for (const child of arrayNode.children()) {\n if (child.kind() === \"call_expression\") {\n // The callee is the first child (the identifier being called)\n const callee = child.children()[0];\n if (callee?.kind() === \"identifier\") {\n usedNames.add(callee.text());\n }\n }\n }\n }\n\n return usedNames;\n}\n\n/**\n * File extensions to try when resolving a relative import to a file path.\n */\nconst RESOLVE_EXTENSIONS = [\".ts\", \".tsx\", \".js\", \".jsx\"];\n\n/**\n * Resolve a relative import source to the plugin directory containing a manifest.json.\n * Follows the convention that plugins live in their own directory with a manifest.json.\n *\n * Resolution strategy:\n * 1. If the import path is a directory, look for manifest.json directly in it\n * 2. If the import path + extension is a file, look for manifest.json in its parent directory\n * 3. If the import path is a directory with an index file, look for manifest.json in that directory\n *\n * @param importSource - The relative import specifier (e.g. \"./plugins/my-plugin\")\n * @param serverFileDir - Absolute path to the directory containing the server file\n * @returns Absolute path to manifest.json, or null if not found\n */\nfunction resolveLocalManifest(\n importSource: string,\n serverFileDir: string,\n projectRoot?: string,\n): string | null {\n const resolved = path.resolve(serverFileDir, importSource);\n\n // Security: Reject paths that escape the project root\n const boundary = projectRoot || serverFileDir;\n if (!isWithinDirectory(resolved, boundary)) {\n console.warn(\n `Warning: Skipping import \"${importSource}\" — resolves outside the project directory`,\n );\n return null;\n }\n\n // Case 1: Import path is a directory with manifest.json\n // e.g. ./plugins/my-plugin → ./plugins/my-plugin/manifest.json\n if (fs.existsSync(resolved) && fs.statSync(resolved).isDirectory()) {\n const manifestPath = path.join(resolved, \"manifest.json\");\n if (fs.existsSync(manifestPath)) return manifestPath;\n }\n\n // Case 2: Import path + extension resolves to a file\n // e.g. ./plugins/my-plugin → ./plugins/my-plugin.ts\n // Look for manifest.json in the same directory\n for (const ext of RESOLVE_EXTENSIONS) {\n const filePath = `${resolved}${ext}`;\n if (fs.existsSync(filePath) && fs.statSync(filePath).isFile()) {\n const dir = path.dirname(filePath);\n const manifestPath = path.join(dir, \"manifest.json\");\n if (fs.existsSync(manifestPath)) return manifestPath;\n break;\n }\n }\n\n // Case 3: Import path is a directory with an index file\n // e.g. ./plugins/my-plugin → ./plugins/my-plugin/index.ts\n for (const ext of RESOLVE_EXTENSIONS) {\n const indexPath = path.join(resolved, `index${ext}`);\n if (fs.existsSync(indexPath)) {\n const manifestPath = path.join(resolved, \"manifest.json\");\n if (fs.existsSync(manifestPath)) return manifestPath;\n break;\n }\n }\n\n return null;\n}\n\n/**\n * Discover plugin manifests from local (relative) imports in the server file.\n * Resolves each relative import to a directory and looks for manifest.json.\n *\n * @param relativeImports - Parsed imports with relative sources (starting with . or /)\n * @param serverFileDir - Absolute path to the directory containing the server file\n * @param cwd - Current working directory (for computing relative paths in output)\n * @returns Map of plugin name to template plugin entry for local plugins\n */\nfunction discoverLocalPlugins(\n relativeImports: ParsedImport[],\n serverFileDir: string,\n cwd: string,\n): TemplatePluginsManifest[\"plugins\"] {\n const plugins: TemplatePluginsManifest[\"plugins\"] = {};\n\n for (const imp of relativeImports) {\n const manifestPath = resolveLocalManifest(imp.source, serverFileDir, cwd);\n if (!manifestPath) continue;\n\n try {\n const content = fs.readFileSync(manifestPath, \"utf-8\");\n const parsed = JSON.parse(content);\n const manifest = validateManifestWithSchema(parsed, manifestPath);\n if (!manifest) continue;\n\n const relativePath = path.relative(cwd, path.dirname(manifestPath));\n\n plugins[manifest.name] = {\n name: manifest.name,\n displayName: manifest.displayName,\n description: manifest.description,\n package: `./${relativePath}`,\n resources: manifest.resources,\n ...(manifest.onSetupMessage && {\n onSetupMessage: manifest.onSetupMessage,\n }),\n };\n } catch (error) {\n console.warn(\n `Warning: Failed to parse manifest at ${manifestPath}:`,\n error instanceof Error ? error.message : error,\n );\n }\n }\n\n return plugins;\n}\n\n/**\n * Discover plugin manifests from a package's dist folder.\n * Looks for manifest.json files in dist/plugins/{plugin-name}/ directories.\n *\n * @param packagePath - Path to the package in node_modules\n * @returns Array of plugin manifests found in the package\n */\nfunction discoverPluginManifests(packagePath: string): PluginManifest[] {\n const pluginsDir = path.join(packagePath, \"dist\", \"plugins\");\n const manifests: PluginManifest[] = [];\n\n if (!fs.existsSync(pluginsDir)) {\n return manifests;\n }\n\n const entries = fs.readdirSync(pluginsDir, { withFileTypes: true });\n for (const entry of entries) {\n if (entry.isDirectory()) {\n const manifestPath = path.join(pluginsDir, entry.name, \"manifest.json\");\n if (fs.existsSync(manifestPath)) {\n try {\n const content = fs.readFileSync(manifestPath, \"utf-8\");\n const parsed = JSON.parse(content);\n const manifest = validateManifestWithSchema(parsed, manifestPath);\n if (manifest) {\n manifests.push(manifest);\n }\n } catch (error) {\n console.warn(\n `Warning: Failed to parse manifest at ${manifestPath}:`,\n error instanceof Error ? error.message : error,\n );\n }\n }\n }\n }\n\n return manifests;\n}\n\n/**\n * Scan node_modules for packages with plugin manifests.\n *\n * @param cwd - Current working directory to search from\n * @param packages - Set of npm package names to scan for plugin manifests\n * @returns Map of plugin name to template plugin entry\n */\nfunction scanForPlugins(\n cwd: string,\n packages: Iterable<string>,\n): TemplatePluginsManifest[\"plugins\"] {\n const plugins: TemplatePluginsManifest[\"plugins\"] = {};\n\n for (const packageName of packages) {\n const packagePath = path.join(cwd, \"node_modules\", packageName);\n if (!fs.existsSync(packagePath)) {\n continue;\n }\n\n const manifests = discoverPluginManifests(packagePath);\n for (const manifest of manifests) {\n // Convert to template plugin format (exclude config schema)\n plugins[manifest.name] = {\n name: manifest.name,\n displayName: manifest.displayName,\n description: manifest.description,\n package: packageName,\n resources: manifest.resources,\n ...(manifest.onSetupMessage && {\n onSetupMessage: manifest.onSetupMessage,\n }),\n };\n }\n }\n\n return plugins;\n}\n\n/**\n * Scan a directory for plugin manifests in direct subdirectories.\n * Each subdirectory is expected to contain a manifest.json file.\n * Used with --plugins-dir to discover plugins from source instead of node_modules.\n *\n * @param dir - Absolute path to the directory containing plugin subdirectories\n * @param packageName - Package name to assign to discovered plugins\n * @returns Map of plugin name to template plugin entry\n */\nfunction scanPluginsDir(\n dir: string,\n packageName: string,\n): TemplatePluginsManifest[\"plugins\"] {\n const plugins: TemplatePluginsManifest[\"plugins\"] = {};\n\n if (!fs.existsSync(dir)) return plugins;\n\n const entries = fs.readdirSync(dir, { withFileTypes: true });\n for (const entry of entries) {\n if (!entry.isDirectory()) continue;\n\n const manifestPath = path.join(dir, entry.name, \"manifest.json\");\n if (!fs.existsSync(manifestPath)) continue;\n\n try {\n const content = fs.readFileSync(manifestPath, \"utf-8\");\n const parsed = JSON.parse(content);\n const manifest = validateManifestWithSchema(parsed, manifestPath);\n if (manifest) {\n plugins[manifest.name] = {\n name: manifest.name,\n displayName: manifest.displayName,\n description: manifest.description,\n package: packageName,\n resources: manifest.resources,\n ...(manifest.onSetupMessage && {\n onSetupMessage: manifest.onSetupMessage,\n }),\n };\n }\n } catch (error) {\n console.warn(\n `Warning: Failed to parse manifest at ${manifestPath}:`,\n error instanceof Error ? error.message : error,\n );\n }\n }\n\n return plugins;\n}\n\n/**\n * Write (or preview) the template plugins manifest to disk.\n */\nfunction writeManifest(\n outputPath: string,\n { plugins }: { plugins: TemplatePluginsManifest[\"plugins\"] },\n options: { write?: boolean; silent?: boolean },\n) {\n const templateManifest: TemplatePluginsManifest = {\n $schema:\n \"https://databricks.github.io/appkit/schemas/template-plugins.schema.json\",\n version: \"1.0\",\n plugins,\n };\n\n if (options.write) {\n fs.writeFileSync(\n outputPath,\n `${JSON.stringify(templateManifest, null, 2)}\\n`,\n );\n if (!options.silent) {\n console.log(`\\n✓ Wrote ${outputPath}`);\n }\n } else if (!options.silent) {\n console.log(\"\\nTo write the manifest, run:\");\n console.log(\" npx appkit plugin sync --write\\n\");\n console.log(\"Preview:\");\n console.log(\"─\".repeat(60));\n console.log(JSON.stringify(templateManifest, null, 2));\n console.log(\"─\".repeat(60));\n }\n}\n\n/**\n * Run the plugin sync command.\n * Parses the server entry file to discover which packages to scan for plugin\n * manifests, then marks plugins that are actually used in the `plugins: [...]`\n * array as requiredByTemplate.\n */\nfunction runPluginsSync(options: {\n write?: boolean;\n output?: string;\n silent?: boolean;\n requirePlugins?: string;\n pluginsDir?: string;\n packageName?: string;\n}) {\n const cwd = process.cwd();\n const outputPath = path.resolve(cwd, options.output || \"appkit.plugins.json\");\n\n // Security: Reject output paths that escape the project root\n if (!isWithinDirectory(outputPath, cwd)) {\n console.error(\n `Error: Output path \"${options.output}\" resolves outside the project directory.`,\n );\n process.exit(1);\n }\n\n if (!options.silent) {\n console.log(\"Scanning for AppKit plugins...\\n\");\n }\n\n // Step 1: Parse server file to discover imports and plugin usages\n const serverFile = findServerFile(cwd);\n let serverImports: ParsedImport[] = [];\n let pluginUsages = new Set<string>();\n\n if (serverFile) {\n if (!options.silent) {\n const relativePath = path.relative(cwd, serverFile);\n console.log(`Server entry file: ${relativePath}`);\n }\n\n const content = fs.readFileSync(serverFile, \"utf-8\");\n const lang = serverFile.endsWith(\".tsx\") ? Lang.Tsx : Lang.TypeScript;\n const ast = parse(lang, content);\n const root = ast.root();\n\n serverImports = parseImports(root);\n pluginUsages = parsePluginUsages(root);\n } else if (!options.silent) {\n console.log(\n \"No server entry file found. Checked:\",\n SERVER_FILE_CANDIDATES.join(\", \"),\n );\n }\n\n // Step 2: Split imports into npm packages and local (relative) imports\n const npmImports = serverImports.filter(\n (i) => !i.source.startsWith(\".\") && !i.source.startsWith(\"/\"),\n );\n const localImports = serverImports.filter(\n (i) => i.source.startsWith(\".\") || i.source.startsWith(\"/\"),\n );\n\n // Step 3: Scan for plugin manifests (--plugins-dir or node_modules)\n const plugins: TemplatePluginsManifest[\"plugins\"] = {};\n\n if (options.pluginsDir) {\n const resolvedDir = path.resolve(cwd, options.pluginsDir);\n const pkgName = options.packageName ?? \"@databricks/appkit\";\n if (!options.silent) {\n console.log(`Scanning plugins directory: ${options.pluginsDir}`);\n }\n Object.assign(plugins, scanPluginsDir(resolvedDir, pkgName));\n } else {\n const npmPackages = new Set([\n ...KNOWN_PLUGIN_PACKAGES,\n ...npmImports.map((i) => i.source),\n ]);\n Object.assign(plugins, scanForPlugins(cwd, npmPackages));\n }\n\n // Step 4: Discover local plugin manifests from relative imports\n if (serverFile && localImports.length > 0) {\n const serverFileDir = path.dirname(serverFile);\n const localPlugins = discoverLocalPlugins(localImports, serverFileDir, cwd);\n Object.assign(plugins, localPlugins);\n }\n\n const pluginCount = Object.keys(plugins).length;\n\n if (pluginCount === 0) {\n if (options.silent) {\n writeManifest(outputPath, { plugins: {} }, options);\n return;\n }\n console.log(\"No plugins found.\");\n if (options.pluginsDir) {\n console.log(`\\nNo manifest.json files found in: ${options.pluginsDir}`);\n } else {\n console.log(\"\\nMake sure you have plugin packages installed.\");\n }\n process.exit(1);\n }\n\n // Step 5: Mark plugins that are imported AND used in the plugins array as mandatory.\n // For npm imports, match by package name + plugin name.\n // For local imports, resolve both paths to absolute and compare.\n const serverFileDir = serverFile ? path.dirname(serverFile) : cwd;\n\n for (const imp of serverImports) {\n if (!pluginUsages.has(imp.name)) continue;\n\n const isLocal = imp.source.startsWith(\".\") || imp.source.startsWith(\"/\");\n let plugin: TemplatePlugin | undefined;\n\n if (isLocal) {\n // Resolve the import source to an absolute path from the server file directory\n const resolvedImportDir = path.resolve(serverFileDir, imp.source);\n plugin = Object.values(plugins).find((p) => {\n if (!p.package.startsWith(\".\")) return false;\n const resolvedPluginDir = path.resolve(cwd, p.package);\n return (\n resolvedPluginDir === resolvedImportDir && p.name === imp.originalName\n );\n });\n } else {\n // npm import: direct string comparison\n plugin = Object.values(plugins).find(\n (p) => p.package === imp.source && p.name === imp.originalName,\n );\n }\n\n if (plugin) {\n plugin.requiredByTemplate = true;\n }\n }\n\n // Step 6: Apply explicit --require-plugins overrides\n if (options.requirePlugins) {\n const explicitNames = options.requirePlugins\n .split(\",\")\n .map((s) => s.trim())\n .filter(Boolean);\n for (const name of explicitNames) {\n if (plugins[name]) {\n plugins[name].requiredByTemplate = true;\n } else if (!options.silent) {\n console.warn(\n `Warning: --require-plugins referenced \"${name}\" but no such plugin was discovered`,\n );\n }\n }\n }\n\n if (!options.silent) {\n console.log(`\\nFound ${pluginCount} plugin(s):`);\n for (const [name, manifest] of Object.entries(plugins)) {\n const resourceCount =\n manifest.resources.required.length + manifest.resources.optional.length;\n const resourceInfo =\n resourceCount > 0 ? ` [${resourceCount} resource(s)]` : \"\";\n const mandatoryTag = manifest.requiredByTemplate ? \" (mandatory)\" : \"\";\n console.log(\n ` ${manifest.requiredByTemplate ? \"●\" : \"○\"} ${manifest.displayName} (${name}) from ${manifest.package}${resourceInfo}${mandatoryTag}`,\n );\n }\n }\n\n writeManifest(outputPath, { plugins }, options);\n}\n\n/** Exported for testing: path boundary check, AST parsing. */\nexport { isWithinDirectory, parseImports, parsePluginUsages };\n\nexport const pluginsSyncCommand = new Command(\"sync\")\n .description(\n \"Sync plugin manifests from installed packages into appkit.plugins.json\",\n )\n .option(\"-w, --write\", \"Write the manifest file\")\n .option(\n \"-o, --output <path>\",\n \"Output file path (default: ./appkit.plugins.json)\",\n )\n .option(\n \"-s, --silent\",\n \"Suppress output and never exit with error (for use in predev/prebuild hooks)\",\n )\n .option(\n \"--require-plugins <names>\",\n \"Comma-separated plugin names to mark as requiredByTemplate (e.g. server,analytics)\",\n )\n .option(\n \"--plugins-dir <path>\",\n \"Scan this directory for plugin subdirectories with manifest.json (instead of node_modules)\",\n )\n .option(\n \"--package-name <name>\",\n \"Package name to assign to plugins found via --plugins-dir (default: @databricks/appkit)\",\n )\n .action(runPluginsSync);\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"sync.js","names":[],"sources":["../../../../../src/cli/commands/plugin/sync/sync.ts"],"sourcesContent":["import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { Lang, parse, type SgNode } from \"@ast-grep/napi\";\nimport { Command } from \"commander\";\nimport type {\n PluginManifest,\n TemplatePlugin,\n TemplatePluginsManifest,\n} from \"../manifest-types\";\nimport {\n formatValidationErrors,\n validateManifest,\n} from \"../validate/validate-manifest\";\n\n/**\n * Checks whether a resolved file path is within a given directory boundary.\n * Uses path.resolve + startsWith to prevent directory traversal.\n *\n * @param filePath - The path to check (will be resolved to absolute)\n * @param boundary - The directory that must contain filePath\n * @returns true if filePath is inside boundary (or equal to it)\n */\nfunction isWithinDirectory(filePath: string, boundary: string): boolean {\n const resolvedPath = path.resolve(filePath);\n const resolvedBoundary = path.resolve(boundary);\n // Append separator to avoid prefix false-positives (e.g. /foo-bar matching /foo)\n return (\n resolvedPath === resolvedBoundary ||\n resolvedPath.startsWith(`${resolvedBoundary}${path.sep}`)\n );\n}\n\n/**\n * Validates a parsed JSON object against the plugin-manifest JSON schema.\n * Returns the manifest if valid, or null and logs schema errors.\n */\nfunction validateManifestWithSchema(\n obj: unknown,\n sourcePath: string,\n): PluginManifest | null {\n const result = validateManifest(obj);\n if (result.valid && result.manifest) return result.manifest;\n if (result.errors?.length) {\n console.warn(\n `Warning: Manifest at ${sourcePath} failed schema validation:\\n${formatValidationErrors(result.errors, obj)}`,\n );\n }\n return null;\n}\n\n/**\n * Known packages that may contain AppKit plugins.\n * Always scanned for manifests, even if not imported in the server file.\n */\nconst KNOWN_PLUGIN_PACKAGES = [\"@databricks/appkit\"];\n\n/**\n * Candidate paths for the server entry file, relative to cwd.\n * Checked in order; the first that exists is used.\n */\nconst SERVER_FILE_CANDIDATES = [\"server/server.ts\", \"server/index.ts\"];\n\n/**\n * Find the server entry file by checking candidate paths in order.\n *\n * @param cwd - Current working directory\n * @returns Absolute path to the server file, or null if none found\n */\nfunction findServerFile(cwd: string): string | null {\n for (const candidate of SERVER_FILE_CANDIDATES) {\n const fullPath = path.join(cwd, candidate);\n if (fs.existsSync(fullPath)) {\n return fullPath;\n }\n }\n return null;\n}\n\n/**\n * Represents a single named import extracted from the server file.\n */\ninterface ParsedImport {\n /** The imported name (or local alias if renamed) */\n name: string;\n /** The original exported name (differs from name when using `import { foo as bar }`) */\n originalName: string;\n /** The module specifier (package name or relative path) */\n source: string;\n}\n\n/**\n * Extract all named imports from the AST root using structural node traversal.\n * Handles single/double quotes, multiline imports, and aliased imports.\n *\n * @param root - AST root node\n * @returns Array of parsed imports with name, original name, and source\n */\nfunction parseImports(root: SgNode): ParsedImport[] {\n const imports: ParsedImport[] = [];\n\n // Find all import_statement nodes in the AST\n const importStatements = root.findAll({\n rule: { kind: \"import_statement\" },\n });\n\n for (const stmt of importStatements) {\n // Extract the module specifier (the string node, e.g. '@databricks/appkit')\n const sourceNode = stmt.find({ rule: { kind: \"string\" } });\n if (!sourceNode) continue;\n\n // Strip surrounding quotes from the string node text\n const source = sourceNode.text().replace(/^['\"]|['\"]$/g, \"\");\n\n // Find named_imports block: { createApp, analytics, server }\n const namedImports = stmt.find({ rule: { kind: \"named_imports\" } });\n if (!namedImports) continue;\n\n // Extract each import_specifier\n const specifiers = namedImports.findAll({\n rule: { kind: \"import_specifier\" },\n });\n\n for (const specifier of specifiers) {\n const children = specifier.children();\n if (children.length >= 3) {\n // Aliased import: `foo as bar` — children are [name, \"as\", alias]\n const originalName = children[0].text();\n const localName = children[children.length - 1].text();\n imports.push({ name: localName, originalName, source });\n } else {\n // Simple import: `foo`\n const name = specifier.text();\n imports.push({ name, originalName: name, source });\n }\n }\n }\n\n return imports;\n}\n\n/**\n * Extract local names of plugins actually used in the `plugins: [...]` array\n * passed to `createApp()`. Uses structural AST traversal to find `pair` nodes\n * with key \"plugins\" and array values containing call expressions.\n *\n * @param root - AST root node\n * @returns Set of local variable names used as plugin calls in the plugins array\n */\nfunction parsePluginUsages(root: SgNode): Set<string> {\n const usedNames = new Set<string>();\n\n // Find all property pairs in the AST\n const pairs = root.findAll({ rule: { kind: \"pair\" } });\n\n for (const pair of pairs) {\n // Check if the property key is \"plugins\"\n const key = pair.find({ rule: { kind: \"property_identifier\" } });\n if (!key || key.text() !== \"plugins\") continue;\n\n // Find the array value\n const arrayNode = pair.find({ rule: { kind: \"array\" } });\n if (!arrayNode) continue;\n\n // Iterate direct children of the array to find call expressions\n for (const child of arrayNode.children()) {\n if (child.kind() === \"call_expression\") {\n // The callee is the first child (the identifier being called)\n const callee = child.children()[0];\n if (callee?.kind() === \"identifier\") {\n usedNames.add(callee.text());\n }\n }\n }\n }\n\n return usedNames;\n}\n\n/**\n * File extensions to try when resolving a relative import to a file path.\n */\nconst RESOLVE_EXTENSIONS = [\".ts\", \".tsx\", \".js\", \".jsx\"];\n\n/**\n * Resolve a relative import source to the plugin directory containing a manifest.json.\n * Follows the convention that plugins live in their own directory with a manifest.json.\n *\n * Resolution strategy:\n * 1. If the import path is a directory, look for manifest.json directly in it\n * 2. If the import path + extension is a file, look for manifest.json in its parent directory\n * 3. If the import path is a directory with an index file, look for manifest.json in that directory\n *\n * @param importSource - The relative import specifier (e.g. \"./plugins/my-plugin\")\n * @param serverFileDir - Absolute path to the directory containing the server file\n * @returns Absolute path to manifest.json, or null if not found\n */\nfunction resolveLocalManifest(\n importSource: string,\n serverFileDir: string,\n projectRoot?: string,\n): string | null {\n const resolved = path.resolve(serverFileDir, importSource);\n\n // Security: Reject paths that escape the project root\n const boundary = projectRoot || serverFileDir;\n if (!isWithinDirectory(resolved, boundary)) {\n console.warn(\n `Warning: Skipping import \"${importSource}\" — resolves outside the project directory`,\n );\n return null;\n }\n\n // Case 1: Import path is a directory with manifest.json\n // e.g. ./plugins/my-plugin → ./plugins/my-plugin/manifest.json\n if (fs.existsSync(resolved) && fs.statSync(resolved).isDirectory()) {\n const manifestPath = path.join(resolved, \"manifest.json\");\n if (fs.existsSync(manifestPath)) return manifestPath;\n }\n\n // Case 2: Import path + extension resolves to a file\n // e.g. ./plugins/my-plugin → ./plugins/my-plugin.ts\n // Look for manifest.json in the same directory\n for (const ext of RESOLVE_EXTENSIONS) {\n const filePath = `${resolved}${ext}`;\n if (fs.existsSync(filePath) && fs.statSync(filePath).isFile()) {\n const dir = path.dirname(filePath);\n const manifestPath = path.join(dir, \"manifest.json\");\n if (fs.existsSync(manifestPath)) return manifestPath;\n break;\n }\n }\n\n // Case 3: Import path is a directory with an index file\n // e.g. ./plugins/my-plugin → ./plugins/my-plugin/index.ts\n for (const ext of RESOLVE_EXTENSIONS) {\n const indexPath = path.join(resolved, `index${ext}`);\n if (fs.existsSync(indexPath)) {\n const manifestPath = path.join(resolved, \"manifest.json\");\n if (fs.existsSync(manifestPath)) return manifestPath;\n break;\n }\n }\n\n return null;\n}\n\n/**\n * Discover plugin manifests from local (relative) imports in the server file.\n * Resolves each relative import to a directory and looks for manifest.json.\n *\n * @param relativeImports - Parsed imports with relative sources (starting with . or /)\n * @param serverFileDir - Absolute path to the directory containing the server file\n * @param cwd - Current working directory (for computing relative paths in output)\n * @returns Map of plugin name to template plugin entry for local plugins\n */\nfunction discoverLocalPlugins(\n relativeImports: ParsedImport[],\n serverFileDir: string,\n cwd: string,\n): TemplatePluginsManifest[\"plugins\"] {\n const plugins: TemplatePluginsManifest[\"plugins\"] = {};\n\n for (const imp of relativeImports) {\n const manifestPath = resolveLocalManifest(imp.source, serverFileDir, cwd);\n if (!manifestPath) continue;\n\n try {\n const content = fs.readFileSync(manifestPath, \"utf-8\");\n const parsed = JSON.parse(content);\n const manifest = validateManifestWithSchema(parsed, manifestPath);\n if (!manifest || manifest.hidden) continue;\n\n const relativePath = path.relative(cwd, path.dirname(manifestPath));\n\n plugins[manifest.name] = {\n name: manifest.name,\n displayName: manifest.displayName,\n description: manifest.description,\n package: `./${relativePath}`,\n resources: manifest.resources,\n ...(manifest.onSetupMessage && {\n onSetupMessage: manifest.onSetupMessage,\n }),\n };\n } catch (error) {\n console.warn(\n `Warning: Failed to parse manifest at ${manifestPath}:`,\n error instanceof Error ? error.message : error,\n );\n }\n }\n\n return plugins;\n}\n\n/**\n * Discover plugin manifests from a package's dist folder.\n * Looks for manifest.json files in dist/plugins/{plugin-name}/ directories.\n *\n * @param packagePath - Path to the package in node_modules\n * @returns Array of plugin manifests found in the package\n */\nfunction discoverPluginManifests(packagePath: string): PluginManifest[] {\n const pluginsDir = path.join(packagePath, \"dist\", \"plugins\");\n const manifests: PluginManifest[] = [];\n\n if (!fs.existsSync(pluginsDir)) {\n return manifests;\n }\n\n const entries = fs.readdirSync(pluginsDir, { withFileTypes: true });\n for (const entry of entries) {\n if (entry.isDirectory()) {\n const manifestPath = path.join(pluginsDir, entry.name, \"manifest.json\");\n if (fs.existsSync(manifestPath)) {\n try {\n const content = fs.readFileSync(manifestPath, \"utf-8\");\n const parsed = JSON.parse(content);\n const manifest = validateManifestWithSchema(parsed, manifestPath);\n if (manifest) {\n manifests.push(manifest);\n }\n } catch (error) {\n console.warn(\n `Warning: Failed to parse manifest at ${manifestPath}:`,\n error instanceof Error ? error.message : error,\n );\n }\n }\n }\n }\n\n return manifests;\n}\n\n/**\n * Scan node_modules for packages with plugin manifests.\n *\n * @param cwd - Current working directory to search from\n * @param packages - Set of npm package names to scan for plugin manifests\n * @returns Map of plugin name to template plugin entry\n */\nfunction scanForPlugins(\n cwd: string,\n packages: Iterable<string>,\n): TemplatePluginsManifest[\"plugins\"] {\n const plugins: TemplatePluginsManifest[\"plugins\"] = {};\n\n for (const packageName of packages) {\n const packagePath = path.join(cwd, \"node_modules\", packageName);\n if (!fs.existsSync(packagePath)) {\n continue;\n }\n\n const manifests = discoverPluginManifests(packagePath);\n for (const manifest of manifests) {\n if (manifest.hidden) continue;\n plugins[manifest.name] = {\n name: manifest.name,\n displayName: manifest.displayName,\n description: manifest.description,\n package: packageName,\n resources: manifest.resources,\n ...(manifest.onSetupMessage && {\n onSetupMessage: manifest.onSetupMessage,\n }),\n };\n }\n }\n\n return plugins;\n}\n\n/**\n * Scan a directory for plugin manifests in direct subdirectories.\n * Each subdirectory is expected to contain a manifest.json file.\n * Used with --plugins-dir to discover plugins from source instead of node_modules.\n *\n * @param dir - Absolute path to the directory containing plugin subdirectories\n * @param packageName - Package name to assign to discovered plugins\n * @returns Map of plugin name to template plugin entry\n */\nfunction scanPluginsDir(\n dir: string,\n packageName: string,\n): TemplatePluginsManifest[\"plugins\"] {\n const plugins: TemplatePluginsManifest[\"plugins\"] = {};\n\n if (!fs.existsSync(dir)) return plugins;\n\n const entries = fs.readdirSync(dir, { withFileTypes: true });\n for (const entry of entries) {\n if (!entry.isDirectory()) continue;\n\n const manifestPath = path.join(dir, entry.name, \"manifest.json\");\n if (!fs.existsSync(manifestPath)) continue;\n\n try {\n const content = fs.readFileSync(manifestPath, \"utf-8\");\n const parsed = JSON.parse(content);\n const manifest = validateManifestWithSchema(parsed, manifestPath);\n if (manifest && !manifest.hidden) {\n plugins[manifest.name] = {\n name: manifest.name,\n displayName: manifest.displayName,\n description: manifest.description,\n package: packageName,\n resources: manifest.resources,\n ...(manifest.onSetupMessage && {\n onSetupMessage: manifest.onSetupMessage,\n }),\n };\n }\n } catch (error) {\n console.warn(\n `Warning: Failed to parse manifest at ${manifestPath}:`,\n error instanceof Error ? error.message : error,\n );\n }\n }\n\n return plugins;\n}\n\n/**\n * Write (or preview) the template plugins manifest to disk.\n */\nfunction writeManifest(\n outputPath: string,\n { plugins }: { plugins: TemplatePluginsManifest[\"plugins\"] },\n options: { write?: boolean; silent?: boolean },\n) {\n const templateManifest: TemplatePluginsManifest = {\n $schema:\n \"https://databricks.github.io/appkit/schemas/template-plugins.schema.json\",\n version: \"1.0\",\n plugins,\n };\n\n if (options.write) {\n fs.writeFileSync(\n outputPath,\n `${JSON.stringify(templateManifest, null, 2)}\\n`,\n );\n if (!options.silent) {\n console.log(`\\n✓ Wrote ${outputPath}`);\n }\n } else if (!options.silent) {\n console.log(\"\\nTo write the manifest, run:\");\n console.log(\" npx appkit plugin sync --write\\n\");\n console.log(\"Preview:\");\n console.log(\"─\".repeat(60));\n console.log(JSON.stringify(templateManifest, null, 2));\n console.log(\"─\".repeat(60));\n }\n}\n\n/**\n * Run the plugin sync command.\n * Parses the server entry file to discover which packages to scan for plugin\n * manifests, then marks plugins that are actually used in the `plugins: [...]`\n * array as requiredByTemplate.\n */\nfunction runPluginsSync(options: {\n write?: boolean;\n output?: string;\n silent?: boolean;\n requirePlugins?: string;\n pluginsDir?: string;\n packageName?: string;\n}) {\n const cwd = process.cwd();\n const outputPath = path.resolve(cwd, options.output || \"appkit.plugins.json\");\n\n // Security: Reject output paths that escape the project root\n if (!isWithinDirectory(outputPath, cwd)) {\n console.error(\n `Error: Output path \"${options.output}\" resolves outside the project directory.`,\n );\n process.exit(1);\n }\n\n if (!options.silent) {\n console.log(\"Scanning for AppKit plugins...\\n\");\n }\n\n // Step 1: Parse server file to discover imports and plugin usages\n const serverFile = findServerFile(cwd);\n let serverImports: ParsedImport[] = [];\n let pluginUsages = new Set<string>();\n\n if (serverFile) {\n if (!options.silent) {\n const relativePath = path.relative(cwd, serverFile);\n console.log(`Server entry file: ${relativePath}`);\n }\n\n const content = fs.readFileSync(serverFile, \"utf-8\");\n const lang = serverFile.endsWith(\".tsx\") ? Lang.Tsx : Lang.TypeScript;\n const ast = parse(lang, content);\n const root = ast.root();\n\n serverImports = parseImports(root);\n pluginUsages = parsePluginUsages(root);\n } else if (!options.silent) {\n console.log(\n \"No server entry file found. Checked:\",\n SERVER_FILE_CANDIDATES.join(\", \"),\n );\n }\n\n // Step 2: Split imports into npm packages and local (relative) imports\n const npmImports = serverImports.filter(\n (i) => !i.source.startsWith(\".\") && !i.source.startsWith(\"/\"),\n );\n const localImports = serverImports.filter(\n (i) => i.source.startsWith(\".\") || i.source.startsWith(\"/\"),\n );\n\n // Step 3: Scan for plugin manifests (--plugins-dir or node_modules)\n const plugins: TemplatePluginsManifest[\"plugins\"] = {};\n\n if (options.pluginsDir) {\n const resolvedDir = path.resolve(cwd, options.pluginsDir);\n const pkgName = options.packageName ?? \"@databricks/appkit\";\n if (!options.silent) {\n console.log(`Scanning plugins directory: ${options.pluginsDir}`);\n }\n Object.assign(plugins, scanPluginsDir(resolvedDir, pkgName));\n } else {\n const npmPackages = new Set([\n ...KNOWN_PLUGIN_PACKAGES,\n ...npmImports.map((i) => i.source),\n ]);\n Object.assign(plugins, scanForPlugins(cwd, npmPackages));\n }\n\n // Step 4: Discover local plugin manifests from relative imports\n if (serverFile && localImports.length > 0) {\n const serverFileDir = path.dirname(serverFile);\n const localPlugins = discoverLocalPlugins(localImports, serverFileDir, cwd);\n Object.assign(plugins, localPlugins);\n }\n\n const pluginCount = Object.keys(plugins).length;\n\n if (pluginCount === 0) {\n if (options.silent) {\n writeManifest(outputPath, { plugins: {} }, options);\n return;\n }\n console.log(\"No plugins found.\");\n if (options.pluginsDir) {\n console.log(`\\nNo manifest.json files found in: ${options.pluginsDir}`);\n } else {\n console.log(\"\\nMake sure you have plugin packages installed.\");\n }\n process.exit(1);\n }\n\n // Step 5: Mark plugins that are imported AND used in the plugins array as mandatory.\n // For npm imports, match by package name + plugin name.\n // For local imports, resolve both paths to absolute and compare.\n const serverFileDir = serverFile ? path.dirname(serverFile) : cwd;\n\n for (const imp of serverImports) {\n if (!pluginUsages.has(imp.name)) continue;\n\n const isLocal = imp.source.startsWith(\".\") || imp.source.startsWith(\"/\");\n let plugin: TemplatePlugin | undefined;\n\n if (isLocal) {\n // Resolve the import source to an absolute path from the server file directory\n const resolvedImportDir = path.resolve(serverFileDir, imp.source);\n plugin = Object.values(plugins).find((p) => {\n if (!p.package.startsWith(\".\")) return false;\n const resolvedPluginDir = path.resolve(cwd, p.package);\n return (\n resolvedPluginDir === resolvedImportDir && p.name === imp.originalName\n );\n });\n } else {\n // npm import: direct string comparison\n plugin = Object.values(plugins).find(\n (p) => p.package === imp.source && p.name === imp.originalName,\n );\n }\n\n if (plugin) {\n plugin.requiredByTemplate = true;\n }\n }\n\n // Step 6: Apply explicit --require-plugins overrides\n if (options.requirePlugins) {\n const explicitNames = options.requirePlugins\n .split(\",\")\n .map((s) => s.trim())\n .filter(Boolean);\n for (const name of explicitNames) {\n if (plugins[name]) {\n plugins[name].requiredByTemplate = true;\n } else if (!options.silent) {\n console.warn(\n `Warning: --require-plugins referenced \"${name}\" but no such plugin was discovered`,\n );\n }\n }\n }\n\n if (!options.silent) {\n console.log(`\\nFound ${pluginCount} plugin(s):`);\n for (const [name, manifest] of Object.entries(plugins)) {\n const resourceCount =\n manifest.resources.required.length + manifest.resources.optional.length;\n const resourceInfo =\n resourceCount > 0 ? ` [${resourceCount} resource(s)]` : \"\";\n const mandatoryTag = manifest.requiredByTemplate ? \" (mandatory)\" : \"\";\n console.log(\n ` ${manifest.requiredByTemplate ? \"●\" : \"○\"} ${manifest.displayName} (${name}) from ${manifest.package}${resourceInfo}${mandatoryTag}`,\n );\n }\n }\n\n writeManifest(outputPath, { plugins }, options);\n}\n\n/** Exported for testing: path boundary check, AST parsing. */\nexport { isWithinDirectory, parseImports, parsePluginUsages };\n\nexport const pluginsSyncCommand = new Command(\"sync\")\n .description(\n \"Sync plugin manifests from installed packages into appkit.plugins.json\",\n )\n .option(\"-w, --write\", \"Write the manifest file\")\n .option(\n \"-o, --output <path>\",\n \"Output file path (default: ./appkit.plugins.json)\",\n )\n .option(\n \"-s, --silent\",\n \"Suppress output and never exit with error (for use in predev/prebuild hooks)\",\n )\n .option(\n \"--require-plugins <names>\",\n \"Comma-separated plugin names to mark as requiredByTemplate (e.g. server,analytics)\",\n )\n .option(\n \"--plugins-dir <path>\",\n \"Scan this directory for plugin subdirectories with manifest.json (instead of node_modules)\",\n )\n .option(\n \"--package-name <name>\",\n \"Package name to assign to plugins found via --plugins-dir (default: @databricks/appkit)\",\n )\n .action(runPluginsSync);\n"],"mappings":"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"}
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
"displayName": "Lakebase",
|
|
5
5
|
"description": "SQL query execution against Databricks Lakebase Autoscaling",
|
|
6
6
|
"onSetupMessage": "Configure environment variables before running or deploying the app.\nSee: https://databricks.github.io/appkit/docs/plugins/lakebase",
|
|
7
|
+
"hidden": true,
|
|
7
8
|
"resources": {
|
|
8
9
|
"required": [],
|
|
9
10
|
"optional": []
|
package/dist/registry/types.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","names":[],"sources":["../../src/registry/types.ts"],"sourcesContent":["/**\n * Resource Registry Type System\n *\n * This module defines the type system for the AppKit Resource Registry,\n * which enables plugins to declare their Databricks resource requirements\n * in a machine-readable format.\n *\n * Resource types and permissions are generated from plugin-manifest.schema.json\n * (see types.generated.ts). Hand-written interfaces below define the registry API.\n */\n\n// Re-export generated registry types (enum + const must be value exports for runtime)\nimport {\n type AppPermission,\n type DatabasePermission,\n type ExperimentPermission,\n type GenieSpacePermission,\n type JobPermission,\n PERMISSION_HIERARCHY_BY_TYPE,\n PERMISSIONS_BY_TYPE,\n type ResourcePermission,\n ResourceType,\n type SecretPermission,\n type ServingEndpointPermission,\n type SqlWarehousePermission,\n type UcConnectionPermission,\n type UcFunctionPermission,\n type VectorSearchIndexPermission,\n type VolumePermission,\n} from \"./types.generated\";\n\nexport {\n PERMISSION_HIERARCHY_BY_TYPE,\n PERMISSIONS_BY_TYPE,\n ResourceType,\n type AppPermission,\n type DatabasePermission,\n type ExperimentPermission,\n type GenieSpacePermission,\n type JobPermission,\n type ResourcePermission,\n type SecretPermission,\n type ServingEndpointPermission,\n type SqlWarehousePermission,\n type UcConnectionPermission,\n type UcFunctionPermission,\n type VectorSearchIndexPermission,\n type VolumePermission,\n};\n\n// ============================================================================\n// Hand-written interfaces (not in JSON schema)\n// ============================================================================\n\n/**\n * Defines a single field for a resource. Each field has its own environment variable and optional description.\n * Single-value types use one key (e.g. id); multi-value types (database, secret) use multiple (e.g. instance_name, database_name or scope, key).\n */\nexport interface ResourceFieldEntry {\n /** Environment variable name for this field */\n env: string;\n /** Human-readable description for this field */\n description?: string;\n}\n\n/**\n * Declares a resource requirement for a plugin.\n * Can be defined statically in a manifest or dynamically via getResourceRequirements().\n */\nexport interface ResourceRequirement {\n /** Type of Databricks resource required */\n type: ResourceType;\n\n /** Unique alias for this resource within the plugin (e.g., 'warehouse', 'secrets'). Used for UI/display. */\n alias: string;\n\n /** Stable key for machine use (env naming, composite keys, app.yaml). Required. */\n resourceKey: string;\n\n /** Human-readable description of why this resource is needed */\n description: string;\n\n /** Required permission level for the resource */\n permission: ResourcePermission;\n\n /**\n * Map of field name to env and optional description.\n * Single-value types use one key (e.g. id); multi-value (database, secret) use multiple keys.\n */\n fields: Record<string, ResourceFieldEntry>;\n\n /** Whether this resource is required (true) or optional (false) */\n required: boolean;\n}\n\n/**\n * Internal representation of a resource in the registry.\n * Extends ResourceRequirement with resolution state and plugin ownership.\n */\nexport interface ResourceEntry extends ResourceRequirement {\n /** Plugin(s) that require this resource (comma-separated if multiple) */\n plugin: string;\n\n /** Whether the resource has been resolved (all field env vars set) */\n resolved: boolean;\n\n /** Resolved value per field name. Populated by validate() when all field env vars are set. */\n values?: Record<string, string>;\n\n /**\n * Per-plugin permission tracking.\n * Maps plugin name to the permission it originally requested.\n * Populated when multiple plugins share the same resource.\n */\n permissionSources?: Record<string, ResourcePermission>;\n}\n\n/**\n * Result of validating all registered resources against the environment.\n */\nexport interface ValidationResult {\n /** Whether all required resources are available */\n valid: boolean;\n\n /** List of missing required resources */\n missing: ResourceEntry[];\n\n /** Complete list of all registered resources (required and optional) */\n all: ResourceEntry[];\n}\n\nimport type { JSONSchema7 } from \"json-schema\";\n\n/**\n * Configuration schema definition for plugin config.\n * Re-exported from the standard JSON Schema Draft 7 types.\n *\n * @see {@link https://json-schema.org/draft-07/json-schema-release-notes | JSON Schema Draft 7}\n */\nexport type ConfigSchema = JSONSchema7;\n\n/**\n * Plugin manifest that declares metadata and resource requirements.\n * Attached to plugin classes as a static property.\n */\nexport interface PluginManifest {\n /** Plugin identifier (matches plugin.name) */\n name: string;\n\n /** Human-readable display name for UI/CLI */\n displayName: string;\n\n /** Brief description of what the plugin does */\n description: string;\n\n /**\n * Resource requirements declaration\n */\n resources: {\n /** Resources that must be available for the plugin to function */\n required: Omit<ResourceRequirement, \"required\">[];\n\n /** Resources that enhance functionality but are not mandatory */\n optional: Omit<ResourceRequirement, \"required\">[];\n };\n\n /**\n * Configuration schema for the plugin.\n * Defines the shape and validation rules for plugin config.\n */\n config?: {\n schema: ConfigSchema;\n };\n\n /**\n * Optional metadata for community plugins\n */\n author?: string;\n version?: string;\n repository?: string;\n keywords?: string[];\n license?: string;\n}\n"],"mappings":""}
|
|
1
|
+
{"version":3,"file":"types.js","names":[],"sources":["../../src/registry/types.ts"],"sourcesContent":["/**\n * Resource Registry Type System\n *\n * This module defines the type system for the AppKit Resource Registry,\n * which enables plugins to declare their Databricks resource requirements\n * in a machine-readable format.\n *\n * Resource types and permissions are generated from plugin-manifest.schema.json\n * (see types.generated.ts). Hand-written interfaces below define the registry API.\n */\n\n// Re-export generated registry types (enum + const must be value exports for runtime)\nimport {\n type AppPermission,\n type DatabasePermission,\n type ExperimentPermission,\n type GenieSpacePermission,\n type JobPermission,\n PERMISSION_HIERARCHY_BY_TYPE,\n PERMISSIONS_BY_TYPE,\n type ResourcePermission,\n ResourceType,\n type SecretPermission,\n type ServingEndpointPermission,\n type SqlWarehousePermission,\n type UcConnectionPermission,\n type UcFunctionPermission,\n type VectorSearchIndexPermission,\n type VolumePermission,\n} from \"./types.generated\";\n\nexport {\n PERMISSION_HIERARCHY_BY_TYPE,\n PERMISSIONS_BY_TYPE,\n ResourceType,\n type AppPermission,\n type DatabasePermission,\n type ExperimentPermission,\n type GenieSpacePermission,\n type JobPermission,\n type ResourcePermission,\n type SecretPermission,\n type ServingEndpointPermission,\n type SqlWarehousePermission,\n type UcConnectionPermission,\n type UcFunctionPermission,\n type VectorSearchIndexPermission,\n type VolumePermission,\n};\n\n// ============================================================================\n// Hand-written interfaces (not in JSON schema)\n// ============================================================================\n\n/**\n * Defines a single field for a resource. Each field has its own environment variable and optional description.\n * Single-value types use one key (e.g. id); multi-value types (database, secret) use multiple (e.g. instance_name, database_name or scope, key).\n */\nexport interface ResourceFieldEntry {\n /** Environment variable name for this field */\n env: string;\n /** Human-readable description for this field */\n description?: string;\n}\n\n/**\n * Declares a resource requirement for a plugin.\n * Can be defined statically in a manifest or dynamically via getResourceRequirements().\n */\nexport interface ResourceRequirement {\n /** Type of Databricks resource required */\n type: ResourceType;\n\n /** Unique alias for this resource within the plugin (e.g., 'warehouse', 'secrets'). Used for UI/display. */\n alias: string;\n\n /** Stable key for machine use (env naming, composite keys, app.yaml). Required. */\n resourceKey: string;\n\n /** Human-readable description of why this resource is needed */\n description: string;\n\n /** Required permission level for the resource */\n permission: ResourcePermission;\n\n /**\n * Map of field name to env and optional description.\n * Single-value types use one key (e.g. id); multi-value (database, secret) use multiple keys.\n */\n fields: Record<string, ResourceFieldEntry>;\n\n /** Whether this resource is required (true) or optional (false) */\n required: boolean;\n}\n\n/**\n * Internal representation of a resource in the registry.\n * Extends ResourceRequirement with resolution state and plugin ownership.\n */\nexport interface ResourceEntry extends ResourceRequirement {\n /** Plugin(s) that require this resource (comma-separated if multiple) */\n plugin: string;\n\n /** Whether the resource has been resolved (all field env vars set) */\n resolved: boolean;\n\n /** Resolved value per field name. Populated by validate() when all field env vars are set. */\n values?: Record<string, string>;\n\n /**\n * Per-plugin permission tracking.\n * Maps plugin name to the permission it originally requested.\n * Populated when multiple plugins share the same resource.\n */\n permissionSources?: Record<string, ResourcePermission>;\n}\n\n/**\n * Result of validating all registered resources against the environment.\n */\nexport interface ValidationResult {\n /** Whether all required resources are available */\n valid: boolean;\n\n /** List of missing required resources */\n missing: ResourceEntry[];\n\n /** Complete list of all registered resources (required and optional) */\n all: ResourceEntry[];\n}\n\nimport type { JSONSchema7 } from \"json-schema\";\n\n/**\n * Configuration schema definition for plugin config.\n * Re-exported from the standard JSON Schema Draft 7 types.\n *\n * @see {@link https://json-schema.org/draft-07/json-schema-release-notes | JSON Schema Draft 7}\n */\nexport type ConfigSchema = JSONSchema7;\n\n/**\n * Plugin manifest that declares metadata and resource requirements.\n * Attached to plugin classes as a static property.\n */\nexport interface PluginManifest {\n /** Plugin identifier (matches plugin.name) */\n name: string;\n\n /** Human-readable display name for UI/CLI */\n displayName: string;\n\n /** Brief description of what the plugin does */\n description: string;\n\n /**\n * Resource requirements declaration\n */\n resources: {\n /** Resources that must be available for the plugin to function */\n required: Omit<ResourceRequirement, \"required\">[];\n\n /** Resources that enhance functionality but are not mandatory */\n optional: Omit<ResourceRequirement, \"required\">[];\n };\n\n /**\n * Configuration schema for the plugin.\n * Defines the shape and validation rules for plugin config.\n */\n config?: {\n schema: ConfigSchema;\n };\n\n /**\n * When true, excluded from the template plugins manifest during sync.\n */\n hidden?: boolean;\n\n /**\n * Optional metadata for community plugins\n */\n author?: string;\n version?: string;\n repository?: string;\n keywords?: string[];\n license?: string;\n}\n"],"mappings":""}
|
|
@@ -90,6 +90,11 @@
|
|
|
90
90
|
"onSetupMessage": {
|
|
91
91
|
"type": "string",
|
|
92
92
|
"description": "Message displayed to the user after project initialization. Use this to inform about manual setup steps (e.g. environment variables, resource provisioning)."
|
|
93
|
+
},
|
|
94
|
+
"hidden": {
|
|
95
|
+
"type": "boolean",
|
|
96
|
+
"default": false,
|
|
97
|
+
"description": "When true, this plugin is excluded from the template plugins manifest (appkit.plugins.json) during sync."
|
|
93
98
|
}
|
|
94
99
|
},
|
|
95
100
|
"additionalProperties": false,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.d.ts","names":[],"sources":["../../../../shared/src/plugin.ts"],"sourcesContent":[],"mappings":";;;;;UAIiB,UAAA;EAAA,IAAA,EAAA,MAAA;EAAU,qBAAA,GAAA,EAAA,IAAA;OAKhB,EAAA,EAAA,OAAA,CAAA,IAAA,CAAA;cAEoB,CAAA,MAAA,EAAR,OAAA,CAAQ,MAAA,CAAA,EAAA,IAAA;cAEb,EAAA,EAAA,iBAAA;EAAiB,OAAA,GAAA,EAAA,OAAA;AAMnC;AAaA;AAaY,UA1BK,gBAAA,CA0BM;EAMX,IAAA,CAAA,EAAA,MAAA;EAAiB,IAAA,CAAA,EAAA,MAAA;MACvB,EAAA,MAAA,CAAA,EAAA,OAAA;WACM,CAAA,EAxBE,gBAwBF;;AAEF,KAvBE,gBAAA,GAuBF,OAAA,GAAA;QACL,CAAA,EAAA,OAAA;SACc,CAAA,EAAA,OAAA;MACT,CAAA,EAAA,OAAA;;AAiBqB,KA9BnB,WAAA,GA8BmB,MAAA,GAAA,QAAA,GAAA,UAAA;;;;;AASnB,KAjCA,iBAiCA,CAAA,IAhCN,gBAgCM,EAAA,UA/BA,UA+BA,GA/Ba,UA+Bb,CAAA,GAAA,CAAA,KAAA,MAAA,EA7BF,CA6BE,EAAA,GA5BP,CA4BO,CAAA,GAAA;EAAW,cAAA,CAAA,EA3BJ,MA2BI,CAAA,MAAA,EAAA,OAAA,CAAA;
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","names":[],"sources":["../../../../shared/src/plugin.ts"],"sourcesContent":[],"mappings":";;;;;UAIiB,UAAA;EAAA,IAAA,EAAA,MAAA;EAAU,qBAAA,GAAA,EAAA,IAAA;OAKhB,EAAA,EAAA,OAAA,CAAA,IAAA,CAAA;cAEoB,CAAA,MAAA,EAAR,OAAA,CAAQ,MAAA,CAAA,EAAA,IAAA;cAEb,EAAA,EAAA,iBAAA;EAAiB,OAAA,GAAA,EAAA,OAAA;AAMnC;AAaA;AAaY,UA1BK,gBAAA,CA0BM;EAMX,IAAA,CAAA,EAAA,MAAA;EAAiB,IAAA,CAAA,EAAA,MAAA;MACvB,EAAA,MAAA,CAAA,EAAA,OAAA;WACM,CAAA,EAxBE,gBAwBF;;AAEF,KAvBE,gBAAA,GAuBF,OAAA,GAAA;QACL,CAAA,EAAA,OAAA;SACc,CAAA,EAAA,OAAA;MACT,CAAA,EAAA,OAAA;;AAiBqB,KA9BnB,WAAA,GA8BmB,MAAA,GAAA,QAAA,GAAA,UAAA;;;;;AASnB,KAjCA,iBAiCA,CAAA,IAhCN,gBAgCM,EAAA,UA/BA,UA+BA,GA/Ba,UA+Bb,CAAA,GAAA,CAAA,KAAA,MAAA,EA7BF,CA6BE,EAAA,GA5BP,CA4BO,CAAA,GAAA;EAAW,cAAA,CAAA,EA3BJ,MA2BI,CAAA,MAAA,EAAA,OAAA,CAAA;EAiBN,KAAA,CAAA,EA3CP,WA2CO;EAWA;;;;EAWD,QAAA,EA5DJ,cA4DI;EAqCJ;;;;yBAC2B,EAAA,MAAA,EA7FJ,CA6FI,CAAA,EA7FA,mBA6FA,EAAA;;;AAMvC;;;AAMgB,UAlGC,cAAA,CAkGD;MAAgB,EAAA,MAAA;EAAG,WAAA,EAAA,MAAA;EAQvB,WAAA,EAAS,MAAA;EAAA,SAAA,EAAA;IACW,QAAA,EAtGlB,IAsGkB,CAtGb,mBAsGa,EAAA,UAAA,CAAA,EAAA;IAAX,QAAA,EArGP,IAqGO,CArGF,mBAqGE,EAAA,UAAA,CAAA,EAAA;;QAEA,CAAA,EAAA;IACU,MAAA,EArGnB,WAqGmB;;gBAA3B,CAAA,EAAA,MAAA;QAD6B,CAAA,EAAA,OAAA;EAAU,MAAA,CAAA,EAAA,MAAA;EAK/B,OAAA,CAAA,EAAA,MAAU;EAAA,UAAA,CAAA,EAAA,MAAA;UAAsB,CAAA,EAAA,MAAA,EAAA;SAAW,CAAA,EAAA,MAAA;;;AACvD;;;;;AAEsB,UA3FL,kBAAA,CA2FK;;EAAP,GAAA,EAAA,MAAA;EAGH;EACA,WAAA,CAAA,EAAA,MAAY;AACxB;AAEA;AAEA;;;AAKiB,UA9FA,mBAAA,CA8FA;MAAkB,EAAA,MAAA;OAAiB,EAAA,MAAA;EAAO;EAI/C,WAAA,EAAA,MAAA;;;;;;;UAvFF,eAAe;;;;;;;;KAqCb,wBAAwB,cAClC,uCAAqC,IAAI;;;;;KAM/B,kBAAkB;;;;;;gBAMd,gBAAgB;;;;;;;KAQpB,6BACS,WAAW,iDAExB,aAAa,YAAY,WAC7B,cAAc,aAAa;KAInB;UAAgC;UAAW;QAAS;;KACpD,6CACD,MACN,WAAW,GAAG,GAAG;;KAGV,UAAA,GAAa,OAAA,CAAQ;KACrB,YAAA,GAAe,OAAA,CAAQ;KACvB,WAAA,GAAc,OAAA,CAAQ;KAEtB,UAAA;KAEA,WAAA;;;UAGF;;iBAEO,kBAAkB,iBAAiB;;;KAIxC,iBAAA,GAAoB"}
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
//#region src/utils/vite-config-merge.ts
|
|
2
|
+
function flattenPlugins(plugins) {
|
|
3
|
+
return plugins.flat(Infinity).filter(Boolean);
|
|
4
|
+
}
|
|
2
5
|
function mergeConfigDedup(base, override, mergeFn) {
|
|
3
6
|
const merged = mergeFn(base, override);
|
|
4
7
|
if (base.plugins && override.plugins) {
|
|
5
8
|
const seen = /* @__PURE__ */ new Set();
|
|
6
|
-
merged.plugins = [...base.plugins, ...override.plugins].filter((p) => {
|
|
9
|
+
merged.plugins = flattenPlugins([...base.plugins, ...override.plugins]).filter((p) => {
|
|
7
10
|
const name = p.name;
|
|
8
11
|
if (seen.has(name)) return false;
|
|
9
12
|
seen.add(name);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vite-config-merge.js","names":[],"sources":["../../src/utils/vite-config-merge.ts"],"sourcesContent":["import type { Plugin } from \"vite\";\n\nexport function mergeConfigDedup(\n base: any,\n override: any,\n mergeFn: (a: any, b: any) => any,\n) {\n const merged = mergeFn(base, override);\n if (base.plugins && override.plugins) {\n const seen = new Set<string>();\n
|
|
1
|
+
{"version":3,"file":"vite-config-merge.js","names":[],"sources":["../../src/utils/vite-config-merge.ts"],"sourcesContent":["import type { Plugin } from \"vite\";\n\nfunction flattenPlugins(plugins: any[]): Plugin[] {\n return plugins.flat(Infinity).filter(Boolean);\n}\n\nexport function mergeConfigDedup(\n base: any,\n override: any,\n mergeFn: (a: any, b: any) => any,\n) {\n const merged = mergeFn(base, override);\n if (base.plugins && override.plugins) {\n const seen = new Set<string>();\n const allPlugins = flattenPlugins([...base.plugins, ...override.plugins]);\n merged.plugins = allPlugins.filter((p) => {\n const name = p.name;\n if (seen.has(name)) return false;\n seen.add(name);\n return true;\n });\n }\n return merged;\n}\n"],"mappings":";AAEA,SAAS,eAAe,SAA0B;AAChD,QAAO,QAAQ,KAAK,SAAS,CAAC,OAAO,QAAQ;;AAG/C,SAAgB,iBACd,MACA,UACA,SACA;CACA,MAAM,SAAS,QAAQ,MAAM,SAAS;AACtC,KAAI,KAAK,WAAW,SAAS,SAAS;EACpC,MAAM,uBAAO,IAAI,KAAa;AAE9B,SAAO,UADY,eAAe,CAAC,GAAG,KAAK,SAAS,GAAG,SAAS,QAAQ,CAAC,CAC7C,QAAQ,MAAM;GACxC,MAAM,OAAO,EAAE;AACf,OAAI,KAAK,IAAI,KAAK,CAAE,QAAO;AAC3B,QAAK,IAAI,KAAK;AACd,UAAO;IACP;;AAEJ,QAAO"}
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
5
|
<meta name="generator" content="Docusaurus v3.9.2">
|
|
6
6
|
<title data-rh="true">Abstract Class: AppKitError | AppKit</title><meta data-rh="true" name="viewport" content="width=device-width,initial-scale=1"><meta data-rh="true" name="twitter:card" content="summary_large_image"><meta data-rh="true" property="og:url" content="https://databricks.github.io/appkit/docs/api/appkit/Class.AppKitError"><meta data-rh="true" property="og:locale" content="en"><meta data-rh="true" name="docusaurus_locale" content="en"><meta data-rh="true" name="docsearch:language" content="en"><meta data-rh="true" name="keywords" content="Databricks Apps, Node.js, React.js, SDK, TypeScript, SQL, Databricks, AI, full-stack, development"><meta data-rh="true" name="docusaurus_version" content="current"><meta data-rh="true" name="docusaurus_tag" content="docs-default-current"><meta data-rh="true" name="docsearch:version" content="current"><meta data-rh="true" name="docsearch:docusaurus_tag" content="docs-default-current"><meta data-rh="true" property="og:title" content="Abstract Class: AppKitError | AppKit"><meta data-rh="true" name="description" content="Base error class for all AppKit errors."><meta data-rh="true" property="og:description" content="Base error class for all AppKit errors."><link data-rh="true" rel="icon" href="/appkit/img/favicon.ico"><link data-rh="true" rel="canonical" href="https://databricks.github.io/appkit/docs/api/appkit/Class.AppKitError"><link data-rh="true" rel="alternate" href="https://databricks.github.io/appkit/docs/api/appkit/Class.AppKitError" hreflang="en"><link data-rh="true" rel="alternate" href="https://databricks.github.io/appkit/docs/api/appkit/Class.AppKitError" hreflang="x-default"><script data-rh="true" type="application/ld+json">{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"API reference","item":"https://databricks.github.io/appkit/docs/api/"},{"@type":"ListItem","position":2,"name":"@databricks/appkit","item":"https://databricks.github.io/appkit/docs/api/appkit/"},{"@type":"ListItem","position":3,"name":"AppKitError","item":"https://databricks.github.io/appkit/docs/api/appkit/Class.AppKitError"}]}</script><link rel="stylesheet" href="/appkit/assets/css/styles.36a38b99.css">
|
|
7
|
-
<script src="/appkit/assets/js/runtime~main.
|
|
8
|
-
<script src="/appkit/assets/js/main.
|
|
7
|
+
<script src="/appkit/assets/js/runtime~main.5342f46a.js" defer="defer"></script>
|
|
8
|
+
<script src="/appkit/assets/js/main.bfddc833.js" defer="defer"></script>
|
|
9
9
|
</head>
|
|
10
10
|
<body class="navigation-with-keyboard">
|
|
11
11
|
<svg style="display: none;"><defs>
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
5
|
<meta name="generator" content="Docusaurus v3.9.2">
|
|
6
6
|
<title data-rh="true">Class: AuthenticationError | AppKit</title><meta data-rh="true" name="viewport" content="width=device-width,initial-scale=1"><meta data-rh="true" name="twitter:card" content="summary_large_image"><meta data-rh="true" property="og:url" content="https://databricks.github.io/appkit/docs/api/appkit/Class.AuthenticationError"><meta data-rh="true" property="og:locale" content="en"><meta data-rh="true" name="docusaurus_locale" content="en"><meta data-rh="true" name="docsearch:language" content="en"><meta data-rh="true" name="keywords" content="Databricks Apps, Node.js, React.js, SDK, TypeScript, SQL, Databricks, AI, full-stack, development"><meta data-rh="true" name="docusaurus_version" content="current"><meta data-rh="true" name="docusaurus_tag" content="docs-default-current"><meta data-rh="true" name="docsearch:version" content="current"><meta data-rh="true" name="docsearch:docusaurus_tag" content="docs-default-current"><meta data-rh="true" property="og:title" content="Class: AuthenticationError | AppKit"><meta data-rh="true" name="description" content="Error thrown when authentication fails."><meta data-rh="true" property="og:description" content="Error thrown when authentication fails."><link data-rh="true" rel="icon" href="/appkit/img/favicon.ico"><link data-rh="true" rel="canonical" href="https://databricks.github.io/appkit/docs/api/appkit/Class.AuthenticationError"><link data-rh="true" rel="alternate" href="https://databricks.github.io/appkit/docs/api/appkit/Class.AuthenticationError" hreflang="en"><link data-rh="true" rel="alternate" href="https://databricks.github.io/appkit/docs/api/appkit/Class.AuthenticationError" hreflang="x-default"><script data-rh="true" type="application/ld+json">{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"API reference","item":"https://databricks.github.io/appkit/docs/api/"},{"@type":"ListItem","position":2,"name":"@databricks/appkit","item":"https://databricks.github.io/appkit/docs/api/appkit/"},{"@type":"ListItem","position":3,"name":"AuthenticationError","item":"https://databricks.github.io/appkit/docs/api/appkit/Class.AuthenticationError"}]}</script><link rel="stylesheet" href="/appkit/assets/css/styles.36a38b99.css">
|
|
7
|
-
<script src="/appkit/assets/js/runtime~main.
|
|
8
|
-
<script src="/appkit/assets/js/main.
|
|
7
|
+
<script src="/appkit/assets/js/runtime~main.5342f46a.js" defer="defer"></script>
|
|
8
|
+
<script src="/appkit/assets/js/main.bfddc833.js" defer="defer"></script>
|
|
9
9
|
</head>
|
|
10
10
|
<body class="navigation-with-keyboard">
|
|
11
11
|
<svg style="display: none;"><defs>
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
5
|
<meta name="generator" content="Docusaurus v3.9.2">
|
|
6
6
|
<title data-rh="true">Class: ConfigurationError | AppKit</title><meta data-rh="true" name="viewport" content="width=device-width,initial-scale=1"><meta data-rh="true" name="twitter:card" content="summary_large_image"><meta data-rh="true" property="og:url" content="https://databricks.github.io/appkit/docs/api/appkit/Class.ConfigurationError"><meta data-rh="true" property="og:locale" content="en"><meta data-rh="true" name="docusaurus_locale" content="en"><meta data-rh="true" name="docsearch:language" content="en"><meta data-rh="true" name="keywords" content="Databricks Apps, Node.js, React.js, SDK, TypeScript, SQL, Databricks, AI, full-stack, development"><meta data-rh="true" name="docusaurus_version" content="current"><meta data-rh="true" name="docusaurus_tag" content="docs-default-current"><meta data-rh="true" name="docsearch:version" content="current"><meta data-rh="true" name="docsearch:docusaurus_tag" content="docs-default-current"><meta data-rh="true" property="og:title" content="Class: ConfigurationError | AppKit"><meta data-rh="true" name="description" content="Error thrown when configuration is missing or invalid."><meta data-rh="true" property="og:description" content="Error thrown when configuration is missing or invalid."><link data-rh="true" rel="icon" href="/appkit/img/favicon.ico"><link data-rh="true" rel="canonical" href="https://databricks.github.io/appkit/docs/api/appkit/Class.ConfigurationError"><link data-rh="true" rel="alternate" href="https://databricks.github.io/appkit/docs/api/appkit/Class.ConfigurationError" hreflang="en"><link data-rh="true" rel="alternate" href="https://databricks.github.io/appkit/docs/api/appkit/Class.ConfigurationError" hreflang="x-default"><script data-rh="true" type="application/ld+json">{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"API reference","item":"https://databricks.github.io/appkit/docs/api/"},{"@type":"ListItem","position":2,"name":"@databricks/appkit","item":"https://databricks.github.io/appkit/docs/api/appkit/"},{"@type":"ListItem","position":3,"name":"ConfigurationError","item":"https://databricks.github.io/appkit/docs/api/appkit/Class.ConfigurationError"}]}</script><link rel="stylesheet" href="/appkit/assets/css/styles.36a38b99.css">
|
|
7
|
-
<script src="/appkit/assets/js/runtime~main.
|
|
8
|
-
<script src="/appkit/assets/js/main.
|
|
7
|
+
<script src="/appkit/assets/js/runtime~main.5342f46a.js" defer="defer"></script>
|
|
8
|
+
<script src="/appkit/assets/js/main.bfddc833.js" defer="defer"></script>
|
|
9
9
|
</head>
|
|
10
10
|
<body class="navigation-with-keyboard">
|
|
11
11
|
<svg style="display: none;"><defs>
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
5
|
<meta name="generator" content="Docusaurus v3.9.2">
|
|
6
6
|
<title data-rh="true">Class: ConnectionError | AppKit</title><meta data-rh="true" name="viewport" content="width=device-width,initial-scale=1"><meta data-rh="true" name="twitter:card" content="summary_large_image"><meta data-rh="true" property="og:url" content="https://databricks.github.io/appkit/docs/api/appkit/Class.ConnectionError"><meta data-rh="true" property="og:locale" content="en"><meta data-rh="true" name="docusaurus_locale" content="en"><meta data-rh="true" name="docsearch:language" content="en"><meta data-rh="true" name="keywords" content="Databricks Apps, Node.js, React.js, SDK, TypeScript, SQL, Databricks, AI, full-stack, development"><meta data-rh="true" name="docusaurus_version" content="current"><meta data-rh="true" name="docusaurus_tag" content="docs-default-current"><meta data-rh="true" name="docsearch:version" content="current"><meta data-rh="true" name="docsearch:docusaurus_tag" content="docs-default-current"><meta data-rh="true" property="og:title" content="Class: ConnectionError | AppKit"><meta data-rh="true" name="description" content="Error thrown when a connection or network operation fails."><meta data-rh="true" property="og:description" content="Error thrown when a connection or network operation fails."><link data-rh="true" rel="icon" href="/appkit/img/favicon.ico"><link data-rh="true" rel="canonical" href="https://databricks.github.io/appkit/docs/api/appkit/Class.ConnectionError"><link data-rh="true" rel="alternate" href="https://databricks.github.io/appkit/docs/api/appkit/Class.ConnectionError" hreflang="en"><link data-rh="true" rel="alternate" href="https://databricks.github.io/appkit/docs/api/appkit/Class.ConnectionError" hreflang="x-default"><script data-rh="true" type="application/ld+json">{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"API reference","item":"https://databricks.github.io/appkit/docs/api/"},{"@type":"ListItem","position":2,"name":"@databricks/appkit","item":"https://databricks.github.io/appkit/docs/api/appkit/"},{"@type":"ListItem","position":3,"name":"ConnectionError","item":"https://databricks.github.io/appkit/docs/api/appkit/Class.ConnectionError"}]}</script><link rel="stylesheet" href="/appkit/assets/css/styles.36a38b99.css">
|
|
7
|
-
<script src="/appkit/assets/js/runtime~main.
|
|
8
|
-
<script src="/appkit/assets/js/main.
|
|
7
|
+
<script src="/appkit/assets/js/runtime~main.5342f46a.js" defer="defer"></script>
|
|
8
|
+
<script src="/appkit/assets/js/main.bfddc833.js" defer="defer"></script>
|
|
9
9
|
</head>
|
|
10
10
|
<body class="navigation-with-keyboard">
|
|
11
11
|
<svg style="display: none;"><defs>
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
5
|
<meta name="generator" content="Docusaurus v3.9.2">
|
|
6
6
|
<title data-rh="true">Class: ExecutionError | AppKit</title><meta data-rh="true" name="viewport" content="width=device-width,initial-scale=1"><meta data-rh="true" name="twitter:card" content="summary_large_image"><meta data-rh="true" property="og:url" content="https://databricks.github.io/appkit/docs/api/appkit/Class.ExecutionError"><meta data-rh="true" property="og:locale" content="en"><meta data-rh="true" name="docusaurus_locale" content="en"><meta data-rh="true" name="docsearch:language" content="en"><meta data-rh="true" name="keywords" content="Databricks Apps, Node.js, React.js, SDK, TypeScript, SQL, Databricks, AI, full-stack, development"><meta data-rh="true" name="docusaurus_version" content="current"><meta data-rh="true" name="docusaurus_tag" content="docs-default-current"><meta data-rh="true" name="docsearch:version" content="current"><meta data-rh="true" name="docsearch:docusaurus_tag" content="docs-default-current"><meta data-rh="true" property="og:title" content="Class: ExecutionError | AppKit"><meta data-rh="true" name="description" content="Error thrown when an operation execution fails."><meta data-rh="true" property="og:description" content="Error thrown when an operation execution fails."><link data-rh="true" rel="icon" href="/appkit/img/favicon.ico"><link data-rh="true" rel="canonical" href="https://databricks.github.io/appkit/docs/api/appkit/Class.ExecutionError"><link data-rh="true" rel="alternate" href="https://databricks.github.io/appkit/docs/api/appkit/Class.ExecutionError" hreflang="en"><link data-rh="true" rel="alternate" href="https://databricks.github.io/appkit/docs/api/appkit/Class.ExecutionError" hreflang="x-default"><script data-rh="true" type="application/ld+json">{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"API reference","item":"https://databricks.github.io/appkit/docs/api/"},{"@type":"ListItem","position":2,"name":"@databricks/appkit","item":"https://databricks.github.io/appkit/docs/api/appkit/"},{"@type":"ListItem","position":3,"name":"ExecutionError","item":"https://databricks.github.io/appkit/docs/api/appkit/Class.ExecutionError"}]}</script><link rel="stylesheet" href="/appkit/assets/css/styles.36a38b99.css">
|
|
7
|
-
<script src="/appkit/assets/js/runtime~main.
|
|
8
|
-
<script src="/appkit/assets/js/main.
|
|
7
|
+
<script src="/appkit/assets/js/runtime~main.5342f46a.js" defer="defer"></script>
|
|
8
|
+
<script src="/appkit/assets/js/main.bfddc833.js" defer="defer"></script>
|
|
9
9
|
</head>
|
|
10
10
|
<body class="navigation-with-keyboard">
|
|
11
11
|
<svg style="display: none;"><defs>
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
5
|
<meta name="generator" content="Docusaurus v3.9.2">
|
|
6
6
|
<title data-rh="true">Class: InitializationError | AppKit</title><meta data-rh="true" name="viewport" content="width=device-width,initial-scale=1"><meta data-rh="true" name="twitter:card" content="summary_large_image"><meta data-rh="true" property="og:url" content="https://databricks.github.io/appkit/docs/api/appkit/Class.InitializationError"><meta data-rh="true" property="og:locale" content="en"><meta data-rh="true" name="docusaurus_locale" content="en"><meta data-rh="true" name="docsearch:language" content="en"><meta data-rh="true" name="keywords" content="Databricks Apps, Node.js, React.js, SDK, TypeScript, SQL, Databricks, AI, full-stack, development"><meta data-rh="true" name="docusaurus_version" content="current"><meta data-rh="true" name="docusaurus_tag" content="docs-default-current"><meta data-rh="true" name="docsearch:version" content="current"><meta data-rh="true" name="docsearch:docusaurus_tag" content="docs-default-current"><meta data-rh="true" property="og:title" content="Class: InitializationError | AppKit"><meta data-rh="true" name="description" content="Error thrown when a service or component is not properly initialized."><meta data-rh="true" property="og:description" content="Error thrown when a service or component is not properly initialized."><link data-rh="true" rel="icon" href="/appkit/img/favicon.ico"><link data-rh="true" rel="canonical" href="https://databricks.github.io/appkit/docs/api/appkit/Class.InitializationError"><link data-rh="true" rel="alternate" href="https://databricks.github.io/appkit/docs/api/appkit/Class.InitializationError" hreflang="en"><link data-rh="true" rel="alternate" href="https://databricks.github.io/appkit/docs/api/appkit/Class.InitializationError" hreflang="x-default"><script data-rh="true" type="application/ld+json">{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"API reference","item":"https://databricks.github.io/appkit/docs/api/"},{"@type":"ListItem","position":2,"name":"@databricks/appkit","item":"https://databricks.github.io/appkit/docs/api/appkit/"},{"@type":"ListItem","position":3,"name":"InitializationError","item":"https://databricks.github.io/appkit/docs/api/appkit/Class.InitializationError"}]}</script><link rel="stylesheet" href="/appkit/assets/css/styles.36a38b99.css">
|
|
7
|
-
<script src="/appkit/assets/js/runtime~main.
|
|
8
|
-
<script src="/appkit/assets/js/main.
|
|
7
|
+
<script src="/appkit/assets/js/runtime~main.5342f46a.js" defer="defer"></script>
|
|
8
|
+
<script src="/appkit/assets/js/main.bfddc833.js" defer="defer"></script>
|
|
9
9
|
</head>
|
|
10
10
|
<body class="navigation-with-keyboard">
|
|
11
11
|
<svg style="display: none;"><defs>
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
5
|
<meta name="generator" content="Docusaurus v3.9.2">
|
|
6
6
|
<title data-rh="true">Abstract Class: Plugin\<TConfig\> | AppKit</title><meta data-rh="true" name="viewport" content="width=device-width,initial-scale=1"><meta data-rh="true" name="twitter:card" content="summary_large_image"><meta data-rh="true" property="og:url" content="https://databricks.github.io/appkit/docs/api/appkit/Class.Plugin"><meta data-rh="true" property="og:locale" content="en"><meta data-rh="true" name="docusaurus_locale" content="en"><meta data-rh="true" name="docsearch:language" content="en"><meta data-rh="true" name="keywords" content="Databricks Apps, Node.js, React.js, SDK, TypeScript, SQL, Databricks, AI, full-stack, development"><meta data-rh="true" name="docusaurus_version" content="current"><meta data-rh="true" name="docusaurus_tag" content="docs-default-current"><meta data-rh="true" name="docsearch:version" content="current"><meta data-rh="true" name="docsearch:docusaurus_tag" content="docs-default-current"><meta data-rh="true" property="og:title" content="Abstract Class: Plugin\<TConfig\> | AppKit"><meta data-rh="true" name="description" content="Base abstract class for creating AppKit plugins."><meta data-rh="true" property="og:description" content="Base abstract class for creating AppKit plugins."><link data-rh="true" rel="icon" href="/appkit/img/favicon.ico"><link data-rh="true" rel="canonical" href="https://databricks.github.io/appkit/docs/api/appkit/Class.Plugin"><link data-rh="true" rel="alternate" href="https://databricks.github.io/appkit/docs/api/appkit/Class.Plugin" hreflang="en"><link data-rh="true" rel="alternate" href="https://databricks.github.io/appkit/docs/api/appkit/Class.Plugin" hreflang="x-default"><script data-rh="true" type="application/ld+json">{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"API reference","item":"https://databricks.github.io/appkit/docs/api/"},{"@type":"ListItem","position":2,"name":"@databricks/appkit","item":"https://databricks.github.io/appkit/docs/api/appkit/"},{"@type":"ListItem","position":3,"name":"Plugin","item":"https://databricks.github.io/appkit/docs/api/appkit/Class.Plugin"}]}</script><link rel="stylesheet" href="/appkit/assets/css/styles.36a38b99.css">
|
|
7
|
-
<script src="/appkit/assets/js/runtime~main.
|
|
8
|
-
<script src="/appkit/assets/js/main.
|
|
7
|
+
<script src="/appkit/assets/js/runtime~main.5342f46a.js" defer="defer"></script>
|
|
8
|
+
<script src="/appkit/assets/js/main.bfddc833.js" defer="defer"></script>
|
|
9
9
|
</head>
|
|
10
10
|
<body class="navigation-with-keyboard">
|
|
11
11
|
<svg style="display: none;"><defs>
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
5
|
<meta name="generator" content="Docusaurus v3.9.2">
|
|
6
6
|
<title data-rh="true">Class: ResourceRegistry | AppKit</title><meta data-rh="true" name="viewport" content="width=device-width,initial-scale=1"><meta data-rh="true" name="twitter:card" content="summary_large_image"><meta data-rh="true" property="og:url" content="https://databricks.github.io/appkit/docs/api/appkit/Class.ResourceRegistry"><meta data-rh="true" property="og:locale" content="en"><meta data-rh="true" name="docusaurus_locale" content="en"><meta data-rh="true" name="docsearch:language" content="en"><meta data-rh="true" name="keywords" content="Databricks Apps, Node.js, React.js, SDK, TypeScript, SQL, Databricks, AI, full-stack, development"><meta data-rh="true" name="docusaurus_version" content="current"><meta data-rh="true" name="docusaurus_tag" content="docs-default-current"><meta data-rh="true" name="docsearch:version" content="current"><meta data-rh="true" name="docsearch:docusaurus_tag" content="docs-default-current"><meta data-rh="true" property="og:title" content="Class: ResourceRegistry | AppKit"><meta data-rh="true" name="description" content="Central registry for tracking plugin resource requirements."><meta data-rh="true" property="og:description" content="Central registry for tracking plugin resource requirements."><link data-rh="true" rel="icon" href="/appkit/img/favicon.ico"><link data-rh="true" rel="canonical" href="https://databricks.github.io/appkit/docs/api/appkit/Class.ResourceRegistry"><link data-rh="true" rel="alternate" href="https://databricks.github.io/appkit/docs/api/appkit/Class.ResourceRegistry" hreflang="en"><link data-rh="true" rel="alternate" href="https://databricks.github.io/appkit/docs/api/appkit/Class.ResourceRegistry" hreflang="x-default"><script data-rh="true" type="application/ld+json">{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"API reference","item":"https://databricks.github.io/appkit/docs/api/"},{"@type":"ListItem","position":2,"name":"@databricks/appkit","item":"https://databricks.github.io/appkit/docs/api/appkit/"},{"@type":"ListItem","position":3,"name":"ResourceRegistry","item":"https://databricks.github.io/appkit/docs/api/appkit/Class.ResourceRegistry"}]}</script><link rel="stylesheet" href="/appkit/assets/css/styles.36a38b99.css">
|
|
7
|
-
<script src="/appkit/assets/js/runtime~main.
|
|
8
|
-
<script src="/appkit/assets/js/main.
|
|
7
|
+
<script src="/appkit/assets/js/runtime~main.5342f46a.js" defer="defer"></script>
|
|
8
|
+
<script src="/appkit/assets/js/main.bfddc833.js" defer="defer"></script>
|
|
9
9
|
</head>
|
|
10
10
|
<body class="navigation-with-keyboard">
|
|
11
11
|
<svg style="display: none;"><defs>
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
5
|
<meta name="generator" content="Docusaurus v3.9.2">
|
|
6
6
|
<title data-rh="true">Class: ServerError | AppKit</title><meta data-rh="true" name="viewport" content="width=device-width,initial-scale=1"><meta data-rh="true" name="twitter:card" content="summary_large_image"><meta data-rh="true" property="og:url" content="https://databricks.github.io/appkit/docs/api/appkit/Class.ServerError"><meta data-rh="true" property="og:locale" content="en"><meta data-rh="true" name="docusaurus_locale" content="en"><meta data-rh="true" name="docsearch:language" content="en"><meta data-rh="true" name="keywords" content="Databricks Apps, Node.js, React.js, SDK, TypeScript, SQL, Databricks, AI, full-stack, development"><meta data-rh="true" name="docusaurus_version" content="current"><meta data-rh="true" name="docusaurus_tag" content="docs-default-current"><meta data-rh="true" name="docsearch:version" content="current"><meta data-rh="true" name="docsearch:docusaurus_tag" content="docs-default-current"><meta data-rh="true" property="og:title" content="Class: ServerError | AppKit"><meta data-rh="true" name="description" content="Error thrown when server lifecycle operations fail."><meta data-rh="true" property="og:description" content="Error thrown when server lifecycle operations fail."><link data-rh="true" rel="icon" href="/appkit/img/favicon.ico"><link data-rh="true" rel="canonical" href="https://databricks.github.io/appkit/docs/api/appkit/Class.ServerError"><link data-rh="true" rel="alternate" href="https://databricks.github.io/appkit/docs/api/appkit/Class.ServerError" hreflang="en"><link data-rh="true" rel="alternate" href="https://databricks.github.io/appkit/docs/api/appkit/Class.ServerError" hreflang="x-default"><script data-rh="true" type="application/ld+json">{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"API reference","item":"https://databricks.github.io/appkit/docs/api/"},{"@type":"ListItem","position":2,"name":"@databricks/appkit","item":"https://databricks.github.io/appkit/docs/api/appkit/"},{"@type":"ListItem","position":3,"name":"ServerError","item":"https://databricks.github.io/appkit/docs/api/appkit/Class.ServerError"}]}</script><link rel="stylesheet" href="/appkit/assets/css/styles.36a38b99.css">
|
|
7
|
-
<script src="/appkit/assets/js/runtime~main.
|
|
8
|
-
<script src="/appkit/assets/js/main.
|
|
7
|
+
<script src="/appkit/assets/js/runtime~main.5342f46a.js" defer="defer"></script>
|
|
8
|
+
<script src="/appkit/assets/js/main.bfddc833.js" defer="defer"></script>
|
|
9
9
|
</head>
|
|
10
10
|
<body class="navigation-with-keyboard">
|
|
11
11
|
<svg style="display: none;"><defs>
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
5
|
<meta name="generator" content="Docusaurus v3.9.2">
|
|
6
6
|
<title data-rh="true">Class: TunnelError | AppKit</title><meta data-rh="true" name="viewport" content="width=device-width,initial-scale=1"><meta data-rh="true" name="twitter:card" content="summary_large_image"><meta data-rh="true" property="og:url" content="https://databricks.github.io/appkit/docs/api/appkit/Class.TunnelError"><meta data-rh="true" property="og:locale" content="en"><meta data-rh="true" name="docusaurus_locale" content="en"><meta data-rh="true" name="docsearch:language" content="en"><meta data-rh="true" name="keywords" content="Databricks Apps, Node.js, React.js, SDK, TypeScript, SQL, Databricks, AI, full-stack, development"><meta data-rh="true" name="docusaurus_version" content="current"><meta data-rh="true" name="docusaurus_tag" content="docs-default-current"><meta data-rh="true" name="docsearch:version" content="current"><meta data-rh="true" name="docsearch:docusaurus_tag" content="docs-default-current"><meta data-rh="true" property="og:title" content="Class: TunnelError | AppKit"><meta data-rh="true" name="description" content="Error thrown when remote tunnel operations fail."><meta data-rh="true" property="og:description" content="Error thrown when remote tunnel operations fail."><link data-rh="true" rel="icon" href="/appkit/img/favicon.ico"><link data-rh="true" rel="canonical" href="https://databricks.github.io/appkit/docs/api/appkit/Class.TunnelError"><link data-rh="true" rel="alternate" href="https://databricks.github.io/appkit/docs/api/appkit/Class.TunnelError" hreflang="en"><link data-rh="true" rel="alternate" href="https://databricks.github.io/appkit/docs/api/appkit/Class.TunnelError" hreflang="x-default"><script data-rh="true" type="application/ld+json">{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"API reference","item":"https://databricks.github.io/appkit/docs/api/"},{"@type":"ListItem","position":2,"name":"@databricks/appkit","item":"https://databricks.github.io/appkit/docs/api/appkit/"},{"@type":"ListItem","position":3,"name":"TunnelError","item":"https://databricks.github.io/appkit/docs/api/appkit/Class.TunnelError"}]}</script><link rel="stylesheet" href="/appkit/assets/css/styles.36a38b99.css">
|
|
7
|
-
<script src="/appkit/assets/js/runtime~main.
|
|
8
|
-
<script src="/appkit/assets/js/main.
|
|
7
|
+
<script src="/appkit/assets/js/runtime~main.5342f46a.js" defer="defer"></script>
|
|
8
|
+
<script src="/appkit/assets/js/main.bfddc833.js" defer="defer"></script>
|
|
9
9
|
</head>
|
|
10
10
|
<body class="navigation-with-keyboard">
|
|
11
11
|
<svg style="display: none;"><defs>
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
5
|
<meta name="generator" content="Docusaurus v3.9.2">
|
|
6
6
|
<title data-rh="true">Class: ValidationError | AppKit</title><meta data-rh="true" name="viewport" content="width=device-width,initial-scale=1"><meta data-rh="true" name="twitter:card" content="summary_large_image"><meta data-rh="true" property="og:url" content="https://databricks.github.io/appkit/docs/api/appkit/Class.ValidationError"><meta data-rh="true" property="og:locale" content="en"><meta data-rh="true" name="docusaurus_locale" content="en"><meta data-rh="true" name="docsearch:language" content="en"><meta data-rh="true" name="keywords" content="Databricks Apps, Node.js, React.js, SDK, TypeScript, SQL, Databricks, AI, full-stack, development"><meta data-rh="true" name="docusaurus_version" content="current"><meta data-rh="true" name="docusaurus_tag" content="docs-default-current"><meta data-rh="true" name="docsearch:version" content="current"><meta data-rh="true" name="docsearch:docusaurus_tag" content="docs-default-current"><meta data-rh="true" property="og:title" content="Class: ValidationError | AppKit"><meta data-rh="true" name="description" content="Error thrown when input validation fails."><meta data-rh="true" property="og:description" content="Error thrown when input validation fails."><link data-rh="true" rel="icon" href="/appkit/img/favicon.ico"><link data-rh="true" rel="canonical" href="https://databricks.github.io/appkit/docs/api/appkit/Class.ValidationError"><link data-rh="true" rel="alternate" href="https://databricks.github.io/appkit/docs/api/appkit/Class.ValidationError" hreflang="en"><link data-rh="true" rel="alternate" href="https://databricks.github.io/appkit/docs/api/appkit/Class.ValidationError" hreflang="x-default"><script data-rh="true" type="application/ld+json">{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"API reference","item":"https://databricks.github.io/appkit/docs/api/"},{"@type":"ListItem","position":2,"name":"@databricks/appkit","item":"https://databricks.github.io/appkit/docs/api/appkit/"},{"@type":"ListItem","position":3,"name":"ValidationError","item":"https://databricks.github.io/appkit/docs/api/appkit/Class.ValidationError"}]}</script><link rel="stylesheet" href="/appkit/assets/css/styles.36a38b99.css">
|
|
7
|
-
<script src="/appkit/assets/js/runtime~main.
|
|
8
|
-
<script src="/appkit/assets/js/main.
|
|
7
|
+
<script src="/appkit/assets/js/runtime~main.5342f46a.js" defer="defer"></script>
|
|
8
|
+
<script src="/appkit/assets/js/main.bfddc833.js" defer="defer"></script>
|
|
9
9
|
</head>
|
|
10
10
|
<body class="navigation-with-keyboard">
|
|
11
11
|
<svg style="display: none;"><defs>
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
5
|
<meta name="generator" content="Docusaurus v3.9.2">
|
|
6
6
|
<title data-rh="true">Enumeration: RequestedClaimsPermissionSet | AppKit</title><meta data-rh="true" name="viewport" content="width=device-width,initial-scale=1"><meta data-rh="true" name="twitter:card" content="summary_large_image"><meta data-rh="true" property="og:url" content="https://databricks.github.io/appkit/docs/api/appkit/Enumeration.RequestedClaimsPermissionSet"><meta data-rh="true" property="og:locale" content="en"><meta data-rh="true" name="docusaurus_locale" content="en"><meta data-rh="true" name="docsearch:language" content="en"><meta data-rh="true" name="keywords" content="Databricks Apps, Node.js, React.js, SDK, TypeScript, SQL, Databricks, AI, full-stack, development"><meta data-rh="true" name="docusaurus_version" content="current"><meta data-rh="true" name="docusaurus_tag" content="docs-default-current"><meta data-rh="true" name="docsearch:version" content="current"><meta data-rh="true" name="docsearch:docusaurus_tag" content="docs-default-current"><meta data-rh="true" property="og:title" content="Enumeration: RequestedClaimsPermissionSet | AppKit"><meta data-rh="true" name="description" content="Permission set for Unity Catalog table access"><meta data-rh="true" property="og:description" content="Permission set for Unity Catalog table access"><link data-rh="true" rel="icon" href="/appkit/img/favicon.ico"><link data-rh="true" rel="canonical" href="https://databricks.github.io/appkit/docs/api/appkit/Enumeration.RequestedClaimsPermissionSet"><link data-rh="true" rel="alternate" href="https://databricks.github.io/appkit/docs/api/appkit/Enumeration.RequestedClaimsPermissionSet" hreflang="en"><link data-rh="true" rel="alternate" href="https://databricks.github.io/appkit/docs/api/appkit/Enumeration.RequestedClaimsPermissionSet" hreflang="x-default"><script data-rh="true" type="application/ld+json">{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"API reference","item":"https://databricks.github.io/appkit/docs/api/"},{"@type":"ListItem","position":2,"name":"@databricks/appkit","item":"https://databricks.github.io/appkit/docs/api/appkit/"},{"@type":"ListItem","position":3,"name":"RequestedClaimsPermissionSet","item":"https://databricks.github.io/appkit/docs/api/appkit/Enumeration.RequestedClaimsPermissionSet"}]}</script><link rel="stylesheet" href="/appkit/assets/css/styles.36a38b99.css">
|
|
7
|
-
<script src="/appkit/assets/js/runtime~main.
|
|
8
|
-
<script src="/appkit/assets/js/main.
|
|
7
|
+
<script src="/appkit/assets/js/runtime~main.5342f46a.js" defer="defer"></script>
|
|
8
|
+
<script src="/appkit/assets/js/main.bfddc833.js" defer="defer"></script>
|
|
9
9
|
</head>
|
|
10
10
|
<body class="navigation-with-keyboard">
|
|
11
11
|
<svg style="display: none;"><defs>
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
5
|
<meta name="generator" content="Docusaurus v3.9.2">
|
|
6
6
|
<title data-rh="true">Enumeration: ResourceType | AppKit</title><meta data-rh="true" name="viewport" content="width=device-width,initial-scale=1"><meta data-rh="true" name="twitter:card" content="summary_large_image"><meta data-rh="true" property="og:url" content="https://databricks.github.io/appkit/docs/api/appkit/Enumeration.ResourceType"><meta data-rh="true" property="og:locale" content="en"><meta data-rh="true" name="docusaurus_locale" content="en"><meta data-rh="true" name="docsearch:language" content="en"><meta data-rh="true" name="keywords" content="Databricks Apps, Node.js, React.js, SDK, TypeScript, SQL, Databricks, AI, full-stack, development"><meta data-rh="true" name="docusaurus_version" content="current"><meta data-rh="true" name="docusaurus_tag" content="docs-default-current"><meta data-rh="true" name="docsearch:version" content="current"><meta data-rh="true" name="docsearch:docusaurus_tag" content="docs-default-current"><meta data-rh="true" property="og:title" content="Enumeration: ResourceType | AppKit"><meta data-rh="true" name="description" content="Resource types from schema $defs.resourceType.enum"><meta data-rh="true" property="og:description" content="Resource types from schema $defs.resourceType.enum"><link data-rh="true" rel="icon" href="/appkit/img/favicon.ico"><link data-rh="true" rel="canonical" href="https://databricks.github.io/appkit/docs/api/appkit/Enumeration.ResourceType"><link data-rh="true" rel="alternate" href="https://databricks.github.io/appkit/docs/api/appkit/Enumeration.ResourceType" hreflang="en"><link data-rh="true" rel="alternate" href="https://databricks.github.io/appkit/docs/api/appkit/Enumeration.ResourceType" hreflang="x-default"><script data-rh="true" type="application/ld+json">{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"API reference","item":"https://databricks.github.io/appkit/docs/api/"},{"@type":"ListItem","position":2,"name":"@databricks/appkit","item":"https://databricks.github.io/appkit/docs/api/appkit/"},{"@type":"ListItem","position":3,"name":"ResourceType","item":"https://databricks.github.io/appkit/docs/api/appkit/Enumeration.ResourceType"}]}</script><link rel="stylesheet" href="/appkit/assets/css/styles.36a38b99.css">
|
|
7
|
-
<script src="/appkit/assets/js/runtime~main.
|
|
8
|
-
<script src="/appkit/assets/js/main.
|
|
7
|
+
<script src="/appkit/assets/js/runtime~main.5342f46a.js" defer="defer"></script>
|
|
8
|
+
<script src="/appkit/assets/js/main.bfddc833.js" defer="defer"></script>
|
|
9
9
|
</head>
|
|
10
10
|
<body class="navigation-with-keyboard">
|
|
11
11
|
<svg style="display: none;"><defs>
|