Skip to content

feat/Admin UI local storage adapter + build improvements#345

Open
jonaspm wants to merge 7 commits intobknd-io:mainfrom
jonaspm:feat/admin-ui-local-storage-adapter
Open

feat/Admin UI local storage adapter + build improvements#345
jonaspm wants to merge 7 commits intobknd-io:mainfrom
jonaspm:feat/admin-ui-local-storage-adapter

Conversation

@jonaspm
Copy link
Contributor

@jonaspm jonaspm commented Jan 28, 2026

This pull request refactors how media storage adapters and their schemas are managed, with a focus on improving modularity, runtime flexibility, and compatibility across different environments (Node.js, Bun, browser). The key changes include extracting adapter schemas to a central location, supporting dynamic adapter loading, and cleaning up registry usage. These improvements make it easier to add new adapters, avoid unnecessary dependencies, and ensure that UI and runtime environments only load what they need.

  • Ran tests
  • Tested with real project via bun link bknd
  • Windows 11 environment used
image

Adapter schema and registry refactor:

  • All storage adapter schemas (local, s3, cloudinary) are now defined in a new central file adapter-schemas.ts, which is free of Node.js dependencies and safe to import in any environment. This enables the Admin UI to display configuration options for all adapters without requiring the actual adapter implementations.
  • The media adapter registry is updated to only register adapters that are safe for the current runtime, and the previous MediaAdapters export is removed to prevent accidental static imports of Node.js-dependent code. [1] [2]
  • The schema-building logic in media-schema.ts now uses the new centralized adapter schemas, ensuring that UI and validation code do not require Node.js modules.

Dynamic adapter loading and backwards compatibility:

  • The AppMedia module now dynamically imports the local storage adapter at runtime if it is not already registered, providing clear error messages if used in unsupported environments. This avoids bundling Node.js code in browser builds and supports flexible adapter registration. [1] [2] [3]
  • The StorageLocalAdapter re-exports the schema and type from the new central schema file for backwards compatibility, and ensures parent directories exist when writing files. Minor improvements include more robust error handling and argument naming. [1] [2] [3] [4] [5]

Loca storage adapter:

  • Attempt to create path directory before create file, avoid error when the directory does not exist.

Testing:

  • Clarified a skipped test in AppMedia.spec.ts to document its purpose as a debug helper for logging the media config.

UI:

  • Now the Local adapter is displayed on the Media Settings Admin UI page.

Build Process:

  • Replaced a shell-based dist cleaning command with a cross-platform Node.js implementation, ensuring compatibility with different operating systems. [1] [2]
  • Improved external dependency handling in the build script to use regular expressions for Node.js and Bun built-ins, making the build process more robust for browser and neutral platform builds.
  • Simplified and fixed the build process for Bun and SQLite adapters to avoid redundant or unnecessary external configuration. [1] [2]

- Move local adapter schema and type to dedicated module
- Add StorageLocalAdapterBase for schema-only usage without Node.js deps
- Update StorageLocalAdapter to extend the new base class
- Register StorageLocalAdapterBase in media registry
- Re-export schema and base class from local adapter index
- Move all adapter schemas to a new adapter-schemas.ts with no Node.js
  deps
- Remove StorageLocalAdapterBase and related files
- Update registry to only register adapters safe for all environments
- Dynamically import and register local adapter at runtime in
  Node.js/Bun
- Update AppMedia to use new getAdapterClass logic
- Update media schema builder to use adapterSchemas
- Comment out AdapterIcon in UI to avoid missing icon for local adapter
Simplify and centralize externalization of Node.js and Bun built-ins.
Remove redundant esbuildOptions and external config in build steps.
@jonaspm jonaspm changed the title feat/Admin UI local storage adapter + cross-platform build feat/Admin UI local storage adapter + build improvements Jan 28, 2026
Copy link
Collaborator

@cameronapak cameronapak left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not someone who can truly affirm and validate this code since I'm not Dennis. However, I think the code feels good.

question: Can make it where the local adapter is available if the mode-specific bknd config flag of isProduction is false? (see https://docs.bknd.io/usage/introduction/#mode-helpers)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems like a good idea. I like the abstraction and keeping the schemas in a specific place.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah this change was a consequence of an error that was showing up when loading the Local Storage Adapter into the UI, the Node imports blocked me from just loading it into the client, therefore I had to separate the schema of the class.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Build improvements come from trying to build and test on Windows and errors showing up.

Copy link
Contributor Author

@jonaspm jonaspm Jan 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automatic path creation for the local storage adapter was not needed really but was easy to implement and is a nice to have when you want to save time by avoiding having to configure the path manually.

@cameronapak
Copy link
Collaborator

And btw, I love the idea of this feature in the Admin Dashboard UI and hope it gets approved

@jonaspm
Copy link
Contributor Author

jonaspm commented Jan 29, 2026

I'm not someone who can truly affirm and validate this code since I'm not Dennis. However, I think the code feels good.

question: Can make it where the local adapter is available if the mode-specific bknd config flag of isProduction is false? (see https://docs.bknd.io/usage/introduction/#mode-helpers)

In code mode it is pretty easy to control what lands into the bknd config before it gets loaded but in the UI mode it's not.

I think it could be implemented an environment specific config, let me explain:

You start setting up production configuration, that is the main source of truth, then you decide that you want a different configuration for development environment, therefore you go into the UI, select "Development" environment at the top navbar then any deviating config is stored into that mode, so now you have main complete production config + development only overrides. does that make sense?

Gemini Nano Banana almost nailed the idea:
image

@cameronapak
Copy link
Collaborator

That makes sense. It's like how on Supabase you can do branching to have a staging environment and config and a separate one for production

What do you think the config would look like in code mode to handle allowing for both?

Or would there be multiple bknd configs?

@jonaspm
Copy link
Contributor Author

jonaspm commented Jan 30, 2026

That makes sense. It's like how on Supabase you can do branching to have a staging environment and config and a separate one for production

What do you think the config would look like in code mode to handle allowing for both?

Or would there be multiple bknd configs?

In code I think it could be like this: the config can be changed just by having multiple json config files. let's say you are using the appconfig-dev.json and the app is running smoothly then, you change the code to import the appconfig-prod.json, then the application reloads and the new configuration is respected.

@jonaspm jonaspm requested a review from cameronapak January 31, 2026 00:54
@jonaspm
Copy link
Contributor Author

jonaspm commented Feb 4, 2026

hello @dswbx @cameronapak is there anything else needed from my side to get these changes merged?

best regards!

@cameronapak
Copy link
Collaborator

I'll admit I've been behind on things due to a pickup of focus at work. I cannot answer your question at this second. But when I get a stretch of free time to look through this, I'll make sure that I'm present and can respond well.

From what I remember, it'd be nice if this could only show local if it's not production in the config, but maybe I'm oversimplifying it. My main concern that I have is we should not have local in production unless the user's running on their own VPS or something, right?

@jonaspm
Copy link
Contributor Author

jonaspm commented Feb 4, 2026

I'll admit I've been behind on things due to a pickup of focus at work. I cannot answer your question at this second. But when I get a stretch of free time to look through this, I'll make sure that I'm present and can respond well.

From what I remember, it'd be nice if this could only show local if it's not production in the config, but maybe I'm oversimplifying it. My main concern that I have is we should not have local in production unless the user's running on their own VPS or something, right?

If the environment does not support local storage then it will gracefully fail when required node packages are dynamically imported. I think we should let the user choose local storage even if it is production for the ones who's use case require it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants