Compare commits
34
Commits
tsdown
...
update-deps
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e001f64767 | ||
|
|
a73609f9ec | ||
|
|
9235467a81 | ||
|
|
dfa37b5244 | ||
|
|
8263db505e | ||
|
|
37bdd6f203 | ||
|
|
0bfcb5ad71 | ||
|
|
05e0086fcd | ||
|
|
282c9f6054 | ||
|
|
b294ee68ac | ||
|
|
e8a256af2a | ||
|
|
4709fec45c | ||
|
|
da80e91074 | ||
|
|
3ad9fd01e1 | ||
|
|
89d7e4ea2b | ||
|
|
6e3b7515d5 | ||
|
|
62d3a9c4f4 | ||
|
|
919d9f15d1 | ||
|
|
e68d29760a | ||
|
|
eba2f8a535 | ||
|
|
6cfdb77ba0 | ||
|
|
8c596781ff | ||
|
|
b2315ed012 | ||
|
|
9e5c77db79 | ||
|
|
5892b898bf | ||
|
|
fc83a593a0 | ||
|
|
8d37f9df3f | ||
|
|
43cbdb3010 | ||
|
|
b3c9f258de | ||
|
|
5c3d3d763e | ||
|
|
407d103a5f | ||
|
|
2fd8b9f9a0 | ||
|
|
e81636ea95 | ||
|
|
37c36e5d07 |
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"mcpServers": {
|
"mcpServers": {
|
||||||
"bknd": {
|
"userbase": {
|
||||||
"url": "http://localhost:28623/api/system/mcp"
|
"url": "http://localhost:28623/api/system/mcp"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,9 +15,9 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
POSTGRES_PASSWORD: postgres
|
POSTGRES_PASSWORD: postgres
|
||||||
POSTGRES_USER: postgres
|
POSTGRES_USER: postgres
|
||||||
POSTGRES_DB: bknd
|
POSTGRES_DB: userbase
|
||||||
ports:
|
# ports:
|
||||||
- 5430:5432
|
# - 5430:5432
|
||||||
options: >-
|
options: >-
|
||||||
--health-cmd pg_isready
|
--health-cmd pg_isready
|
||||||
--health-interval 10s
|
--health-interval 10s
|
||||||
|
|||||||
Vendored
+8
-5
@@ -1,19 +1,22 @@
|
|||||||
{
|
{
|
||||||
"typescript.tsdk": "node_modules/typescript/lib",
|
"js/ts.tsdk.path": "node_modules/typescript/lib",
|
||||||
"biome.enabled": true,
|
"biome.enabled": true,
|
||||||
"editor.defaultFormatter": "biomejs.biome",
|
"editor.defaultFormatter": "biomejs.biome",
|
||||||
"editor.codeActionsOnSave": {
|
"editor.codeActionsOnSave": {
|
||||||
//"source.organizeImports.biome": "explicit",
|
//"source.organizeImports.biome": "explicit",
|
||||||
"source.fixAll.biome": "explicit"
|
"source.fixAll.biome": "explicit"
|
||||||
},
|
},
|
||||||
"typescript.preferences.importModuleSpecifier": "non-relative",
|
"js/ts.preferences.importModuleSpecifier": "non-relative",
|
||||||
"typescript.preferences.autoImportFileExcludePatterns": [
|
"js/ts.preferences.autoImportFileExcludePatterns": [
|
||||||
"**/dist/**",
|
"**/dist/**",
|
||||||
"**/node_modules/**/dist/**",
|
"**/node_modules/**/dist/**",
|
||||||
"**/node_modules/**/!(src|lib|esm)/**" // optional, stricter
|
"**/node_modules/**/!(src|lib|esm)/**" // optional, stricter
|
||||||
],
|
],
|
||||||
"typescript.preferences.includePackageJsonAutoImports": "on",
|
"js/ts.preferences.includePackageJsonAutoImports": "on",
|
||||||
"typescript.tsserver.watchOptions": {
|
"js/ts.tsserver.watchOptions": {
|
||||||
"excludeDirectories": ["**/dist", "**/node_modules/**/dist"]
|
"excludeDirectories": ["**/dist", "**/node_modules/**/dist"]
|
||||||
|
},
|
||||||
|
"[typescriptreact]": {
|
||||||
|
"editor.defaultFormatter": "biomejs.biome"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+22
-22
@@ -1,6 +1,6 @@
|
|||||||
# Contributing to bknd
|
# Contributing to userbase
|
||||||
|
|
||||||
Thank you for your interest in contributing to bknd. This guide will help you get started, understand the codebase, and submit contributions that align with the project's direction.
|
Thank you for your interest in contributing to userbase. This guide will help you get started, understand the codebase, and submit contributions that align with the project's direction.
|
||||||
|
|
||||||
## Table of Contents
|
## Table of Contents
|
||||||
|
|
||||||
@@ -23,7 +23,7 @@ Thank you for your interest in contributing to bknd. This guide will help you ge
|
|||||||
|
|
||||||
**Open a GitHub Issue before writing code.** This is the preferred way to propose any change. It lets maintainers and the community align on the approach before time is spent on implementation. If you have discussed a contribution in the [Discord server](https://discord.com/invite/952SFk8Tb8) instead, include a link to the relevant Discord thread in your pull request. Pull requests submitted without a corresponding issue or Discord discussion may be closed.
|
**Open a GitHub Issue before writing code.** This is the preferred way to propose any change. It lets maintainers and the community align on the approach before time is spent on implementation. If you have discussed a contribution in the [Discord server](https://discord.com/invite/952SFk8Tb8) instead, include a link to the relevant Discord thread in your pull request. Pull requests submitted without a corresponding issue or Discord discussion may be closed.
|
||||||
|
|
||||||
**Unsolicited architectural changes will be closed.** The internal architecture of bknd is intentional. Refactors, restructuring, or changes to core patterns must be discussed and approved before any code is written.
|
**Unsolicited architectural changes will be closed.** The internal architecture of userbase is intentional. Refactors, restructuring, or changes to core patterns must be discussed and approved before any code is written.
|
||||||
|
|
||||||
Contributions that are generally welcome (after opening an issue):
|
Contributions that are generally welcome (after opening an issue):
|
||||||
|
|
||||||
@@ -33,12 +33,12 @@ Contributions that are generally welcome (after opening an issue):
|
|||||||
- New examples
|
- New examples
|
||||||
- Test coverage improvements
|
- Test coverage improvements
|
||||||
|
|
||||||
**A note on versioning**: bknd is pre-1.0 and under active development. Full backward compatibility is not guaranteed before v1.0.0. Contributors should be aware that APIs and internal interfaces may change between releases.
|
**A note on versioning**: userbase is pre-1.0 and under active development. Full backward compatibility is not guaranteed before v1.0.0. Contributors should be aware that APIs and internal interfaces may change between releases.
|
||||||
|
|
||||||
## Important Resources
|
## Important Resources
|
||||||
|
|
||||||
- **Documentation**: https://docs.bknd.io
|
- **Documentation**: https://docs.userbase.io
|
||||||
- **Issue Tracker**: https://github.com/bknd-io/bknd/issues
|
- **Issue Tracker**: https://github.com/userbase-io/userbase/issues
|
||||||
- **Discord**: https://discord.com/invite/952SFk8Tb8
|
- **Discord**: https://discord.com/invite/952SFk8Tb8
|
||||||
- **FAQ / Search**: https://www.answeroverflow.com/c/1308395750564302952
|
- **FAQ / Search**: https://www.answeroverflow.com/c/1308395750564302952
|
||||||
|
|
||||||
@@ -86,8 +86,8 @@ Contributions that are generally welcome (after opening an issue):
|
|||||||
This is a Bun monorepo using workspaces. The vast majority of the code lives in `app/`.
|
This is a Bun monorepo using workspaces. The vast majority of the code lives in `app/`.
|
||||||
|
|
||||||
```
|
```
|
||||||
bknd/
|
userbase/
|
||||||
app/ # Main "bknd" npm package (this is where most work happens)
|
app/ # Main "userbase" npm package (this is where most work happens)
|
||||||
src/
|
src/
|
||||||
adapter/ # Runtime/framework adapters (node, bun, cloudflare, nextjs, astro, etc.)
|
adapter/ # Runtime/framework adapters (node, bun, cloudflare, nextjs, astro, etc.)
|
||||||
auth/ # Authentication module (strategies, sessions, user pool)
|
auth/ # Authentication module (strategies, sessions, user pool)
|
||||||
@@ -100,9 +100,9 @@ bknd/
|
|||||||
modules/ # Module system, MCP server, permissions framework
|
modules/ # Module system, MCP server, permissions framework
|
||||||
plugins/ # Built-in plugins (auth, data, cloudflare, dev)
|
plugins/ # Built-in plugins (auth, data, cloudflare, dev)
|
||||||
ui/ # All frontend code
|
ui/ # All frontend code
|
||||||
client/ # TypeScript SDK and React hooks (exported as bknd/client)
|
client/ # TypeScript SDK and React hooks (exported as userbase/client)
|
||||||
elements/ # React components for auth/media (exported as bknd/elements)
|
elements/ # React components for auth/media (exported as userbase/elements)
|
||||||
(everything else) # Admin UI (exported as bknd/ui)
|
(everything else) # Admin UI (exported as userbase/ui)
|
||||||
App.ts # Central application orchestrator
|
App.ts # Central application orchestrator
|
||||||
index.ts # Main package exports
|
index.ts # Main package exports
|
||||||
__test__/ # Unit tests (mirrors src/ structure)
|
__test__/ # Unit tests (mirrors src/ structure)
|
||||||
@@ -110,11 +110,11 @@ bknd/
|
|||||||
build.ts # Build script (tsup/esbuild)
|
build.ts # Build script (tsup/esbuild)
|
||||||
build.cli.ts # CLI build script
|
build.cli.ts # CLI build script
|
||||||
packages/ # Small satellite packages
|
packages/ # Small satellite packages
|
||||||
cli/ # Standalone CLI package (bknd-cli)
|
cli/ # Standalone CLI package (userbase-cli)
|
||||||
plasmic/ # Plasmic integration
|
plasmic/ # Plasmic integration
|
||||||
postgres/ # Postgres helper
|
postgres/ # Postgres helper
|
||||||
sqlocal/ # SQLocal helper
|
sqlocal/ # SQLocal helper
|
||||||
docs/ # Documentation site (Next.js + Fumadocs, deployed to docs.bknd.io)
|
docs/ # Documentation site (Next.js + Fumadocs, deployed to docs.userbase.io)
|
||||||
examples/ # Example projects across runtimes and frameworks
|
examples/ # Example projects across runtimes and frameworks
|
||||||
docker/ # Docker configuration
|
docker/ # Docker configuration
|
||||||
```
|
```
|
||||||
@@ -127,7 +127,7 @@ The project uses TypeScript path aliases defined in `app/tsconfig.json`. Imports
|
|||||||
|
|
||||||
### Module System
|
### Module System
|
||||||
|
|
||||||
bknd is built around four core modules, each with its own schema, API routes, and permissions:
|
userbase is built around four core modules, each with its own schema, API routes, and permissions:
|
||||||
|
|
||||||
- **Data** -- entity definitions, field types, relations, queries (backed by Kysely)
|
- **Data** -- entity definitions, field types, relations, queries (backed by Kysely)
|
||||||
- **Auth** -- authentication strategies, sessions, user management
|
- **Auth** -- authentication strategies, sessions, user management
|
||||||
@@ -138,7 +138,7 @@ These modules are managed by the `ModuleManager` (in `app/src/modules/`), which
|
|||||||
|
|
||||||
### Adapter Pattern
|
### Adapter Pattern
|
||||||
|
|
||||||
Adapters in `app/src/adapter/` allow bknd to run on different runtimes and frameworks. Each adapter provides the glue between bknd's Hono-based server and a specific environment (Node, Bun, Cloudflare Workers, Next.js, Astro, etc.).
|
Adapters in `app/src/adapter/` allow userbase to run on different runtimes and frameworks. Each adapter provides the glue between userbase's Hono-based server and a specific environment (Node, Bun, Cloudflare Workers, Next.js, Astro, etc.).
|
||||||
|
|
||||||
### Plugin System
|
### Plugin System
|
||||||
|
|
||||||
@@ -242,26 +242,26 @@ Open a GitHub Issue with:
|
|||||||
- A clear title describing the problem.
|
- A clear title describing the problem.
|
||||||
- Steps to reproduce the bug.
|
- Steps to reproduce the bug.
|
||||||
- Expected behavior vs. actual behavior.
|
- Expected behavior vs. actual behavior.
|
||||||
- Your environment (runtime, database, adapter, bknd version).
|
- Your environment (runtime, database, adapter, userbase version).
|
||||||
- Any relevant error messages or logs.
|
- Any relevant error messages or logs.
|
||||||
|
|
||||||
## Getting Help
|
## Getting Help
|
||||||
|
|
||||||
- **Discord**: https://discord.com/invite/952SFk8Tb8
|
- **Discord**: https://discord.com/invite/952SFk8Tb8
|
||||||
- **FAQ / Search**: https://www.answeroverflow.com/c/1308395750564302952
|
- **FAQ / Search**: https://www.answeroverflow.com/c/1308395750564302952
|
||||||
- **GitHub Issues**: https://github.com/bknd-io/bknd/issues
|
- **GitHub Issues**: https://github.com/userbase-io/userbase/issues
|
||||||
|
|
||||||
## Contributors
|
## Contributors
|
||||||
|
|
||||||
Thank you to everyone who has contributed to bknd.
|
Thank you to everyone who has contributed to userbase.
|
||||||
|
|
||||||
<a href="https://github.com/bknd-io/bknd/graphs/contributors">
|
<a href="https://github.com/userbase-io/userbase/graphs/contributors">
|
||||||
<img src="https://contrib.rocks/image?repo=bknd-io/bknd" />
|
<img src="https://contrib.rocks/image?repo=userbase-io/userbase" />
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
Made with [contrib.rocks](https://contrib.rocks).
|
Made with [contrib.rocks](https://contrib.rocks).
|
||||||
|
|
||||||
## Maintainers
|
## Maintainers
|
||||||
|
|
||||||
- **Dennis** ([@dswbx](https://github.com/dswbx)) -- Creator and maintainer of bknd
|
- **Dennis** ([@dswbx](https://github.com/dswbx)) -- Creator and maintainer of userbase
|
||||||
- **Cameron Pak** ([@cameronapak](https://github.com/cameronapak)) -- Maintainer of bknd docs
|
- **Cameron Pak** ([@cameronapak](https://github.com/cameronapak)) -- Maintainer of userbase docs
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
This is an independently maintained fork of [bknd](https://github.com/bknd-io/bknd) which is a drop in replacement for the original package. It is intended to be used in projects that require a more up-to-date version of bknd, or that need to use features that are not available in the original package.
|
||||||
|
|
||||||
[](https://npmjs.org/package/bknd)
|
[](https://npmjs.org/package/bknd)
|
||||||
|
|
||||||

|

|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
playwright-report
|
playwright-report
|
||||||
test-results
|
test-results
|
||||||
bknd.config.*
|
userbase.config.*
|
||||||
__test__/helper.d.ts
|
__test__/helper.d.ts
|
||||||
.env.local
|
.env.local
|
||||||
@@ -4,73 +4,72 @@ import { disableConsoleLog, enableConsoleLog, omitKeys } from "core/utils";
|
|||||||
import { adapterTestSuite } from "adapter/adapter-test-suite";
|
import { adapterTestSuite } from "adapter/adapter-test-suite";
|
||||||
import { bunTestRunner } from "adapter/bun/test";
|
import { bunTestRunner } from "adapter/bun/test";
|
||||||
|
|
||||||
const stripConnection = <T extends Record<string, any>>(cfg: T) =>
|
const stripConnection = <T extends Record<string, any>>(cfg: T) => omitKeys(cfg, ["connection"]);
|
||||||
omitKeys(cfg, ["connection"]);
|
|
||||||
|
|
||||||
beforeAll(disableConsoleLog);
|
beforeAll(disableConsoleLog);
|
||||||
afterAll(enableConsoleLog);
|
afterAll(enableConsoleLog);
|
||||||
|
|
||||||
describe("adapter", () => {
|
describe("adapter", () => {
|
||||||
describe("makeConfig", () => {
|
describe("makeConfig", () => {
|
||||||
it("returns empty config for empty inputs", async () => {
|
it("returns empty config for empty inputs", async () => {
|
||||||
const cases: Array<Parameters<typeof adapter.makeConfig>> = [
|
const cases: Array<Parameters<typeof adapter.makeConfig>> = [
|
||||||
[{}],
|
[{}],
|
||||||
[{}, { env: { TEST: "test" } }],
|
[{}, { env: { TEST: "test" } }],
|
||||||
];
|
];
|
||||||
|
|
||||||
for (const args of cases) {
|
for (const args of cases) {
|
||||||
const cfg = await adapter.makeConfig(...(args as any));
|
const cfg = await adapter.makeConfig(...(args as any));
|
||||||
expect(stripConnection(cfg)).toEqual({});
|
expect(stripConnection(cfg)).toEqual({});
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
|
||||||
it("merges app output into config", async () => {
|
|
||||||
const cfg = await adapter.makeConfig(
|
|
||||||
{ app: (a) => ({ config: { server: { cors: { origin: a.env.TEST } } } }) },
|
|
||||||
{ env: { TEST: "test" } },
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(stripConnection(cfg)).toEqual({
|
|
||||||
config: { server: { cors: { origin: "test" } } },
|
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
it("allows all properties in app() result", async () => {
|
it("merges app output into config", async () => {
|
||||||
const called = mock(() => null);
|
const cfg = await adapter.makeConfig(
|
||||||
|
{ app: (a) => ({ config: { server: { cors: { origin: a.env.TEST } } } }) },
|
||||||
|
{ env: { TEST: "test" } },
|
||||||
|
);
|
||||||
|
|
||||||
const cfg = await adapter.makeConfig(
|
expect(stripConnection(cfg)).toEqual({
|
||||||
{
|
|
||||||
app: (env) => ({
|
|
||||||
connection: { url: "test" },
|
|
||||||
config: { server: { cors: { origin: "test" } } },
|
config: { server: { cors: { origin: "test" } } },
|
||||||
options: { mode: "db" as const },
|
});
|
||||||
onBuilt: () => {
|
});
|
||||||
called();
|
|
||||||
expect(env).toEqual({ foo: "bar" });
|
it("allows all properties in app() result", async () => {
|
||||||
|
const called = mock(() => null);
|
||||||
|
|
||||||
|
const cfg = await adapter.makeConfig(
|
||||||
|
{
|
||||||
|
app: (env) => ({
|
||||||
|
connection: { url: "test" },
|
||||||
|
config: { server: { cors: { origin: "test" } } },
|
||||||
|
options: { mode: "db" as const },
|
||||||
|
onBuilt: () => {
|
||||||
|
called();
|
||||||
|
expect(env).toEqual({ foo: "bar" });
|
||||||
|
},
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
}),
|
{ foo: "bar" },
|
||||||
},
|
);
|
||||||
{ foo: "bar" },
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(cfg.connection).toEqual({ url: "test" });
|
expect(cfg.connection).toEqual({ url: "test" });
|
||||||
expect(cfg.config).toEqual({ server: { cors: { origin: "test" } } });
|
expect(cfg.config).toEqual({ server: { cors: { origin: "test" } } });
|
||||||
expect(cfg.options).toEqual({ mode: "db" });
|
expect(cfg.options).toEqual({ mode: "db" });
|
||||||
|
|
||||||
await cfg.onBuilt?.({} as any);
|
await cfg.onBuilt?.({} as any);
|
||||||
expect(called).toHaveBeenCalledTimes(1);
|
expect(called).toHaveBeenCalledTimes(1);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("adapter test suites", () => {
|
describe("adapter test suites", () => {
|
||||||
adapterTestSuite(bunTestRunner, {
|
adapterTestSuite(bunTestRunner, {
|
||||||
makeApp: adapter.createFrameworkApp,
|
makeApp: adapter.createFrameworkApp,
|
||||||
label: "framework app",
|
label: "framework app",
|
||||||
});
|
});
|
||||||
|
|
||||||
adapterTestSuite(bunTestRunner, {
|
adapterTestSuite(bunTestRunner, {
|
||||||
makeApp: adapter.createRuntimeApp,
|
makeApp: adapter.createRuntimeApp,
|
||||||
label: "runtime app",
|
label: "runtime app",
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -73,7 +73,13 @@ describe("Api", async () => {
|
|||||||
|
|
||||||
it("should extract tokens case insensitive", async () => {
|
it("should extract tokens case insensitive", async () => {
|
||||||
const token = await sign({ sub: "test" }, "1234");
|
const token = await sign({ sub: "test" }, "1234");
|
||||||
expect(new Api({ headers: new Headers({ Authorization: `Bearer ${token}` }) }).getAuthState().token).toBe(token);
|
expect(
|
||||||
expect(new Api({ headers: new Headers({ Authorization: `bearer ${token}` }) }).getAuthState().token).toBe(token);
|
new Api({ headers: new Headers({ Authorization: `Bearer ${token}` }) }).getAuthState()
|
||||||
})
|
.token,
|
||||||
|
).toBe(token);
|
||||||
|
expect(
|
||||||
|
new Api({ headers: new Headers({ Authorization: `bearer ${token}` }) }).getAuthState()
|
||||||
|
.token,
|
||||||
|
).toBe(token);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { describe, expect, mock, test, beforeAll, afterAll } from "bun:test";
|
import { describe, expect, mock, test, beforeAll, afterAll } from "bun:test";
|
||||||
import { createApp as internalCreateApp, type CreateAppConfig } from "bknd";
|
import { createApp as internalCreateApp, type CreateAppConfig } from "userbase";
|
||||||
import { getDummyConnection } from "../../__test__/helper";
|
import { getDummyConnection } from "../../__test__/helper";
|
||||||
import { ModuleManager } from "modules/ModuleManager";
|
import { ModuleManager } from "modules/ModuleManager";
|
||||||
import { em, entity, text } from "data/prototype";
|
import { em, entity, text } from "data/prototype";
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { describe, test, expect, beforeEach, beforeAll, afterAll } from "bun:test";
|
import { describe, test, expect, beforeEach, beforeAll, afterAll } from "bun:test";
|
||||||
import { type App, createApp, createMcpToolCaller } from "core/test/utils";
|
import { type App, createApp, createMcpToolCaller } from "core/test/utils";
|
||||||
import { disableConsoleLog, enableConsoleLog } from "core/utils";
|
import { disableConsoleLog, enableConsoleLog } from "core/utils";
|
||||||
import type { McpServer } from "bknd/utils";
|
import type { McpServer } from "userbase/utils";
|
||||||
|
|
||||||
beforeAll(disableConsoleLog);
|
beforeAll(disableConsoleLog);
|
||||||
afterAll(enableConsoleLog);
|
afterAll(enableConsoleLog);
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { describe, test, expect, beforeEach, beforeAll, afterAll } from "bun:test";
|
import { describe, test, expect, beforeEach, beforeAll, afterAll } from "bun:test";
|
||||||
import { type App, createApp, createMcpToolCaller } from "core/test/utils";
|
import { type App, createApp, createMcpToolCaller } from "core/test/utils";
|
||||||
import { getSystemMcp } from "modules/mcp/system-mcp";
|
import { getSystemMcp } from "modules/mcp/system-mcp";
|
||||||
import { pickKeys, type McpServer } from "bknd/utils";
|
import { pickKeys, type McpServer } from "userbase/utils";
|
||||||
import { entity, text } from "bknd";
|
import { entity, text } from "userbase";
|
||||||
import { disableConsoleLog, enableConsoleLog } from "core/utils";
|
import { disableConsoleLog, enableConsoleLog } from "core/utils";
|
||||||
|
|
||||||
beforeAll(disableConsoleLog);
|
beforeAll(disableConsoleLog);
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { getSystemMcp } from "modules/mcp/system-mcp";
|
|||||||
import { registries } from "index";
|
import { registries } from "index";
|
||||||
import { StorageLocalAdapter } from "adapter/node/storage/StorageLocalAdapter";
|
import { StorageLocalAdapter } from "adapter/node/storage/StorageLocalAdapter";
|
||||||
import { disableConsoleLog, enableConsoleLog } from "core/utils";
|
import { disableConsoleLog, enableConsoleLog } from "core/utils";
|
||||||
import type { McpServer } from "bknd/utils";
|
import type { McpServer } from "userbase/utils";
|
||||||
|
|
||||||
beforeAll(disableConsoleLog);
|
beforeAll(disableConsoleLog);
|
||||||
afterAll(enableConsoleLog);
|
afterAll(enableConsoleLog);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { describe, test, expect, beforeAll, afterAll } from "bun:test";
|
import { describe, test, expect, beforeAll, afterAll } from "bun:test";
|
||||||
import { type App, createApp, createMcpToolCaller } from "core/test/utils";
|
import { type App, createApp, createMcpToolCaller } from "core/test/utils";
|
||||||
import type { McpServer } from "bknd/utils";
|
import type { McpServer } from "userbase/utils";
|
||||||
import { disableConsoleLog, enableConsoleLog } from "core/utils/test";
|
import { disableConsoleLog, enableConsoleLog } from "core/utils/test";
|
||||||
|
|
||||||
beforeAll(() => disableConsoleLog());
|
beforeAll(() => disableConsoleLog());
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { AppEvents } from "App";
|
import { AppEvents } from "App";
|
||||||
import { describe, test, expect, beforeAll, mock, afterAll } from "bun:test";
|
import { describe, test, expect, beforeAll, mock, afterAll } from "bun:test";
|
||||||
import { type App, createApp, createMcpToolCaller } from "core/test/utils";
|
import { type App, createApp, createMcpToolCaller } from "core/test/utils";
|
||||||
import type { McpServer } from "bknd/utils";
|
import type { McpServer } from "userbase/utils";
|
||||||
import { disableConsoleLog, enableConsoleLog } from "core/utils/test";
|
import { disableConsoleLog, enableConsoleLog } from "core/utils/test";
|
||||||
|
|
||||||
beforeAll(disableConsoleLog);
|
beforeAll(disableConsoleLog);
|
||||||
|
|||||||
@@ -51,14 +51,18 @@ describe("Authenticator", async () => {
|
|||||||
});
|
});
|
||||||
const token = await auth.jwt({ sub: "test" });
|
const token = await auth.jwt({ sub: "test" });
|
||||||
|
|
||||||
const res = await auth.resolveAuthFromRequest(new Headers({
|
const res = await auth.resolveAuthFromRequest(
|
||||||
Authorization: `Bearer ${token}`,
|
new Headers({
|
||||||
}));
|
Authorization: `Bearer ${token}`,
|
||||||
expect((res as any).sub).toBe("test")
|
}),
|
||||||
|
);
|
||||||
|
expect((res as any).sub).toBe("test");
|
||||||
|
|
||||||
const res2 = await auth.resolveAuthFromRequest(new Headers({
|
const res2 = await auth.resolveAuthFromRequest(
|
||||||
Authorization: `bearer ${token}`,
|
new Headers({
|
||||||
}));
|
Authorization: `bearer ${token}`,
|
||||||
expect((res2 as any).sub).toBe("test")
|
}),
|
||||||
})
|
);
|
||||||
|
expect((res2 as any).sub).toBe("test");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { describe, expect, test, beforeAll, afterAll } from "bun:test";
|
|||||||
import { Guard, type GuardConfig } from "auth/authorize/Guard";
|
import { Guard, type GuardConfig } from "auth/authorize/Guard";
|
||||||
import { Permission } from "auth/authorize/Permission";
|
import { Permission } from "auth/authorize/Permission";
|
||||||
import { Role, type RoleSchema } from "auth/authorize/Role";
|
import { Role, type RoleSchema } from "auth/authorize/Role";
|
||||||
import { objectTransform, s } from "bknd/utils";
|
import { objectTransform, s } from "userbase/utils";
|
||||||
import { disableConsoleLog, enableConsoleLog } from "core/utils/test";
|
import { disableConsoleLog, enableConsoleLog } from "core/utils/test";
|
||||||
|
|
||||||
beforeAll(disableConsoleLog);
|
beforeAll(disableConsoleLog);
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { createApp } from "core/test/utils";
|
|||||||
import type { CreateAppConfig } from "App";
|
import type { CreateAppConfig } from "App";
|
||||||
import * as proto from "data/prototype";
|
import * as proto from "data/prototype";
|
||||||
import { mergeObject } from "core/utils/objects";
|
import { mergeObject } from "core/utils/objects";
|
||||||
import type { App, DB } from "bknd";
|
import type { App, DB } from "userbase";
|
||||||
import type { CreateUserPayload } from "auth/AppAuth";
|
import type { CreateUserPayload } from "auth/AppAuth";
|
||||||
import { disableConsoleLog, enableConsoleLog } from "core/utils/test";
|
import { disableConsoleLog, enableConsoleLog } from "core/utils/test";
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { describe, it, expect } from "bun:test";
|
import { describe, it, expect } from "bun:test";
|
||||||
import { s } from "bknd/utils";
|
import { s } from "userbase/utils";
|
||||||
import { Permission } from "auth/authorize/Permission";
|
import { Permission } from "auth/authorize/Permission";
|
||||||
import { Policy } from "auth/authorize/Policy";
|
import { Policy } from "auth/authorize/Policy";
|
||||||
import { Hono } from "hono";
|
import { Hono } from "hono";
|
||||||
@@ -7,7 +7,7 @@ import { getPermissionRoutes, permission } from "auth/middlewares/permission.mid
|
|||||||
import { auth } from "auth/middlewares/auth.middleware";
|
import { auth } from "auth/middlewares/auth.middleware";
|
||||||
import { Guard, mergeFilters, type GuardConfig } from "auth/authorize/Guard";
|
import { Guard, mergeFilters, type GuardConfig } from "auth/authorize/Guard";
|
||||||
import { Role, RolePermission } from "auth/authorize/Role";
|
import { Role, RolePermission } from "auth/authorize/Role";
|
||||||
import { Exception } from "bknd";
|
import { Exception } from "userbase";
|
||||||
import { convert } from "core/object/query/object-query";
|
import { convert } from "core/object/query/object-query";
|
||||||
|
|
||||||
describe("Permission", () => {
|
describe("Permission", () => {
|
||||||
@@ -421,7 +421,7 @@ describe("permission middleware", () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const res = await hono.request("/test");
|
const res = await hono.request("/test");
|
||||||
// expecting 500 because bknd should have handled it correctly
|
// expecting 500 because userbase should have handled it correctly
|
||||||
expect(res.status).toBe(500);
|
expect(res.status).toBe(500);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ describe("Polymorphic", async () => {
|
|||||||
target: "media",
|
target: "media",
|
||||||
config: {
|
config: {
|
||||||
mappedBy: "image",
|
mappedBy: "image",
|
||||||
|
on_delete: "set null",
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
// media should not see categories
|
// media should not see categories
|
||||||
|
|||||||
@@ -1,19 +1,21 @@
|
|||||||
import { describe, beforeAll, afterAll, test } from "bun:test";
|
import { describe, beforeAll, afterAll, test } from "bun:test";
|
||||||
import type { PostgresConnection } from "data/connection/postgres/PostgresConnection";
|
import type { PostgresConnection } from "data/connection/postgres/PostgresConnection";
|
||||||
import { pg, postgresJs } from "bknd";
|
import { pg, postgresJs } from "userbase";
|
||||||
import { Pool } from "pg";
|
import { Pool } from "pg";
|
||||||
import postgres from "postgres";
|
import postgres from "postgres";
|
||||||
import { disableConsoleLog, enableConsoleLog, $waitUntil } from "bknd/utils";
|
import { disableConsoleLog, enableConsoleLog, $waitUntil } from "userbase/utils";
|
||||||
import { $ } from "bun";
|
import { $ } from "bun";
|
||||||
import { connectionTestSuite } from "data/connection/connection-test-suite";
|
import { connectionTestSuite } from "data/connection/connection-test-suite";
|
||||||
import { bunTestRunner } from "adapter/bun/test";
|
import { bunTestRunner } from "adapter/bun/test";
|
||||||
|
|
||||||
|
const isCI = !!(process.env.GITEA_ACTIONS || process.env.GITHUB_ACTIONS);
|
||||||
|
|
||||||
const credentials = {
|
const credentials = {
|
||||||
host: "localhost",
|
host: isCI ? "postgres" : "localhost",
|
||||||
port: 5430,
|
port: 5432,
|
||||||
user: "postgres",
|
user: "postgres",
|
||||||
password: "postgres",
|
password: "postgres",
|
||||||
database: "bknd",
|
database: "userbase",
|
||||||
};
|
};
|
||||||
|
|
||||||
async function cleanDatabase(connection: InstanceType<typeof PostgresConnection>) {
|
async function cleanDatabase(connection: InstanceType<typeof PostgresConnection>) {
|
||||||
@@ -39,8 +41,13 @@ async function isPostgresRunning() {
|
|||||||
|
|
||||||
describe("postgres", () => {
|
describe("postgres", () => {
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
|
if (process.env.GITEA_ACTIONS || process.env.GITHUB_ACTIONS) {
|
||||||
|
console.log("Running in CI: Skipping manual docker run");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!(await isPostgresRunning())) {
|
if (!(await isPostgresRunning())) {
|
||||||
await $`docker run --rm --name bknd-test-postgres -d -e POSTGRES_PASSWORD=${credentials.password} -e POSTGRES_USER=${credentials.user} -e POSTGRES_DB=${credentials.database} -p ${credentials.port}:5432 postgres:17`;
|
await $`docker run --rm --name userbase-test-postgres -d -e POSTGRES_PASSWORD=${credentials.password} -e POSTGRES_USER=${credentials.user} -e POSTGRES_DB=${credentials.database} -p ${credentials.port}:5432 postgres:17`;
|
||||||
await $waitUntil("Postgres is running", isPostgresRunning, 500, 20);
|
await $waitUntil("Postgres is running", isPostgresRunning, 500, 20);
|
||||||
await new Promise((resolve) => setTimeout(resolve, 500));
|
await new Promise((resolve) => setTimeout(resolve, 500));
|
||||||
}
|
}
|
||||||
@@ -50,7 +57,7 @@ describe("postgres", () => {
|
|||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
if (await isPostgresRunning()) {
|
if (await isPostgresRunning()) {
|
||||||
try {
|
try {
|
||||||
await $`docker stop bknd-test-postgres`;
|
await $`docker stop userbase-test-postgres`;
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import { describe, it, expect } from "bun:test";
|
import { describe, it, expect } from "bun:test";
|
||||||
import * as sDirect from "jsonv-ts";
|
import * as sDirect from "jsonv-ts";
|
||||||
import { s as sFromBknd } from "bknd/utils";
|
import { s as sFromUserbase } from "userbase/utils";
|
||||||
|
|
||||||
describe("jsonv-ts resolution", () => {
|
describe("jsonv-ts resolution", () => {
|
||||||
it("should resolve to a single instance", () => {
|
it("should resolve to a single instance", () => {
|
||||||
const sameNamespace = sDirect === (sFromBknd as unknown as typeof sDirect);
|
const sameNamespace = sDirect === (sFromUserbase as unknown as typeof sDirect);
|
||||||
// If this fails, two instances are being loaded via different specifiers/paths
|
// If this fails, two instances are being loaded via different specifiers/paths
|
||||||
expect(sameNamespace).toBe(true);
|
expect(sameNamespace).toBe(true);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { format as sqlFormat } from "sql-formatter";
|
|||||||
import type { em as protoEm } from "../src/data/prototype";
|
import type { em as protoEm } from "../src/data/prototype";
|
||||||
import { writeFile } from "node:fs/promises";
|
import { writeFile } from "node:fs/promises";
|
||||||
import { join } from "node:path";
|
import { join } from "node:path";
|
||||||
import { slugify } from "bknd/utils";
|
import { slugify } from "userbase/utils";
|
||||||
import { type Connection, SqliteLocalConnection } from "data/connection";
|
import { type Connection, SqliteLocalConnection } from "data/connection";
|
||||||
import { EntityManager } from "data/entities/EntityManager";
|
import { EntityManager } from "data/entities/EntityManager";
|
||||||
|
|
||||||
|
|||||||
@@ -57,11 +57,11 @@ const configs = {
|
|||||||
},
|
},
|
||||||
users: {
|
users: {
|
||||||
normal: {
|
normal: {
|
||||||
email: "normal@bknd.io",
|
email: "normal@userbase.io",
|
||||||
password: "12345678",
|
password: "12345678",
|
||||||
},
|
},
|
||||||
admin: {
|
admin: {
|
||||||
email: "admin@bknd.io",
|
email: "admin@userbase.io",
|
||||||
password: "12345678",
|
password: "12345678",
|
||||||
role: "admin",
|
role: "admin",
|
||||||
},
|
},
|
||||||
@@ -271,7 +271,7 @@ describe("integration auth", () => {
|
|||||||
expect(
|
expect(
|
||||||
await app
|
await app
|
||||||
.createUser({
|
.createUser({
|
||||||
email: "test@bknd.io",
|
email: "test@userbase.io",
|
||||||
password: "12345678",
|
password: "12345678",
|
||||||
})
|
})
|
||||||
.then((r) => r.role),
|
.then((r) => r.role),
|
||||||
@@ -280,7 +280,7 @@ describe("integration auth", () => {
|
|||||||
// throws error if role doesn't exist
|
// throws error if role doesn't exist
|
||||||
expect(
|
expect(
|
||||||
app.createUser({
|
app.createUser({
|
||||||
email: "test@bknd.io",
|
email: "test@userbase.io",
|
||||||
password: "12345678",
|
password: "12345678",
|
||||||
role: "doesnt exist",
|
role: "doesnt exist",
|
||||||
}),
|
}),
|
||||||
@@ -290,7 +290,7 @@ describe("integration auth", () => {
|
|||||||
expect(
|
expect(
|
||||||
await app
|
await app
|
||||||
.createUser({
|
.createUser({
|
||||||
email: "test2@bknd.io",
|
email: "test2@userbase.io",
|
||||||
password: "12345678",
|
password: "12345678",
|
||||||
role: "admin",
|
role: "admin",
|
||||||
})
|
})
|
||||||
@@ -301,7 +301,7 @@ describe("integration auth", () => {
|
|||||||
expect(
|
expect(
|
||||||
await $fns
|
await $fns
|
||||||
.register({
|
.register({
|
||||||
email: "test3@bknd.io",
|
email: "test3@userbase.io",
|
||||||
password: "12345678",
|
password: "12345678",
|
||||||
role: "admin",
|
role: "admin",
|
||||||
})
|
})
|
||||||
@@ -312,7 +312,7 @@ describe("integration auth", () => {
|
|||||||
expect(
|
expect(
|
||||||
await $fns
|
await $fns
|
||||||
.register({
|
.register({
|
||||||
email: "test3@bknd.io",
|
email: "test3@userbase.io",
|
||||||
password: "12345678",
|
password: "12345678",
|
||||||
})
|
})
|
||||||
.then((r) => r.data.user.role),
|
.then((r) => r.data.user.role),
|
||||||
|
|||||||
@@ -136,7 +136,7 @@ describe("AppAuth", () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
test("registers auth middleware for bknd routes only", async () => {
|
test("registers auth middleware for userbase routes only", async () => {
|
||||||
const app = createApp({
|
const app = createApp({
|
||||||
config: {
|
config: {
|
||||||
auth: {
|
auth: {
|
||||||
|
|||||||
@@ -7,7 +7,9 @@ import v7 from "./samples/v7.json";
|
|||||||
import v8 from "./samples/v8.json";
|
import v8 from "./samples/v8.json";
|
||||||
import v8_2 from "./samples/v8-2.json";
|
import v8_2 from "./samples/v8-2.json";
|
||||||
import v9 from "./samples/v9.json";
|
import v9 from "./samples/v9.json";
|
||||||
|
import v10 from "./samples/v10.json";
|
||||||
import { disableConsoleLog, enableConsoleLog } from "core/utils/test";
|
import { disableConsoleLog, enableConsoleLog } from "core/utils/test";
|
||||||
|
import { CURRENT_VERSION } from "modules/db/migrations";
|
||||||
|
|
||||||
beforeAll(() => disableConsoleLog());
|
beforeAll(() => disableConsoleLog());
|
||||||
afterAll(enableConsoleLog);
|
afterAll(enableConsoleLog);
|
||||||
@@ -23,7 +25,7 @@ async function createVersionedApp(
|
|||||||
const { version, ...rest } = config;
|
const { version, ...rest } = config;
|
||||||
|
|
||||||
const db = dummyConnection.kysely as Kysely<any>;
|
const db = dummyConnection.kysely as Kysely<any>;
|
||||||
await sql`CREATE TABLE "__bknd" (
|
await sql`CREATE TABLE "__userbase" (
|
||||||
"id" integer not null primary key autoincrement,
|
"id" integer not null primary key autoincrement,
|
||||||
"version" integer,
|
"version" integer,
|
||||||
"type" text,
|
"type" text,
|
||||||
@@ -33,7 +35,7 @@ async function createVersionedApp(
|
|||||||
)`.execute(db);
|
)`.execute(db);
|
||||||
|
|
||||||
await db
|
await db
|
||||||
.insertInto("__bknd")
|
.insertInto("__userbase")
|
||||||
.values({
|
.values({
|
||||||
version,
|
version,
|
||||||
type: "config",
|
type: "config",
|
||||||
@@ -59,9 +61,9 @@ async function getRawConfig(
|
|||||||
) {
|
) {
|
||||||
const db = app.em.connection.kysely;
|
const db = app.em.connection.kysely;
|
||||||
return await db
|
return await db
|
||||||
.selectFrom("__bknd")
|
.selectFrom("__userbase")
|
||||||
.selectAll()
|
.selectAll()
|
||||||
.$if(!!opts?.version, (qb) => qb.where("version", "=", opts?.version))
|
.where("version", "=", opts?.version ?? CURRENT_VERSION)
|
||||||
.$if((opts?.types?.length ?? 0) > 0, (qb) => qb.where("type", "in", opts?.types))
|
.$if((opts?.types?.length ?? 0) > 0, (qb) => qb.where("type", "in", opts?.types))
|
||||||
.execute();
|
.execute();
|
||||||
}
|
}
|
||||||
@@ -115,7 +117,6 @@ describe("Migrations", () => {
|
|||||||
"^^s3.secret_access_key^^",
|
"^^s3.secret_access_key^^",
|
||||||
);
|
);
|
||||||
const [config, secrets] = (await getRawConfig(app, {
|
const [config, secrets] = (await getRawConfig(app, {
|
||||||
version: 10,
|
|
||||||
types: ["config", "secrets"],
|
types: ["config", "secrets"],
|
||||||
})) as any;
|
})) as any;
|
||||||
|
|
||||||
@@ -129,4 +130,15 @@ describe("Migrations", () => {
|
|||||||
"^^s3.secret_access_key^^",
|
"^^s3.secret_access_key^^",
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("migration from 10 to 11", async () => {
|
||||||
|
expect(v10.version).toBe(10);
|
||||||
|
expect(v10.data.entities.test.fields.title.config.fillable).toEqual(["read", "update"]);
|
||||||
|
|
||||||
|
const app = await createVersionedApp(v10);
|
||||||
|
|
||||||
|
expect(app.version()).toBeGreaterThan(10);
|
||||||
|
const [config] = (await getRawConfig(app, { types: ["config"] })) as any;
|
||||||
|
expect(config.json.data.entities.test.fields.title.config.fillable).toEqual(true);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -0,0 +1,270 @@
|
|||||||
|
{
|
||||||
|
"version": 10,
|
||||||
|
"server": {
|
||||||
|
"cors": {
|
||||||
|
"origin": "*",
|
||||||
|
"allow_methods": ["GET", "POST", "PATCH", "PUT", "DELETE"],
|
||||||
|
"allow_headers": [
|
||||||
|
"Content-Type",
|
||||||
|
"Content-Length",
|
||||||
|
"Authorization",
|
||||||
|
"Accept"
|
||||||
|
],
|
||||||
|
"allow_credentials": true
|
||||||
|
},
|
||||||
|
"mcp": {
|
||||||
|
"enabled": true,
|
||||||
|
"path": "/api/system/mcp",
|
||||||
|
"logLevel": "warning"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"data": {
|
||||||
|
"basepath": "/api/data",
|
||||||
|
"default_primary_format": "integer",
|
||||||
|
"entities": {
|
||||||
|
"test": {
|
||||||
|
"type": "regular",
|
||||||
|
"fields": {
|
||||||
|
"id": {
|
||||||
|
"type": "primary",
|
||||||
|
"config": {
|
||||||
|
"format": "integer",
|
||||||
|
"fillable": false,
|
||||||
|
"required": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"title": {
|
||||||
|
"type": "text",
|
||||||
|
"config": {
|
||||||
|
"required": false,
|
||||||
|
"fillable": ["read", "update"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"status": {
|
||||||
|
"type": "enum",
|
||||||
|
"config": {
|
||||||
|
"default_value": "INACTIVE",
|
||||||
|
"options": {
|
||||||
|
"type": "strings",
|
||||||
|
"values": ["INACTIVE", "SUBSCRIBED", "UNSUBSCRIBED"]
|
||||||
|
},
|
||||||
|
"required": true,
|
||||||
|
"fillable": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"created_at": {
|
||||||
|
"type": "date",
|
||||||
|
"config": {
|
||||||
|
"type": "datetime",
|
||||||
|
"required": true,
|
||||||
|
"fillable": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"schema": {
|
||||||
|
"type": "jsonschema",
|
||||||
|
"config": {
|
||||||
|
"default_from_schema": true,
|
||||||
|
"schema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"one": {
|
||||||
|
"type": "number",
|
||||||
|
"default": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": true,
|
||||||
|
"fillable": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"text": {
|
||||||
|
"type": "text",
|
||||||
|
"config": {
|
||||||
|
"required": false,
|
||||||
|
"fillable": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"config": {
|
||||||
|
"sort_field": "id",
|
||||||
|
"sort_dir": "asc"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"items": {
|
||||||
|
"type": "regular",
|
||||||
|
"fields": {
|
||||||
|
"id": {
|
||||||
|
"type": "primary",
|
||||||
|
"config": {
|
||||||
|
"format": "integer",
|
||||||
|
"fillable": false,
|
||||||
|
"required": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"title": {
|
||||||
|
"type": "text",
|
||||||
|
"config": {
|
||||||
|
"required": false,
|
||||||
|
"fillable": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"config": {
|
||||||
|
"sort_field": "id",
|
||||||
|
"sort_dir": "asc"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"media": {
|
||||||
|
"type": "system",
|
||||||
|
"fields": {
|
||||||
|
"id": {
|
||||||
|
"type": "primary",
|
||||||
|
"config": {
|
||||||
|
"format": "integer",
|
||||||
|
"fillable": false,
|
||||||
|
"required": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"path": {
|
||||||
|
"type": "text",
|
||||||
|
"config": {
|
||||||
|
"required": true,
|
||||||
|
"fillable": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"folder": {
|
||||||
|
"type": "boolean",
|
||||||
|
"config": {
|
||||||
|
"default_value": false,
|
||||||
|
"hidden": true,
|
||||||
|
"fillable": ["create"],
|
||||||
|
"required": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mime_type": {
|
||||||
|
"type": "text",
|
||||||
|
"config": {
|
||||||
|
"required": false,
|
||||||
|
"fillable": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"size": {
|
||||||
|
"type": "number",
|
||||||
|
"config": {
|
||||||
|
"required": false,
|
||||||
|
"fillable": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"scope": {
|
||||||
|
"type": "text",
|
||||||
|
"config": {
|
||||||
|
"hidden": true,
|
||||||
|
"fillable": ["create"],
|
||||||
|
"required": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"etag": {
|
||||||
|
"type": "text",
|
||||||
|
"config": {
|
||||||
|
"required": false,
|
||||||
|
"fillable": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"modified_at": {
|
||||||
|
"type": "date",
|
||||||
|
"config": {
|
||||||
|
"type": "datetime",
|
||||||
|
"required": false,
|
||||||
|
"fillable": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"reference": {
|
||||||
|
"type": "text",
|
||||||
|
"config": {
|
||||||
|
"required": false,
|
||||||
|
"fillable": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"entity_id": {
|
||||||
|
"type": "text",
|
||||||
|
"config": {
|
||||||
|
"required": false,
|
||||||
|
"fillable": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"metadata": {
|
||||||
|
"type": "json",
|
||||||
|
"config": {
|
||||||
|
"required": false,
|
||||||
|
"fillable": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"config": {
|
||||||
|
"sort_field": "id",
|
||||||
|
"sort_dir": "asc"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"relations": {},
|
||||||
|
"indices": {
|
||||||
|
"idx_unique_media_path": {
|
||||||
|
"entity": "media",
|
||||||
|
"fields": ["path"],
|
||||||
|
"unique": true
|
||||||
|
},
|
||||||
|
"idx_media_reference": {
|
||||||
|
"entity": "media",
|
||||||
|
"fields": ["reference"],
|
||||||
|
"unique": false
|
||||||
|
},
|
||||||
|
"idx_media_entity_id": {
|
||||||
|
"entity": "media",
|
||||||
|
"fields": ["entity_id"],
|
||||||
|
"unique": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"auth": {
|
||||||
|
"enabled": false,
|
||||||
|
"basepath": "/api/auth",
|
||||||
|
"entity_name": "users",
|
||||||
|
"allow_register": true,
|
||||||
|
"jwt": {
|
||||||
|
"secret": "",
|
||||||
|
"alg": "HS256",
|
||||||
|
"fields": ["id", "email", "role"]
|
||||||
|
},
|
||||||
|
"cookie": {
|
||||||
|
"path": "/",
|
||||||
|
"sameSite": "lax",
|
||||||
|
"secure": true,
|
||||||
|
"httpOnly": true,
|
||||||
|
"expires": 604800,
|
||||||
|
"partitioned": false,
|
||||||
|
"renew": true,
|
||||||
|
"pathSuccess": "/",
|
||||||
|
"pathLoggedOut": "/"
|
||||||
|
},
|
||||||
|
"strategies": {
|
||||||
|
"password": {
|
||||||
|
"type": "password",
|
||||||
|
"enabled": true,
|
||||||
|
"config": {
|
||||||
|
"hashing": "sha256"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"guard": {
|
||||||
|
"enabled": false
|
||||||
|
},
|
||||||
|
"roles": {}
|
||||||
|
},
|
||||||
|
"media": {
|
||||||
|
"enabled": false
|
||||||
|
},
|
||||||
|
"flows": {
|
||||||
|
"basepath": "/api/flows",
|
||||||
|
"flows": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -546,7 +546,7 @@
|
|||||||
"config": {
|
"config": {
|
||||||
"access_key": "123",
|
"access_key": "123",
|
||||||
"secret_access_key": "123",
|
"secret_access_key": "123",
|
||||||
"url": "https://123.r2.cloudflarestorage.com/bknd-123"
|
"url": "https://123.r2.cloudflarestorage.com/userbase-123"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import { EntityManager } from "data/entities/EntityManager";
|
|||||||
import { Module, type ModuleBuildContext } from "modules/Module";
|
import { Module, type ModuleBuildContext } from "modules/Module";
|
||||||
import { getDummyConnection } from "../helper";
|
import { getDummyConnection } from "../helper";
|
||||||
import { ModuleHelper } from "modules/ModuleHelper";
|
import { ModuleHelper } from "modules/ModuleHelper";
|
||||||
import { DebugLogger, McpServer } from "bknd/utils";
|
import { DebugLogger, McpServer } from "userbase/utils";
|
||||||
|
|
||||||
export function makeCtx(overrides?: Partial<ModuleBuildContext>): ModuleBuildContext {
|
export function makeCtx(overrides?: Partial<ModuleBuildContext>): ModuleBuildContext {
|
||||||
const { dummyConnection } = getDummyConnection();
|
const { dummyConnection } = getDummyConnection();
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { describe, it, expect, beforeEach } from "vitest";
|
import { describe, it, expect, beforeEach } from "vitest";
|
||||||
import { AppReduced, type AppType } from "ui/client/utils/AppReduced";
|
import { AppReduced, type AppType } from "ui/client/utils/AppReduced";
|
||||||
import type { BkndAdminProps } from "ui/Admin";
|
import type { UserbaseAdminProps } from "ui/Admin";
|
||||||
|
|
||||||
// Import the normalizeAdminPath function for testing
|
// Import the normalizeAdminPath function for testing
|
||||||
// Note: This assumes the function is exported or we need to test it indirectly through public methods
|
// Note: This assumes the function is exported or we need to test it indirectly through public methods
|
||||||
@@ -24,7 +24,7 @@ describe("AppReduced", () => {
|
|||||||
|
|
||||||
describe("getSettingsPath", () => {
|
describe("getSettingsPath", () => {
|
||||||
it("should return settings path with basepath", () => {
|
it("should return settings path with basepath", () => {
|
||||||
const options: BkndAdminProps["config"] = {
|
const options: UserbaseAdminProps["config"] = {
|
||||||
basepath: "/admin",
|
basepath: "/admin",
|
||||||
logo_return_path: "/",
|
logo_return_path: "/",
|
||||||
};
|
};
|
||||||
@@ -36,7 +36,7 @@ describe("AppReduced", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("should return settings path with empty basepath", () => {
|
it("should return settings path with empty basepath", () => {
|
||||||
const options: BkndAdminProps["config"] = {
|
const options: UserbaseAdminProps["config"] = {
|
||||||
basepath: "",
|
basepath: "",
|
||||||
logo_return_path: "/",
|
logo_return_path: "/",
|
||||||
};
|
};
|
||||||
@@ -48,7 +48,7 @@ describe("AppReduced", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("should append additional path segments", () => {
|
it("should append additional path segments", () => {
|
||||||
const options: BkndAdminProps["config"] = {
|
const options: UserbaseAdminProps["config"] = {
|
||||||
basepath: "/admin",
|
basepath: "/admin",
|
||||||
logo_return_path: "/",
|
logo_return_path: "/",
|
||||||
};
|
};
|
||||||
@@ -60,7 +60,7 @@ describe("AppReduced", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("should normalize multiple slashes", () => {
|
it("should normalize multiple slashes", () => {
|
||||||
const options: BkndAdminProps["config"] = {
|
const options: UserbaseAdminProps["config"] = {
|
||||||
basepath: "//admin//",
|
basepath: "//admin//",
|
||||||
logo_return_path: "/",
|
logo_return_path: "/",
|
||||||
};
|
};
|
||||||
@@ -72,7 +72,7 @@ describe("AppReduced", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("should handle basepath without leading slash", () => {
|
it("should handle basepath without leading slash", () => {
|
||||||
const options: BkndAdminProps["config"] = {
|
const options: UserbaseAdminProps["config"] = {
|
||||||
basepath: "admin",
|
basepath: "admin",
|
||||||
logo_return_path: "/",
|
logo_return_path: "/",
|
||||||
};
|
};
|
||||||
@@ -86,7 +86,7 @@ describe("AppReduced", () => {
|
|||||||
|
|
||||||
describe("getAbsolutePath", () => {
|
describe("getAbsolutePath", () => {
|
||||||
it("should return absolute path with basepath", () => {
|
it("should return absolute path with basepath", () => {
|
||||||
const options: BkndAdminProps["config"] = {
|
const options: UserbaseAdminProps["config"] = {
|
||||||
basepath: "/admin",
|
basepath: "/admin",
|
||||||
logo_return_path: "/",
|
logo_return_path: "/",
|
||||||
};
|
};
|
||||||
@@ -98,7 +98,7 @@ describe("AppReduced", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("should return base path when no path provided", () => {
|
it("should return base path when no path provided", () => {
|
||||||
const options: BkndAdminProps["config"] = {
|
const options: UserbaseAdminProps["config"] = {
|
||||||
basepath: "/admin",
|
basepath: "/admin",
|
||||||
logo_return_path: "/",
|
logo_return_path: "/",
|
||||||
};
|
};
|
||||||
@@ -110,7 +110,7 @@ describe("AppReduced", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("should normalize paths correctly", () => {
|
it("should normalize paths correctly", () => {
|
||||||
const options: BkndAdminProps["config"] = {
|
const options: UserbaseAdminProps["config"] = {
|
||||||
basepath: "//admin//",
|
basepath: "//admin//",
|
||||||
logo_return_path: "/",
|
logo_return_path: "/",
|
||||||
};
|
};
|
||||||
@@ -124,7 +124,7 @@ describe("AppReduced", () => {
|
|||||||
|
|
||||||
describe("options getter", () => {
|
describe("options getter", () => {
|
||||||
it("should return merged options with defaults", () => {
|
it("should return merged options with defaults", () => {
|
||||||
const customOptions: BkndAdminProps["config"] = {
|
const customOptions: UserbaseAdminProps["config"] = {
|
||||||
basepath: "/custom-admin",
|
basepath: "/custom-admin",
|
||||||
logo_return_path: "/custom-home",
|
logo_return_path: "/custom-home",
|
||||||
};
|
};
|
||||||
@@ -139,7 +139,7 @@ describe("AppReduced", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("should use default logo_return_path when not provided", () => {
|
it("should use default logo_return_path when not provided", () => {
|
||||||
const customOptions: BkndAdminProps["config"] = {
|
const customOptions: UserbaseAdminProps["config"] = {
|
||||||
basepath: "/admin",
|
basepath: "/admin",
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -153,7 +153,7 @@ describe("AppReduced", () => {
|
|||||||
|
|
||||||
describe("path normalization behavior", () => {
|
describe("path normalization behavior", () => {
|
||||||
it("should normalize duplicate slashes in settings path", () => {
|
it("should normalize duplicate slashes in settings path", () => {
|
||||||
const options: BkndAdminProps["config"] = {
|
const options: UserbaseAdminProps["config"] = {
|
||||||
basepath: "/admin",
|
basepath: "/admin",
|
||||||
logo_return_path: "/",
|
logo_return_path: "/",
|
||||||
};
|
};
|
||||||
@@ -165,7 +165,7 @@ describe("AppReduced", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("should handle root path normalization", () => {
|
it("should handle root path normalization", () => {
|
||||||
const options: BkndAdminProps["config"] = {
|
const options: UserbaseAdminProps["config"] = {
|
||||||
basepath: "/",
|
basepath: "/",
|
||||||
logo_return_path: "/",
|
logo_return_path: "/",
|
||||||
};
|
};
|
||||||
@@ -179,7 +179,7 @@ describe("AppReduced", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("should preserve entity paths ending with slash", () => {
|
it("should preserve entity paths ending with slash", () => {
|
||||||
const options: BkndAdminProps["config"] = {
|
const options: UserbaseAdminProps["config"] = {
|
||||||
basepath: "/admin",
|
basepath: "/admin",
|
||||||
logo_return_path: "/",
|
logo_return_path: "/",
|
||||||
};
|
};
|
||||||
@@ -191,7 +191,7 @@ describe("AppReduced", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("should remove trailing slashes from non-entity paths", () => {
|
it("should remove trailing slashes from non-entity paths", () => {
|
||||||
const options: BkndAdminProps["config"] = {
|
const options: UserbaseAdminProps["config"] = {
|
||||||
basepath: "/admin",
|
basepath: "/admin",
|
||||||
logo_return_path: "/",
|
logo_return_path: "/",
|
||||||
};
|
};
|
||||||
@@ -205,7 +205,7 @@ describe("AppReduced", () => {
|
|||||||
|
|
||||||
describe("withBasePath - double slash fix (admin_basepath with trailing slash)", () => {
|
describe("withBasePath - double slash fix (admin_basepath with trailing slash)", () => {
|
||||||
it("should not produce double slashes when admin_basepath has trailing slash", () => {
|
it("should not produce double slashes when admin_basepath has trailing slash", () => {
|
||||||
const options: BkndAdminProps["config"] = {
|
const options: UserbaseAdminProps["config"] = {
|
||||||
basepath: "/admin",
|
basepath: "/admin",
|
||||||
logo_return_path: "/",
|
logo_return_path: "/",
|
||||||
};
|
};
|
||||||
@@ -218,7 +218,7 @@ describe("AppReduced", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("should work correctly when admin_basepath has no trailing slash", () => {
|
it("should work correctly when admin_basepath has no trailing slash", () => {
|
||||||
const options: BkndAdminProps["config"] = {
|
const options: UserbaseAdminProps["config"] = {
|
||||||
basepath: "/admin",
|
basepath: "/admin",
|
||||||
logo_return_path: "/",
|
logo_return_path: "/",
|
||||||
};
|
};
|
||||||
@@ -230,7 +230,7 @@ describe("AppReduced", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("should handle absolute paths with admin_basepath trailing slash", () => {
|
it("should handle absolute paths with admin_basepath trailing slash", () => {
|
||||||
const options: BkndAdminProps["config"] = {
|
const options: UserbaseAdminProps["config"] = {
|
||||||
basepath: "/admin",
|
basepath: "/admin",
|
||||||
logo_return_path: "/",
|
logo_return_path: "/",
|
||||||
};
|
};
|
||||||
@@ -243,7 +243,7 @@ describe("AppReduced", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("should handle settings path with admin_basepath trailing slash", () => {
|
it("should handle settings path with admin_basepath trailing slash", () => {
|
||||||
const options: BkndAdminProps["config"] = {
|
const options: UserbaseAdminProps["config"] = {
|
||||||
basepath: "/admin",
|
basepath: "/admin",
|
||||||
logo_return_path: "/",
|
logo_return_path: "/",
|
||||||
};
|
};
|
||||||
@@ -258,7 +258,7 @@ describe("AppReduced", () => {
|
|||||||
|
|
||||||
describe("edge cases", () => {
|
describe("edge cases", () => {
|
||||||
it("should handle undefined basepath", () => {
|
it("should handle undefined basepath", () => {
|
||||||
const options: BkndAdminProps["config"] = {
|
const options: UserbaseAdminProps["config"] = {
|
||||||
logo_return_path: "/",
|
logo_return_path: "/",
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -270,7 +270,7 @@ describe("AppReduced", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("should handle null path segments", () => {
|
it("should handle null path segments", () => {
|
||||||
const options: BkndAdminProps["config"] = {
|
const options: UserbaseAdminProps["config"] = {
|
||||||
basepath: "/admin",
|
basepath: "/admin",
|
||||||
logo_return_path: "/",
|
logo_return_path: "/",
|
||||||
};
|
};
|
||||||
|
|||||||
+2
-2
@@ -1,9 +1,9 @@
|
|||||||
import pkg from "./package.json" with { type: "json" };
|
import pkg from "./package.json" with { type: "json" };
|
||||||
import c from "picocolors";
|
import c from "picocolors";
|
||||||
import { formatNumber } from "bknd/utils";
|
import { formatNumber } from "userbase/utils";
|
||||||
|
|
||||||
const deps = Object.keys(pkg.dependencies);
|
const deps = Object.keys(pkg.dependencies);
|
||||||
const external = ["jsonv-ts/*", "wrangler", "bknd", "bknd/*", ...deps];
|
const external = ["jsonv-ts/*", "wrangler", "userbase", "userbase/*", ...deps];
|
||||||
|
|
||||||
const result = await Bun.build({
|
const result = await Bun.build({
|
||||||
entrypoints: ["./src/cli/index.ts"],
|
entrypoints: ["./src/cli/index.ts"],
|
||||||
|
|||||||
+296
-313
@@ -14,15 +14,15 @@ const clean = args.includes("--clean");
|
|||||||
|
|
||||||
// silence tsup
|
// silence tsup
|
||||||
const oldConsole = {
|
const oldConsole = {
|
||||||
log: console.log,
|
log: console.log,
|
||||||
warn: console.warn,
|
warn: console.warn,
|
||||||
};
|
};
|
||||||
console.log = () => {};
|
console.log = () => {};
|
||||||
console.warn = () => {};
|
console.warn = () => {};
|
||||||
|
|
||||||
const define = {
|
const define = {
|
||||||
__isDev: "0",
|
__isDev: "0",
|
||||||
__version: JSON.stringify(pkg.version),
|
__version: JSON.stringify(pkg.version),
|
||||||
};
|
};
|
||||||
|
|
||||||
if (clean) {
|
if (clean) {
|
||||||
@@ -43,341 +43,332 @@ if (clean) {
|
|||||||
|
|
||||||
let types_running = false;
|
let types_running = false;
|
||||||
function buildTypes() {
|
function buildTypes() {
|
||||||
if (types_running || !types) return;
|
if (types_running || !types) return;
|
||||||
types_running = true;
|
types_running = true;
|
||||||
|
|
||||||
Bun.spawn(["bun", "build:types"], {
|
Bun.spawn(["bun", "build:types"], {
|
||||||
stdout: "inherit",
|
stdout: "inherit",
|
||||||
onExit: () => {
|
onExit: () => {
|
||||||
oldConsole.log(c.cyan("[Types]"), c.green("built"));
|
oldConsole.log(c.cyan("[Types]"), c.green("built"));
|
||||||
Bun.spawn(["bun", "tsc-alias"], {
|
Bun.spawn(["bun", "tsc-alias"], {
|
||||||
stdout: "inherit",
|
stdout: "inherit",
|
||||||
onExit: () => {
|
onExit: () => {
|
||||||
oldConsole.log(c.cyan("[Types]"), c.green("aliased"));
|
oldConsole.log(c.cyan("[Types]"), c.green("aliased"));
|
||||||
types_running = false;
|
types_running = false;
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (types && !watch) {
|
if (types && !watch) {
|
||||||
buildTypes();
|
buildTypes();
|
||||||
}
|
}
|
||||||
|
|
||||||
let watcher_timeout: any;
|
let watcher_timeout: any;
|
||||||
function delayTypes() {
|
function delayTypes() {
|
||||||
if (!watch || !types) return;
|
if (!watch || !types) return;
|
||||||
if (watcher_timeout) {
|
if (watcher_timeout) {
|
||||||
clearTimeout(watcher_timeout);
|
clearTimeout(watcher_timeout);
|
||||||
}
|
}
|
||||||
watcher_timeout = setTimeout(buildTypes, 1000);
|
watcher_timeout = setTimeout(buildTypes, 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
const dependencies = Object.keys(pkg.dependencies);
|
const dependencies = Object.keys(pkg.dependencies);
|
||||||
|
|
||||||
// collection of always-external packages
|
// collection of always-external packages
|
||||||
const external = [
|
const external = [
|
||||||
...dependencies,
|
...dependencies,
|
||||||
"bun:test",
|
"bun:test",
|
||||||
"node:test",
|
"node:test",
|
||||||
"node:assert/strict",
|
"node:assert/strict",
|
||||||
"@libsql/client",
|
"@libsql/client",
|
||||||
"bknd",
|
"userbase",
|
||||||
/^bknd\/.*/,
|
/^userbase\/.*/,
|
||||||
"jsonv-ts",
|
"jsonv-ts",
|
||||||
/^jsonv-ts\/.*/,
|
/^jsonv-ts\/.*/,
|
||||||
] as const;
|
] as const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Building backend and general API
|
* Building backend and general API
|
||||||
*/
|
*/
|
||||||
async function buildApi() {
|
async function buildApi() {
|
||||||
await tsup.build({
|
await tsup.build({
|
||||||
minify,
|
minify,
|
||||||
sourcemap,
|
sourcemap,
|
||||||
// don't use tsup's broken watch, we'll handle it ourselves
|
// don't use tsup's broken watch, we'll handle it ourselves
|
||||||
watch: false,
|
watch: false,
|
||||||
define,
|
define,
|
||||||
entry: [
|
entry: [
|
||||||
"src/index.ts",
|
"src/index.ts",
|
||||||
"src/core/utils/index.ts",
|
"src/core/utils/index.ts",
|
||||||
"src/plugins/index.ts",
|
"src/plugins/index.ts",
|
||||||
"src/modes/index.ts",
|
"src/modes/index.ts",
|
||||||
],
|
],
|
||||||
outDir: "dist",
|
outDir: "dist",
|
||||||
external: [...external],
|
external: [...external],
|
||||||
metafile: true,
|
metafile: true,
|
||||||
target: "esnext",
|
target: "esnext",
|
||||||
platform: "browser",
|
platform: "browser",
|
||||||
removeNodeProtocol: false,
|
removeNodeProtocol: false,
|
||||||
format: ["esm"],
|
format: ["esm"],
|
||||||
splitting: false,
|
splitting: false,
|
||||||
loader: {
|
loader: {
|
||||||
".svg": "dataurl",
|
".svg": "dataurl",
|
||||||
},
|
},
|
||||||
onSuccess: async () => {
|
onSuccess: async () => {
|
||||||
delayTypes();
|
delayTypes();
|
||||||
oldConsole.log(c.cyan("[API]"), c.green("built"));
|
oldConsole.log(c.cyan("[API]"), c.green("built"));
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function rewriteClient(path: string) {
|
async function rewriteClient(path: string) {
|
||||||
const bundle = await Bun.file(path).text();
|
const bundle = await Bun.file(path).text();
|
||||||
await Bun.write(
|
await Bun.write(path, '"use client";\n' + bundle.replaceAll("ui/client", "userbase/client"));
|
||||||
path,
|
|
||||||
'"use client";\n' + bundle.replaceAll("ui/client", "bknd/client"),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Building UI for direct imports
|
* Building UI for direct imports
|
||||||
*/
|
*/
|
||||||
async function buildUi() {
|
async function buildUi() {
|
||||||
const base = {
|
const base = {
|
||||||
minify,
|
minify,
|
||||||
sourcemap,
|
sourcemap,
|
||||||
watch: false,
|
watch: false,
|
||||||
define,
|
define,
|
||||||
external: [
|
external: [
|
||||||
...external,
|
...external,
|
||||||
"react",
|
"react",
|
||||||
"react-dom",
|
"react-dom",
|
||||||
"react/jsx-runtime",
|
"react/jsx-runtime",
|
||||||
"react/jsx-dev-runtime",
|
"react/jsx-dev-runtime",
|
||||||
"use-sync-external-store",
|
/codemirror/,
|
||||||
/codemirror/,
|
"@xyflow/react",
|
||||||
"@xyflow/react",
|
"@mantine/core",
|
||||||
"@mantine/core",
|
],
|
||||||
],
|
metafile: true,
|
||||||
metafile: true,
|
platform: "browser",
|
||||||
platform: "browser",
|
format: ["esm"],
|
||||||
format: ["esm"],
|
splitting: false,
|
||||||
splitting: false,
|
bundle: true,
|
||||||
bundle: true,
|
treeshake: true,
|
||||||
treeshake: true,
|
loader: {
|
||||||
loader: {
|
".svg": "dataurl",
|
||||||
".svg": "dataurl",
|
},
|
||||||
},
|
esbuildOptions: (options) => {
|
||||||
esbuildOptions: (options) => {
|
options.logLevel = "silent";
|
||||||
options.logLevel = "silent";
|
},
|
||||||
},
|
} satisfies tsup.Options;
|
||||||
} satisfies tsup.Options;
|
|
||||||
|
|
||||||
await tsup.build({
|
await tsup.build({
|
||||||
...base,
|
...base,
|
||||||
entry: ["src/ui/index.ts", "src/ui/main.css", "src/ui/styles.css"],
|
entry: ["src/ui/index.ts", "src/ui/main.css", "src/ui/styles.css"],
|
||||||
outDir: "dist/ui",
|
outDir: "dist/ui",
|
||||||
onSuccess: async () => {
|
onSuccess: async () => {
|
||||||
await rewriteClient("./dist/ui/index.js");
|
await rewriteClient("./dist/ui/index.js");
|
||||||
delayTypes();
|
delayTypes();
|
||||||
oldConsole.log(c.cyan("[UI]"), c.green("built"));
|
oldConsole.log(c.cyan("[UI]"), c.green("built"));
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
await tsup.build({
|
await tsup.build({
|
||||||
...base,
|
...base,
|
||||||
entry: ["src/ui/client/index.ts"],
|
entry: ["src/ui/client/index.ts"],
|
||||||
outDir: "dist/ui/client",
|
outDir: "dist/ui/client",
|
||||||
onSuccess: async () => {
|
onSuccess: async () => {
|
||||||
await rewriteClient("./dist/ui/client/index.js");
|
await rewriteClient("./dist/ui/client/index.js");
|
||||||
delayTypes();
|
delayTypes();
|
||||||
oldConsole.log(c.cyan("[UI]"), "Client", c.green("built"));
|
oldConsole.log(c.cyan("[UI]"), "Client", c.green("built"));
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Building UI Elements
|
* Building UI Elements
|
||||||
* - tailwind-merge is mocked, no exclude
|
* - tailwind-merge is mocked, no exclude
|
||||||
* - ui/client is external, and after built replaced with "bknd/client"
|
* - ui/client is external, and after built replaced with "userbase/client"
|
||||||
*/
|
*/
|
||||||
async function buildUiElements() {
|
async function buildUiElements() {
|
||||||
await tsup.build({
|
await tsup.build({
|
||||||
minify,
|
minify,
|
||||||
sourcemap,
|
sourcemap,
|
||||||
watch: false,
|
watch: false,
|
||||||
define,
|
define,
|
||||||
entry: ["src/ui/elements/index.ts"],
|
entry: ["src/ui/elements/index.ts"],
|
||||||
outDir: "dist/ui/elements",
|
outDir: "dist/ui/elements",
|
||||||
external: [
|
external: [
|
||||||
"ui/client",
|
"ui/client",
|
||||||
"bknd",
|
"userbase",
|
||||||
/^bknd\/.*/,
|
/^userbase\/.*/,
|
||||||
"wouter",
|
"wouter",
|
||||||
"react",
|
"react",
|
||||||
"react-dom",
|
"react-dom",
|
||||||
"react/jsx-runtime",
|
"react/jsx-runtime",
|
||||||
"react/jsx-dev-runtime",
|
"react/jsx-dev-runtime",
|
||||||
"use-sync-external-store",
|
],
|
||||||
],
|
metafile: true,
|
||||||
metafile: true,
|
platform: "browser",
|
||||||
platform: "browser",
|
format: ["esm"],
|
||||||
format: ["esm"],
|
splitting: false,
|
||||||
splitting: false,
|
bundle: true,
|
||||||
bundle: true,
|
treeshake: true,
|
||||||
treeshake: true,
|
loader: {
|
||||||
loader: {
|
".svg": "dataurl",
|
||||||
".svg": "dataurl",
|
},
|
||||||
},
|
esbuildOptions: (options) => {
|
||||||
esbuildOptions: (options) => {
|
options.alias = {
|
||||||
options.alias = {
|
// not important for elements, mock to reduce bundle
|
||||||
// not important for elements, mock to reduce bundle
|
"tailwind-merge": "./src/ui/elements/mocks/tailwind-merge.ts",
|
||||||
"tailwind-merge": "./src/ui/elements/mocks/tailwind-merge.ts",
|
};
|
||||||
};
|
},
|
||||||
},
|
onSuccess: async () => {
|
||||||
onSuccess: async () => {
|
await rewriteClient("./dist/ui/elements/index.js");
|
||||||
await rewriteClient("./dist/ui/elements/index.js");
|
delayTypes();
|
||||||
delayTypes();
|
oldConsole.log(c.cyan("[UI]"), "Elements", c.green("built"));
|
||||||
oldConsole.log(c.cyan("[UI]"), "Elements", c.green("built"));
|
},
|
||||||
},
|
});
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Building adapters
|
* Building adapters
|
||||||
*/
|
*/
|
||||||
function baseConfig(
|
function baseConfig(adapter: string, overrides: Partial<tsup.Options> = {}): tsup.Options {
|
||||||
adapter: string,
|
return {
|
||||||
overrides: Partial<tsup.Options> = {},
|
minify,
|
||||||
): tsup.Options {
|
sourcemap,
|
||||||
return {
|
watch: false,
|
||||||
minify,
|
entry: [`src/adapter/${adapter}/index.ts`],
|
||||||
sourcemap,
|
format: ["esm"],
|
||||||
watch: false,
|
platform: "neutral",
|
||||||
entry: [`src/adapter/${adapter}/index.ts`],
|
outDir: `dist/adapter/${adapter}`,
|
||||||
format: ["esm"],
|
metafile: true,
|
||||||
platform: "neutral",
|
splitting: false,
|
||||||
outDir: `dist/adapter/${adapter}`,
|
removeNodeProtocol: false,
|
||||||
metafile: true,
|
onSuccess: async () => {
|
||||||
splitting: false,
|
delayTypes();
|
||||||
removeNodeProtocol: false,
|
oldConsole.log(c.cyan("[Adapter]"), adapter || "base", c.green("built"));
|
||||||
onSuccess: async () => {
|
},
|
||||||
delayTypes();
|
...overrides,
|
||||||
oldConsole.log(c.cyan("[Adapter]"), adapter || "base", c.green("built"));
|
define: {
|
||||||
},
|
...define,
|
||||||
...overrides,
|
...overrides.define,
|
||||||
define: {
|
},
|
||||||
...define,
|
external: [
|
||||||
...overrides.define,
|
/^cloudflare*/,
|
||||||
},
|
/^@?hono.*?/,
|
||||||
external: [
|
/^(userbase|react|next|node).*?/,
|
||||||
/^cloudflare*/,
|
/.*\.(html)$/,
|
||||||
/^@?hono.*?/,
|
...external,
|
||||||
/^(bknd|react|next|node).*?/,
|
...(Array.isArray(overrides.external) ? overrides.external : []),
|
||||||
/.*\.(html)$/,
|
],
|
||||||
...external,
|
};
|
||||||
...(Array.isArray(overrides.external) ? overrides.external : []),
|
|
||||||
],
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function buildAdapters() {
|
async function buildAdapters() {
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
// base adapter handles
|
// base adapter handles
|
||||||
tsup.build({
|
tsup.build({
|
||||||
...baseConfig(""),
|
...baseConfig(""),
|
||||||
target: "esnext",
|
target: "esnext",
|
||||||
platform: "neutral",
|
platform: "neutral",
|
||||||
entry: ["src/adapter/index.ts"],
|
entry: ["src/adapter/index.ts"],
|
||||||
outDir: "dist/adapter",
|
outDir: "dist/adapter",
|
||||||
// only way to keep @vite-ignore comments
|
// only way to keep @vite-ignore comments
|
||||||
minify: false,
|
minify: false,
|
||||||
}),
|
|
||||||
|
|
||||||
// specific adatpers
|
|
||||||
tsup.build(baseConfig("react-router")),
|
|
||||||
tsup.build(
|
|
||||||
baseConfig("browser", {
|
|
||||||
external: [/^sqlocal\/?.*?/, "wouter"],
|
|
||||||
}),
|
}),
|
||||||
),
|
|
||||||
tsup.build(
|
// specific adatpers
|
||||||
baseConfig("bun", {
|
tsup.build(baseConfig("react-router")),
|
||||||
external: [/^bun\:.*/],
|
tsup.build(
|
||||||
|
baseConfig("browser", {
|
||||||
|
external: [/^sqlocal\/?.*?/, "wouter"],
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
tsup.build(
|
||||||
|
baseConfig("bun", {
|
||||||
|
external: [/^bun\:.*/],
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
tsup.build(baseConfig("astro")),
|
||||||
|
tsup.build(baseConfig("aws")),
|
||||||
|
tsup.build(
|
||||||
|
baseConfig("cloudflare", {
|
||||||
|
external: ["wrangler", "node:process"],
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
tsup.build(
|
||||||
|
baseConfig("cloudflare/proxy", {
|
||||||
|
target: "esnext",
|
||||||
|
entry: ["src/adapter/cloudflare/proxy.ts"],
|
||||||
|
outDir: "dist/adapter/cloudflare",
|
||||||
|
metafile: false,
|
||||||
|
external: [/userbase/, "wrangler", "node:process"],
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
|
||||||
|
tsup.build({
|
||||||
|
...baseConfig("vite"),
|
||||||
|
platform: "node",
|
||||||
}),
|
}),
|
||||||
),
|
|
||||||
tsup.build(baseConfig("astro")),
|
tsup.build({
|
||||||
tsup.build(baseConfig("aws")),
|
...baseConfig("nextjs"),
|
||||||
tsup.build(
|
platform: "node",
|
||||||
baseConfig("cloudflare", {
|
|
||||||
external: ["wrangler", "node:process"],
|
|
||||||
}),
|
}),
|
||||||
),
|
|
||||||
tsup.build(
|
tsup.build({
|
||||||
baseConfig("cloudflare/proxy", {
|
...baseConfig("tanstack-start"),
|
||||||
target: "esnext",
|
platform: "node",
|
||||||
entry: ["src/adapter/cloudflare/proxy.ts"],
|
|
||||||
outDir: "dist/adapter/cloudflare",
|
|
||||||
metafile: false,
|
|
||||||
external: [/bknd/, "wrangler", "node:process"],
|
|
||||||
}),
|
}),
|
||||||
),
|
|
||||||
|
|
||||||
tsup.build({
|
tsup.build({
|
||||||
...baseConfig("vite"),
|
...baseConfig("sveltekit"),
|
||||||
platform: "node",
|
platform: "node",
|
||||||
}),
|
}),
|
||||||
|
|
||||||
tsup.build({
|
tsup.build({
|
||||||
...baseConfig("nextjs"),
|
...baseConfig("nuxt"),
|
||||||
platform: "node",
|
platform: "node",
|
||||||
}),
|
}),
|
||||||
|
|
||||||
tsup.build({
|
tsup.build({
|
||||||
...baseConfig("tanstack-start"),
|
...baseConfig("node"),
|
||||||
platform: "node",
|
platform: "node",
|
||||||
}),
|
}),
|
||||||
|
|
||||||
tsup.build({
|
tsup.build({
|
||||||
...baseConfig("sveltekit"),
|
...baseConfig("solid-start"),
|
||||||
platform: "node",
|
platform: "node",
|
||||||
}),
|
}),
|
||||||
|
|
||||||
tsup.build({
|
tsup.build({
|
||||||
...baseConfig("nuxt"),
|
...baseConfig("sqlite/edge"),
|
||||||
platform: "node",
|
entry: ["src/adapter/sqlite/edge.ts"],
|
||||||
}),
|
outDir: "dist/adapter/sqlite",
|
||||||
|
metafile: false,
|
||||||
|
}),
|
||||||
|
|
||||||
tsup.build({
|
tsup.build({
|
||||||
...baseConfig("node"),
|
...baseConfig("sqlite/node"),
|
||||||
platform: "node",
|
entry: ["src/adapter/sqlite/node.ts"],
|
||||||
}),
|
outDir: "dist/adapter/sqlite",
|
||||||
|
platform: "node",
|
||||||
|
metafile: false,
|
||||||
|
}),
|
||||||
|
|
||||||
tsup.build({
|
tsup.build({
|
||||||
...baseConfig("sqlite/edge"),
|
...baseConfig("sqlite/bun"),
|
||||||
entry: ["src/adapter/sqlite/edge.ts"],
|
entry: ["src/adapter/sqlite/bun.ts"],
|
||||||
outDir: "dist/adapter/sqlite",
|
outDir: "dist/adapter/sqlite",
|
||||||
metafile: false,
|
metafile: false,
|
||||||
}),
|
external: [/^bun\:.*/],
|
||||||
|
}),
|
||||||
tsup.build({
|
]);
|
||||||
...baseConfig("sqlite/node"),
|
|
||||||
entry: ["src/adapter/sqlite/node.ts"],
|
|
||||||
outDir: "dist/adapter/sqlite",
|
|
||||||
platform: "node",
|
|
||||||
metafile: false,
|
|
||||||
}),
|
|
||||||
|
|
||||||
tsup.build({
|
|
||||||
...baseConfig("sqlite/bun"),
|
|
||||||
entry: ["src/adapter/sqlite/bun.ts"],
|
|
||||||
outDir: "dist/adapter/sqlite",
|
|
||||||
metafile: false,
|
|
||||||
external: [/^bun\:.*/],
|
|
||||||
}),
|
|
||||||
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function buildAll() {
|
async function buildAll() {
|
||||||
await Promise.all([
|
await Promise.all([buildApi(), buildUi(), buildUiElements(), buildAdapters()]);
|
||||||
buildApi(),
|
|
||||||
buildUi(),
|
|
||||||
buildUiElements(),
|
|
||||||
buildAdapters(),
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// initial build
|
// initial build
|
||||||
@@ -385,47 +376,39 @@ await buildAll();
|
|||||||
|
|
||||||
// custom watcher since tsup's watch is broken in 8.3.5+
|
// custom watcher since tsup's watch is broken in 8.3.5+
|
||||||
if (watch) {
|
if (watch) {
|
||||||
oldConsole.log(c.cyan("[Watch]"), "watching for changes in src/...");
|
oldConsole.log(c.cyan("[Watch]"), "watching for changes in src/...");
|
||||||
|
|
||||||
let debounceTimer: ReturnType<typeof setTimeout> | null = null;
|
let debounceTimer: ReturnType<typeof setTimeout> | null = null;
|
||||||
let isBuilding = false;
|
let isBuilding = false;
|
||||||
|
|
||||||
const rebuild = async () => {
|
const rebuild = async () => {
|
||||||
if (isBuilding) return;
|
if (isBuilding) return;
|
||||||
isBuilding = true;
|
isBuilding = true;
|
||||||
oldConsole.log(c.cyan("[Watch]"), "rebuilding...");
|
oldConsole.log(c.cyan("[Watch]"), "rebuilding...");
|
||||||
try {
|
try {
|
||||||
await buildAll();
|
await buildAll();
|
||||||
oldConsole.log(c.cyan("[Watch]"), c.green("done"));
|
oldConsole.log(c.cyan("[Watch]"), c.green("done"));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
oldConsole.warn(c.cyan("[Watch]"), c.red("build failed"), e);
|
oldConsole.warn(c.cyan("[Watch]"), c.red("build failed"), e);
|
||||||
}
|
}
|
||||||
isBuilding = false;
|
isBuilding = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
const debouncedRebuild = () => {
|
const debouncedRebuild = () => {
|
||||||
if (debounceTimer) clearTimeout(debounceTimer);
|
if (debounceTimer) clearTimeout(debounceTimer);
|
||||||
debounceTimer = setTimeout(rebuild, 100);
|
debounceTimer = setTimeout(rebuild, 100);
|
||||||
};
|
};
|
||||||
|
|
||||||
// watch src directory recursively
|
// watch src directory recursively
|
||||||
fsWatch(
|
fsWatch(join(import.meta.dir, "src"), { recursive: true }, (event, filename) => {
|
||||||
join(import.meta.dir, "src"),
|
|
||||||
{ recursive: true },
|
|
||||||
(event, filename) => {
|
|
||||||
if (!filename) return;
|
if (!filename) return;
|
||||||
// ignore non-source files
|
// ignore non-source files
|
||||||
if (
|
if (!filename.endsWith(".ts") && !filename.endsWith(".tsx") && !filename.endsWith(".css"))
|
||||||
!filename.endsWith(".ts") &&
|
return;
|
||||||
!filename.endsWith(".tsx") &&
|
|
||||||
!filename.endsWith(".css")
|
|
||||||
)
|
|
||||||
return;
|
|
||||||
oldConsole.log(c.cyan("[Watch]"), c.dim(`${event}: ${filename}`));
|
oldConsole.log(c.cyan("[Watch]"), c.dim(`${event}: ${filename}`));
|
||||||
debouncedRebuild();
|
debouncedRebuild();
|
||||||
},
|
});
|
||||||
);
|
|
||||||
|
|
||||||
// keep process alive
|
// keep process alive
|
||||||
await new Promise(() => {});
|
await new Promise(() => {});
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-1
@@ -3,7 +3,10 @@ import path from "node:path";
|
|||||||
import c from "picocolors";
|
import c from "picocolors";
|
||||||
|
|
||||||
const basePath = new URL(import.meta.resolve("../../")).pathname.slice(0, -1);
|
const basePath = new URL(import.meta.resolve("../../")).pathname.slice(0, -1);
|
||||||
type RunOptions = Omit<Bun.SpawnOptions.SpawnOptions<"ignore", "pipe", "pipe">, "stdout" | "stderr">;
|
type RunOptions = Omit<
|
||||||
|
Bun.SpawnOptions.SpawnOptions<"ignore", "pipe", "pipe">,
|
||||||
|
"stdout" | "stderr"
|
||||||
|
>;
|
||||||
|
|
||||||
async function run(
|
async function run(
|
||||||
cmd: string[] | string,
|
cmd: string[] | string,
|
||||||
|
|||||||
+42
-39
@@ -1,50 +1,53 @@
|
|||||||
const adapter = process.env.TEST_ADAPTER;
|
const adapter = process.env.TEST_ADAPTER;
|
||||||
|
|
||||||
const default_config = {
|
const default_config = {
|
||||||
media_adapter: "local",
|
media_adapter: "local",
|
||||||
base_path: "",
|
base_path: "",
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
const configs = {
|
const configs = {
|
||||||
cloudflare: {
|
cloudflare: {
|
||||||
media_adapter: "r2",
|
media_adapter: "r2",
|
||||||
},
|
},
|
||||||
"react-router": {
|
"react-router": {
|
||||||
base_path: "/admin",
|
base_path: "/admin",
|
||||||
},
|
},
|
||||||
nextjs: {
|
nextjs: {
|
||||||
base_path: "/admin",
|
base_path: "/admin",
|
||||||
},
|
},
|
||||||
nuxt: {
|
nuxt: {
|
||||||
base_path: "/admin",
|
base_path: "/admin",
|
||||||
},
|
},
|
||||||
astro: {
|
"solid-start": {
|
||||||
base_path: "/admin",
|
base_path: "/admin",
|
||||||
},
|
},
|
||||||
node: {
|
astro: {
|
||||||
base_path: "",
|
base_path: "/admin",
|
||||||
},
|
},
|
||||||
bun: {
|
node: {
|
||||||
base_path: "",
|
base_path: "",
|
||||||
},
|
},
|
||||||
"tanstack-start": {
|
bun: {
|
||||||
base_path: "/admin",
|
base_path: "",
|
||||||
},
|
},
|
||||||
|
"tanstack-start": {
|
||||||
|
base_path: "/admin",
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export function getAdapterConfig(): typeof default_config {
|
export function getAdapterConfig(): typeof default_config {
|
||||||
if (adapter) {
|
if (adapter) {
|
||||||
if (!configs[adapter]) {
|
if (!configs[adapter]) {
|
||||||
console.warn(
|
console.warn(
|
||||||
`Adapter "${adapter}" not found. Available adapters: ${Object.keys(configs).join(", ")}`,
|
`Adapter "${adapter}" not found. Available adapters: ${Object.keys(configs).join(", ")}`,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return {
|
return {
|
||||||
...default_config,
|
...default_config,
|
||||||
...configs[adapter],
|
...configs[adapter],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return default_config;
|
return default_config;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { createApp } from "bknd/adapter/bun";
|
import { createApp } from "userbase/adapter/bun";
|
||||||
|
|
||||||
async function generate() {
|
async function generate() {
|
||||||
console.info("Generating MCP documentation...");
|
console.info("Generating MCP documentation...");
|
||||||
|
|||||||
+25
-20
@@ -1,24 +1,24 @@
|
|||||||
{
|
{
|
||||||
"name": "bknd",
|
"name": "userbase",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
"bin": "./dist/cli/index.js",
|
"bin": "./dist/cli/index.js",
|
||||||
"version": "0.21.0-rc.1",
|
"version": "0.0.1",
|
||||||
"description": "Lightweight Firebase/Supabase alternative built to run anywhere — incl. Next.js, React Router, Astro, Cloudflare, Bun, Node, AWS Lambda & more.",
|
"description": "Lightweight Firebase/Supabase alternative built to run anywhere — incl. Next.js, React Router, Astro, Cloudflare, Bun, Node, AWS Lambda & more.",
|
||||||
"homepage": "https://bknd.io",
|
"homepage": "https://gitea.bsws.in/shishantbiswas/userbase",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/bknd-io/bknd.git"
|
"url": "https://gitea.bsws.in/shishantbiswas/userbase.git"
|
||||||
},
|
},
|
||||||
"bugs": {
|
"bugs": {
|
||||||
"url": "https://github.com/bknd-io/bknd/issues"
|
"url": "https://gitea.bsws.in/shishantbiswas/userbase/issues"
|
||||||
},
|
},
|
||||||
"packageManager": "bun@1.3.3",
|
"packageManager": "bun@1.3.3",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=22.13"
|
"node": ">=22.13"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "BKND_CLI_LOG_LEVEL=debug vite",
|
"dev": "USERBASE_CLI_LOG_LEVEL=debug vite",
|
||||||
"build": "NODE_ENV=production bun run build.ts --minify --types",
|
"build": "NODE_ENV=production bun run build.ts --minify --types",
|
||||||
"build:all": "rm -rf dist && bun run build:static && NODE_ENV=production bun run build.ts --minify --types --clean && bun run build:cli",
|
"build:all": "rm -rf dist && bun run build:static && NODE_ENV=production bun run build.ts --minify --types --clean && bun run build:cli",
|
||||||
"build:ci": "mkdir -p dist/static/.vite && echo '{}' > dist/static/.vite/manifest.json && NODE_ENV=production bun run build.ts",
|
"build:ci": "mkdir -p dist/static/.vite && echo '{}' > dist/static/.vite/manifest.json && NODE_ENV=production bun run build.ts",
|
||||||
@@ -52,7 +52,7 @@
|
|||||||
"@codemirror/lang-html": "^6.4.11",
|
"@codemirror/lang-html": "^6.4.11",
|
||||||
"@codemirror/lang-json": "^6.0.2",
|
"@codemirror/lang-json": "^6.0.2",
|
||||||
"@hello-pangea/dnd": "^18.0.1",
|
"@hello-pangea/dnd": "^18.0.1",
|
||||||
"@hono/swagger-ui": "^0.5.2",
|
"@hono/swagger-ui": "0.6.1",
|
||||||
"@mantine/core": "^7.17.1",
|
"@mantine/core": "^7.17.1",
|
||||||
"@mantine/hooks": "^7.17.1",
|
"@mantine/hooks": "^7.17.1",
|
||||||
"@tanstack/react-form": "^1.0.5",
|
"@tanstack/react-form": "^1.0.5",
|
||||||
@@ -62,7 +62,7 @@
|
|||||||
"bcryptjs": "^3.0.3",
|
"bcryptjs": "^3.0.3",
|
||||||
"dayjs": "^1.11.20",
|
"dayjs": "^1.11.20",
|
||||||
"fast-xml-parser": "^5.3.1",
|
"fast-xml-parser": "^5.3.1",
|
||||||
"hono": "4.10.4",
|
"hono": "4.13.9",
|
||||||
"json-schema-library": "10.0.0-rc7",
|
"json-schema-library": "10.0.0-rc7",
|
||||||
"json-schema-to-ts": "^3.1.1",
|
"json-schema-to-ts": "^3.1.1",
|
||||||
"jsonv-ts": "^0.10.1",
|
"jsonv-ts": "^0.10.1",
|
||||||
@@ -73,7 +73,6 @@
|
|||||||
"picocolors": "^1.1.1",
|
"picocolors": "^1.1.1",
|
||||||
"radix-ui": "^1.1.3",
|
"radix-ui": "^1.1.3",
|
||||||
"swr": "^2.3.6",
|
"swr": "^2.3.6",
|
||||||
"use-sync-external-store": "^1.6.0",
|
|
||||||
"zustand": "^4"
|
"zustand": "^4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
@@ -83,12 +82,12 @@
|
|||||||
"@cloudflare/vitest-pool-workers": "^0.10.4",
|
"@cloudflare/vitest-pool-workers": "^0.10.4",
|
||||||
"@cloudflare/workers-types": "^4.20251014.0",
|
"@cloudflare/workers-types": "^4.20251014.0",
|
||||||
"@dagrejs/dagre": "^1.1.4",
|
"@dagrejs/dagre": "^1.1.4",
|
||||||
"@hono/vite-dev-server": "^0.23.0",
|
"@hono/vite-dev-server": "0.26.1",
|
||||||
"@hookform/resolvers": "^5.2.2",
|
"@hookform/resolvers": "^5.2.2",
|
||||||
"@libsql/client": "^0.15.15",
|
"@libsql/client": "^0.15.15",
|
||||||
"@mantine/modals": "^7.17.1",
|
"@mantine/modals": "^7.17.1",
|
||||||
"@mantine/notifications": "^7.17.1",
|
"@mantine/notifications": "^7.17.1",
|
||||||
"@playwright/test": "^1.56.1",
|
"@playwright/test": "^1.63.0",
|
||||||
"@rjsf/core": "5.22.2",
|
"@rjsf/core": "5.22.2",
|
||||||
"@rjsf/utils": "5.22.0",
|
"@rjsf/utils": "5.22.0",
|
||||||
"@standard-schema/spec": "^1.0.0",
|
"@standard-schema/spec": "^1.0.0",
|
||||||
@@ -100,8 +99,8 @@
|
|||||||
"@testing-library/react": "^16.2.0",
|
"@testing-library/react": "^16.2.0",
|
||||||
"@types/node": "^24.10.0",
|
"@types/node": "^24.10.0",
|
||||||
"@types/pg": "^8.15.6",
|
"@types/pg": "^8.15.6",
|
||||||
"@types/react": "^19.0.10",
|
"@types/react": "^19.3.0",
|
||||||
"@types/react-dom": "^19.0.4",
|
"@types/react-dom": "^19.3.0",
|
||||||
"@vitejs/plugin-react": "^5.1.0",
|
"@vitejs/plugin-react": "^5.1.0",
|
||||||
"@vitest/coverage-v8": "3.0.9",
|
"@vitest/coverage-v8": "3.0.9",
|
||||||
"autoprefixer": "^10.4.21",
|
"autoprefixer": "^10.4.21",
|
||||||
@@ -123,8 +122,8 @@
|
|||||||
"postcss-simple-vars": "^7.0.1",
|
"postcss-simple-vars": "^7.0.1",
|
||||||
"postgres": "^3.4.7",
|
"postgres": "^3.4.7",
|
||||||
"posthog-js-lite": "^3.6.0",
|
"posthog-js-lite": "^3.6.0",
|
||||||
"react": "^19.0.0",
|
"react": "^19.3.0",
|
||||||
"react-dom": "^19.0.0",
|
"react-dom": "^19.3.0",
|
||||||
"react-hook-form": "^7.66.0",
|
"react-hook-form": "^7.66.0",
|
||||||
"react-icons": "5.5.0",
|
"react-icons": "5.5.0",
|
||||||
"react-json-view-lite": "^2.5.0",
|
"react-json-view-lite": "^2.5.0",
|
||||||
@@ -137,9 +136,8 @@
|
|||||||
"tsup": "^8.5.0",
|
"tsup": "^8.5.0",
|
||||||
"tsx": "^4.20.6",
|
"tsx": "^4.20.6",
|
||||||
"uuid": "^13.0.0",
|
"uuid": "^13.0.0",
|
||||||
"vite": "^7.1.12",
|
"vite": "^8.3.1",
|
||||||
"vite-plugin-circular-dependency": "^0.5.0",
|
"vite-plugin-circular-dependency": "^0.5.0",
|
||||||
"vite-tsconfig-paths": "^5.1.4",
|
|
||||||
"vitest": "3.0.9",
|
"vitest": "3.0.9",
|
||||||
"wouter": "^3.7.1",
|
"wouter": "^3.7.1",
|
||||||
"wrangler": "^4.45.4"
|
"wrangler": "^4.45.4"
|
||||||
@@ -148,8 +146,8 @@
|
|||||||
"@hono/node-server": "^1.19.6"
|
"@hono/node-server": "^1.19.6"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"react": ">=19",
|
"react": ">=19.3.0",
|
||||||
"react-dom": ">=19"
|
"react-dom": ">=19.3.0"
|
||||||
},
|
},
|
||||||
"main": "./dist/index.js",
|
"main": "./dist/index.js",
|
||||||
"module": "./dist/index.js",
|
"module": "./dist/index.js",
|
||||||
@@ -263,6 +261,11 @@
|
|||||||
"import": "./dist/adapter/sveltekit/index.js",
|
"import": "./dist/adapter/sveltekit/index.js",
|
||||||
"require": "./dist/adapter/sveltekit/index.js"
|
"require": "./dist/adapter/sveltekit/index.js"
|
||||||
},
|
},
|
||||||
|
"./adapter/solid-start": {
|
||||||
|
"types": "./dist/types/adapter/solid-start/index.d.ts",
|
||||||
|
"import": "./dist/adapter/solid-start/index.js",
|
||||||
|
"require": "./dist/adapter/solid-start/index.js"
|
||||||
|
},
|
||||||
"./adapter/aws": {
|
"./adapter/aws": {
|
||||||
"types": "./dist/types/adapter/aws/index.d.ts",
|
"types": "./dist/types/adapter/aws/index.d.ts",
|
||||||
"import": "./dist/adapter/aws/index.js",
|
"import": "./dist/adapter/aws/index.js",
|
||||||
@@ -298,6 +301,7 @@
|
|||||||
"adapter/node": ["./dist/types/adapter/node/index.d.ts"],
|
"adapter/node": ["./dist/types/adapter/node/index.d.ts"],
|
||||||
"adapter/sveltekit": ["./dist/types/adapter/sveltekit/index.d.ts"],
|
"adapter/sveltekit": ["./dist/types/adapter/sveltekit/index.d.ts"],
|
||||||
"adapter/tanstack-start": ["./dist/types/adapter/tanstack-start/index.d.ts"],
|
"adapter/tanstack-start": ["./dist/types/adapter/tanstack-start/index.d.ts"],
|
||||||
|
"adapter/solid-start": ["./dist/types/adapter/solid-start/index.d.ts"],
|
||||||
"adapter/sqlite": ["./dist/types/adapter/sqlite/edge.d.ts"]
|
"adapter/sqlite": ["./dist/types/adapter/sqlite/edge.d.ts"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -331,6 +335,7 @@
|
|||||||
"sveltekit",
|
"sveltekit",
|
||||||
"svelte",
|
"svelte",
|
||||||
"bun",
|
"bun",
|
||||||
"node"
|
"node",
|
||||||
|
"solid-start"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -1,10 +1,10 @@
|
|||||||
import type { SafeUser } from "bknd";
|
import type { SafeUser } from "userbase";
|
||||||
import { AuthApi, type AuthApiOptions } from "auth/api/AuthApi";
|
import { AuthApi, type AuthApiOptions } from "auth/api/AuthApi";
|
||||||
import { DataApi, type DataApiOptions } from "data/api/DataApi";
|
import { DataApi, type DataApiOptions } from "data/api/DataApi";
|
||||||
import { decode } from "hono/jwt";
|
import { decode } from "hono/jwt";
|
||||||
import { MediaApi, type MediaApiOptions } from "media/api/MediaApi";
|
import { MediaApi, type MediaApiOptions } from "media/api/MediaApi";
|
||||||
import { SystemApi } from "modules/SystemApi";
|
import { SystemApi } from "modules/SystemApi";
|
||||||
import { omitKeys } from "bknd/utils";
|
import { omitKeys } from "userbase/utils";
|
||||||
import type { BaseModuleApiOptions } from "modules";
|
import type { BaseModuleApiOptions } from "modules";
|
||||||
|
|
||||||
export type TApiUser = SafeUser;
|
export type TApiUser = SafeUser;
|
||||||
|
|||||||
+2
-2
@@ -1,5 +1,5 @@
|
|||||||
import type { CreateUserPayload } from "auth/AppAuth";
|
import type { CreateUserPayload } from "auth/AppAuth";
|
||||||
import { $console, McpClient } from "bknd/utils";
|
import { $console, McpClient } from "userbase/utils";
|
||||||
import { Event } from "core/events";
|
import { Event } from "core/events";
|
||||||
import type { em as prototypeEm } from "data/prototype";
|
import type { em as prototypeEm } from "data/prototype";
|
||||||
import { Connection } from "data/connection/Connection";
|
import { Connection } from "data/connection/Connection";
|
||||||
@@ -346,7 +346,7 @@ export class App<
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
// gracefully add the app id
|
// gracefully add the app id
|
||||||
c.res.headers.set("X-bknd-id", this._id);
|
c.res.headers.set("X-userbase-id", this._id);
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
|
|
||||||
await this.emgr.emit(
|
await this.emgr.emit(
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import type { TestRunner } from "core/test";
|
import type { TestRunner } from "core/test";
|
||||||
import type { BkndConfig, DefaultArgs } from "./index";
|
import type { UserbaseConfig, DefaultArgs } from "./index";
|
||||||
import type { App } from "App";
|
import type { App } from "App";
|
||||||
import { disableConsoleLog, enableConsoleLog } from "core/utils/test";
|
import { disableConsoleLog, enableConsoleLog } from "core/utils/test";
|
||||||
|
|
||||||
export function adapterTestSuite<
|
export function adapterTestSuite<
|
||||||
Config extends BkndConfig = BkndConfig,
|
Config extends UserbaseConfig = UserbaseConfig,
|
||||||
Args extends DefaultArgs = DefaultArgs,
|
Args extends DefaultArgs = DefaultArgs,
|
||||||
>(
|
>(
|
||||||
testRunner: TestRunner,
|
testRunner: TestRunner,
|
||||||
@@ -39,7 +39,7 @@ export function adapterTestSuite<
|
|||||||
}),
|
}),
|
||||||
beforeBuild,
|
beforeBuild,
|
||||||
onBuilt,
|
onBuilt,
|
||||||
} as const satisfies BkndConfig;
|
} as const satisfies UserbaseConfig;
|
||||||
|
|
||||||
const app = await makeApp(
|
const app = await makeApp(
|
||||||
config as any,
|
config as any,
|
||||||
|
|||||||
@@ -1,20 +1,20 @@
|
|||||||
import { type FrameworkBkndConfig, createFrameworkApp } from "bknd/adapter";
|
import { type FrameworkUserbaseConfig, createFrameworkApp } from "userbase/adapter";
|
||||||
|
|
||||||
type AstroEnv = NodeJS.ProcessEnv;
|
type AstroEnv = NodeJS.ProcessEnv;
|
||||||
type TAstro = {
|
type TAstro = {
|
||||||
request: Request;
|
request: Request;
|
||||||
};
|
};
|
||||||
export type AstroBkndConfig<Env = AstroEnv> = FrameworkBkndConfig<Env>;
|
export type AstroUserbaseConfig<Env = AstroEnv> = FrameworkUserbaseConfig<Env>;
|
||||||
|
|
||||||
export async function getApp<Env = AstroEnv>(
|
export async function getApp<Env = AstroEnv>(
|
||||||
config: AstroBkndConfig<Env> = {},
|
config: AstroUserbaseConfig<Env> = {},
|
||||||
args: Env = import.meta.env as Env,
|
args: Env = import.meta.env as Env,
|
||||||
) {
|
) {
|
||||||
return await createFrameworkApp(config, args);
|
return await createFrameworkApp(config, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function serve<Env = AstroEnv>(
|
export function serve<Env = AstroEnv>(
|
||||||
config: AstroBkndConfig<Env> = {},
|
config: AstroUserbaseConfig<Env> = {},
|
||||||
args: Env = import.meta.env as Env,
|
args: Env = import.meta.env as Env,
|
||||||
) {
|
) {
|
||||||
return async (fnArgs: TAstro) => {
|
return async (fnArgs: TAstro) => {
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import type { App } from "bknd";
|
import type { App } from "userbase";
|
||||||
import { handle } from "hono/aws-lambda";
|
import { handle } from "hono/aws-lambda";
|
||||||
import { serveStatic } from "@hono/node-server/serve-static";
|
import { serveStatic } from "@hono/node-server/serve-static";
|
||||||
import { type RuntimeBkndConfig, createRuntimeApp } from "bknd/adapter";
|
import { type RuntimeUserbaseConfig, createRuntimeApp } from "userbase/adapter";
|
||||||
|
|
||||||
type AwsLambdaEnv = object;
|
type AwsLambdaEnv = object;
|
||||||
export type AwsLambdaBkndConfig<Env extends AwsLambdaEnv = AwsLambdaEnv> =
|
export type AwsLambdaUserbaseConfig<Env extends AwsLambdaEnv = AwsLambdaEnv> =
|
||||||
RuntimeBkndConfig<Env> & {
|
RuntimeUserbaseConfig<Env> & {
|
||||||
assets?:
|
assets?:
|
||||||
| {
|
| {
|
||||||
mode: "local";
|
mode: "local";
|
||||||
@@ -18,10 +18,10 @@ export type AwsLambdaBkndConfig<Env extends AwsLambdaEnv = AwsLambdaEnv> =
|
|||||||
};
|
};
|
||||||
|
|
||||||
export async function createApp<Env extends AwsLambdaEnv = AwsLambdaEnv>(
|
export async function createApp<Env extends AwsLambdaEnv = AwsLambdaEnv>(
|
||||||
{ adminOptions = false, assets, ...config }: AwsLambdaBkndConfig<Env> = {},
|
{ adminOptions = false, assets, ...config }: AwsLambdaUserbaseConfig<Env> = {},
|
||||||
args: Env = {} as Env,
|
args: Env = {} as Env,
|
||||||
): Promise<App> {
|
): Promise<App> {
|
||||||
let additional: Partial<RuntimeBkndConfig> = {
|
let additional: Partial<RuntimeUserbaseConfig> = {
|
||||||
adminOptions,
|
adminOptions,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -60,7 +60,7 @@ export async function createApp<Env extends AwsLambdaEnv = AwsLambdaEnv>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function serve<Env extends AwsLambdaEnv = AwsLambdaEnv>(
|
export function serve<Env extends AwsLambdaEnv = AwsLambdaEnv>(
|
||||||
config: AwsLambdaBkndConfig<Env> = {},
|
config: AwsLambdaUserbaseConfig<Env> = {},
|
||||||
args: Env = {} as Env,
|
args: Env = {} as Env,
|
||||||
) {
|
) {
|
||||||
return async (event) => {
|
return async (event) => {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import type { FileBody, FileListObject, FileMeta, FileUploadPayload } from "bknd";
|
import type { FileBody, FileListObject, FileMeta, FileUploadPayload } from "userbase";
|
||||||
import { StorageAdapter, guessMimeType } from "bknd";
|
import { StorageAdapter, guessMimeType } from "userbase";
|
||||||
import { parse, s, isFile, isBlob } from "bknd/utils";
|
import { parse, s, isFile, isBlob } from "userbase/utils";
|
||||||
|
|
||||||
export const opfsAdapterConfig = s.object(
|
export const opfsAdapterConfig = s.object(
|
||||||
{
|
{
|
||||||
|
|||||||
+19
-19
@@ -7,20 +7,20 @@ import {
|
|||||||
useState,
|
useState,
|
||||||
type ReactNode,
|
type ReactNode,
|
||||||
} from "react";
|
} from "react";
|
||||||
import { checksum } from "bknd/utils";
|
import { checksum } from "userbase/utils";
|
||||||
import { App, registries, sqlocal, type BkndConfig } from "bknd";
|
import { App, registries, sqlocal, type UserbaseConfig } from "userbase";
|
||||||
import { Route, Router, Switch } from "wouter";
|
import { Route, Router, Switch } from "wouter";
|
||||||
import { ClientProvider } from "bknd/client";
|
import { ClientProvider } from "userbase/client";
|
||||||
import { SQLocalKysely } from "sqlocal/kysely";
|
import { SQLocalKysely } from "sqlocal/kysely";
|
||||||
import type { ClientConfig, DatabasePath } from "sqlocal";
|
import type { ClientConfig, DatabasePath } from "sqlocal";
|
||||||
import { OpfsStorageAdapter } from "bknd/adapter/browser";
|
import { OpfsStorageAdapter } from "userbase/adapter/browser";
|
||||||
import type { BkndAdminConfig } from "bknd/ui";
|
import type { UserbaseAdminConfig } from "userbase/ui";
|
||||||
|
|
||||||
const Admin = lazy(() =>
|
const Admin = lazy(() =>
|
||||||
Promise.all([
|
Promise.all([
|
||||||
import("bknd/ui"),
|
import("userbase/ui"),
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import("bknd/dist/styles.css"),
|
import("userbase/dist/styles.css"),
|
||||||
]).then(([mod]) => ({
|
]).then(([mod]) => ({
|
||||||
default: mod.Admin,
|
default: mod.Admin,
|
||||||
})),
|
})),
|
||||||
@@ -34,34 +34,34 @@ function safeViewTransition(fn: () => void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export type BrowserBkndConfig<Args = ImportMetaEnv> = Omit<
|
export type BrowserUserbaseConfig<Args = ImportMetaEnv> = Omit<
|
||||||
BkndConfig<Args>,
|
UserbaseConfig<Args>,
|
||||||
"connection" | "app"
|
"connection" | "app"
|
||||||
> & {
|
> & {
|
||||||
adminConfig?: BkndAdminConfig;
|
adminConfig?: UserbaseAdminConfig;
|
||||||
connection?: ClientConfig | DatabasePath;
|
connection?: ClientConfig | DatabasePath;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type BkndBrowserAppProps = {
|
export type UserbaseBrowserAppProps = {
|
||||||
children: ReactNode;
|
children: ReactNode;
|
||||||
header?: ReactNode;
|
header?: ReactNode;
|
||||||
loading?: ReactNode;
|
loading?: ReactNode;
|
||||||
notFound?: ReactNode;
|
notFound?: ReactNode;
|
||||||
} & BrowserBkndConfig;
|
} & BrowserUserbaseConfig;
|
||||||
|
|
||||||
const BkndBrowserAppContext = createContext<{
|
const UserbaseBrowserAppContext = createContext<{
|
||||||
app: App;
|
app: App;
|
||||||
hash: string;
|
hash: string;
|
||||||
}>(undefined!);
|
}>(undefined!);
|
||||||
|
|
||||||
export function BkndBrowserApp({
|
export function UserbaseBrowserApp({
|
||||||
children,
|
children,
|
||||||
adminConfig,
|
adminConfig,
|
||||||
header,
|
header,
|
||||||
loading,
|
loading,
|
||||||
notFound,
|
notFound,
|
||||||
...config
|
...config
|
||||||
}: BkndBrowserAppProps) {
|
}: UserbaseBrowserAppProps) {
|
||||||
const [app, setApp] = useState<App | undefined>(undefined);
|
const [app, setApp] = useState<App | undefined>(undefined);
|
||||||
const [hash, setHash] = useState<string>("");
|
const [hash, setHash] = useState<string>("");
|
||||||
const adminRoutePath = (adminConfig?.basepath ?? "") + "/*?";
|
const adminRoutePath = (adminConfig?.basepath ?? "") + "/*?";
|
||||||
@@ -90,7 +90,7 @@ export function BkndBrowserApp({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<BkndBrowserAppContext.Provider value={{ app, hash }}>
|
<UserbaseBrowserAppContext.Provider value={{ app, hash }}>
|
||||||
<ClientProvider storage={window.localStorage} fetcher={app.server.request}>
|
<ClientProvider storage={window.localStorage} fetcher={app.server.request}>
|
||||||
{header}
|
{header}
|
||||||
<Router key={hash}>
|
<Router key={hash}>
|
||||||
@@ -110,12 +110,12 @@ export function BkndBrowserApp({
|
|||||||
</Switch>
|
</Switch>
|
||||||
</Router>
|
</Router>
|
||||||
</ClientProvider>
|
</ClientProvider>
|
||||||
</BkndBrowserAppContext.Provider>
|
</UserbaseBrowserAppContext.Provider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useApp() {
|
export function useApp() {
|
||||||
return useContext(BkndBrowserAppContext);
|
return useContext(UserbaseBrowserAppContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
const Center = (props: React.HTMLAttributes<HTMLDivElement>) => (
|
const Center = (props: React.HTMLAttributes<HTMLDivElement>) => (
|
||||||
@@ -133,7 +133,7 @@ const Center = (props: React.HTMLAttributes<HTMLDivElement>) => (
|
|||||||
);
|
);
|
||||||
|
|
||||||
let initialized = false;
|
let initialized = false;
|
||||||
async function setup(config: BrowserBkndConfig = {}) {
|
async function setup(config: BrowserUserbaseConfig = {}) {
|
||||||
if (initialized) return;
|
if (initialized) return;
|
||||||
initialized = true;
|
initialized = true;
|
||||||
|
|
||||||
@@ -1,2 +1,2 @@
|
|||||||
export * from "./OpfsStorageAdapter";
|
export * from "./OpfsStorageAdapter";
|
||||||
export * from "./BkndBrowserApp";
|
export * from "./UserbaseBrowserApp";
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
import path from "node:path";
|
import path from "node:path";
|
||||||
import { type RuntimeBkndConfig, createRuntimeApp } from "bknd/adapter";
|
import { type RuntimeUserbaseConfig, createRuntimeApp } from "userbase/adapter";
|
||||||
import { registerLocalMediaAdapter } from ".";
|
import { registerLocalMediaAdapter } from ".";
|
||||||
import { config, type App } from "bknd";
|
import { config, type App } from "userbase";
|
||||||
import { serveStatic } from "hono/bun";
|
import { serveStatic } from "hono/bun";
|
||||||
|
|
||||||
type BunEnv = Bun.Env;
|
type BunEnv = Bun.Env;
|
||||||
export type BunBkndConfig<Env = BunEnv> = RuntimeBkndConfig<Env> &
|
export type BunUserbaseConfig<Env = BunEnv> = RuntimeUserbaseConfig<Env> &
|
||||||
Omit<Bun.Serve.Options<undefined, string>, "fetch">;
|
Omit<Bun.Serve.Options<undefined, string>, "fetch">;
|
||||||
|
|
||||||
export async function createApp<Env = BunEnv>(
|
export async function createApp<Env = BunEnv>(
|
||||||
{ distPath, serveStatic: _serveStatic, ...config }: BunBkndConfig<Env> = {},
|
{ distPath, serveStatic: _serveStatic, ...config }: BunUserbaseConfig<Env> = {},
|
||||||
args: Env = Bun.env as Env,
|
args: Env = Bun.env as Env,
|
||||||
) {
|
) {
|
||||||
const root = path.resolve(distPath ?? "./node_modules/bknd/dist", "static");
|
const root = path.resolve(distPath ?? "./node_modules/userbase/dist", "static");
|
||||||
registerLocalMediaAdapter();
|
registerLocalMediaAdapter();
|
||||||
|
|
||||||
return await createRuntimeApp(
|
return await createRuntimeApp(
|
||||||
@@ -29,7 +29,7 @@ export async function createApp<Env = BunEnv>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function createHandler<Env = BunEnv>(
|
export function createHandler<Env = BunEnv>(
|
||||||
config: BunBkndConfig<Env> = {},
|
config: BunUserbaseConfig<Env> = {},
|
||||||
args: Env = Bun.env as Env,
|
args: Env = Bun.env as Env,
|
||||||
) {
|
) {
|
||||||
let app: App | undefined;
|
let app: App | undefined;
|
||||||
@@ -55,7 +55,7 @@ export function serve<Env = BunEnv>(
|
|||||||
serveStatic,
|
serveStatic,
|
||||||
beforeBuild,
|
beforeBuild,
|
||||||
...serveOptions
|
...serveOptions
|
||||||
}: BunBkndConfig<Env> = {},
|
}: BunUserbaseConfig<Env> = {},
|
||||||
args: Env = Bun.env as Env,
|
args: Env = Bun.env as Env,
|
||||||
) {
|
) {
|
||||||
Bun.serve({
|
Bun.serve({
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ import {
|
|||||||
genericSqlite,
|
genericSqlite,
|
||||||
type GenericSqliteConnection,
|
type GenericSqliteConnection,
|
||||||
type GenericSqliteConnectionConfig,
|
type GenericSqliteConnectionConfig,
|
||||||
} from "bknd";
|
} from "userbase";
|
||||||
import { omitKeys } from "bknd/utils";
|
import { omitKeys } from "userbase/utils";
|
||||||
|
|
||||||
export type BunSqliteConnection = GenericSqliteConnection<Database>;
|
export type BunSqliteConnection = GenericSqliteConnection<Database>;
|
||||||
export type BunSqliteConnectionConfig = Omit<
|
export type BunSqliteConnectionConfig = Omit<
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { makeConfig, type CloudflareContext } from "./config";
|
|||||||
import { disableConsoleLog, enableConsoleLog } from "core/utils";
|
import { disableConsoleLog, enableConsoleLog } from "core/utils";
|
||||||
import { adapterTestSuite } from "adapter/adapter-test-suite";
|
import { adapterTestSuite } from "adapter/adapter-test-suite";
|
||||||
import { bunTestRunner } from "adapter/bun/test";
|
import { bunTestRunner } from "adapter/bun/test";
|
||||||
import { type CloudflareBkndConfig, createApp } from "./cloudflare-workers.adapter";
|
import { type CloudflareUserbaseConfig, createApp } from "./cloudflare-workers.adapter";
|
||||||
|
|
||||||
beforeAll(disableConsoleLog);
|
beforeAll(disableConsoleLog);
|
||||||
afterAll(enableConsoleLog);
|
afterAll(enableConsoleLog);
|
||||||
@@ -40,7 +40,7 @@ describe("cf adapter", () => {
|
|||||||
expect(dynamicConfig.connection).toBeDefined();
|
expect(dynamicConfig.connection).toBeDefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
adapterTestSuite<CloudflareBkndConfig, CloudflareContext<any>>(bunTestRunner, {
|
adapterTestSuite<CloudflareUserbaseConfig, CloudflareContext<any>>(bunTestRunner, {
|
||||||
makeApp: async (c, a) => {
|
makeApp: async (c, a) => {
|
||||||
return await createApp(c, { env: a } as any);
|
return await createApp(c, { env: a } as any);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
/// <reference types="@cloudflare/workers-types" />
|
/// <reference types="@cloudflare/workers-types" />
|
||||||
|
|
||||||
import type { RuntimeBkndConfig } from "bknd/adapter";
|
import type { RuntimeUserbaseConfig } from "userbase/adapter";
|
||||||
import { Hono } from "hono";
|
import { Hono } from "hono";
|
||||||
import { serveStatic } from "hono/cloudflare-workers";
|
import { serveStatic } from "hono/cloudflare-workers";
|
||||||
import type { App, MaybePromise } from "bknd";
|
import type { App, MaybePromise } from "userbase";
|
||||||
import { $console } from "bknd/utils";
|
import { $console } from "userbase/utils";
|
||||||
import { createRuntimeApp } from "bknd/adapter";
|
import { createRuntimeApp } from "userbase/adapter";
|
||||||
import { registerAsyncsExecutionContext, makeConfig, type CloudflareContext } from "./config";
|
import { registerAsyncsExecutionContext, makeConfig, type CloudflareContext } from "./config";
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
@@ -15,7 +15,7 @@ declare global {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export type CloudflareEnv = Cloudflare.Env;
|
export type CloudflareEnv = Cloudflare.Env;
|
||||||
export type CloudflareBkndConfig<Env = CloudflareEnv> = RuntimeBkndConfig<Env> & {
|
export type CloudflareUserbaseConfig<Env = CloudflareEnv> = RuntimeUserbaseConfig<Env> & {
|
||||||
bindings?: (args: Env) => MaybePromise<{
|
bindings?: (args: Env) => MaybePromise<{
|
||||||
kv?: KVNamespace;
|
kv?: KVNamespace;
|
||||||
db?: D1Database;
|
db?: D1Database;
|
||||||
@@ -34,7 +34,7 @@ export type CloudflareBkndConfig<Env = CloudflareEnv> = RuntimeBkndConfig<Env> &
|
|||||||
};
|
};
|
||||||
|
|
||||||
export async function createApp<Env extends CloudflareEnv = CloudflareEnv>(
|
export async function createApp<Env extends CloudflareEnv = CloudflareEnv>(
|
||||||
config: CloudflareBkndConfig<Env> = {},
|
config: CloudflareUserbaseConfig<Env> = {},
|
||||||
ctx: Partial<CloudflareContext<Env>> = {},
|
ctx: Partial<CloudflareContext<Env>> = {},
|
||||||
) {
|
) {
|
||||||
const appConfig = await makeConfig(config, ctx);
|
const appConfig = await makeConfig(config, ctx);
|
||||||
@@ -57,7 +57,7 @@ export const getFresh = createApp;
|
|||||||
|
|
||||||
let app: App | undefined;
|
let app: App | undefined;
|
||||||
export function serve<Env extends CloudflareEnv = CloudflareEnv>(
|
export function serve<Env extends CloudflareEnv = CloudflareEnv>(
|
||||||
config: CloudflareBkndConfig<Env> = {},
|
config: CloudflareUserbaseConfig<Env> = {},
|
||||||
serveOptions?: (args: Env) => {
|
serveOptions?: (args: Env) => {
|
||||||
warm?: boolean;
|
warm?: boolean;
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,21 +1,22 @@
|
|||||||
|
|
||||||
/// <reference types="@cloudflare/workers-types" />
|
/// <reference types="@cloudflare/workers-types" />
|
||||||
|
|
||||||
import { Connection } from "bknd";
|
import { Connection } from "userbase";
|
||||||
import { sqlite } from "bknd/adapter/sqlite";
|
import { sqlite } from "userbase/adapter/sqlite";
|
||||||
import { makeConfig as makeAdapterConfig } from "bknd/adapter";
|
import { makeConfig as makeAdapterConfig } from "userbase/adapter";
|
||||||
import { registerMedia } from "./storage/StorageR2Adapter";
|
import { registerMedia } from "./storage/StorageR2Adapter";
|
||||||
import { getBinding } from "./bindings";
|
import { getBinding } from "./bindings";
|
||||||
import { d1Sqlite } from "./connection/D1Connection";
|
import { d1Sqlite } from "./connection/D1Connection";
|
||||||
import type { CloudflareBkndConfig, CloudflareEnv } from ".";
|
import type { CloudflareUserbaseConfig, CloudflareEnv } from ".";
|
||||||
import { App } from "bknd";
|
import { App } from "userbase";
|
||||||
import type { Context as HonoContext, ExecutionContext } from "hono";
|
import type { Context as HonoContext, ExecutionContext } from "hono";
|
||||||
import { $console } from "bknd/utils";
|
import { $console } from "userbase/utils";
|
||||||
import { setCookie } from "hono/cookie";
|
import { setCookie } from "hono/cookie";
|
||||||
|
|
||||||
export const constants = {
|
export const constants = {
|
||||||
exec_async_event_id: "cf_register_waituntil",
|
exec_async_event_id: "cf_register_waituntil",
|
||||||
cache_endpoint: "/__bknd/cache",
|
cache_endpoint: "/__userbase/cache",
|
||||||
do_endpoint: "/__bknd/do",
|
do_endpoint: "/__userbase/do",
|
||||||
d1_session: {
|
d1_session: {
|
||||||
cookie: "cf_d1_session",
|
cookie: "cf_d1_session",
|
||||||
header: "x-cf-d1-session",
|
header: "x-cf-d1-session",
|
||||||
@@ -40,7 +41,7 @@ function getCookieValue(cookies: string | null, name: string) {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function d1SessionHelper(config: CloudflareBkndConfig<any>) {
|
export function d1SessionHelper(config: CloudflareUserbaseConfig<any>) {
|
||||||
const headerKey = constants.d1_session.header;
|
const headerKey = constants.d1_session.header;
|
||||||
const cookieKey = constants.d1_session.cookie;
|
const cookieKey = constants.d1_session.cookie;
|
||||||
const transport = config.d1?.transport;
|
const transport = config.d1?.transport;
|
||||||
@@ -90,7 +91,7 @@ export function d1SessionHelper(config: CloudflareBkndConfig<any>) {
|
|||||||
|
|
||||||
let media_registered: boolean = false;
|
let media_registered: boolean = false;
|
||||||
export async function makeConfig<Env extends CloudflareEnv = CloudflareEnv>(
|
export async function makeConfig<Env extends CloudflareEnv = CloudflareEnv>(
|
||||||
config: CloudflareBkndConfig<Env>,
|
config: CloudflareUserbaseConfig<Env>,
|
||||||
args?: Partial<CloudflareContext<Env>>,
|
args?: Partial<CloudflareContext<Env>>,
|
||||||
) {
|
) {
|
||||||
if (!media_registered && config.registerMedia !== false) {
|
if (!media_registered && config.registerMedia !== false) {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/// <reference types="@cloudflare/workers-types" />
|
/// <reference types="@cloudflare/workers-types" />
|
||||||
|
|
||||||
import { genericSqlite, type GenericSqliteConnection } from "bknd";
|
import { genericSqlite, type GenericSqliteConnection } from "userbase";
|
||||||
import type { QueryResult } from "kysely";
|
import type { QueryResult } from "kysely";
|
||||||
|
|
||||||
export type D1SqliteConnection = GenericSqliteConnection<D1Database>;
|
export type D1SqliteConnection = GenericSqliteConnection<D1Database>;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/// <reference types="@cloudflare/workers-types" />
|
/// <reference types="@cloudflare/workers-types" />
|
||||||
|
|
||||||
import { genericSqlite, type GenericSqliteConnection } from "bknd";
|
import { genericSqlite, type GenericSqliteConnection } from "userbase";
|
||||||
import type { QueryResult } from "kysely";
|
import type { QueryResult } from "kysely";
|
||||||
|
|
||||||
export type DoSqliteConnection = GenericSqliteConnection<DurableObjectState["storage"]["sql"]>;
|
export type DoSqliteConnection = GenericSqliteConnection<DurableObjectState["storage"]["sql"]>;
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ export {
|
|||||||
createApp,
|
createApp,
|
||||||
serve,
|
serve,
|
||||||
type CloudflareEnv,
|
type CloudflareEnv,
|
||||||
type CloudflareBkndConfig,
|
type CloudflareUserbaseConfig,
|
||||||
} from "./cloudflare-workers.adapter";
|
} from "./cloudflare-workers.adapter";
|
||||||
export { d1Sqlite, type D1ConnectionConfig };
|
export { d1Sqlite, type D1ConnectionConfig };
|
||||||
export { doSqlite, type DoConnectionConfig } from "./connection/DoConnection";
|
export { doSqlite, type DoConnectionConfig } from "./connection/DoConnection";
|
||||||
@@ -18,7 +18,7 @@ export {
|
|||||||
} from "./bindings";
|
} from "./bindings";
|
||||||
export { constants, makeConfig, type CloudflareContext } from "./config";
|
export { constants, makeConfig, type CloudflareContext } from "./config";
|
||||||
export { StorageR2Adapter, registerMedia } from "./storage/StorageR2Adapter";
|
export { StorageR2Adapter, registerMedia } from "./storage/StorageR2Adapter";
|
||||||
export { registries } from "bknd";
|
export { registries } from "userbase";
|
||||||
export { devFsVitePlugin, devFsWrite } from "./vite";
|
export { devFsVitePlugin, devFsWrite } from "./vite";
|
||||||
|
|
||||||
// for compatibility with old code
|
// for compatibility with old code
|
||||||
|
|||||||
@@ -2,12 +2,12 @@ import {
|
|||||||
d1Sqlite,
|
d1Sqlite,
|
||||||
getBinding,
|
getBinding,
|
||||||
registerMedia,
|
registerMedia,
|
||||||
type CloudflareBkndConfig,
|
type CloudflareUserbaseConfig,
|
||||||
type CloudflareEnv,
|
type CloudflareEnv,
|
||||||
} from "bknd/adapter/cloudflare";
|
} from "userbase/adapter/cloudflare";
|
||||||
import type { GetPlatformProxyOptions, PlatformProxy } from "wrangler";
|
import type { GetPlatformProxyOptions, PlatformProxy } from "wrangler";
|
||||||
import process from "node:process";
|
import process from "node:process";
|
||||||
import { $console } from "bknd/utils";
|
import { $console } from "userbase/utils";
|
||||||
|
|
||||||
export type WithPlatformProxyOptions = {
|
export type WithPlatformProxyOptions = {
|
||||||
/**
|
/**
|
||||||
@@ -42,7 +42,7 @@ async function getPlatformProxy(opts?: GetPlatformProxyOptions) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function withPlatformProxy<Env extends CloudflareEnv>(
|
export function withPlatformProxy<Env extends CloudflareEnv>(
|
||||||
config: CloudflareBkndConfig<Env> = {},
|
config: CloudflareUserbaseConfig<Env> = {},
|
||||||
opts?: WithPlatformProxyOptions,
|
opts?: WithPlatformProxyOptions,
|
||||||
) {
|
) {
|
||||||
const use_proxy =
|
const use_proxy =
|
||||||
@@ -91,5 +91,5 @@ export function withPlatformProxy<Env extends CloudflareEnv>(
|
|||||||
connection,
|
connection,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
} satisfies CloudflareBkndConfig<Env>;
|
} satisfies CloudflareUserbaseConfig<Env>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { registries as $registries, isDebug, guessMimeType } from "bknd";
|
import { registries as $registries, isDebug, guessMimeType } from "userbase";
|
||||||
import { getBindings } from "../bindings";
|
import { getBindings } from "../bindings";
|
||||||
import { s } from "bknd/utils";
|
import { s } from "userbase/utils";
|
||||||
import { StorageAdapter, type FileBody } from "bknd";
|
import { StorageAdapter, type FileBody } from "userbase";
|
||||||
|
|
||||||
export function makeSchema(bindings: string[] = []) {
|
export function makeSchema(bindings: string[] = []) {
|
||||||
return s.object(
|
return s.object(
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import { resolve } from "node:path";
|
|||||||
*/
|
*/
|
||||||
export function devFsVitePlugin({
|
export function devFsVitePlugin({
|
||||||
verbose = false,
|
verbose = false,
|
||||||
configFile = "bknd.config.ts",
|
configFile = "userbase.config.ts",
|
||||||
}: {
|
}: {
|
||||||
verbose?: boolean;
|
verbose?: boolean;
|
||||||
configFile?: string;
|
configFile?: string;
|
||||||
@@ -195,7 +195,7 @@ export function devFsVitePlugin({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if this is the bknd config file
|
// Check if this is the userbase config file
|
||||||
if (id.includes(configFile)) {
|
if (id.includes(configFile)) {
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
console.debug("[dev-fs-plugin] Transforming", configFile);
|
console.debug("[dev-fs-plugin] Transforming", configFile);
|
||||||
|
|||||||
+16
-16
@@ -7,27 +7,27 @@ import {
|
|||||||
type MaybePromise,
|
type MaybePromise,
|
||||||
registries as $registries,
|
registries as $registries,
|
||||||
type Merge,
|
type Merge,
|
||||||
} from "bknd";
|
} from "userbase";
|
||||||
import { $console } from "bknd/utils";
|
import { $console } from "userbase/utils";
|
||||||
import type { Context, MiddlewareHandler, Next } from "hono";
|
import type { Context, MiddlewareHandler, Next } from "hono";
|
||||||
import type { AdminControllerOptions } from "modules/server/AdminController";
|
import type { AdminControllerOptions } from "modules/server/AdminController";
|
||||||
import type { Manifest } from "vite";
|
import type { Manifest } from "vite";
|
||||||
|
|
||||||
export type BkndConfig<Args = any, Additional = {}> = Merge<
|
export type UserbaseConfig<Args = any, Additional = {}> = Merge<
|
||||||
CreateAppConfig &
|
CreateAppConfig &
|
||||||
Omit<Additional, "app"> & {
|
Omit<Additional, "app"> & {
|
||||||
app?:
|
app?:
|
||||||
| Omit<BkndConfig<Args, Additional>, "app">
|
| Omit<UserbaseConfig<Args, Additional>, "app">
|
||||||
| ((args: Args) => MaybePromise<Omit<BkndConfig<Args, Additional>, "app">>);
|
| ((args: Args) => MaybePromise<Omit<UserbaseConfig<Args, Additional>, "app">>);
|
||||||
onBuilt?: (app: App) => MaybePromise<void>;
|
onBuilt?: (app: App) => MaybePromise<void>;
|
||||||
beforeBuild?: (app?: App, registries?: typeof $registries) => MaybePromise<void>;
|
beforeBuild?: (app?: App, registries?: typeof $registries) => MaybePromise<void>;
|
||||||
buildConfig?: Parameters<App["build"]>[0];
|
buildConfig?: Parameters<App["build"]>[0];
|
||||||
}
|
}
|
||||||
>;
|
>;
|
||||||
|
|
||||||
export type FrameworkBkndConfig<Args = any> = BkndConfig<Args>;
|
export type FrameworkUserbaseConfig<Args = any> = UserbaseConfig<Args>;
|
||||||
|
|
||||||
export type RuntimeBkndConfig<Args = any> = BkndConfig<Args> & {
|
export type RuntimeUserbaseConfig<Args = any> = UserbaseConfig<Args> & {
|
||||||
distPath?: string;
|
distPath?: string;
|
||||||
serveStatic?: MiddlewareHandler | [string, MiddlewareHandler];
|
serveStatic?: MiddlewareHandler | [string, MiddlewareHandler];
|
||||||
adminOptions?: AdminControllerOptions | false;
|
adminOptions?: AdminControllerOptions | false;
|
||||||
@@ -38,9 +38,9 @@ export type DefaultArgs = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export async function makeConfig<Args = DefaultArgs>(
|
export async function makeConfig<Args = DefaultArgs>(
|
||||||
config: BkndConfig<Args>,
|
config: UserbaseConfig<Args>,
|
||||||
args?: Args,
|
args?: Args,
|
||||||
): Promise<Omit<BkndConfig<Args>, "app">> {
|
): Promise<Omit<UserbaseConfig<Args>, "app">> {
|
||||||
let additionalConfig: CreateAppConfig = {};
|
let additionalConfig: CreateAppConfig = {};
|
||||||
const { app, ...rest } = config;
|
const { app, ...rest } = config;
|
||||||
if (app) {
|
if (app) {
|
||||||
@@ -57,10 +57,10 @@ export async function makeConfig<Args = DefaultArgs>(
|
|||||||
return { ...rest, ...additionalConfig };
|
return { ...rest, ...additionalConfig };
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function createAdapterApp<Config extends BkndConfig = BkndConfig, Args = DefaultArgs>(
|
export async function createAdapterApp<Config extends UserbaseConfig = UserbaseConfig, Args = DefaultArgs>(
|
||||||
config: Config = {} as Config,
|
config: Config = {} as Config,
|
||||||
args?: Args,
|
args?: Args,
|
||||||
): Promise<{ app: App; config: BkndConfig<Args> }> {
|
): Promise<{ app: App; config: UserbaseConfig<Args> }> {
|
||||||
await config.beforeBuild?.(undefined, $registries);
|
await config.beforeBuild?.(undefined, $registries);
|
||||||
|
|
||||||
const appConfig = await makeConfig(config, args);
|
const appConfig = await makeConfig(config, args);
|
||||||
@@ -69,7 +69,7 @@ export async function createAdapterApp<Config extends BkndConfig = BkndConfig, A
|
|||||||
if (Connection.isConnection(config.connection)) {
|
if (Connection.isConnection(config.connection)) {
|
||||||
connection = config.connection;
|
connection = config.connection;
|
||||||
} else {
|
} else {
|
||||||
const sqlite = (await import("bknd/adapter/sqlite")).sqlite;
|
const sqlite = (await import("userbase/adapter/sqlite")).sqlite;
|
||||||
const conf = appConfig.connection ?? { url: "file:data.db" };
|
const conf = appConfig.connection ?? { url: "file:data.db" };
|
||||||
connection = sqlite(conf) as any;
|
connection = sqlite(conf) as any;
|
||||||
$console.info(`Using ${connection!.name} connection`, conf.url);
|
$console.info(`Using ${connection!.name} connection`, conf.url);
|
||||||
@@ -84,7 +84,7 @@ export async function createAdapterApp<Config extends BkndConfig = BkndConfig, A
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function createFrameworkApp<Args = DefaultArgs>(
|
export async function createFrameworkApp<Args = DefaultArgs>(
|
||||||
config: FrameworkBkndConfig = {},
|
config: FrameworkUserbaseConfig = {},
|
||||||
args?: Args,
|
args?: Args,
|
||||||
): Promise<App> {
|
): Promise<App> {
|
||||||
const { app, config: appConfig } = await createAdapterApp(config, args);
|
const { app, config: appConfig } = await createAdapterApp(config, args);
|
||||||
@@ -108,7 +108,7 @@ export async function createFrameworkApp<Args = DefaultArgs>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function createRuntimeApp<Args = DefaultArgs>(
|
export async function createRuntimeApp<Args = DefaultArgs>(
|
||||||
{ serveStatic, adminOptions, ...config }: RuntimeBkndConfig<Args> = {},
|
{ serveStatic, adminOptions, ...config }: RuntimeUserbaseConfig<Args> = {},
|
||||||
args?: Args,
|
args?: Args,
|
||||||
): Promise<App> {
|
): Promise<App> {
|
||||||
const { app, config: appConfig } = await createAdapterApp(config, args);
|
const { app, config: appConfig } = await createAdapterApp(config, args);
|
||||||
@@ -148,7 +148,7 @@ export async function createRuntimeApp<Args = DefaultArgs>(
|
|||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
* ```typescript
|
* ```typescript
|
||||||
* import { serveStaticViaImport } from "bknd/adapter";
|
* import { serveStaticViaImport } from "userbase/adapter";
|
||||||
*
|
*
|
||||||
* serve({
|
* serve({
|
||||||
* serveStatic: serveStaticViaImport(),
|
* serveStatic: serveStaticViaImport(),
|
||||||
@@ -161,7 +161,7 @@ export function serveStaticViaImport(opts?: {
|
|||||||
package?: string;
|
package?: string;
|
||||||
}) {
|
}) {
|
||||||
let files: string[] | undefined;
|
let files: string[] | undefined;
|
||||||
const pkg = opts?.package ?? "bknd";
|
const pkg = opts?.package ?? "userbase";
|
||||||
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
return async (c: Context, next: Next) => {
|
return async (c: Context, next: Next) => {
|
||||||
|
|||||||
@@ -3,13 +3,13 @@ import * as nextjs from "./nextjs.adapter";
|
|||||||
import { disableConsoleLog, enableConsoleLog } from "core/utils";
|
import { disableConsoleLog, enableConsoleLog } from "core/utils";
|
||||||
import { adapterTestSuite } from "adapter/adapter-test-suite";
|
import { adapterTestSuite } from "adapter/adapter-test-suite";
|
||||||
import { bunTestRunner } from "adapter/bun/test";
|
import { bunTestRunner } from "adapter/bun/test";
|
||||||
import type { NextjsBkndConfig } from "./nextjs.adapter";
|
import type { NextjsUserbaseConfig } from "./nextjs.adapter";
|
||||||
|
|
||||||
beforeAll(disableConsoleLog);
|
beforeAll(disableConsoleLog);
|
||||||
afterAll(enableConsoleLog);
|
afterAll(enableConsoleLog);
|
||||||
|
|
||||||
describe("nextjs adapter", () => {
|
describe("nextjs adapter", () => {
|
||||||
adapterTestSuite<NextjsBkndConfig>(bunTestRunner, {
|
adapterTestSuite<NextjsUserbaseConfig>(bunTestRunner, {
|
||||||
makeApp: nextjs.getApp,
|
makeApp: nextjs.getApp,
|
||||||
makeHandler: nextjs.serve,
|
makeHandler: nextjs.serve,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,21 +1,21 @@
|
|||||||
import { createFrameworkApp, type FrameworkBkndConfig } from "bknd/adapter";
|
import { createFrameworkApp, type FrameworkUserbaseConfig } from "userbase/adapter";
|
||||||
import { isNode } from "bknd/utils";
|
import { isNode } from "userbase/utils";
|
||||||
// @ts-expect-error next is not installed
|
// @ts-expect-error next is not installed
|
||||||
import type { NextApiRequest } from "next";
|
import type { NextApiRequest } from "next";
|
||||||
|
|
||||||
type NextjsEnv = NextApiRequest["env"];
|
type NextjsEnv = NextApiRequest["env"];
|
||||||
export type NextjsBkndConfig<Env = NextjsEnv> = FrameworkBkndConfig<Env> & {
|
export type NextjsUserbaseConfig<Env = NextjsEnv> = FrameworkUserbaseConfig<Env> & {
|
||||||
cleanRequest?: { searchParams?: string[] };
|
cleanRequest?: { searchParams?: string[] };
|
||||||
};
|
};
|
||||||
|
|
||||||
export async function getApp<Env = NextjsEnv>(
|
export async function getApp<Env = NextjsEnv>(
|
||||||
config: NextjsBkndConfig<Env>,
|
config: NextjsUserbaseConfig<Env>,
|
||||||
args: Env = process.env as Env,
|
args: Env = process.env as Env,
|
||||||
) {
|
) {
|
||||||
return await createFrameworkApp(config, args);
|
return await createFrameworkApp(config, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getCleanRequest(req: Request, cleanRequest: NextjsBkndConfig["cleanRequest"]) {
|
function getCleanRequest(req: Request, cleanRequest: NextjsUserbaseConfig["cleanRequest"]) {
|
||||||
if (!cleanRequest) return req;
|
if (!cleanRequest) return req;
|
||||||
|
|
||||||
const url = new URL(req.url);
|
const url = new URL(req.url);
|
||||||
@@ -41,7 +41,7 @@ function getCleanRequest(req: Request, cleanRequest: NextjsBkndConfig["cleanRequ
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function serve<Env = NextjsEnv>(
|
export function serve<Env = NextjsEnv>(
|
||||||
{ cleanRequest, ...config }: NextjsBkndConfig<Env> = {},
|
{ cleanRequest, ...config }: NextjsUserbaseConfig<Env> = {},
|
||||||
args: Env = process.env as Env,
|
args: Env = process.env as Env,
|
||||||
) {
|
) {
|
||||||
return async (req: Request) => {
|
return async (req: Request) => {
|
||||||
|
|||||||
@@ -2,9 +2,9 @@ import {
|
|||||||
genericSqlite,
|
genericSqlite,
|
||||||
type GenericSqliteConnection,
|
type GenericSqliteConnection,
|
||||||
type GenericSqliteConnectionConfig,
|
type GenericSqliteConnectionConfig,
|
||||||
} from "bknd";
|
} from "userbase";
|
||||||
import { DatabaseSync } from "node:sqlite";
|
import { DatabaseSync } from "node:sqlite";
|
||||||
import { omitKeys } from "bknd/utils";
|
import { omitKeys } from "userbase/utils";
|
||||||
|
|
||||||
export type NodeSqliteConnection = GenericSqliteConnection<DatabaseSync>;
|
export type NodeSqliteConnection = GenericSqliteConnection<DatabaseSync>;
|
||||||
export type NodeSqliteConnectionConfig = Omit<
|
export type NodeSqliteConnectionConfig = Omit<
|
||||||
|
|||||||
@@ -2,12 +2,12 @@ import path from "node:path";
|
|||||||
import { serve as honoServe } from "@hono/node-server";
|
import { serve as honoServe } from "@hono/node-server";
|
||||||
import { serveStatic } from "@hono/node-server/serve-static";
|
import { serveStatic } from "@hono/node-server/serve-static";
|
||||||
import { registerLocalMediaAdapter } from "adapter/node/storage";
|
import { registerLocalMediaAdapter } from "adapter/node/storage";
|
||||||
import { type RuntimeBkndConfig, createRuntimeApp } from "bknd/adapter";
|
import { type RuntimeUserbaseConfig, createRuntimeApp } from "userbase/adapter";
|
||||||
import { config as $config, type App } from "bknd";
|
import { config as $config, type App } from "userbase";
|
||||||
import { $console } from "bknd/utils";
|
import { $console } from "userbase/utils";
|
||||||
|
|
||||||
type NodeEnv = NodeJS.ProcessEnv;
|
type NodeEnv = NodeJS.ProcessEnv;
|
||||||
export type NodeBkndConfig<Env = NodeEnv> = RuntimeBkndConfig<Env> & {
|
export type NodeUserbaseConfig<Env = NodeEnv> = RuntimeUserbaseConfig<Env> & {
|
||||||
port?: number;
|
port?: number;
|
||||||
hostname?: string;
|
hostname?: string;
|
||||||
listener?: Parameters<typeof honoServe>[1];
|
listener?: Parameters<typeof honoServe>[1];
|
||||||
@@ -16,12 +16,12 @@ export type NodeBkndConfig<Env = NodeEnv> = RuntimeBkndConfig<Env> & {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export async function createApp<Env = NodeEnv>(
|
export async function createApp<Env = NodeEnv>(
|
||||||
{ distPath, relativeDistPath, ...config }: NodeBkndConfig<Env> = {},
|
{ distPath, relativeDistPath, ...config }: NodeUserbaseConfig<Env> = {},
|
||||||
args: Env = process.env as Env,
|
args: Env = process.env as Env,
|
||||||
) {
|
) {
|
||||||
const root = path.relative(
|
const root = path.relative(
|
||||||
process.cwd(),
|
process.cwd(),
|
||||||
path.resolve(distPath ?? relativeDistPath ?? "./node_modules/bknd/dist", "static"),
|
path.resolve(distPath ?? relativeDistPath ?? "./node_modules/userbase/dist", "static"),
|
||||||
);
|
);
|
||||||
if (relativeDistPath) {
|
if (relativeDistPath) {
|
||||||
$console.warn("relativeDistPath is deprecated, please use distPath instead");
|
$console.warn("relativeDistPath is deprecated, please use distPath instead");
|
||||||
@@ -38,7 +38,7 @@ export async function createApp<Env = NodeEnv>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function createHandler<Env = NodeEnv>(
|
export function createHandler<Env = NodeEnv>(
|
||||||
config: NodeBkndConfig<Env> = {},
|
config: NodeUserbaseConfig<Env> = {},
|
||||||
args: Env = process.env as Env,
|
args: Env = process.env as Env,
|
||||||
) {
|
) {
|
||||||
let app: App | undefined;
|
let app: App | undefined;
|
||||||
@@ -51,7 +51,7 @@ export function createHandler<Env = NodeEnv>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function serve<Env = NodeEnv>(
|
export function serve<Env = NodeEnv>(
|
||||||
{ port = $config.server.default_port, hostname, listener, ...config }: NodeBkndConfig<Env> = {},
|
{ port = $config.server.default_port, hostname, listener, ...config }: NodeUserbaseConfig<Env> = {},
|
||||||
args: Env = process.env as Env,
|
args: Env = process.env as Env,
|
||||||
) {
|
) {
|
||||||
honoServe(
|
honoServe(
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { readFile, readdir, stat, unlink, writeFile } from "node:fs/promises";
|
import { readFile, readdir, stat, unlink, writeFile } from "node:fs/promises";
|
||||||
import type { FileBody, FileListObject, FileMeta, FileUploadPayload } from "bknd";
|
import type { FileBody, FileListObject, FileMeta, FileUploadPayload } from "userbase";
|
||||||
import { StorageAdapter, guessMimeType } from "bknd";
|
import { StorageAdapter, guessMimeType } from "userbase";
|
||||||
import { parse, s, isFile } from "bknd/utils";
|
import { parse, s, isFile } from "userbase/utils";
|
||||||
|
|
||||||
export const localAdapterConfig = s.object(
|
export const localAdapterConfig = s.object(
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { registries } from "bknd";
|
import { registries } from "userbase";
|
||||||
import { type LocalAdapterConfig, StorageLocalAdapter } from "./StorageLocalAdapter";
|
import { type LocalAdapterConfig, StorageLocalAdapter } from "./StorageLocalAdapter";
|
||||||
|
|
||||||
export * from "./StorageLocalAdapter";
|
export * from "./StorageLocalAdapter";
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
import { createRuntimeApp, type RuntimeBkndConfig } from "bknd/adapter";
|
import { createRuntimeApp, type RuntimeUserbaseConfig } from "userbase/adapter";
|
||||||
|
|
||||||
export type NuxtEnv = NodeJS.ProcessEnv;
|
export type NuxtEnv = NodeJS.ProcessEnv;
|
||||||
export type NuxtBkndConfig<Env = NuxtEnv> = RuntimeBkndConfig<Env>;
|
export type NuxtUserbaseConfig<Env = NuxtEnv> = RuntimeUserbaseConfig<Env>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get bknd app instance
|
* Get userbase app instance
|
||||||
* @param config - bknd configuration
|
* @param config - userbase configuration
|
||||||
* @param args - environment variables
|
* @param args - environment variables
|
||||||
*/
|
*/
|
||||||
export async function getApp<Env>(
|
export async function getApp<Env>(
|
||||||
config: NuxtBkndConfig<Env> = {} as NuxtBkndConfig<Env>,
|
config: NuxtUserbaseConfig<Env> = {} as NuxtUserbaseConfig<Env>,
|
||||||
args: Env,
|
args: Env,
|
||||||
) {
|
) {
|
||||||
return await createRuntimeApp(config, args);
|
return await createRuntimeApp(config, args);
|
||||||
@@ -17,13 +17,10 @@ export async function getApp<Env>(
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Create middleware handler for Nuxt
|
* Create middleware handler for Nuxt
|
||||||
* @param config - bknd configuration
|
* @param config - userbase configuration
|
||||||
* @param args - environment variables
|
* @param args - environment variables
|
||||||
*/
|
*/
|
||||||
export function serve<Env>(
|
export function serve<Env>(config: NuxtUserbaseConfig<Env> = {} as NuxtUserbaseConfig<Env>, args: Env) {
|
||||||
config: NuxtBkndConfig<Env> = {} as NuxtBkndConfig<Env>,
|
|
||||||
args: Env,
|
|
||||||
) {
|
|
||||||
return async (request: Request) => {
|
return async (request: Request) => {
|
||||||
return (await getApp(config, args)).fetch(request);
|
return (await getApp(config, args)).fetch(request);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,20 +1,20 @@
|
|||||||
import { type FrameworkBkndConfig, createFrameworkApp } from "bknd/adapter";
|
import { type FrameworkUserbaseConfig, createFrameworkApp } from "userbase/adapter";
|
||||||
|
|
||||||
type ReactRouterEnv = NodeJS.ProcessEnv;
|
type ReactRouterEnv = NodeJS.ProcessEnv;
|
||||||
type ReactRouterFunctionArgs = {
|
type ReactRouterFunctionArgs = {
|
||||||
request: Request;
|
request: Request;
|
||||||
};
|
};
|
||||||
export type ReactRouterBkndConfig<Env = ReactRouterEnv> = FrameworkBkndConfig<Env>;
|
export type ReactRouterUserbaseConfig<Env = ReactRouterEnv> = FrameworkUserbaseConfig<Env>;
|
||||||
|
|
||||||
export async function getApp<Env = ReactRouterEnv>(
|
export async function getApp<Env = ReactRouterEnv>(
|
||||||
config: ReactRouterBkndConfig<Env>,
|
config: ReactRouterUserbaseConfig<Env>,
|
||||||
args: Env = process.env as Env,
|
args: Env = process.env as Env,
|
||||||
) {
|
) {
|
||||||
return await createFrameworkApp(config, args);
|
return await createFrameworkApp(config, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function serve<Env = ReactRouterEnv>(
|
export function serve<Env = ReactRouterEnv>(
|
||||||
config: ReactRouterBkndConfig<Env> = {},
|
config: ReactRouterUserbaseConfig<Env> = {},
|
||||||
args: Env = process.env as Env,
|
args: Env = process.env as Env,
|
||||||
) {
|
) {
|
||||||
return async (fnArgs: ReactRouterFunctionArgs) => {
|
return async (fnArgs: ReactRouterFunctionArgs) => {
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
export * from "./solid-start.adapter";
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
import { afterAll, beforeAll, describe } from "bun:test";
|
||||||
|
import * as solidStart from "./solid-start.adapter";
|
||||||
|
import { disableConsoleLog, enableConsoleLog } from "core/utils";
|
||||||
|
import { adapterTestSuite } from "adapter/adapter-test-suite";
|
||||||
|
import { bunTestRunner } from "adapter/bun/test";
|
||||||
|
import type { SolidStartUserbaseConfig } from "./solid-start.adapter";
|
||||||
|
|
||||||
|
beforeAll(disableConsoleLog);
|
||||||
|
afterAll(enableConsoleLog);
|
||||||
|
|
||||||
|
describe("solid-start adapter", () => {
|
||||||
|
adapterTestSuite<SolidStartUserbaseConfig>(bunTestRunner, {
|
||||||
|
makeApp: solidStart.getApp,
|
||||||
|
makeHandler: solidStart.serve,
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
import { createRuntimeApp, type RuntimeUserbaseConfig } from "userbase/adapter";
|
||||||
|
|
||||||
|
export type SolidStartEnv = NodeJS.ProcessEnv;
|
||||||
|
export type SolidStartUserbaseConfig<Env = SolidStartEnv> = RuntimeUserbaseConfig<Env>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get userbase app instance
|
||||||
|
* @param config - userbase configuration
|
||||||
|
* @param args - environment variables
|
||||||
|
*/
|
||||||
|
export async function getApp<Env = SolidStartEnv>(
|
||||||
|
config: SolidStartUserbaseConfig<Env>,
|
||||||
|
args: Env = process.env as Env,
|
||||||
|
) {
|
||||||
|
return await createRuntimeApp(config, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create middleware handler for Solid Start
|
||||||
|
* @param config - userbase configuration
|
||||||
|
* @param args - environment variables
|
||||||
|
*/
|
||||||
|
export function serve<Env = SolidStartEnv>(
|
||||||
|
config: SolidStartUserbaseConfig<Env> = {},
|
||||||
|
args: Env = process.env as Env,
|
||||||
|
) {
|
||||||
|
return async (req: Request) => {
|
||||||
|
const app = await getApp(config, args);
|
||||||
|
return app.fetch(req);
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { Connection } from "bknd";
|
import type { Connection } from "userbase";
|
||||||
import { bunSqlite } from "../bun/connection/BunSqliteConnection";
|
import { bunSqlite } from "../bun/connection/BunSqliteConnection";
|
||||||
|
|
||||||
export function sqlite(config?: { url: string }): Connection {
|
export function sqlite(config?: { url: string }): Connection {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { type Connection, libsql } from "bknd";
|
import { type Connection, libsql } from "userbase";
|
||||||
|
|
||||||
export function sqlite(config: { url: string }): Connection {
|
export function sqlite(config: { url: string }): Connection {
|
||||||
return libsql(config);
|
return libsql(config);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { Connection } from "bknd";
|
import type { Connection } from "userbase";
|
||||||
import { nodeSqlite } from "../node/connection/NodeSqliteConnection";
|
import { nodeSqlite } from "../node/connection/NodeSqliteConnection";
|
||||||
|
|
||||||
export function sqlite(config?: { url: string }): Connection {
|
export function sqlite(config?: { url: string }): Connection {
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
import { createRuntimeApp, type RuntimeBkndConfig } from "bknd/adapter";
|
import { createRuntimeApp, type RuntimeUserbaseConfig } from "userbase/adapter";
|
||||||
|
|
||||||
type TSvelteKit = {
|
type TSvelteKit = {
|
||||||
request: Request;
|
request: Request;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type SvelteKitBkndConfig<Env> = Pick<RuntimeBkndConfig<Env>, "adminOptions">;
|
export type SvelteKitUserbaseConfig<Env> = Pick<RuntimeUserbaseConfig<Env>, "adminOptions">;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get bknd app instance
|
* Get userbase app instance
|
||||||
* @param config - bknd configuration
|
* @param config - userbase configuration
|
||||||
* @param args - environment variables (use $env/dynamic/private for universal runtime support)
|
* @param args - environment variables (use $env/dynamic/private for universal runtime support)
|
||||||
*/
|
*/
|
||||||
export async function getApp<Env>(
|
export async function getApp<Env>(
|
||||||
config: SvelteKitBkndConfig<Env> = {} as SvelteKitBkndConfig<Env>,
|
config: SvelteKitUserbaseConfig<Env> = {} as SvelteKitUserbaseConfig<Env>,
|
||||||
args: Env,
|
args: Env,
|
||||||
) {
|
) {
|
||||||
return await createRuntimeApp(config, args);
|
return await createRuntimeApp(config, args);
|
||||||
@@ -20,11 +20,11 @@ export async function getApp<Env>(
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Create request handler for hooks.server.ts
|
* Create request handler for hooks.server.ts
|
||||||
* @param config - bknd configuration
|
* @param config - userbase configuration
|
||||||
* @param args - environment variables (use $env/dynamic/private for universal runtime support)
|
* @param args - environment variables (use $env/dynamic/private for universal runtime support)
|
||||||
*/
|
*/
|
||||||
export function serve<Env>(
|
export function serve<Env>(
|
||||||
config: SvelteKitBkndConfig<Env> = {} as SvelteKitBkndConfig<Env>,
|
config: SvelteKitUserbaseConfig<Env> = {} as SvelteKitUserbaseConfig<Env>,
|
||||||
args: Env,
|
args: Env,
|
||||||
) {
|
) {
|
||||||
return async (fnArgs: TSvelteKit) => {
|
return async (fnArgs: TSvelteKit) => {
|
||||||
|
|||||||
@@ -1,33 +1,32 @@
|
|||||||
import { createFrameworkApp, type FrameworkBkndConfig } from "bknd/adapter";
|
import { createFrameworkApp, type FrameworkUserbaseConfig } from "userbase/adapter";
|
||||||
|
|
||||||
export type TanstackStartEnv = NodeJS.ProcessEnv;
|
export type TanstackStartEnv = NodeJS.ProcessEnv;
|
||||||
|
|
||||||
export type TanstackStartConfig<Env = TanstackStartEnv> =
|
export type TanstackStartConfig<Env = TanstackStartEnv> = FrameworkUserbaseConfig<Env>;
|
||||||
FrameworkBkndConfig<Env>;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get bknd app instance
|
* Get userbase app instance
|
||||||
* @param config - bknd configuration
|
* @param config - userbase configuration
|
||||||
* @param args - environment variables
|
* @param args - environment variables
|
||||||
*/
|
*/
|
||||||
export async function getApp<Env = TanstackStartEnv>(
|
export async function getApp<Env = TanstackStartEnv>(
|
||||||
config: TanstackStartConfig<Env> = {},
|
config: TanstackStartConfig<Env> = {},
|
||||||
args: Env = process.env as Env,
|
args: Env = process.env as Env,
|
||||||
) {
|
) {
|
||||||
return await createFrameworkApp(config, args);
|
return await createFrameworkApp(config, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create request handler for src/routes/api.$.ts
|
* Create request handler for src/routes/api.$.ts
|
||||||
* @param config - bknd configuration
|
* @param config - userbase configuration
|
||||||
* @param args - environment variables
|
* @param args - environment variables
|
||||||
*/
|
*/
|
||||||
export function serve<Env = TanstackStartEnv>(
|
export function serve<Env = TanstackStartEnv>(
|
||||||
config: TanstackStartConfig<Env> = {},
|
config: TanstackStartConfig<Env> = {},
|
||||||
args: Env = process.env as Env,
|
args: Env = process.env as Env,
|
||||||
) {
|
) {
|
||||||
return async (request: Request) => {
|
return async (request: Request) => {
|
||||||
const app = await getApp(config, args);
|
const app = await getApp(config, args);
|
||||||
return app.fetch(request);
|
return app.fetch(request);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
import { serveStatic } from "@hono/node-server/serve-static";
|
import { serveStatic } from "@hono/node-server/serve-static";
|
||||||
import { type DevServerOptions, default as honoViteDevServer } from "@hono/vite-dev-server";
|
import { type DevServerOptions, default as honoViteDevServer } from "@hono/vite-dev-server";
|
||||||
import type { App } from "bknd";
|
import type { App } from "userbase";
|
||||||
import { type RuntimeBkndConfig, createRuntimeApp } from "bknd/adapter";
|
import { type RuntimeUserbaseConfig, createRuntimeApp } from "userbase/adapter";
|
||||||
import { registerLocalMediaAdapter } from "bknd/adapter/node";
|
import { registerLocalMediaAdapter } from "userbase/adapter/node";
|
||||||
import { devServerConfig } from "./dev-server-config";
|
import { devServerConfig } from "./dev-server-config";
|
||||||
import type { MiddlewareHandler } from "hono";
|
import type { MiddlewareHandler } from "hono";
|
||||||
|
|
||||||
export type ViteEnv = NodeJS.ProcessEnv;
|
export type ViteEnv = NodeJS.ProcessEnv;
|
||||||
export type ViteBkndConfig<Env = ViteEnv> = RuntimeBkndConfig<Env> & {
|
export type ViteUserbaseConfig<Env = ViteEnv> = RuntimeUserbaseConfig<Env> & {
|
||||||
serveStatic?: false | MiddlewareHandler;
|
serveStatic?: false | MiddlewareHandler;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function addViteScript(html: string, addBkndContext: boolean = true) {
|
export function addViteScript(html: string, addUserbaseContext: boolean = true) {
|
||||||
return html.replace(
|
return html.replace(
|
||||||
"</head>",
|
"</head>",
|
||||||
`<script type="module">
|
`<script type="module">
|
||||||
@@ -22,13 +22,13 @@ window.$RefreshSig$ = () => (type) => type
|
|||||||
window.__vite_plugin_react_preamble_installed__ = true
|
window.__vite_plugin_react_preamble_installed__ = true
|
||||||
</script>
|
</script>
|
||||||
<script type="module" src="/@vite/client"></script>
|
<script type="module" src="/@vite/client"></script>
|
||||||
${addBkndContext ? "<!-- BKND_CONTEXT -->" : ""}
|
${addUserbaseContext ? "<!-- BKND_CONTEXT -->" : ""}
|
||||||
</head>`,
|
</head>`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function createApp<ViteEnv>(
|
async function createApp<ViteEnv>(
|
||||||
config: ViteBkndConfig<ViteEnv> = {},
|
config: ViteUserbaseConfig<ViteEnv> = {},
|
||||||
env: ViteEnv = {} as ViteEnv,
|
env: ViteEnv = {} as ViteEnv,
|
||||||
): Promise<App> {
|
): Promise<App> {
|
||||||
registerLocalMediaAdapter();
|
registerLocalMediaAdapter();
|
||||||
@@ -49,7 +49,7 @@ async function createApp<ViteEnv>(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function serve<ViteEnv>(config: ViteBkndConfig<ViteEnv> = {}, args?: ViteEnv) {
|
export function serve<ViteEnv>(config: ViteUserbaseConfig<ViteEnv> = {}, args?: ViteEnv) {
|
||||||
return {
|
return {
|
||||||
async fetch(request: Request, env: any, ctx: ExecutionContext) {
|
async fetch(request: Request, env: any, ctx: ExecutionContext) {
|
||||||
const app = await createApp(config, env);
|
const app = await createApp(config, env);
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import type { DB, PrimaryFieldType } from "bknd";
|
import type { DB, PrimaryFieldType } from "userbase";
|
||||||
import * as AuthPermissions from "auth/auth-permissions";
|
import * as AuthPermissions from "auth/auth-permissions";
|
||||||
import type { AuthStrategy } from "auth/authenticate/strategies/Strategy";
|
import type { AuthStrategy } from "auth/authenticate/strategies/Strategy";
|
||||||
import type { PasswordStrategy } from "auth/authenticate/strategies/PasswordStrategy";
|
import type { PasswordStrategy } from "auth/authenticate/strategies/PasswordStrategy";
|
||||||
import { $console, secureRandomString, transformObject, pickKeys } from "bknd/utils";
|
import { $console, secureRandomString, transformObject, pickKeys } from "userbase/utils";
|
||||||
import type { Entity, EntityManager } from "data/entities";
|
import type { Entity, EntityManager } from "data/entities";
|
||||||
import { em, entity, enumm, type FieldSchema } from "data/prototype";
|
import { em, entity, enumm, type FieldSchema } from "data/prototype";
|
||||||
import { Module } from "modules/Module";
|
import { Module } from "modules/Module";
|
||||||
@@ -16,7 +16,7 @@ import { Role } from "./authorize/Role";
|
|||||||
|
|
||||||
export type UsersFields = typeof AppAuth.usersFields;
|
export type UsersFields = typeof AppAuth.usersFields;
|
||||||
export type UserFieldSchema = FieldSchema<typeof AppAuth.usersFields>;
|
export type UserFieldSchema = FieldSchema<typeof AppAuth.usersFields>;
|
||||||
declare module "bknd" {
|
declare module "userbase" {
|
||||||
interface Users extends AppEntity, UserFieldSchema {}
|
interface Users extends AppEntity, UserFieldSchema {}
|
||||||
interface DB {
|
interface DB {
|
||||||
users: Users;
|
users: Users;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { AppAuth } from "auth/AppAuth";
|
import { AppAuth } from "auth/AppAuth";
|
||||||
import type { CreateUser, SafeUser, User, UserPool } from "auth/authenticate/Authenticator";
|
import type { CreateUser, SafeUser, User, UserPool } from "auth/authenticate/Authenticator";
|
||||||
import { $console } from "bknd/utils";
|
import { $console } from "userbase/utils";
|
||||||
import { pick } from "lodash-es";
|
import { pick } from "lodash-es";
|
||||||
import {
|
import {
|
||||||
InvalidConditionsException,
|
InvalidConditionsException,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import type { AuthActionResponse } from "auth/api/AuthController";
|
import type { AuthActionResponse } from "auth/api/AuthController";
|
||||||
import type { AppAuthSchema } from "auth/auth-schema";
|
import type { AppAuthSchema } from "auth/auth-schema";
|
||||||
import type { AuthResponse, SafeUser, AuthStrategy } from "bknd";
|
import type { AuthResponse, SafeUser, AuthStrategy } from "userbase";
|
||||||
import { type BaseModuleApiOptions, ModuleApi } from "modules/ModuleApi";
|
import { type BaseModuleApiOptions, ModuleApi } from "modules/ModuleApi";
|
||||||
|
|
||||||
export type AuthApiOptions = BaseModuleApiOptions & {
|
export type AuthApiOptions = BaseModuleApiOptions & {
|
||||||
@@ -69,7 +69,7 @@ export class AuthApi extends ModuleApi<AuthApiOptions> {
|
|||||||
async logout() {
|
async logout() {
|
||||||
return this.get(["logout"], undefined, {
|
return this.get(["logout"], undefined, {
|
||||||
headers: {
|
headers: {
|
||||||
// this way bknd detects a json request and doesn't redirect back
|
// this way userbase detects a json request and doesn't redirect back
|
||||||
Accept: "application/json",
|
Accept: "application/json",
|
||||||
},
|
},
|
||||||
}).then(() => this.options.onTokenUpdate?.(undefined, true));
|
}).then(() => this.options.onTokenUpdate?.(undefined, true));
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { DB, SafeUser } from "bknd";
|
import type { DB, SafeUser } from "userbase";
|
||||||
import type { AuthStrategy } from "auth/authenticate/strategies/Strategy";
|
import type { AuthStrategy } from "auth/authenticate/strategies/Strategy";
|
||||||
import type { AppAuth } from "auth/AppAuth";
|
import type { AppAuth } from "auth/AppAuth";
|
||||||
import * as AuthPermissions from "auth/auth-permissions";
|
import * as AuthPermissions from "auth/auth-permissions";
|
||||||
@@ -14,7 +14,7 @@ import {
|
|||||||
transformObject,
|
transformObject,
|
||||||
mcpTool,
|
mcpTool,
|
||||||
$console,
|
$console,
|
||||||
} from "bknd/utils";
|
} from "userbase/utils";
|
||||||
import type { PasswordStrategy } from "auth/authenticate/strategies";
|
import type { PasswordStrategy } from "auth/authenticate/strategies";
|
||||||
|
|
||||||
export type AuthActionResponse = {
|
export type AuthActionResponse = {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { cookieConfig, jwtConfig } from "auth/authenticate/Authenticator";
|
import { cookieConfig, jwtConfig } from "auth/authenticate/Authenticator";
|
||||||
import { CustomOAuthStrategy, OAuthStrategy, PasswordStrategy } from "auth/authenticate/strategies";
|
import { CustomOAuthStrategy, OAuthStrategy, PasswordStrategy } from "auth/authenticate/strategies";
|
||||||
import { roleSchema } from "auth/authorize/Role";
|
import { roleSchema } from "auth/authorize/Role";
|
||||||
import { objectTransform, omitKeys, pick, s } from "bknd/utils";
|
import { objectTransform, omitKeys, pick, s } from "userbase/utils";
|
||||||
import { $object, $record } from "modules/mcp";
|
import { $object, $record } from "modules/mcp";
|
||||||
|
|
||||||
export const Strategies = {
|
export const Strategies = {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { DB } from "bknd";
|
import type { DB } from "userbase";
|
||||||
import { Exception } from "core/errors";
|
import { Exception } from "core/errors";
|
||||||
import { addFlashMessage } from "core/server/flash";
|
import { addFlashMessage } from "core/server/flash";
|
||||||
import type { Context } from "hono";
|
import type { Context } from "hono";
|
||||||
@@ -7,7 +7,7 @@ import { sign, verify } from "hono/jwt";
|
|||||||
import { type CookieOptions, serializeSigned } from "hono/utils/cookie";
|
import { type CookieOptions, serializeSigned } from "hono/utils/cookie";
|
||||||
import type { ServerEnv } from "modules/Controller";
|
import type { ServerEnv } from "modules/Controller";
|
||||||
import { InvalidConditionsException } from "auth/errors";
|
import { InvalidConditionsException } from "auth/errors";
|
||||||
import { s, parse, secret, runtimeSupports, truncate, $console, pickKeys } from "bknd/utils";
|
import { s, parse, secret, runtimeSupports, truncate, $console, pickKeys } from "userbase/utils";
|
||||||
import type { AuthStrategy } from "./strategies/Strategy";
|
import type { AuthStrategy } from "./strategies/Strategy";
|
||||||
|
|
||||||
type Input = any; // workaround
|
type Input = any; // workaround
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import type { User } from "bknd";
|
import type { User } from "userbase";
|
||||||
import type { Authenticator } from "auth/authenticate/Authenticator";
|
import type { Authenticator } from "auth/authenticate/Authenticator";
|
||||||
import { InvalidCredentialsException } from "auth/errors";
|
import { InvalidCredentialsException } from "auth/errors";
|
||||||
import { hash, $console, s, parse, jsc, describeRoute } from "bknd/utils";
|
import { hash, $console, s, parse, jsc, describeRoute } from "userbase/utils";
|
||||||
import { Hono } from "hono";
|
import { Hono } from "hono";
|
||||||
import { compare as bcryptCompare, genSalt as bcryptGenSalt, hash as bcryptHash } from "bcryptjs";
|
import { compare as bcryptCompare, genSalt as bcryptGenSalt, hash as bcryptHash } from "bcryptjs";
|
||||||
import { AuthStrategy } from "./Strategy";
|
import { AuthStrategy } from "./Strategy";
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import type {
|
|||||||
StrategyActions,
|
StrategyActions,
|
||||||
} from "../Authenticator";
|
} from "../Authenticator";
|
||||||
import type { Hono } from "hono";
|
import type { Hono } from "hono";
|
||||||
import { type s, parse } from "bknd/utils";
|
import { type s, parse } from "userbase/utils";
|
||||||
|
|
||||||
export type StrategyMode = "form" | "external";
|
export type StrategyMode = "form" | "external";
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import type * as oauth from "oauth4webapi";
|
import type * as oauth from "oauth4webapi";
|
||||||
import { OAuthStrategy } from "./OAuthStrategy";
|
import { OAuthStrategy } from "./OAuthStrategy";
|
||||||
import { s } from "bknd/utils";
|
import { s } from "userbase/utils";
|
||||||
|
|
||||||
type SupportedTypes = "oauth2" | "oidc";
|
type SupportedTypes = "oauth2" | "oidc";
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { type Context, Hono } from "hono";
|
|||||||
import { getSignedCookie, setSignedCookie } from "hono/cookie";
|
import { getSignedCookie, setSignedCookie } from "hono/cookie";
|
||||||
import * as oauth from "oauth4webapi";
|
import * as oauth from "oauth4webapi";
|
||||||
import * as issuers from "./issuers";
|
import * as issuers from "./issuers";
|
||||||
import { s, filterKeys } from "bknd/utils";
|
import { s, filterKeys } from "userbase/utils";
|
||||||
import { Exception } from "core/errors";
|
import { Exception } from "core/errors";
|
||||||
import { isDebug } from "core/env";
|
import { isDebug } from "core/env";
|
||||||
import { AuthStrategy } from "../Strategy";
|
import { AuthStrategy } from "../Strategy";
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ export const github: IssuerConfig<GithubUserInfo> = {
|
|||||||
try {
|
try {
|
||||||
const res = await fetch("https://api.github.com/user/emails", {
|
const res = await fetch("https://api.github.com/user/emails", {
|
||||||
headers: {
|
headers: {
|
||||||
"User-Agent": "bknd", // this is mandatory... *smh*
|
"User-Agent": "userbase", // this is mandatory... *smh*
|
||||||
Accept: "application/json",
|
Accept: "application/json",
|
||||||
Authorization: `Bearer ${tokenResponse.access_token}`,
|
Authorization: `Bearer ${tokenResponse.access_token}`,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import { Exception } from "core/errors";
|
import { Exception } from "core/errors";
|
||||||
import { $console, mergeObject, type s } from "bknd/utils";
|
import { $console, mergeObject, type s } from "userbase/utils";
|
||||||
import type { Permission, PermissionContext } from "auth/authorize/Permission";
|
import type { Permission, PermissionContext } from "auth/authorize/Permission";
|
||||||
import type { Context } from "hono";
|
import type { Context } from "hono";
|
||||||
import type { ServerEnv } from "modules/Controller";
|
import type { ServerEnv } from "modules/Controller";
|
||||||
import type { Role } from "./Role";
|
import type { Role } from "./Role";
|
||||||
import { HttpStatus } from "bknd/utils";
|
import { HttpStatus } from "userbase/utils";
|
||||||
import type { Policy, PolicySchema } from "./Policy";
|
import type { Policy, PolicySchema } from "./Policy";
|
||||||
import { convert, type ObjectQuery } from "core/object/query/object-query";
|
import { convert, type ObjectQuery } from "core/object/query/object-query";
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { s, type ParseOptions, parse, InvalidSchemaError, HttpStatus } from "bknd/utils";
|
import { s, type ParseOptions, parse, InvalidSchemaError, HttpStatus } from "userbase/utils";
|
||||||
|
|
||||||
export const permissionOptionsSchema = s
|
export const permissionOptionsSchema = s
|
||||||
.strictObject({
|
.strictObject({
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { s, parse, recursivelyReplacePlaceholders } from "bknd/utils";
|
import { s, parse, recursivelyReplacePlaceholders } from "userbase/utils";
|
||||||
import * as query from "core/object/query/object-query";
|
import * as query from "core/object/query/object-query";
|
||||||
|
|
||||||
export const policySchema = s
|
export const policySchema = s
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { s } from "bknd/utils";
|
import { s } from "userbase/utils";
|
||||||
import { Permission } from "./Permission";
|
import { Permission } from "./Permission";
|
||||||
import { Policy, policySchema } from "./Policy";
|
import { Policy, policySchema } from "./Policy";
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Exception } from "core/errors";
|
import { Exception } from "core/errors";
|
||||||
import { isDebug } from "core/env";
|
import { isDebug } from "core/env";
|
||||||
import { HttpStatus } from "bknd/utils";
|
import { HttpStatus } from "userbase/utils";
|
||||||
|
|
||||||
export class AuthException extends Exception {
|
export class AuthException extends Exception {
|
||||||
getSafeErrorAndCode() {
|
getSafeErrorAndCode() {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { $console, patternMatch } from "bknd/utils";
|
import { $console, patternMatch } from "userbase/utils";
|
||||||
import type { Context } from "hono";
|
import type { Context } from "hono";
|
||||||
import { createMiddleware } from "hono/factory";
|
import { createMiddleware } from "hono/factory";
|
||||||
import type { ServerEnv } from "modules/Controller";
|
import type { ServerEnv } from "modules/Controller";
|
||||||
@@ -26,9 +26,7 @@ export function shouldSkip(c: Context<ServerEnv>, skip?: (string | RegExp)[]) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const auth = (options?: {
|
export const auth = (options?: { skip?: (string | RegExp)[] }) =>
|
||||||
skip?: (string | RegExp)[];
|
|
||||||
}) =>
|
|
||||||
createMiddleware<ServerEnv>(async (c, next) => {
|
createMiddleware<ServerEnv>(async (c, next) => {
|
||||||
if (!c.get("auth")) {
|
if (!c.get("auth")) {
|
||||||
c.set("auth", {
|
c.set("auth", {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import type { Permission, PermissionContext } from "auth/authorize/Permission";
|
import type { Permission, PermissionContext } from "auth/authorize/Permission";
|
||||||
import { $console, threw } from "bknd/utils";
|
import { $console, threw } from "userbase/utils";
|
||||||
import type { Context, Hono } from "hono";
|
import type { Context, Hono } from "hono";
|
||||||
import type { RouterRoute } from "hono/types";
|
import type { RouterRoute } from "hono/types";
|
||||||
import { createMiddleware } from "hono/factory";
|
import { createMiddleware } from "hono/factory";
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { makeAppFromEnv } from "cli/commands/run";
|
|||||||
import { writeFile } from "node:fs/promises";
|
import { writeFile } from "node:fs/promises";
|
||||||
import c from "picocolors";
|
import c from "picocolors";
|
||||||
import { withConfigOptions } from "cli/utils/options";
|
import { withConfigOptions } from "cli/utils/options";
|
||||||
import { $console } from "bknd/utils";
|
import { $console } from "userbase/utils";
|
||||||
|
|
||||||
export const config: CliCommand = (program) => {
|
export const config: CliCommand = (program) => {
|
||||||
withConfigOptions(program.command("config"))
|
withConfigOptions(program.command("config"))
|
||||||
|
|||||||
@@ -5,9 +5,9 @@ import type { CliCommand } from "cli/types";
|
|||||||
import { typewriter, wait } from "cli/utils/cli";
|
import { typewriter, wait } from "cli/utils/cli";
|
||||||
import { execAsync, getVersion } from "cli/utils/sys";
|
import { execAsync, getVersion } from "cli/utils/sys";
|
||||||
import { Option } from "commander";
|
import { Option } from "commander";
|
||||||
import { env } from "bknd";
|
import { env } from "userbase";
|
||||||
import color from "picocolors";
|
import color from "picocolors";
|
||||||
import { overridePackageJson, updateBkndPackages } from "./npm";
|
import { overridePackageJson, updateUserbasePackages } from "./npm";
|
||||||
import { type Template, templates, type TemplateSetupCtx } from "./templates";
|
import { type Template, templates, type TemplateSetupCtx } from "./templates";
|
||||||
import { createScoped, flush } from "cli/utils/telemetry";
|
import { createScoped, flush } from "cli/utils/telemetry";
|
||||||
import path from "node:path";
|
import path from "node:path";
|
||||||
@@ -45,12 +45,12 @@ export const create: CliCommand = (program) => {
|
|||||||
|
|
||||||
function errorOutro() {
|
function errorOutro() {
|
||||||
$p.outro(color.red("Failed to create project."));
|
$p.outro(color.red("Failed to create project."));
|
||||||
// biome-ignore lint/suspicious/noConsoleLog:
|
// biome-ignore lint/suspicious/noConsole: empty log for newline
|
||||||
console.log(
|
console.log(
|
||||||
color.yellow("Sorry that this happened. If you think this is a bug, please report it at: ") +
|
color.yellow("Sorry that this happened. If you think this is a bug, please report it at: ") +
|
||||||
color.cyan("https://github.com/bknd-io/bknd/issues"),
|
color.cyan("https://github.com/userbase-io/userbase/issues"),
|
||||||
);
|
);
|
||||||
// biome-ignore lint/suspicious/noConsoleLog:
|
// biome-ignore lint/suspicious/noConsole: empty log for newline
|
||||||
console.log("");
|
console.log("");
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
@@ -66,7 +66,7 @@ async function action(options: {
|
|||||||
yes?: boolean;
|
yes?: boolean;
|
||||||
clean?: boolean;
|
clean?: boolean;
|
||||||
}) {
|
}) {
|
||||||
// biome-ignore lint/suspicious/noConsoleLog:
|
// biome-ignore lint/suspicious/noConsole: empty log for newline
|
||||||
console.log("");
|
console.log("");
|
||||||
const $t = createScoped("create");
|
const $t = createScoped("create");
|
||||||
$t.capture("start", {
|
$t.capture("start", {
|
||||||
@@ -80,12 +80,12 @@ async function action(options: {
|
|||||||
|
|
||||||
const version = await getVersion();
|
const version = await getVersion();
|
||||||
$p.intro(
|
$p.intro(
|
||||||
`👋 Welcome to the ${color.bold(color.cyan("bknd"))} create cli ${color.bold(`v${version}`)}`,
|
`👋 Welcome to the ${color.bold(color.cyan("userbase"))} create cli ${color.bold(`v${version}`)}`,
|
||||||
);
|
);
|
||||||
|
|
||||||
await $p.stream.message(
|
await $p.stream.message(
|
||||||
(async function* () {
|
(async function* () {
|
||||||
yield* typewriter("Thanks for choosing to create a new project with bknd!", color.dim);
|
yield* typewriter("Thanks for choosing to create a new project with userbase!", color.dim);
|
||||||
await wait();
|
await wait();
|
||||||
})(),
|
})(),
|
||||||
);
|
);
|
||||||
@@ -127,7 +127,7 @@ async function action(options: {
|
|||||||
? downloadOpts.dir.split("/").pop()
|
? downloadOpts.dir.split("/").pop()
|
||||||
: downloadOpts.dir.replace(/[./]/g, "");
|
: downloadOpts.dir.replace(/[./]/g, "");
|
||||||
|
|
||||||
if (!name || name.length === 0) name = "bknd";
|
if (!name || name.length === 0) name = "userbase";
|
||||||
|
|
||||||
let template: Template | undefined;
|
let template: Template | undefined;
|
||||||
|
|
||||||
@@ -254,7 +254,7 @@ async function action(options: {
|
|||||||
}
|
}
|
||||||
|
|
||||||
s.stop("Template downloaded.");
|
s.stop("Template downloaded.");
|
||||||
await updateBkndPackages(ctx.dir);
|
await updateUserbasePackages(ctx.dir);
|
||||||
|
|
||||||
if (template.preinstall) {
|
if (template.preinstall) {
|
||||||
await template.preinstall(ctx);
|
await template.preinstall(ctx);
|
||||||
@@ -335,7 +335,7 @@ async function action(options: {
|
|||||||
yield "\n\n";
|
yield "\n\n";
|
||||||
yield* typewriter(
|
yield* typewriter(
|
||||||
`Enter your project's directory using ${color.cyan("cd " + ctx.dir)}
|
`Enter your project's directory using ${color.cyan("cd " + ctx.dir)}
|
||||||
If you need help, check ${color.cyan("https://docs.bknd.io")} or join our Discord!`,
|
If you need help, check ${color.cyan("https://docs.userbase.io")} or join our Discord!`,
|
||||||
);
|
);
|
||||||
await wait(2);
|
await wait(2);
|
||||||
})(),
|
})(),
|
||||||
|
|||||||
@@ -92,10 +92,10 @@ export async function replacePackageJsonVersions(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function updateBkndPackages(dir?: string, map?: Record<string, string>) {
|
export async function updateUserbasePackages(dir?: string, map?: Record<string, string>) {
|
||||||
try {
|
try {
|
||||||
const versions = {
|
const versions = {
|
||||||
bknd: await sysGetVersion(),
|
userbase: await sysGetVersion(),
|
||||||
...(map ?? {}),
|
...(map ?? {}),
|
||||||
};
|
};
|
||||||
await replacePackageJsonVersions(
|
await replacePackageJsonVersions(
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ export const aws = {
|
|||||||
key: "aws",
|
key: "aws",
|
||||||
title: "AWS Lambda Basic",
|
title: "AWS Lambda Basic",
|
||||||
integration: "aws",
|
integration: "aws",
|
||||||
description: "A basic bknd AWS Lambda starter",
|
description: "A basic userbase AWS Lambda starter",
|
||||||
path: "gh:bknd-io/bknd/examples/aws-lambda",
|
path: "gh:userbase-io/userbase/examples/aws-lambda",
|
||||||
ref: true,
|
ref: true,
|
||||||
setup: async (ctx) => {
|
setup: async (ctx) => {
|
||||||
await $p.stream.info(
|
await $p.stream.info(
|
||||||
|
|||||||
@@ -11,8 +11,8 @@ export const cloudflare = {
|
|||||||
key: "cloudflare",
|
key: "cloudflare",
|
||||||
title: "Cloudflare Basic",
|
title: "Cloudflare Basic",
|
||||||
integration: "cloudflare",
|
integration: "cloudflare",
|
||||||
description: "A basic bknd Cloudflare worker",
|
description: "A basic userbase Cloudflare worker",
|
||||||
path: "gh:bknd-io/bknd/examples/cloudflare-worker",
|
path: "gh:userbase-io/userbase/examples/cloudflare-worker",
|
||||||
ref: true,
|
ref: true,
|
||||||
setup: async (ctx) => {
|
setup: async (ctx) => {
|
||||||
// overwrite assets directory & name
|
// overwrite assets directory & name
|
||||||
@@ -22,7 +22,7 @@ export const cloudflare = {
|
|||||||
...json,
|
...json,
|
||||||
name: ctx.name,
|
name: ctx.name,
|
||||||
assets: {
|
assets: {
|
||||||
directory: "node_modules/bknd/dist/static",
|
directory: "node_modules/userbase/dist/static",
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
{ dir: ctx.dir },
|
{ dir: ctx.dir },
|
||||||
|
|||||||
@@ -6,15 +6,15 @@ export const deno = {
|
|||||||
key: "deno",
|
key: "deno",
|
||||||
title: "Deno Basic",
|
title: "Deno Basic",
|
||||||
integration: "deno",
|
integration: "deno",
|
||||||
description: "A basic bknd Deno server with static assets",
|
description: "A basic userbase Deno server with static assets",
|
||||||
path: "gh:bknd-io/bknd/examples/deno",
|
path: "gh:userbase-io/userbase/examples/deno",
|
||||||
installDeps: false,
|
installDeps: false,
|
||||||
ref: true,
|
ref: true,
|
||||||
setup: async (ctx) => {
|
setup: async (ctx) => {
|
||||||
const version = await getVersion();
|
const version = await getVersion();
|
||||||
await overrideJson(
|
await overrideJson(
|
||||||
"deno.json",
|
"deno.json",
|
||||||
(json) => ({ ...json, links: undefined, imports: { bknd: `npm:bknd@${version}` } }),
|
(json) => ({ ...json, links: undefined, imports: { userbase: `npm:userbase@${version}` } }),
|
||||||
{ dir: ctx.dir },
|
{ dir: ctx.dir },
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ export type Template = {
|
|||||||
description?: string;
|
description?: string;
|
||||||
path: string;
|
path: string;
|
||||||
/**
|
/**
|
||||||
* adds a ref "#{ref}" to the path. If "true", adds the current version of bknd
|
* adds a ref "#{ref}" to the path. If "true", adds the current version of userbase
|
||||||
*/
|
*/
|
||||||
ref?: true | string;
|
ref?: true | string;
|
||||||
/**
|
/**
|
||||||
@@ -53,48 +53,48 @@ export const templates: Template[] = [
|
|||||||
key: "node",
|
key: "node",
|
||||||
title: "Node.js Basic",
|
title: "Node.js Basic",
|
||||||
integration: "node",
|
integration: "node",
|
||||||
description: "A basic bknd Node.js server",
|
description: "A basic userbase Node.js server",
|
||||||
path: "gh:bknd-io/bknd/examples/node",
|
path: "gh:userbase-io/userbase/examples/node",
|
||||||
ref: true,
|
ref: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "bun",
|
key: "bun",
|
||||||
title: "Bun Basic",
|
title: "Bun Basic",
|
||||||
integration: "bun",
|
integration: "bun",
|
||||||
description: "A basic bknd Bun server",
|
description: "A basic userbase Bun server",
|
||||||
path: "gh:bknd-io/bknd/examples/bun",
|
path: "gh:userbase-io/userbase/examples/bun",
|
||||||
ref: true,
|
ref: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "nextjs",
|
key: "nextjs",
|
||||||
title: "Next.js Basic",
|
title: "Next.js Basic",
|
||||||
integration: "nextjs",
|
integration: "nextjs",
|
||||||
description: "A basic bknd Next.js starter",
|
description: "A basic userbase Next.js starter",
|
||||||
path: "gh:bknd-io/bknd/examples/nextjs",
|
path: "gh:userbase-io/userbase/examples/nextjs",
|
||||||
ref: true,
|
ref: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "astro",
|
key: "astro",
|
||||||
title: "Astro Basic",
|
title: "Astro Basic",
|
||||||
integration: "astro",
|
integration: "astro",
|
||||||
description: "A basic bknd Astro starter",
|
description: "A basic userbase Astro starter",
|
||||||
path: "gh:bknd-io/bknd/examples/astro",
|
path: "gh:userbase-io/userbase/examples/astro",
|
||||||
ref: true,
|
ref: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "react-router",
|
key: "react-router",
|
||||||
title: "React Router Basic",
|
title: "React Router Basic",
|
||||||
integration: "react-router",
|
integration: "react-router",
|
||||||
description: "A basic bknd React Router starter",
|
description: "A basic userbase React Router starter",
|
||||||
path: "gh:bknd-io/bknd/examples/react-router",
|
path: "gh:userbase-io/userbase/examples/react-router",
|
||||||
ref: true,
|
ref: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "aws",
|
key: "aws",
|
||||||
title: "AWS Lambda Basic",
|
title: "AWS Lambda Basic",
|
||||||
integration: "aws",
|
integration: "aws",
|
||||||
description: "A basic bknd AWS Lambda starter",
|
description: "A basic userbase AWS Lambda starter",
|
||||||
path: "gh:bknd-io/bknd/examples/aws-lambda",
|
path: "gh:userbase-io/userbase/examples/aws-lambda",
|
||||||
ref: true,
|
ref: true,
|
||||||
},
|
},
|
||||||
deno,
|
deno,
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import type { CliCommand } from "../types";
|
|||||||
export const debug: CliCommand = (program) => {
|
export const debug: CliCommand = (program) => {
|
||||||
program
|
program
|
||||||
.command("debug")
|
.command("debug")
|
||||||
.description("debug bknd")
|
.description("debug userbase")
|
||||||
.addArgument(new Argument("<subject>", "subject to debug").choices(Object.keys(subjects)))
|
.addArgument(new Argument("<subject>", "subject to debug").choices(Object.keys(subjects)))
|
||||||
.action(action);
|
.action(action);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import type { CliCommand } from "cli/types";
|
import type { CliCommand } from "cli/types";
|
||||||
import { makeAppFromEnv } from "../run";
|
import { makeAppFromEnv } from "../run";
|
||||||
import { getSystemMcp } from "modules/mcp/system-mcp";
|
import { getSystemMcp } from "modules/mcp/system-mcp";
|
||||||
import { $console, stdioTransport } from "bknd/utils";
|
import { $console, stdioTransport } from "userbase/utils";
|
||||||
import { withConfigOptions, type WithConfigOptions } from "cli/utils/options";
|
import { withConfigOptions, type WithConfigOptions } from "cli/utils/options";
|
||||||
|
|
||||||
export const mcp: CliCommand = (program) =>
|
export const mcp: CliCommand = (program) =>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import path from "node:path";
|
import path from "node:path";
|
||||||
import { $console } from "bknd/utils";
|
import { $console } from "userbase/utils";
|
||||||
import type { MiddlewareHandler } from "hono";
|
import type { MiddlewareHandler } from "hono";
|
||||||
import open from "open";
|
import open from "open";
|
||||||
import { fileExists, getRelativeDistPath } from "../../utils/sys";
|
import { fileExists, getRelativeDistPath } from "../../utils/sys";
|
||||||
@@ -86,7 +86,7 @@ export async function getConfigPath(filePath?: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const exts = ["", ".js", ".ts", ".mjs", ".cjs", ".json"];
|
const exts = ["", ".js", ".ts", ".mjs", ".cjs", ".json"];
|
||||||
const paths = exts.map((e) => `bknd.config${e}`);
|
const paths = exts.map((e) => `userbase.config${e}`);
|
||||||
for (const p of paths) {
|
for (const p of paths) {
|
||||||
const _p = path.resolve(process.cwd(), p);
|
const _p = path.resolve(process.cwd(), p);
|
||||||
if (await fileExists(_p)) {
|
if (await fileExists(_p)) {
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user