alepha 0.15.2 → 0.15.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +68 -80
- package/dist/api/audits/index.d.ts +332 -332
- package/dist/api/audits/index.d.ts.map +1 -1
- package/dist/api/files/index.d.ts +170 -170
- package/dist/api/files/index.d.ts.map +1 -1
- package/dist/api/jobs/index.d.ts +151 -151
- package/dist/api/keys/index.d.ts +195 -195
- package/dist/api/keys/index.d.ts.map +1 -1
- package/dist/api/parameters/index.d.ts +260 -260
- package/dist/api/users/index.d.ts +22 -11
- package/dist/api/users/index.d.ts.map +1 -1
- package/dist/api/users/index.js +7 -2
- package/dist/api/users/index.js.map +1 -1
- package/dist/api/verifications/index.d.ts +128 -128
- package/dist/api/verifications/index.d.ts.map +1 -1
- package/dist/bucket/index.d.ts +8 -0
- package/dist/bucket/index.d.ts.map +1 -1
- package/dist/bucket/index.js +7 -2
- package/dist/bucket/index.js.map +1 -1
- package/dist/cli/index.d.ts +191 -74
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +215 -48
- package/dist/cli/index.js.map +1 -1
- package/dist/command/index.d.ts +10 -0
- package/dist/command/index.d.ts.map +1 -1
- package/dist/command/index.js +67 -13
- package/dist/command/index.js.map +1 -1
- package/dist/core/index.browser.js +28 -21
- package/dist/core/index.browser.js.map +1 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +28 -21
- package/dist/core/index.js.map +1 -1
- package/dist/core/index.native.js +28 -21
- package/dist/core/index.native.js.map +1 -1
- package/dist/email/index.d.ts +8 -0
- package/dist/email/index.d.ts.map +1 -1
- package/dist/email/index.js +7 -2
- package/dist/email/index.js.map +1 -1
- package/dist/mcp/index.d.ts +5 -5
- package/dist/orm/index.bun.js +32 -16
- package/dist/orm/index.bun.js.map +1 -1
- package/dist/orm/index.d.ts +4 -1
- package/dist/orm/index.d.ts.map +1 -1
- package/dist/orm/index.js +34 -22
- package/dist/orm/index.js.map +1 -1
- package/dist/react/router/index.browser.js +9 -15
- package/dist/react/router/index.browser.js.map +1 -1
- package/dist/react/router/index.d.ts +295 -407
- package/dist/react/router/index.d.ts.map +1 -1
- package/dist/react/router/index.js +566 -776
- package/dist/react/router/index.js.map +1 -1
- package/dist/redis/index.d.ts +19 -19
- package/dist/security/index.d.ts +42 -42
- package/dist/security/index.d.ts.map +1 -1
- package/dist/security/index.js +8 -7
- package/dist/security/index.js.map +1 -1
- package/dist/server/auth/index.d.ts +167 -167
- package/dist/server/core/index.d.ts +9 -9
- package/dist/server/health/index.d.ts +17 -17
- package/dist/server/links/index.d.ts +39 -39
- package/dist/server/static/index.js +7 -2
- package/dist/server/static/index.js.map +1 -1
- package/dist/server/swagger/index.d.ts +8 -0
- package/dist/server/swagger/index.d.ts.map +1 -1
- package/dist/server/swagger/index.js +7 -2
- package/dist/server/swagger/index.js.map +1 -1
- package/dist/sms/index.d.ts +8 -0
- package/dist/sms/index.d.ts.map +1 -1
- package/dist/sms/index.js +7 -2
- package/dist/sms/index.js.map +1 -1
- package/dist/system/index.browser.js +734 -12
- package/dist/system/index.browser.js.map +1 -1
- package/dist/system/index.d.ts +8 -0
- package/dist/system/index.d.ts.map +1 -1
- package/dist/system/index.js +7 -2
- package/dist/system/index.js.map +1 -1
- package/dist/vite/index.d.ts +1 -1
- package/dist/vite/index.js +15 -7
- package/dist/vite/index.js.map +1 -1
- package/package.json +4 -2
- package/src/api/logs/TODO.md +13 -10
- package/src/cli/apps/AlephaPackageBuilderCli.ts +9 -0
- package/src/cli/atoms/buildOptions.ts +99 -9
- package/src/cli/commands/build.ts +149 -32
- package/src/cli/commands/db.ts +5 -7
- package/src/cli/commands/init.spec.ts +50 -6
- package/src/cli/commands/init.ts +28 -5
- package/src/cli/providers/ViteDevServerProvider.ts +1 -10
- package/src/cli/services/AlephaCliUtils.ts +16 -0
- package/src/cli/services/PackageManagerUtils.ts +2 -0
- package/src/cli/services/ProjectScaffolder.spec.ts +97 -0
- package/src/cli/services/ProjectScaffolder.ts +28 -6
- package/src/cli/templates/agentMd.ts +6 -1
- package/src/cli/templates/apiAppSecurityTs.ts +11 -0
- package/src/cli/templates/apiIndexTs.ts +18 -4
- package/src/cli/templates/webAppRouterTs.ts +25 -1
- package/src/cli/templates/webHelloComponentTsx.ts +15 -5
- package/src/command/helpers/Runner.spec.ts +135 -0
- package/src/command/helpers/Runner.ts +4 -1
- package/src/command/providers/CliProvider.spec.ts +325 -0
- package/src/command/providers/CliProvider.ts +117 -7
- package/src/core/Alepha.ts +32 -25
- package/src/orm/index.bun.ts +1 -1
- package/src/orm/index.ts +2 -6
- package/src/orm/providers/drivers/BunSqliteProvider.ts +4 -1
- package/src/orm/providers/drivers/CloudflareD1Provider.ts +57 -30
- package/src/orm/providers/drivers/DatabaseProvider.ts +9 -1
- package/src/orm/providers/drivers/NodeSqliteProvider.ts +4 -1
- package/src/react/router/hooks/useActive.ts +1 -1
- package/src/react/router/hooks/useRouter.ts +1 -1
- package/src/react/router/index.ts +4 -0
- package/src/react/router/primitives/$page.browser.spec.tsx +24 -24
- package/src/react/router/primitives/$page.spec.tsx +0 -32
- package/src/react/router/primitives/$page.ts +6 -14
- package/src/react/router/providers/ReactBrowserProvider.ts +6 -3
- package/src/react/router/providers/ReactPageProvider.ts +1 -1
- package/src/react/router/providers/ReactPreloadProvider.spec.ts +142 -0
- package/src/react/router/providers/ReactPreloadProvider.ts +85 -0
- package/src/react/router/providers/ReactServerProvider.ts +7 -78
- package/src/react/router/providers/ReactServerTemplateProvider.spec.ts +210 -0
- package/src/react/router/providers/ReactServerTemplateProvider.ts +228 -665
- package/src/react/router/services/ReactRouter.ts +13 -13
- package/src/security/__tests__/ServerSecurityProvider.spec.ts +77 -0
- package/src/security/providers/ServerSecurityProvider.ts +30 -22
- package/src/server/core/providers/NodeHttpServerProvider.spec.ts +9 -3
- package/src/system/index.browser.ts +25 -0
- package/src/system/index.workerd.ts +1 -0
- package/src/system/providers/FileSystemProvider.ts +8 -0
- package/src/system/providers/NodeFileSystemProvider.ts +11 -2
- package/src/vite/tasks/buildServer.ts +2 -12
- package/src/vite/tasks/generateCloudflare.ts +10 -7
- package/src/vite/tasks/generateDocker.ts +4 -0
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
type ReactRouterState,
|
|
8
8
|
} from "../providers/ReactPageProvider.ts";
|
|
9
9
|
|
|
10
|
-
export interface
|
|
10
|
+
export interface RouterPushOptions {
|
|
11
11
|
replace?: boolean;
|
|
12
12
|
params?: Record<string, string>;
|
|
13
13
|
query?: Record<string, string>;
|
|
@@ -114,7 +114,7 @@ export class ReactRouter<T extends object> {
|
|
|
114
114
|
return;
|
|
115
115
|
}
|
|
116
116
|
|
|
117
|
-
await this.
|
|
117
|
+
await this.push(this.location.pathname + this.location.search, {
|
|
118
118
|
replace: true,
|
|
119
119
|
force: true,
|
|
120
120
|
});
|
|
@@ -168,18 +168,18 @@ export class ReactRouter<T extends object> {
|
|
|
168
168
|
await this.browser?.invalidate(props);
|
|
169
169
|
}
|
|
170
170
|
|
|
171
|
-
public async
|
|
172
|
-
public async
|
|
171
|
+
public async push(path: string, options?: RouterPushOptions): Promise<void>;
|
|
172
|
+
public async push(
|
|
173
173
|
path: keyof VirtualRouter<T>,
|
|
174
|
-
options?:
|
|
174
|
+
options?: RouterPushOptions,
|
|
175
175
|
): Promise<void>;
|
|
176
|
-
public async
|
|
176
|
+
public async push(
|
|
177
177
|
path: string | keyof VirtualRouter<T>,
|
|
178
|
-
options?:
|
|
178
|
+
options?: RouterPushOptions,
|
|
179
179
|
): Promise<void> {
|
|
180
180
|
for (const page of this.pages) {
|
|
181
181
|
if (page.name === path) {
|
|
182
|
-
await this.browser?.
|
|
182
|
+
await this.browser?.push(
|
|
183
183
|
this.path(path as keyof VirtualRouter<T>, options),
|
|
184
184
|
options,
|
|
185
185
|
);
|
|
@@ -187,17 +187,17 @@ export class ReactRouter<T extends object> {
|
|
|
187
187
|
}
|
|
188
188
|
}
|
|
189
189
|
|
|
190
|
-
await this.browser?.
|
|
190
|
+
await this.browser?.push(path as string, options);
|
|
191
191
|
}
|
|
192
192
|
|
|
193
|
-
public anchor(path: string, options?:
|
|
193
|
+
public anchor(path: string, options?: RouterPushOptions): AnchorProps;
|
|
194
194
|
public anchor(
|
|
195
195
|
path: keyof VirtualRouter<T>,
|
|
196
|
-
options?:
|
|
196
|
+
options?: RouterPushOptions,
|
|
197
197
|
): AnchorProps;
|
|
198
198
|
public anchor(
|
|
199
199
|
path: string | keyof VirtualRouter<T>,
|
|
200
|
-
options:
|
|
200
|
+
options: RouterPushOptions = {},
|
|
201
201
|
): AnchorProps {
|
|
202
202
|
let href = path as string;
|
|
203
203
|
|
|
@@ -214,7 +214,7 @@ export class ReactRouter<T extends object> {
|
|
|
214
214
|
ev.stopPropagation();
|
|
215
215
|
ev.preventDefault();
|
|
216
216
|
|
|
217
|
-
this.
|
|
217
|
+
this.push(href, options).catch(console.error);
|
|
218
218
|
},
|
|
219
219
|
};
|
|
220
220
|
}
|
|
@@ -15,6 +15,7 @@ describe("ServerSecurityProvider", () => {
|
|
|
15
15
|
it("should protect action from unauthorized users", async () => {
|
|
16
16
|
class TestApp {
|
|
17
17
|
ok = $action({
|
|
18
|
+
secure: true,
|
|
18
19
|
handler: () => "OK",
|
|
19
20
|
});
|
|
20
21
|
}
|
|
@@ -63,10 +64,12 @@ describe("ServerSecurityProvider", () => {
|
|
|
63
64
|
it("should guard by permission", async () => {
|
|
64
65
|
class TestApp {
|
|
65
66
|
admin = $action({
|
|
67
|
+
secure: true,
|
|
66
68
|
group: "read",
|
|
67
69
|
handler: () => "ADMIN",
|
|
68
70
|
});
|
|
69
71
|
user = $action({
|
|
72
|
+
secure: true,
|
|
70
73
|
group: "read",
|
|
71
74
|
handler: () => "USER",
|
|
72
75
|
});
|
|
@@ -128,4 +131,78 @@ describe("ServerSecurityProvider", () => {
|
|
|
128
131
|
await app.admin.fetch({}, { user: admin }).then((it) => it.data),
|
|
129
132
|
).toBe("ADMIN");
|
|
130
133
|
});
|
|
134
|
+
|
|
135
|
+
it("should allow public actions by default (no secure option)", async () => {
|
|
136
|
+
class TestApp {
|
|
137
|
+
public = $action({
|
|
138
|
+
handler: () => "PUBLIC",
|
|
139
|
+
});
|
|
140
|
+
issuer = $issuer({
|
|
141
|
+
secret: "test",
|
|
142
|
+
roles: [{ name: "user", permissions: [{ name: "*" }] }],
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
const alepha = Alepha.create().with(AlephaServer).with(AlephaSecurity);
|
|
147
|
+
const app = alepha.inject(TestApp);
|
|
148
|
+
await alepha.start();
|
|
149
|
+
|
|
150
|
+
// Should work without authentication via .run()
|
|
151
|
+
expect(await app.public.run({})).toBe("PUBLIC");
|
|
152
|
+
|
|
153
|
+
// Should work without authentication via .fetch()
|
|
154
|
+
expect(await app.public.fetch({}).then((it) => it.data)).toBe("PUBLIC");
|
|
155
|
+
|
|
156
|
+
// Should work via HTTP without token
|
|
157
|
+
const response = await fetch(
|
|
158
|
+
`${alepha.inject(ServerProvider).hostname}${app.public.route.path}`,
|
|
159
|
+
);
|
|
160
|
+
expect(response.status).toBe(200);
|
|
161
|
+
expect(await response.text()).toBe("PUBLIC");
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
it("should allow explicit secure: false", async () => {
|
|
165
|
+
class TestApp {
|
|
166
|
+
public = $action({
|
|
167
|
+
secure: false,
|
|
168
|
+
handler: () => "PUBLIC",
|
|
169
|
+
});
|
|
170
|
+
issuer = $issuer({
|
|
171
|
+
secret: "test",
|
|
172
|
+
roles: [{ name: "user", permissions: [{ name: "*" }] }],
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
const alepha = Alepha.create().with(AlephaServer).with(AlephaSecurity);
|
|
177
|
+
const app = alepha.inject(TestApp);
|
|
178
|
+
await alepha.start();
|
|
179
|
+
|
|
180
|
+
// Should work without authentication
|
|
181
|
+
expect(await app.public.run({})).toBe("PUBLIC");
|
|
182
|
+
expect(await app.public.fetch({}).then((it) => it.data)).toBe("PUBLIC");
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
it("should require auth when secure: true is explicit", async () => {
|
|
186
|
+
class TestApp {
|
|
187
|
+
protected = $action({
|
|
188
|
+
secure: true,
|
|
189
|
+
handler: () => "PROTECTED",
|
|
190
|
+
});
|
|
191
|
+
issuer = $issuer({
|
|
192
|
+
secret: "test",
|
|
193
|
+
roles: [{ name: "user", permissions: [{ name: "*" }] }],
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
const alepha = Alepha.create().with(AlephaServer).with(AlephaSecurity);
|
|
198
|
+
const app = alepha.inject(TestApp);
|
|
199
|
+
await alepha.start();
|
|
200
|
+
|
|
201
|
+
// Should fail without user
|
|
202
|
+
await expect(app.protected.run({})).rejects.toThrowError(UnauthorizedError);
|
|
203
|
+
|
|
204
|
+
// Should succeed with user
|
|
205
|
+
const user = { id: randomUUID(), roles: ["user"] };
|
|
206
|
+
expect(await app.protected.run({}, { user })).toBe("PROTECTED");
|
|
207
|
+
});
|
|
131
208
|
});
|
|
@@ -31,25 +31,23 @@ export class ServerSecurityProvider {
|
|
|
31
31
|
handler: async () => {
|
|
32
32
|
for (const action of this.alepha.primitives($action)) {
|
|
33
33
|
// -------------------------------------------------------------------------------------------------------------
|
|
34
|
-
//
|
|
34
|
+
// Only create permission when secure is explicitly set to true
|
|
35
|
+
// Actions are public by default (like $route)
|
|
35
36
|
// -------------------------------------------------------------------------------------------------------------
|
|
36
37
|
if (
|
|
37
38
|
action.options.disabled ||
|
|
38
|
-
action.options.secure
|
|
39
|
+
action.options.secure !== true ||
|
|
39
40
|
this.securityProvider.getRealms().length === 0
|
|
40
41
|
) {
|
|
41
42
|
continue;
|
|
42
43
|
}
|
|
43
44
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
path: action.route.path,
|
|
51
|
-
});
|
|
52
|
-
}
|
|
45
|
+
this.securityProvider.createPermission({
|
|
46
|
+
name: action.name,
|
|
47
|
+
group: action.group,
|
|
48
|
+
method: action.route.method,
|
|
49
|
+
path: action.route.path,
|
|
50
|
+
});
|
|
53
51
|
}
|
|
54
52
|
},
|
|
55
53
|
});
|
|
@@ -59,10 +57,12 @@ export class ServerSecurityProvider {
|
|
|
59
57
|
protected readonly onActionRequest = $hook({
|
|
60
58
|
on: "action:onRequest",
|
|
61
59
|
handler: async ({ action, request, options }) => {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
if (
|
|
65
|
-
|
|
60
|
+
const secure = action.options.secure;
|
|
61
|
+
|
|
62
|
+
// Skip security if not explicitly enabled (secure: true or secure: { realm: ... })
|
|
63
|
+
// Actions are public by default (like $route)
|
|
64
|
+
if (secure !== true && typeof secure !== "object" && !options.user) {
|
|
65
|
+
this.log.trace("Skipping security check for action - not secured");
|
|
66
66
|
return;
|
|
67
67
|
}
|
|
68
68
|
|
|
@@ -93,7 +93,7 @@ export class ServerSecurityProvider {
|
|
|
93
93
|
this.alepha.codec.decode(userAccountInfoSchema, request.user),
|
|
94
94
|
);
|
|
95
95
|
} catch (error) {
|
|
96
|
-
if (
|
|
96
|
+
if (secure === true || typeof secure === "object" || permission) {
|
|
97
97
|
throw error;
|
|
98
98
|
}
|
|
99
99
|
// else, we skip the security check
|
|
@@ -106,7 +106,7 @@ export class ServerSecurityProvider {
|
|
|
106
106
|
on: "server:onRequest",
|
|
107
107
|
priority: "last",
|
|
108
108
|
handler: async ({ request, route }) => {
|
|
109
|
-
//
|
|
109
|
+
// Skip entirely only if explicitly disabled
|
|
110
110
|
if (route.secure === false) {
|
|
111
111
|
this.log.trace(
|
|
112
112
|
"Skipping security check for route - explicitly disabled",
|
|
@@ -126,7 +126,7 @@ export class ServerSecurityProvider {
|
|
|
126
126
|
typeof route.secure === "object" ? route.secure.realm : undefined;
|
|
127
127
|
|
|
128
128
|
try {
|
|
129
|
-
// Try to resolve user (JWT, API key, etc.)
|
|
129
|
+
// Try to resolve user (JWT, API key, etc.) - even for public routes (optional auth)
|
|
130
130
|
request.user = await this.securityProvider.resolveUserFromServerRequest(
|
|
131
131
|
request,
|
|
132
132
|
{ permission, realm },
|
|
@@ -135,7 +135,11 @@ export class ServerSecurityProvider {
|
|
|
135
135
|
// No user resolved?
|
|
136
136
|
if (!request.user) {
|
|
137
137
|
// Route requires auth → throw
|
|
138
|
-
if (
|
|
138
|
+
if (
|
|
139
|
+
route.secure === true ||
|
|
140
|
+
typeof route.secure === "object" ||
|
|
141
|
+
permission
|
|
142
|
+
) {
|
|
139
143
|
// Provide a more specific error message when no auth header was provided
|
|
140
144
|
if (!request.headers.authorization) {
|
|
141
145
|
throw new InvalidTokenError(
|
|
@@ -144,7 +148,7 @@ export class ServerSecurityProvider {
|
|
|
144
148
|
}
|
|
145
149
|
throw new UnauthorizedError("Authentication required");
|
|
146
150
|
}
|
|
147
|
-
// Route is public → skip
|
|
151
|
+
// Route is public → skip (but we tried to resolve user for optional auth)
|
|
148
152
|
this.log.trace(
|
|
149
153
|
"Skipping security check for route - no auth provided and not required",
|
|
150
154
|
);
|
|
@@ -166,11 +170,15 @@ export class ServerSecurityProvider {
|
|
|
166
170
|
permission,
|
|
167
171
|
});
|
|
168
172
|
} catch (error) {
|
|
169
|
-
if (
|
|
173
|
+
if (
|
|
174
|
+
route.secure === true ||
|
|
175
|
+
typeof route.secure === "object" ||
|
|
176
|
+
permission
|
|
177
|
+
) {
|
|
170
178
|
throw error;
|
|
171
179
|
}
|
|
172
180
|
|
|
173
|
-
// else, we skip the security check
|
|
181
|
+
// else, we skip the security check (route is public)
|
|
174
182
|
this.log.trace(
|
|
175
183
|
"Skipping security check for route - error occurred",
|
|
176
184
|
error,
|
|
@@ -31,7 +31,9 @@ describe("NodeHttpServerProvider", () => {
|
|
|
31
31
|
});
|
|
32
32
|
|
|
33
33
|
test("production mode: waits for connections then closes", async () => {
|
|
34
|
-
alepha = Alepha.create({
|
|
34
|
+
alepha = Alepha.create({
|
|
35
|
+
env: { NODE_ENV: "production", SERVER_PORT: 0 },
|
|
36
|
+
});
|
|
35
37
|
alepha.with(NodeHttpServerProvider);
|
|
36
38
|
|
|
37
39
|
await alepha.start();
|
|
@@ -52,7 +54,9 @@ describe("NodeHttpServerProvider", () => {
|
|
|
52
54
|
});
|
|
53
55
|
|
|
54
56
|
test("production mode: forces close after timeout", async () => {
|
|
55
|
-
alepha = Alepha.create({
|
|
57
|
+
alepha = Alepha.create({
|
|
58
|
+
env: { NODE_ENV: "production", SERVER_PORT: 0 },
|
|
59
|
+
});
|
|
56
60
|
alepha.with(NodeHttpServerProvider);
|
|
57
61
|
|
|
58
62
|
await alepha.start();
|
|
@@ -89,7 +93,9 @@ describe("NodeHttpServerProvider", () => {
|
|
|
89
93
|
});
|
|
90
94
|
|
|
91
95
|
test("rejects new requests during shutdown", async () => {
|
|
92
|
-
alepha = Alepha.create({
|
|
96
|
+
alepha = Alepha.create({
|
|
97
|
+
env: { NODE_ENV: "production", SERVER_PORT: 0 },
|
|
98
|
+
});
|
|
93
99
|
alepha.with(NodeHttpServerProvider);
|
|
94
100
|
|
|
95
101
|
await alepha.start();
|
|
@@ -1,11 +1,36 @@
|
|
|
1
1
|
import { $module } from "alepha";
|
|
2
|
+
import { FileSystemProvider } from "./providers/FileSystemProvider.ts";
|
|
3
|
+
import { MemoryFileSystemProvider } from "./providers/MemoryFileSystemProvider.ts";
|
|
4
|
+
import { MemoryShellProvider } from "./providers/MemoryShellProvider.ts";
|
|
5
|
+
import { ShellProvider } from "./providers/ShellProvider.ts";
|
|
6
|
+
import { FileDetector } from "./services/FileDetector.ts";
|
|
2
7
|
|
|
3
8
|
export * from "./errors/FileError.ts";
|
|
4
9
|
export * from "./providers/FileSystemProvider.ts";
|
|
5
10
|
export * from "./providers/MemoryFileSystemProvider.ts";
|
|
6
11
|
export * from "./providers/MemoryShellProvider.ts";
|
|
7
12
|
export * from "./providers/ShellProvider.ts";
|
|
13
|
+
export * from "./services/FileDetector.ts";
|
|
8
14
|
|
|
9
15
|
export const AlephaSystem = $module({
|
|
10
16
|
name: "alepha.system",
|
|
17
|
+
services: [
|
|
18
|
+
FileDetector,
|
|
19
|
+
FileSystemProvider,
|
|
20
|
+
MemoryFileSystemProvider,
|
|
21
|
+
ShellProvider,
|
|
22
|
+
MemoryShellProvider,
|
|
23
|
+
],
|
|
24
|
+
register: (alepha) =>
|
|
25
|
+
alepha
|
|
26
|
+
.with({
|
|
27
|
+
optional: true,
|
|
28
|
+
provide: FileSystemProvider,
|
|
29
|
+
use: MemoryFileSystemProvider,
|
|
30
|
+
})
|
|
31
|
+
.with({
|
|
32
|
+
optional: true,
|
|
33
|
+
provide: ShellProvider,
|
|
34
|
+
use: MemoryShellProvider,
|
|
35
|
+
}),
|
|
11
36
|
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./index.browser.ts";
|
|
@@ -196,8 +196,16 @@ export interface CpOptions {
|
|
|
196
196
|
export interface MkdirOptions {
|
|
197
197
|
/**
|
|
198
198
|
* If true, creates parent directories as needed
|
|
199
|
+
*
|
|
200
|
+
* @default true
|
|
199
201
|
*/
|
|
200
202
|
recursive?: boolean;
|
|
203
|
+
/**
|
|
204
|
+
* If true, does not throw an error if the directory already exists
|
|
205
|
+
*
|
|
206
|
+
* @default true
|
|
207
|
+
*/
|
|
208
|
+
force?: boolean;
|
|
201
209
|
/**
|
|
202
210
|
* File mode (permission and sticky bits)
|
|
203
211
|
*/
|
|
@@ -291,8 +291,17 @@ export class NodeFileSystemProvider implements FileSystemProvider {
|
|
|
291
291
|
* await fs.mkdir("/tmp/mydir", { mode: 0o755 });
|
|
292
292
|
* ```
|
|
293
293
|
*/
|
|
294
|
-
async mkdir(path: string, options
|
|
295
|
-
|
|
294
|
+
async mkdir(path: string, options: MkdirOptions = {}): Promise<void> {
|
|
295
|
+
const p = fsMkdir(path, {
|
|
296
|
+
recursive: options.recursive ?? true,
|
|
297
|
+
mode: options.mode,
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
if (options.force === false) {
|
|
301
|
+
await p;
|
|
302
|
+
} else {
|
|
303
|
+
await p.catch(() => {});
|
|
304
|
+
}
|
|
296
305
|
}
|
|
297
306
|
|
|
298
307
|
/**
|
|
@@ -23,7 +23,7 @@ export interface BuildServerOptions {
|
|
|
23
23
|
|
|
24
24
|
/**
|
|
25
25
|
* Optional client directory name (relative to distDir).
|
|
26
|
-
* If provided, the
|
|
26
|
+
* If provided, the SSR manifest will be embedded in the server output.
|
|
27
27
|
*/
|
|
28
28
|
clientDir?: string;
|
|
29
29
|
|
|
@@ -167,16 +167,6 @@ export async function buildServer(
|
|
|
167
167
|
|
|
168
168
|
const entryFile = extractEntryFromBundle(opts.entry, result);
|
|
169
169
|
|
|
170
|
-
// Embed client template if client was built
|
|
171
|
-
let template = "";
|
|
172
|
-
if (opts.clientDir) {
|
|
173
|
-
const index = await readFile(
|
|
174
|
-
`${opts.distDir}/${opts.clientDir}/index.html`,
|
|
175
|
-
"utf-8",
|
|
176
|
-
);
|
|
177
|
-
template = `__alepha.set("alepha.react.server.template", \`${index.replace(/>\s*</g, "><").trim()}\`);\n`;
|
|
178
|
-
}
|
|
179
|
-
|
|
180
170
|
// Embed SSR manifests if client was built
|
|
181
171
|
// This bundles all manifest data into index.js for serverless deployments
|
|
182
172
|
let manifest = "";
|
|
@@ -230,7 +220,7 @@ export async function buildServer(
|
|
|
230
220
|
|
|
231
221
|
await writeFile(
|
|
232
222
|
`${opts.distDir}/index.js`,
|
|
233
|
-
`${warning}\n${
|
|
223
|
+
`${warning}\n${manifest}import './server/${entryFile}';\n`.trim(),
|
|
234
224
|
);
|
|
235
225
|
|
|
236
226
|
return { entryFile, manifest: manifestData };
|
|
@@ -63,11 +63,8 @@ export async function generateCloudflare(
|
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
const url = process.env.DATABASE_URL;
|
|
66
|
-
if (url?.startsWith("
|
|
67
|
-
const [name, id] = url
|
|
68
|
-
.replace("cloudflare-d1://", "")
|
|
69
|
-
.replace("cloudflare-d1:", "")
|
|
70
|
-
.split(":");
|
|
66
|
+
if (url?.startsWith("d1:")) {
|
|
67
|
+
const [name, id] = url.replace("d1://", "").replace("d1:", "").split(":");
|
|
71
68
|
wrangler.d1_databases = wrangler.d1_databases || [];
|
|
72
69
|
wrangler.d1_databases.push({
|
|
73
70
|
binding: name,
|
|
@@ -75,7 +72,7 @@ export async function generateCloudflare(
|
|
|
75
72
|
database_id: id,
|
|
76
73
|
});
|
|
77
74
|
wrangler.vars ??= {};
|
|
78
|
-
wrangler.vars.DATABASE_URL = `
|
|
75
|
+
wrangler.vars.DATABASE_URL = `d1://${name}:${id}`;
|
|
79
76
|
}
|
|
80
77
|
|
|
81
78
|
await writeFile(
|
|
@@ -102,7 +99,13 @@ export default {
|
|
|
102
99
|
|
|
103
100
|
__alepha.set("cloudflare.env", env);
|
|
104
101
|
|
|
105
|
-
|
|
102
|
+
try {
|
|
103
|
+
await __alepha.start();
|
|
104
|
+
} catch (err) {
|
|
105
|
+
console.error(err);
|
|
106
|
+
return new Response("Internal Server Error", { status: 500 });
|
|
107
|
+
}
|
|
108
|
+
|
|
106
109
|
await __alepha.events.emit("web:request", ctx);
|
|
107
110
|
|
|
108
111
|
return ctx.res;
|