@porulle/core 0.1.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/dist/auth/middleware.d.ts.map +1 -1
- package/dist/auth/middleware.js +17 -1
- package/dist/config/define-config.d.ts.map +1 -1
- package/dist/config/define-config.js +6 -0
- package/dist/config/types.d.ts +12 -0
- package/dist/config/types.d.ts.map +1 -1
- package/dist/hooks/checkout.d.ts +3 -3
- package/dist/hooks/checkout.js +4 -4
- package/dist/index.d.ts +9 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -1
- package/dist/interfaces/rest/audit-middleware.d.ts +46 -0
- package/dist/interfaces/rest/audit-middleware.d.ts.map +1 -0
- package/dist/interfaces/rest/audit-middleware.js +82 -0
- package/dist/interfaces/rest/parse-json.d.ts +39 -0
- package/dist/interfaces/rest/parse-json.d.ts.map +1 -0
- package/dist/interfaces/rest/parse-json.js +45 -0
- package/dist/interfaces/rest/routes/catalog.d.ts.map +1 -1
- package/dist/interfaces/rest/routes/catalog.js +17 -2
- package/dist/interfaces/rest/routes/customers.d.ts.map +1 -1
- package/dist/interfaces/rest/routes/customers.js +59 -4
- package/dist/interfaces/rest/routes/inventory.d.ts.map +1 -1
- package/dist/interfaces/rest/routes/inventory.js +4 -2
- package/dist/interfaces/rest/routes/media.d.ts.map +1 -1
- package/dist/interfaces/rest/routes/media.js +6 -0
- package/dist/interfaces/rest/routes/orders.d.ts.map +1 -1
- package/dist/interfaces/rest/routes/orders.js +23 -1
- package/dist/interfaces/rest/routes/promotions.d.ts.map +1 -1
- package/dist/interfaces/rest/routes/promotions.js +21 -1
- package/dist/interfaces/rest/schemas/carts.d.ts +175 -0
- package/dist/interfaces/rest/schemas/carts.d.ts.map +1 -1
- package/dist/interfaces/rest/schemas/catalog.d.ts +1410 -0
- package/dist/interfaces/rest/schemas/catalog.d.ts.map +1 -1
- package/dist/interfaces/rest/schemas/catalog.js +28 -1
- package/dist/interfaces/rest/schemas/checkout.d.ts +35 -0
- package/dist/interfaces/rest/schemas/checkout.d.ts.map +1 -1
- package/dist/interfaces/rest/schemas/customer-portal.d.ts +280 -0
- package/dist/interfaces/rest/schemas/customer-portal.d.ts.map +1 -1
- package/dist/interfaces/rest/schemas/customers.d.ts +863 -0
- package/dist/interfaces/rest/schemas/customers.d.ts.map +1 -1
- package/dist/interfaces/rest/schemas/customers.js +88 -0
- package/dist/interfaces/rest/schemas/inventory.d.ts +182 -1
- package/dist/interfaces/rest/schemas/inventory.d.ts.map +1 -1
- package/dist/interfaces/rest/schemas/media.d.ts +105 -0
- package/dist/interfaces/rest/schemas/media.d.ts.map +1 -1
- package/dist/interfaces/rest/schemas/orders.d.ts +136 -0
- package/dist/interfaces/rest/schemas/orders.d.ts.map +1 -1
- package/dist/interfaces/rest/schemas/orders.js +20 -0
- package/dist/interfaces/rest/schemas/pricing.d.ts +70 -0
- package/dist/interfaces/rest/schemas/pricing.d.ts.map +1 -1
- package/dist/interfaces/rest/schemas/promotions.d.ts +298 -0
- package/dist/interfaces/rest/schemas/promotions.d.ts.map +1 -1
- package/dist/interfaces/rest/schemas/promotions.js +25 -1
- package/dist/interfaces/rest/schemas/shared.d.ts +47 -0
- package/dist/interfaces/rest/schemas/shared.d.ts.map +1 -1
- package/dist/interfaces/rest/schemas/shared.js +8 -0
- package/dist/interfaces/rest/schemas/webhooks.d.ts +70 -0
- package/dist/interfaces/rest/schemas/webhooks.d.ts.map +1 -1
- package/dist/kernel/database/adapter.d.ts +6 -0
- package/dist/kernel/database/adapter.d.ts.map +1 -1
- package/dist/kernel/database/adapter.js +62 -1
- package/dist/kernel/database/migrate.d.ts +22 -2
- package/dist/kernel/database/migrate.d.ts.map +1 -1
- package/dist/kernel/database/migrate.js +42 -2
- package/dist/modules/analytics/hooks.d.ts +5 -5
- package/dist/modules/analytics/hooks.js +5 -5
- package/dist/modules/analytics/repository/index.d.ts.map +1 -1
- package/dist/modules/catalog/category-service.d.ts +6 -1
- package/dist/modules/catalog/category-service.d.ts.map +1 -1
- package/dist/modules/catalog/category-service.js +35 -5
- package/dist/modules/catalog/schema.d.ts +17 -0
- package/dist/modules/catalog/schema.d.ts.map +1 -1
- package/dist/modules/catalog/schema.js +2 -0
- package/dist/modules/catalog/service.d.ts +11 -2
- package/dist/modules/catalog/service.d.ts.map +1 -1
- package/dist/modules/catalog/service.js +8 -2
- package/dist/modules/customers/repository/index.d.ts +8 -1
- package/dist/modules/customers/repository/index.d.ts.map +1 -1
- package/dist/modules/customers/repository/index.js +42 -2
- package/dist/modules/customers/schema.d.ts +162 -0
- package/dist/modules/customers/schema.d.ts.map +1 -1
- package/dist/modules/customers/schema.js +18 -0
- package/dist/modules/customers/service.d.ts +32 -2
- package/dist/modules/customers/service.d.ts.map +1 -1
- package/dist/modules/customers/service.js +119 -3
- package/dist/modules/inventory/schemas.d.ts +7 -1
- package/dist/modules/inventory/schemas.d.ts.map +1 -1
- package/dist/modules/inventory/schemas.js +6 -1
- package/dist/modules/inventory/service.d.ts +18 -0
- package/dist/modules/inventory/service.d.ts.map +1 -1
- package/dist/modules/inventory/service.js +58 -21
- package/dist/modules/media/noop-adapter.d.ts +11 -0
- package/dist/modules/media/noop-adapter.d.ts.map +1 -0
- package/dist/modules/media/noop-adapter.js +31 -0
- package/dist/modules/orders/repository/index.d.ts +19 -0
- package/dist/modules/orders/repository/index.d.ts.map +1 -1
- package/dist/modules/orders/repository/index.js +42 -1
- package/dist/modules/orders/service.d.ts +31 -0
- package/dist/modules/orders/service.d.ts.map +1 -1
- package/dist/modules/orders/service.js +52 -2
- package/dist/modules/payments/repository/index.d.ts.map +1 -1
- package/dist/modules/promotions/schemas.d.ts +46 -0
- package/dist/modules/promotions/schemas.d.ts.map +1 -1
- package/dist/modules/promotions/schemas.js +19 -8
- package/dist/modules/promotions/service.d.ts +8 -2
- package/dist/modules/promotions/service.d.ts.map +1 -1
- package/dist/modules/promotions/service.js +74 -9
- package/dist/modules/search/repository/index.d.ts.map +1 -1
- package/dist/modules/shipping/repository/index.d.ts.map +1 -1
- package/dist/modules/tax/repository/index.d.ts.map +1 -1
- package/dist/runtime/client-ip.d.ts +31 -0
- package/dist/runtime/client-ip.d.ts.map +1 -0
- package/dist/runtime/client-ip.js +31 -0
- package/dist/runtime/server.d.ts +4 -0
- package/dist/runtime/server.d.ts.map +1 -1
- package/dist/runtime/server.js +35 -19
- package/dist/test-utils/create-plugin-test-app.d.ts.map +1 -1
- package/dist/test-utils/create-plugin-test-app.js +4 -1
- package/dist/test-utils/test-actors.d.ts +3 -2
- package/dist/test-utils/test-actors.d.ts.map +1 -1
- package/dist/test-utils/test-actors.js +3 -2
- package/package.json +15 -15
- package/src/auth/middleware.ts +18 -1
- package/src/config/define-config.ts +7 -0
- package/src/config/types.ts +12 -0
- package/src/hooks/checkout.ts +4 -4
- package/src/index.ts +18 -1
- package/src/interfaces/rest/audit-middleware.ts +110 -0
- package/src/interfaces/rest/parse-json.ts +81 -0
- package/src/interfaces/rest/routes/catalog.ts +21 -1
- package/src/interfaces/rest/routes/customers.ts +64 -3
- package/src/interfaces/rest/routes/inventory.ts +4 -2
- package/src/interfaces/rest/routes/media.ts +7 -0
- package/src/interfaces/rest/routes/orders.ts +21 -1
- package/src/interfaces/rest/routes/promotions.ts +22 -1
- package/src/interfaces/rest/schemas/catalog.ts +30 -1
- package/src/interfaces/rest/schemas/customers.ts +99 -0
- package/src/interfaces/rest/schemas/orders.ts +21 -0
- package/src/interfaces/rest/schemas/promotions.ts +32 -1
- package/src/interfaces/rest/schemas/shared.ts +9 -0
- package/src/kernel/database/adapter.ts +64 -1
- package/src/kernel/database/migrate.ts +50 -2
- package/src/modules/analytics/hooks.ts +5 -5
- package/src/modules/analytics/repository/index.ts +0 -1
- package/src/modules/catalog/category-service.ts +26 -5
- package/src/modules/catalog/schema.ts +2 -0
- package/src/modules/catalog/service.ts +25 -3
- package/src/modules/customers/repository/index.ts +55 -1
- package/src/modules/customers/schema.ts +19 -0
- package/src/modules/customers/service.ts +137 -2
- package/src/modules/inventory/schemas.ts +6 -1
- package/src/modules/inventory/service.ts +84 -29
- package/src/modules/media/noop-adapter.ts +36 -0
- package/src/modules/orders/repository/index.ts +63 -1
- package/src/modules/orders/service.ts +86 -3
- package/src/modules/payments/repository/index.ts +0 -1
- package/src/modules/promotions/schemas.ts +21 -4
- package/src/modules/promotions/service.ts +90 -18
- package/src/modules/search/repository/index.ts +0 -1
- package/src/modules/shipping/repository/index.ts +0 -1
- package/src/modules/tax/repository/index.ts +0 -1
- package/src/runtime/client-ip.ts +49 -0
- package/src/runtime/server.ts +39 -18
- package/src/test-utils/create-plugin-test-app.ts +3 -1
- package/src/test-utils/test-actors.ts +3 -2
package/src/runtime/server.ts
CHANGED
|
@@ -5,6 +5,7 @@ import { csrf } from "hono/csrf";
|
|
|
5
5
|
import { bodyLimit } from "hono/body-limit";
|
|
6
6
|
import { rateLimiter } from "hono-rate-limiter";
|
|
7
7
|
import { createHash } from "node:crypto";
|
|
8
|
+
import { createClientIpResolver } from "./client-ip.js";
|
|
8
9
|
import type { Actor } from "../auth/types.js";
|
|
9
10
|
import type { AuthInstance } from "../auth/setup.js";
|
|
10
11
|
import type { CommerceConfig } from "../config/types.js";
|
|
@@ -90,14 +91,14 @@ export async function createServer(config: CommerceConfig) {
|
|
|
90
91
|
throw new Error(
|
|
91
92
|
"FATAL: auth.enableDevKey has been removed. " +
|
|
92
93
|
"Use 'bunx @porulle/cli api-key create --scope admin' to generate a real API key. " +
|
|
93
|
-
"See
|
|
94
|
+
"See https://github.com/asyncdotengineering/porulle/blob/main/SECURITY.md for the auth/key scoping rationale.",
|
|
94
95
|
);
|
|
95
96
|
}
|
|
96
97
|
if ((config.auth as Record<string, unknown>)?.devKey !== undefined) {
|
|
97
98
|
throw new Error(
|
|
98
99
|
"FATAL: auth.devKey has been removed. " +
|
|
99
100
|
"Use 'bunx @porulle/cli api-key create --scope admin' to generate a real API key. " +
|
|
100
|
-
"See
|
|
101
|
+
"See https://github.com/asyncdotengineering/porulle/blob/main/SECURITY.md for the auth/key scoping rationale.",
|
|
101
102
|
);
|
|
102
103
|
}
|
|
103
104
|
|
|
@@ -184,28 +185,35 @@ export async function createServer(config: CommerceConfig) {
|
|
|
184
185
|
}));
|
|
185
186
|
|
|
186
187
|
// ─── Body Size Limit (F6) ──────────────────────────────────────────
|
|
187
|
-
|
|
188
|
+
// Media uploads (phone photos are 3–8MB) get their own larger limit and are
|
|
189
|
+
// exempt from the global 1MB limit. Everything else stays at 1MB.
|
|
190
|
+
const mediaMaxUploadSize = config.media?.maxUploadSize ?? 10 * 1024 * 1024;
|
|
191
|
+
const MEDIA_UPLOAD_PATH = "/api/media/upload";
|
|
192
|
+
|
|
193
|
+
app.use(MEDIA_UPLOAD_PATH, bodyLimit({
|
|
194
|
+
maxSize: mediaMaxUploadSize,
|
|
195
|
+
onError: (c) => c.json({
|
|
196
|
+
error: { code: "FILE_TOO_LARGE", message: `Upload exceeds the ${mediaMaxUploadSize}-byte limit.` },
|
|
197
|
+
}, 413),
|
|
198
|
+
}));
|
|
199
|
+
|
|
200
|
+
const globalBodyLimit = bodyLimit({
|
|
188
201
|
maxSize: 1024 * 1024, // 1 MB default
|
|
189
202
|
onError: (c) => c.json({
|
|
190
203
|
error: { code: "PAYLOAD_TOO_LARGE", message: "Request body exceeds 1MB limit." },
|
|
191
204
|
}, 413),
|
|
192
|
-
})
|
|
205
|
+
});
|
|
206
|
+
app.use("*", (c, next) =>
|
|
207
|
+
c.req.path === MEDIA_UPLOAD_PATH ? next() : globalBodyLimit(c, next),
|
|
208
|
+
);
|
|
193
209
|
|
|
194
210
|
// ─── Rate Limiting (F1) ──────────────────────────────────────────────
|
|
195
|
-
//
|
|
196
|
-
//
|
|
197
|
-
|
|
211
|
+
// Client IP drives the rate-limit key. Defaults to the Node socket address
|
|
212
|
+
// (trusting X-Forwarded-For only from a known proxy via config.runtime
|
|
213
|
+
// .trustedProxyIp / TRUSTED_PROXY_IP); edge runtimes inject
|
|
214
|
+
// config.runtime.getClientIp to read the platform header instead.
|
|
198
215
|
const signInEmailRateKeyCache = new WeakMap<Request, string>();
|
|
199
|
-
const getClientIp = (
|
|
200
|
-
const raw = c.req.raw as { socket?: { remoteAddress?: string } };
|
|
201
|
-
const remoteAddress = raw.socket?.remoteAddress;
|
|
202
|
-
// Only trust X-Forwarded-For when the direct connection is from a trusted proxy
|
|
203
|
-
if (trustedProxyIp && remoteAddress === trustedProxyIp) {
|
|
204
|
-
const xff = c.req.header("x-forwarded-for")?.split(",")[0]?.trim();
|
|
205
|
-
if (xff) return xff;
|
|
206
|
-
}
|
|
207
|
-
return remoteAddress ?? "unknown";
|
|
208
|
-
};
|
|
216
|
+
const getClientIp = createClientIpResolver(config);
|
|
209
217
|
const keyGenerator = getClientIp;
|
|
210
218
|
|
|
211
219
|
app.use("/api/auth/*", rateLimiter({
|
|
@@ -466,5 +474,18 @@ export async function createServer(config: CommerceConfig) {
|
|
|
466
474
|
return dispatchFetch(rewritten as Request, env as never, executionCtx as never);
|
|
467
475
|
}) as typeof app.fetch;
|
|
468
476
|
|
|
469
|
-
|
|
477
|
+
// `runJobs` triggers one job-runner tick. On Cloudflare Workers, call it
|
|
478
|
+
// from `scheduled()` so cron triggers drive the queue without an in-process
|
|
479
|
+
// setInterval (which can't outlive a request on Workers):
|
|
480
|
+
//
|
|
481
|
+
// // wrangler.toml
|
|
482
|
+
// [triggers]
|
|
483
|
+
// crons = ["*/5 * * * *"]
|
|
484
|
+
//
|
|
485
|
+
// // worker.ts
|
|
486
|
+
// export default {
|
|
487
|
+
// fetch: (req, env, ctx) => server.app.fetch(req, env, ctx),
|
|
488
|
+
// scheduled: (_event, env, ctx) => ctx.waitUntil(server.runJobs()),
|
|
489
|
+
// };
|
|
490
|
+
return { app, kernel, logger, commerce, runJobs };
|
|
470
491
|
}
|
|
@@ -26,6 +26,7 @@ import { createTestConfig } from "./create-test-config.js";
|
|
|
26
26
|
import { createKernel } from "../runtime/kernel.js";
|
|
27
27
|
import type { Kernel } from "../runtime/kernel.js";
|
|
28
28
|
import { buildSchema } from "../kernel/database/migrate.js";
|
|
29
|
+
import { unwrapDb } from "../kernel/database/adapter.js";
|
|
29
30
|
import { ensureDefaultOrg } from "../auth/org.js";
|
|
30
31
|
import { mapErrorToStatus } from "../kernel/error-mapper.js";
|
|
31
32
|
|
|
@@ -93,7 +94,8 @@ export async function createPluginTestApp(
|
|
|
93
94
|
};
|
|
94
95
|
const { apply } = await drizzleKit.pushSchema(
|
|
95
96
|
mergedSchema,
|
|
96
|
-
|
|
97
|
+
// drizzle-kit needs the native driver result shape; unwrap the normalized db.
|
|
98
|
+
unwrapDb(kernel.database.db) as PgDatabase<PgQueryResultHKT>,
|
|
97
99
|
);
|
|
98
100
|
await apply();
|
|
99
101
|
|
|
@@ -3,8 +3,9 @@ import { DEFAULT_ORG_ID } from "../auth/org.js";
|
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Organization ID used in test fixtures. Tests use the deprecated DEFAULT_ORG_ID
|
|
6
|
-
* because ensureDefaultOrg() creates this org
|
|
7
|
-
*
|
|
6
|
+
* because ensureDefaultOrg() creates this org during test setup. When
|
|
7
|
+
* DEFAULT_ORG_ID is removed, test setup will create a real org via the
|
|
8
|
+
* Better Auth API instead.
|
|
8
9
|
*/
|
|
9
10
|
export const TEST_ORG_ID = DEFAULT_ORG_ID;
|
|
10
11
|
|