@h-ai/serv 0.1.0-alpha.69 → 0.1.0-alpha.71
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.en.md +16 -10
- package/README.ja.md +16 -10
- package/README.md +16 -10
- package/dist/{chunk-TWHCU6HT.js → chunk-KR4H56KP.js} +15 -6
- package/dist/chunk-KR4H56KP.js.map +1 -0
- package/dist/{chunk-BGWE4S6Z.js → chunk-WW25756Z.js} +3 -3
- package/dist/chunk-WW25756Z.js.map +1 -0
- package/dist/features/ai.d.ts +6 -0
- package/dist/features/ai.js +1 -1
- package/dist/features/feedback.d.ts +44 -1
- package/dist/features/feedback.js +6 -3
- package/dist/features/feedback.js.map +1 -1
- package/dist/features/iam.d.ts +28 -0
- package/dist/features/iam.js +1 -1
- package/dist/features/storage.d.ts +6 -0
- package/dist/features/storage.js +8 -4
- package/dist/features/storage.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +13 -4
- package/dist/index.js.map +1 -1
- package/package.json +15 -15
- package/dist/chunk-BGWE4S6Z.js.map +0 -1
- package/dist/chunk-TWHCU6HT.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/features/serv-feature-feedback.ts"],"names":[],"mappings":"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","file":"feedback.js","sourcesContent":["/** @h-ai/serv — 按需挂载反馈领域,不接收客户端身份或对象存储路径。 */\nimport type { FeedbackContext, FeedbackFunctions } from '@h-ai/feedback'\nimport type { ServContext } from '../serv-context.js'\nimport type { AuthenticatedServContext } from '../serv-router.js'\nimport { apiContract } from '@h-ai/api-contract'\nimport { core, err, HaiCommonError } from '@h-ai/core'\nimport { servM } from '../serv-i18n.js'\nimport { implement } from '../serv-router.js'\n\n/**\n * 已认证请求到反馈范围的可信映射,返回 null 时拒绝访问。\n * @example\n * ```ts\n * import type { FeedbackProcedureDeps } from '@h-ai/serv/features/feedback'\n * import { feedback } from '@h-ai/feedback'\n * const deps: FeedbackProcedureDeps = { feedback, resolveContext: ({ session }) => ({ scopeId: 'tenant-from-server', userId: session.userId, permissions: session.permissions }) }\n * ```\n */\nexport interface FeedbackProcedureDeps {\n readonly feedback: FeedbackFunctions\n readonly resolveContext: (context: AuthenticatedServContext) => FeedbackContext | null | Promise<FeedbackContext | null>\n}\n\n/**\n * 创建反馈的默认 procedures。宿主解析租户与权限,领域模块再次检查资源范围。\n * @example\n * ```ts\n * import { feedback } from '@h-ai/feedback'\n * import { createFeedbackProcedures } from '@h-ai/serv/features/feedback'\n * const procedures = createFeedbackProcedures({ feedback, resolveContext: ({ session }) => ({ scopeId: 'trusted-tenant', userId: session.userId, permissions: session.permissions }) })\n * ```\n */\nexport function createFeedbackProcedures(deps: FeedbackProcedureDeps) {\n const contextFor = async (context: AuthenticatedServContext) => {\n try {\n const actor = await deps.resolveContext(context)\n if (!actor?.scopeId || actor.userId !== context.session.userId)\n return err(HaiCommonError.FORBIDDEN, servM('serv_errorForbidden', { locale: context.locale }))\n return { success: true as const, data: actor }\n }\n catch {\n return err(HaiCommonError.INTERNAL_ERROR, servM('serv_errorInternal', { locale: context.locale }))\n }\n }\n const router = implement(apiContract.feedback).context<ServContext>()\n return router\n .route('reports.submit')\n .auth()\n .handle(async ({ input, context }) => {\n const actor = await contextFor(context)\n if (!actor.success)\n return actor\n return core.context.run(actor.data, () => deps.feedback.submit(input, actor.data))\n })\n .route('reports.list')\n .auth()\n .handle(async ({ input, context }) => {\n const actor = await contextFor(context)\n if (!actor.success)\n return actor\n return core.context.run(actor.data, () => deps.feedback.list(input, actor.data))\n })\n .route('reports.get')\n .auth()\n .handle(async ({ input, context }) => {\n const actor = await contextFor(context)\n if (!actor.success)\n return actor\n return core.context.run(actor.data, () => deps.feedback.get(input.id, actor.data))\n })\n .route('reports.getEvidence')\n .auth()\n .handle(async ({ input, context }) => {\n const actor = await contextFor(context)\n if (!actor.success)\n return actor\n return core.context.run(actor.data, () => deps.feedback.getEvidence(input, actor.data))\n })\n .route('reports.setStatus')\n .auth()\n .handle(async ({ input, context }) => {\n const actor = await contextFor(context)\n if (!actor.success)\n return actor\n return core.context.run(actor.data, () => deps.feedback.setStatus(input, actor.data))\n })\n .route('reports.retry')\n .auth()\n .handle(async ({ input, context }) => {\n const actor = await contextFor(context)\n if (!actor.success)\n return actor\n return core.context.run(actor.data, () => deps.feedback.retry(input, actor.data))\n })\n .route('reports.export')\n .auth()\n .handle(async ({ input, context }) => {\n const actor = await contextFor(context)\n if (!actor.success)\n return actor\n return core.context.run(actor.data, () => deps.feedback.export(input, actor.data))\n })\n .route('reports.getExport')\n .auth()\n .handle(async ({ input, context }) => {\n const actor = await contextFor(context)\n if (!actor.success)\n return actor\n return core.context.run(actor.data, () => deps.feedback.getExport(input, actor.data))\n })\n .route('reports.appendEvidence')\n .auth()\n .handle(async ({ input, context }) => {\n const actor = await contextFor(context)\n if (!actor.success)\n return actor\n return core.context.run(actor.data, () => deps.feedback.appendEvidence(input, actor.data))\n })\n .route('reports.completeCollection')\n .auth()\n .handle(async ({ input, context }) => {\n const actor = await contextFor(context)\n if (!actor.success)\n return actor\n return core.context.run(actor.data, () => deps.feedback.completeCollection(input, actor.data))\n })\n .route('attachments.upload')\n .auth()\n .handle(async ({ input, context }) => {\n const actor = await contextFor(context)\n if (!actor.success)\n return actor\n return core.context.run(actor.data, () => deps.feedback.uploadAttachment(input, actor.data))\n })\n .route('attachments.get')\n .auth()\n .handle(async ({ input, context }) => {\n const actor = await contextFor(context)\n if (!actor.success)\n return actor\n return core.context.run(actor.data, () => deps.feedback.getAttachment(input, actor.data))\n })\n .build()\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/features/serv-feature-feedback.ts"],"names":[],"mappings":"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","file":"feedback.js","sourcesContent":["/** @h-ai/serv — 按需挂载反馈领域,不接收客户端身份或对象存储路径。 */\nimport type { FeedbackContext, FeedbackFunctions } from '@h-ai/feedback'\nimport type { ServContext } from '../serv-context.js'\nimport type { AuthenticatedServContext } from '../serv-router.js'\nimport { apiContract } from '@h-ai/api-contract'\nimport { core, err, HaiCommonError, ok } from '@h-ai/core'\nimport { servM } from '../serv-i18n.js'\nimport { implement } from '../serv-router.js'\n\n/**\n * 已认证请求到反馈范围的可信映射,返回 null 时拒绝访问。\n * @example\n * ```ts\n * import type { FeedbackProcedureDeps } from '@h-ai/serv/features/feedback'\n * import { feedback } from '@h-ai/feedback'\n * const deps: FeedbackProcedureDeps = { feedback, resolveContext: ({ session }) => ({ scopeId: 'tenant-from-server', userId: session.userId, permissions: session.permissions }) }\n * ```\n */\nexport interface FeedbackProcedureDeps {\n readonly feedback: FeedbackFunctions\n readonly resolveContext: (context: AuthenticatedServContext) => FeedbackContext | null | Promise<FeedbackContext | null>\n}\n\n/**\n * 创建反馈的默认 procedures。宿主解析租户与权限,领域模块再次检查资源范围。\n * @example\n * ```ts\n * import { feedback } from '@h-ai/feedback'\n * import { createFeedbackProcedures } from '@h-ai/serv/features/feedback'\n * const procedures = createFeedbackProcedures({ feedback, resolveContext: ({ session }) => ({ scopeId: 'trusted-tenant', userId: session.userId, permissions: session.permissions }) })\n * ```\n */\nexport function createFeedbackProcedures(deps: FeedbackProcedureDeps) {\n const contextFor = async (context: AuthenticatedServContext) => {\n try {\n const actor = await deps.resolveContext(context)\n if (!actor?.scopeId || actor.userId !== context.session.userId)\n return err(HaiCommonError.FORBIDDEN, servM('serv_errorForbidden', { locale: context.locale }))\n return { success: true as const, data: actor }\n }\n catch {\n return err(HaiCommonError.INTERNAL_ERROR, servM('serv_errorInternal', { locale: context.locale }))\n }\n }\n const router = implement(apiContract.feedback).context<ServContext>()\n return router\n .route('reports.policy')\n .auth()\n .handle(async ({ context }) => {\n const actor = await contextFor(context)\n return actor.success ? ok(deps.feedback.budget) : actor\n })\n .route('reports.submit')\n .auth()\n .handle(async ({ input, context }) => {\n const actor = await contextFor(context)\n if (!actor.success)\n return actor\n return core.context.run(actor.data, () => deps.feedback.submit(input, actor.data))\n })\n .route('reports.list')\n .auth()\n .handle(async ({ input, context }) => {\n const actor = await contextFor(context)\n if (!actor.success)\n return actor\n return core.context.run(actor.data, () => deps.feedback.list(input, actor.data))\n })\n .route('reports.get')\n .auth()\n .handle(async ({ input, context }) => {\n const actor = await contextFor(context)\n if (!actor.success)\n return actor\n return core.context.run(actor.data, () => deps.feedback.get(input.id, actor.data))\n })\n .route('reports.getEvidence')\n .auth()\n .handle(async ({ input, context }) => {\n const actor = await contextFor(context)\n if (!actor.success)\n return actor\n return core.context.run(actor.data, () => deps.feedback.getEvidence(input, actor.data))\n })\n .route('reports.setStatus')\n .auth()\n .handle(async ({ input, context }) => {\n const actor = await contextFor(context)\n if (!actor.success)\n return actor\n return core.context.run(actor.data, () => deps.feedback.setStatus(input, actor.data))\n })\n .route('reports.retry')\n .auth()\n .handle(async ({ input, context }) => {\n const actor = await contextFor(context)\n if (!actor.success)\n return actor\n return core.context.run(actor.data, () => deps.feedback.retry(input, actor.data))\n })\n .route('reports.export')\n .auth()\n .handle(async ({ input, context }) => {\n const actor = await contextFor(context)\n if (!actor.success)\n return actor\n return core.context.run(actor.data, () => deps.feedback.export(input, actor.data))\n })\n .route('reports.getExport')\n .auth()\n .handle(async ({ input, context }) => {\n const actor = await contextFor(context)\n if (!actor.success)\n return actor\n return core.context.run(actor.data, () => deps.feedback.getExport(input, actor.data))\n })\n .route('reports.appendEvidence')\n .auth()\n .handle(async ({ input, context }) => {\n const actor = await contextFor(context)\n if (!actor.success)\n return actor\n return core.context.run(actor.data, () => deps.feedback.appendEvidence(input, actor.data))\n })\n .route('reports.completeCollection')\n .auth()\n .handle(async ({ input, context }) => {\n const actor = await contextFor(context)\n if (!actor.success)\n return actor\n return core.context.run(actor.data, () => deps.feedback.completeCollection(input, actor.data))\n })\n .route('attachments.upload')\n .auth()\n .handle(async ({ input, context }) => {\n const actor = await contextFor(context)\n if (!actor.success)\n return actor\n return core.context.run(actor.data, () => deps.feedback.uploadAttachment(input, actor.data))\n })\n .route('attachments.get')\n .auth()\n .handle(async ({ input, context }) => {\n const actor = await contextFor(context)\n if (!actor.success)\n return actor\n return core.context.run(actor.data, () => deps.feedback.getAttachment(input, actor.data))\n })\n .build()\n}\n"]}
|
package/dist/features/iam.d.ts
CHANGED
|
@@ -102,6 +102,7 @@ declare function createIamProcedures(deps: IamProcedureDeps): {
|
|
|
102
102
|
error: zod.ZodObject<{
|
|
103
103
|
code: zod.ZodUnion<readonly [zod.ZodString, zod.ZodNumber]>;
|
|
104
104
|
message: zod.ZodString;
|
|
105
|
+
traceId: zod.ZodOptional<zod.ZodString>;
|
|
105
106
|
httpStatus: zod.ZodOptional<zod.ZodNumber>;
|
|
106
107
|
system: zod.ZodOptional<zod.ZodString>;
|
|
107
108
|
module: zod.ZodOptional<zod.ZodString>;
|
|
@@ -152,6 +153,7 @@ declare function createIamProcedures(deps: IamProcedureDeps): {
|
|
|
152
153
|
error: zod.ZodObject<{
|
|
153
154
|
code: zod.ZodUnion<readonly [zod.ZodString, zod.ZodNumber]>;
|
|
154
155
|
message: zod.ZodString;
|
|
156
|
+
traceId: zod.ZodOptional<zod.ZodString>;
|
|
155
157
|
httpStatus: zod.ZodOptional<zod.ZodNumber>;
|
|
156
158
|
system: zod.ZodOptional<zod.ZodString>;
|
|
157
159
|
module: zod.ZodOptional<zod.ZodString>;
|
|
@@ -170,6 +172,7 @@ declare function createIamProcedures(deps: IamProcedureDeps): {
|
|
|
170
172
|
error: zod.ZodObject<{
|
|
171
173
|
code: zod.ZodUnion<readonly [zod.ZodString, zod.ZodNumber]>;
|
|
172
174
|
message: zod.ZodString;
|
|
175
|
+
traceId: zod.ZodOptional<zod.ZodString>;
|
|
173
176
|
httpStatus: zod.ZodOptional<zod.ZodNumber>;
|
|
174
177
|
system: zod.ZodOptional<zod.ZodString>;
|
|
175
178
|
module: zod.ZodOptional<zod.ZodString>;
|
|
@@ -189,6 +192,7 @@ declare function createIamProcedures(deps: IamProcedureDeps): {
|
|
|
189
192
|
error: zod.ZodObject<{
|
|
190
193
|
code: zod.ZodUnion<readonly [zod.ZodString, zod.ZodNumber]>;
|
|
191
194
|
message: zod.ZodString;
|
|
195
|
+
traceId: zod.ZodOptional<zod.ZodString>;
|
|
192
196
|
httpStatus: zod.ZodOptional<zod.ZodNumber>;
|
|
193
197
|
system: zod.ZodOptional<zod.ZodString>;
|
|
194
198
|
module: zod.ZodOptional<zod.ZodString>;
|
|
@@ -239,6 +243,7 @@ declare function createIamProcedures(deps: IamProcedureDeps): {
|
|
|
239
243
|
error: zod.ZodObject<{
|
|
240
244
|
code: zod.ZodUnion<readonly [zod.ZodString, zod.ZodNumber]>;
|
|
241
245
|
message: zod.ZodString;
|
|
246
|
+
traceId: zod.ZodOptional<zod.ZodString>;
|
|
242
247
|
httpStatus: zod.ZodOptional<zod.ZodNumber>;
|
|
243
248
|
system: zod.ZodOptional<zod.ZodString>;
|
|
244
249
|
module: zod.ZodOptional<zod.ZodString>;
|
|
@@ -289,6 +294,7 @@ declare function createIamProcedures(deps: IamProcedureDeps): {
|
|
|
289
294
|
error: zod.ZodObject<{
|
|
290
295
|
code: zod.ZodUnion<readonly [zod.ZodString, zod.ZodNumber]>;
|
|
291
296
|
message: zod.ZodString;
|
|
297
|
+
traceId: zod.ZodOptional<zod.ZodString>;
|
|
292
298
|
httpStatus: zod.ZodOptional<zod.ZodNumber>;
|
|
293
299
|
system: zod.ZodOptional<zod.ZodString>;
|
|
294
300
|
module: zod.ZodOptional<zod.ZodString>;
|
|
@@ -307,6 +313,7 @@ declare function createIamProcedures(deps: IamProcedureDeps): {
|
|
|
307
313
|
error: zod.ZodObject<{
|
|
308
314
|
code: zod.ZodUnion<readonly [zod.ZodString, zod.ZodNumber]>;
|
|
309
315
|
message: zod.ZodString;
|
|
316
|
+
traceId: zod.ZodOptional<zod.ZodString>;
|
|
310
317
|
httpStatus: zod.ZodOptional<zod.ZodNumber>;
|
|
311
318
|
system: zod.ZodOptional<zod.ZodString>;
|
|
312
319
|
module: zod.ZodOptional<zod.ZodString>;
|
|
@@ -338,6 +345,7 @@ declare function createIamProcedures(deps: IamProcedureDeps): {
|
|
|
338
345
|
error: zod.ZodObject<{
|
|
339
346
|
code: zod.ZodUnion<readonly [zod.ZodString, zod.ZodNumber]>;
|
|
340
347
|
message: zod.ZodString;
|
|
348
|
+
traceId: zod.ZodOptional<zod.ZodString>;
|
|
341
349
|
httpStatus: zod.ZodOptional<zod.ZodNumber>;
|
|
342
350
|
system: zod.ZodOptional<zod.ZodString>;
|
|
343
351
|
module: zod.ZodOptional<zod.ZodString>;
|
|
@@ -363,6 +371,7 @@ declare function createIamProcedures(deps: IamProcedureDeps): {
|
|
|
363
371
|
error: zod.ZodObject<{
|
|
364
372
|
code: zod.ZodUnion<readonly [zod.ZodString, zod.ZodNumber]>;
|
|
365
373
|
message: zod.ZodString;
|
|
374
|
+
traceId: zod.ZodOptional<zod.ZodString>;
|
|
366
375
|
httpStatus: zod.ZodOptional<zod.ZodNumber>;
|
|
367
376
|
system: zod.ZodOptional<zod.ZodString>;
|
|
368
377
|
module: zod.ZodOptional<zod.ZodString>;
|
|
@@ -383,6 +392,7 @@ declare function createIamProcedures(deps: IamProcedureDeps): {
|
|
|
383
392
|
error: zod.ZodObject<{
|
|
384
393
|
code: zod.ZodUnion<readonly [zod.ZodString, zod.ZodNumber]>;
|
|
385
394
|
message: zod.ZodString;
|
|
395
|
+
traceId: zod.ZodOptional<zod.ZodString>;
|
|
386
396
|
httpStatus: zod.ZodOptional<zod.ZodNumber>;
|
|
387
397
|
system: zod.ZodOptional<zod.ZodString>;
|
|
388
398
|
module: zod.ZodOptional<zod.ZodString>;
|
|
@@ -437,6 +447,7 @@ declare function createIamProcedures(deps: IamProcedureDeps): {
|
|
|
437
447
|
error: zod.ZodObject<{
|
|
438
448
|
code: zod.ZodUnion<readonly [zod.ZodString, zod.ZodNumber]>;
|
|
439
449
|
message: zod.ZodString;
|
|
450
|
+
traceId: zod.ZodOptional<zod.ZodString>;
|
|
440
451
|
httpStatus: zod.ZodOptional<zod.ZodNumber>;
|
|
441
452
|
system: zod.ZodOptional<zod.ZodString>;
|
|
442
453
|
module: zod.ZodOptional<zod.ZodString>;
|
|
@@ -456,6 +467,7 @@ declare function createIamProcedures(deps: IamProcedureDeps): {
|
|
|
456
467
|
error: zod.ZodObject<{
|
|
457
468
|
code: zod.ZodUnion<readonly [zod.ZodString, zod.ZodNumber]>;
|
|
458
469
|
message: zod.ZodString;
|
|
470
|
+
traceId: zod.ZodOptional<zod.ZodString>;
|
|
459
471
|
httpStatus: zod.ZodOptional<zod.ZodNumber>;
|
|
460
472
|
system: zod.ZodOptional<zod.ZodString>;
|
|
461
473
|
module: zod.ZodOptional<zod.ZodString>;
|
|
@@ -492,6 +504,7 @@ declare function createIamProcedures(deps: IamProcedureDeps): {
|
|
|
492
504
|
error: zod.ZodObject<{
|
|
493
505
|
code: zod.ZodUnion<readonly [zod.ZodString, zod.ZodNumber]>;
|
|
494
506
|
message: zod.ZodString;
|
|
507
|
+
traceId: zod.ZodOptional<zod.ZodString>;
|
|
495
508
|
httpStatus: zod.ZodOptional<zod.ZodNumber>;
|
|
496
509
|
system: zod.ZodOptional<zod.ZodString>;
|
|
497
510
|
module: zod.ZodOptional<zod.ZodString>;
|
|
@@ -537,6 +550,7 @@ declare function createIamProcedures(deps: IamProcedureDeps): {
|
|
|
537
550
|
error: zod.ZodObject<{
|
|
538
551
|
code: zod.ZodUnion<readonly [zod.ZodString, zod.ZodNumber]>;
|
|
539
552
|
message: zod.ZodString;
|
|
553
|
+
traceId: zod.ZodOptional<zod.ZodString>;
|
|
540
554
|
httpStatus: zod.ZodOptional<zod.ZodNumber>;
|
|
541
555
|
system: zod.ZodOptional<zod.ZodString>;
|
|
542
556
|
module: zod.ZodOptional<zod.ZodString>;
|
|
@@ -568,6 +582,7 @@ declare function createIamProcedures(deps: IamProcedureDeps): {
|
|
|
568
582
|
error: zod.ZodObject<{
|
|
569
583
|
code: zod.ZodUnion<readonly [zod.ZodString, zod.ZodNumber]>;
|
|
570
584
|
message: zod.ZodString;
|
|
585
|
+
traceId: zod.ZodOptional<zod.ZodString>;
|
|
571
586
|
httpStatus: zod.ZodOptional<zod.ZodNumber>;
|
|
572
587
|
system: zod.ZodOptional<zod.ZodString>;
|
|
573
588
|
module: zod.ZodOptional<zod.ZodString>;
|
|
@@ -606,6 +621,7 @@ declare function createIamProcedures(deps: IamProcedureDeps): {
|
|
|
606
621
|
error: zod.ZodObject<{
|
|
607
622
|
code: zod.ZodUnion<readonly [zod.ZodString, zod.ZodNumber]>;
|
|
608
623
|
message: zod.ZodString;
|
|
624
|
+
traceId: zod.ZodOptional<zod.ZodString>;
|
|
609
625
|
httpStatus: zod.ZodOptional<zod.ZodNumber>;
|
|
610
626
|
system: zod.ZodOptional<zod.ZodString>;
|
|
611
627
|
module: zod.ZodOptional<zod.ZodString>;
|
|
@@ -645,6 +661,7 @@ declare function createIamProcedures(deps: IamProcedureDeps): {
|
|
|
645
661
|
error: zod.ZodObject<{
|
|
646
662
|
code: zod.ZodUnion<readonly [zod.ZodString, zod.ZodNumber]>;
|
|
647
663
|
message: zod.ZodString;
|
|
664
|
+
traceId: zod.ZodOptional<zod.ZodString>;
|
|
648
665
|
httpStatus: zod.ZodOptional<zod.ZodNumber>;
|
|
649
666
|
system: zod.ZodOptional<zod.ZodString>;
|
|
650
667
|
module: zod.ZodOptional<zod.ZodString>;
|
|
@@ -663,6 +680,7 @@ declare function createIamProcedures(deps: IamProcedureDeps): {
|
|
|
663
680
|
error: zod.ZodObject<{
|
|
664
681
|
code: zod.ZodUnion<readonly [zod.ZodString, zod.ZodNumber]>;
|
|
665
682
|
message: zod.ZodString;
|
|
683
|
+
traceId: zod.ZodOptional<zod.ZodString>;
|
|
666
684
|
httpStatus: zod.ZodOptional<zod.ZodNumber>;
|
|
667
685
|
system: zod.ZodOptional<zod.ZodString>;
|
|
668
686
|
module: zod.ZodOptional<zod.ZodString>;
|
|
@@ -682,6 +700,7 @@ declare function createIamProcedures(deps: IamProcedureDeps): {
|
|
|
682
700
|
error: zod.ZodObject<{
|
|
683
701
|
code: zod.ZodUnion<readonly [zod.ZodString, zod.ZodNumber]>;
|
|
684
702
|
message: zod.ZodString;
|
|
703
|
+
traceId: zod.ZodOptional<zod.ZodString>;
|
|
685
704
|
httpStatus: zod.ZodOptional<zod.ZodNumber>;
|
|
686
705
|
system: zod.ZodOptional<zod.ZodString>;
|
|
687
706
|
module: zod.ZodOptional<zod.ZodString>;
|
|
@@ -713,6 +732,7 @@ declare function createIamProcedures(deps: IamProcedureDeps): {
|
|
|
713
732
|
error: zod.ZodObject<{
|
|
714
733
|
code: zod.ZodUnion<readonly [zod.ZodString, zod.ZodNumber]>;
|
|
715
734
|
message: zod.ZodString;
|
|
735
|
+
traceId: zod.ZodOptional<zod.ZodString>;
|
|
716
736
|
httpStatus: zod.ZodOptional<zod.ZodNumber>;
|
|
717
737
|
system: zod.ZodOptional<zod.ZodString>;
|
|
718
738
|
module: zod.ZodOptional<zod.ZodString>;
|
|
@@ -739,6 +759,7 @@ declare function createIamProcedures(deps: IamProcedureDeps): {
|
|
|
739
759
|
error: zod.ZodObject<{
|
|
740
760
|
code: zod.ZodUnion<readonly [zod.ZodString, zod.ZodNumber]>;
|
|
741
761
|
message: zod.ZodString;
|
|
762
|
+
traceId: zod.ZodOptional<zod.ZodString>;
|
|
742
763
|
httpStatus: zod.ZodOptional<zod.ZodNumber>;
|
|
743
764
|
system: zod.ZodOptional<zod.ZodString>;
|
|
744
765
|
module: zod.ZodOptional<zod.ZodString>;
|
|
@@ -768,6 +789,7 @@ declare function createIamProcedures(deps: IamProcedureDeps): {
|
|
|
768
789
|
error: zod.ZodObject<{
|
|
769
790
|
code: zod.ZodUnion<readonly [zod.ZodString, zod.ZodNumber]>;
|
|
770
791
|
message: zod.ZodString;
|
|
792
|
+
traceId: zod.ZodOptional<zod.ZodString>;
|
|
771
793
|
httpStatus: zod.ZodOptional<zod.ZodNumber>;
|
|
772
794
|
system: zod.ZodOptional<zod.ZodString>;
|
|
773
795
|
module: zod.ZodOptional<zod.ZodString>;
|
|
@@ -796,6 +818,7 @@ declare function createIamProcedures(deps: IamProcedureDeps): {
|
|
|
796
818
|
error: zod.ZodObject<{
|
|
797
819
|
code: zod.ZodUnion<readonly [zod.ZodString, zod.ZodNumber]>;
|
|
798
820
|
message: zod.ZodString;
|
|
821
|
+
traceId: zod.ZodOptional<zod.ZodString>;
|
|
799
822
|
httpStatus: zod.ZodOptional<zod.ZodNumber>;
|
|
800
823
|
system: zod.ZodOptional<zod.ZodString>;
|
|
801
824
|
module: zod.ZodOptional<zod.ZodString>;
|
|
@@ -814,6 +837,7 @@ declare function createIamProcedures(deps: IamProcedureDeps): {
|
|
|
814
837
|
error: zod.ZodObject<{
|
|
815
838
|
code: zod.ZodUnion<readonly [zod.ZodString, zod.ZodNumber]>;
|
|
816
839
|
message: zod.ZodString;
|
|
840
|
+
traceId: zod.ZodOptional<zod.ZodString>;
|
|
817
841
|
httpStatus: zod.ZodOptional<zod.ZodNumber>;
|
|
818
842
|
system: zod.ZodOptional<zod.ZodString>;
|
|
819
843
|
module: zod.ZodOptional<zod.ZodString>;
|
|
@@ -860,6 +884,7 @@ declare function createIamProcedures(deps: IamProcedureDeps): {
|
|
|
860
884
|
error: zod.ZodObject<{
|
|
861
885
|
code: zod.ZodUnion<readonly [zod.ZodString, zod.ZodNumber]>;
|
|
862
886
|
message: zod.ZodString;
|
|
887
|
+
traceId: zod.ZodOptional<zod.ZodString>;
|
|
863
888
|
httpStatus: zod.ZodOptional<zod.ZodNumber>;
|
|
864
889
|
system: zod.ZodOptional<zod.ZodString>;
|
|
865
890
|
module: zod.ZodOptional<zod.ZodString>;
|
|
@@ -892,6 +917,7 @@ declare function createIamProcedures(deps: IamProcedureDeps): {
|
|
|
892
917
|
error: zod.ZodObject<{
|
|
893
918
|
code: zod.ZodUnion<readonly [zod.ZodString, zod.ZodNumber]>;
|
|
894
919
|
message: zod.ZodString;
|
|
920
|
+
traceId: zod.ZodOptional<zod.ZodString>;
|
|
895
921
|
httpStatus: zod.ZodOptional<zod.ZodNumber>;
|
|
896
922
|
system: zod.ZodOptional<zod.ZodString>;
|
|
897
923
|
module: zod.ZodOptional<zod.ZodString>;
|
|
@@ -933,6 +959,7 @@ declare function createIamProcedures(deps: IamProcedureDeps): {
|
|
|
933
959
|
error: zod.ZodObject<{
|
|
934
960
|
code: zod.ZodUnion<readonly [zod.ZodString, zod.ZodNumber]>;
|
|
935
961
|
message: zod.ZodString;
|
|
962
|
+
traceId: zod.ZodOptional<zod.ZodString>;
|
|
936
963
|
httpStatus: zod.ZodOptional<zod.ZodNumber>;
|
|
937
964
|
system: zod.ZodOptional<zod.ZodString>;
|
|
938
965
|
module: zod.ZodOptional<zod.ZodString>;
|
|
@@ -951,6 +978,7 @@ declare function createIamProcedures(deps: IamProcedureDeps): {
|
|
|
951
978
|
error: zod.ZodObject<{
|
|
952
979
|
code: zod.ZodUnion<readonly [zod.ZodString, zod.ZodNumber]>;
|
|
953
980
|
message: zod.ZodString;
|
|
981
|
+
traceId: zod.ZodOptional<zod.ZodString>;
|
|
954
982
|
httpStatus: zod.ZodOptional<zod.ZodNumber>;
|
|
955
983
|
system: zod.ZodOptional<zod.ZodString>;
|
|
956
984
|
module: zod.ZodOptional<zod.ZodString>;
|
package/dist/features/iam.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { mapHaiResult } from '../chunk-XKCLD42I.js';
|
|
2
|
-
import { implement, servM } from '../chunk-
|
|
2
|
+
import { implement, servM } from '../chunk-KR4H56KP.js';
|
|
3
3
|
import { apiContract } from '@h-ai/api-contract';
|
|
4
4
|
import { core, ok, err, HaiCommonError } from '@h-ai/core';
|
|
5
5
|
|
|
@@ -87,6 +87,7 @@ declare function createStorageProcedures(deps: StorageProcedureDeps): {
|
|
|
87
87
|
error: zod.ZodObject<{
|
|
88
88
|
code: zod.ZodUnion<readonly [zod.ZodString, zod.ZodNumber]>;
|
|
89
89
|
message: zod.ZodString;
|
|
90
|
+
traceId: zod.ZodOptional<zod.ZodString>;
|
|
90
91
|
httpStatus: zod.ZodOptional<zod.ZodNumber>;
|
|
91
92
|
system: zod.ZodOptional<zod.ZodString>;
|
|
92
93
|
module: zod.ZodOptional<zod.ZodString>;
|
|
@@ -111,6 +112,7 @@ declare function createStorageProcedures(deps: StorageProcedureDeps): {
|
|
|
111
112
|
error: zod.ZodObject<{
|
|
112
113
|
code: zod.ZodUnion<readonly [zod.ZodString, zod.ZodNumber]>;
|
|
113
114
|
message: zod.ZodString;
|
|
115
|
+
traceId: zod.ZodOptional<zod.ZodString>;
|
|
114
116
|
httpStatus: zod.ZodOptional<zod.ZodNumber>;
|
|
115
117
|
system: zod.ZodOptional<zod.ZodString>;
|
|
116
118
|
module: zod.ZodOptional<zod.ZodString>;
|
|
@@ -146,6 +148,7 @@ declare function createStorageProcedures(deps: StorageProcedureDeps): {
|
|
|
146
148
|
error: zod.ZodObject<{
|
|
147
149
|
code: zod.ZodUnion<readonly [zod.ZodString, zod.ZodNumber]>;
|
|
148
150
|
message: zod.ZodString;
|
|
151
|
+
traceId: zod.ZodOptional<zod.ZodString>;
|
|
149
152
|
httpStatus: zod.ZodOptional<zod.ZodNumber>;
|
|
150
153
|
system: zod.ZodOptional<zod.ZodString>;
|
|
151
154
|
module: zod.ZodOptional<zod.ZodString>;
|
|
@@ -171,6 +174,7 @@ declare function createStorageProcedures(deps: StorageProcedureDeps): {
|
|
|
171
174
|
error: zod.ZodObject<{
|
|
172
175
|
code: zod.ZodUnion<readonly [zod.ZodString, zod.ZodNumber]>;
|
|
173
176
|
message: zod.ZodString;
|
|
177
|
+
traceId: zod.ZodOptional<zod.ZodString>;
|
|
174
178
|
httpStatus: zod.ZodOptional<zod.ZodNumber>;
|
|
175
179
|
system: zod.ZodOptional<zod.ZodString>;
|
|
176
180
|
module: zod.ZodOptional<zod.ZodString>;
|
|
@@ -189,6 +193,7 @@ declare function createStorageProcedures(deps: StorageProcedureDeps): {
|
|
|
189
193
|
error: zod.ZodObject<{
|
|
190
194
|
code: zod.ZodUnion<readonly [zod.ZodString, zod.ZodNumber]>;
|
|
191
195
|
message: zod.ZodString;
|
|
196
|
+
traceId: zod.ZodOptional<zod.ZodString>;
|
|
192
197
|
httpStatus: zod.ZodOptional<zod.ZodNumber>;
|
|
193
198
|
system: zod.ZodOptional<zod.ZodString>;
|
|
194
199
|
module: zod.ZodOptional<zod.ZodString>;
|
|
@@ -219,6 +224,7 @@ declare function createStorageProcedures(deps: StorageProcedureDeps): {
|
|
|
219
224
|
error: zod.ZodObject<{
|
|
220
225
|
code: zod.ZodUnion<readonly [zod.ZodString, zod.ZodNumber]>;
|
|
221
226
|
message: zod.ZodString;
|
|
227
|
+
traceId: zod.ZodOptional<zod.ZodString>;
|
|
222
228
|
httpStatus: zod.ZodOptional<zod.ZodNumber>;
|
|
223
229
|
system: zod.ZodOptional<zod.ZodString>;
|
|
224
230
|
module: zod.ZodOptional<zod.ZodString>;
|
package/dist/features/storage.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { validateInputOrFail } from '../chunk-
|
|
1
|
+
import { validateInputOrFail } from '../chunk-WW25756Z.js';
|
|
2
2
|
import { mapHaiResult } from '../chunk-XKCLD42I.js';
|
|
3
|
-
import { implement, servM } from '../chunk-
|
|
4
|
-
import { apiContract } from '@h-ai/api-contract';
|
|
3
|
+
import { implement, servM } from '../chunk-KR4H56KP.js';
|
|
4
|
+
import { apiContract, StorageDeleteSummarySchema } from '@h-ai/api-contract';
|
|
5
5
|
import { err, HaiCommonError, ok } from '@h-ai/core';
|
|
6
6
|
import { getStorageKeyIssue, StorageDeleteKeysSchema, STORAGE_KEY_MAX_BYTES } from '@h-ai/storage/schemas';
|
|
7
7
|
|
|
@@ -109,7 +109,11 @@ function createStorageProcedures(deps) {
|
|
|
109
109
|
const access = await authorize({ context, operation: "deleteMany", keys: keysResult.data });
|
|
110
110
|
if (!access.success)
|
|
111
111
|
return access;
|
|
112
|
-
|
|
112
|
+
const result = await storage.file.deleteMany(keysResult.data);
|
|
113
|
+
if (result.success)
|
|
114
|
+
return result;
|
|
115
|
+
const progress = StorageDeleteSummarySchema.safeParse(result.error.ext?.deleteMany);
|
|
116
|
+
return err({ ...result.error, publicExt: progress.success ? { deleteMany: progress.data } : void 0 });
|
|
113
117
|
}).build();
|
|
114
118
|
}
|
|
115
119
|
function toPresignedResult(key, expiresIn, result) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/features/serv-feature-storage.ts"],"names":[],"mappings":"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","file":"storage.js","sourcesContent":["/**\n * @h-ai/serv — Storage 默认 procedures\n *\n * 基于 `@h-ai/storage` 提供开箱即用的 Storage procedures 实现:预签名 URL、列表、元数据、删除。\n *\n * 所有操作先验证路径,再调用应用提供的资源授权策略;未提供策略时拒绝访问。\n * 策略必须从已认证 session 确定用户/租户范围,不能信任客户端提供的前缀。\n * @module features/serv-feature-storage\n */\n\nimport type { HaiResult } from '@h-ai/core'\nimport type { StorageFunctions } from '@h-ai/storage'\nimport type { ServContext } from '../serv-context.js'\nimport type { ServMessageKey } from '../serv-i18n.js'\nimport type { AuthenticatedServContext } from '../serv-router.js'\nimport { apiContract } from '@h-ai/api-contract'\nimport { err, HaiCommonError, ok } from '@h-ai/core'\nimport { getStorageKeyIssue, STORAGE_KEY_MAX_BYTES, StorageDeleteKeysSchema } from '@h-ai/storage/schemas'\nimport { servM } from '../serv-i18n.js'\nimport { implement } from '../serv-router.js'\nimport { validateInputOrFail } from '../serv-validation.js'\nimport { mapHaiResult } from './serv-feature-helpers.js'\n\nconst storageContract = apiContract.storage\n\nfunction buildStorageKeyValidationFailure(\n field: string,\n locale: string,\n messageKey: ServMessageKey,\n params?: Record<string, string | number>,\n): HaiResult<never> {\n const message = servM(messageKey, { locale, params })\n return err(\n HaiCommonError.VALIDATION_ERROR,\n servM('serv_validationFailed', { locale }),\n [{ field, message }],\n )\n}\n\n/**\n * 对业务层再次校验存储 key 是否安全。\n *\n * 与公开 Schema 共用规则,保留业务入口防线;后续仍必须执行授权和 Provider 防逃逸。\n */\nfunction validateStorageKeyOrFail(key: string, locale: string, field: string = 'key'): HaiResult<string> {\n const issue = getStorageKeyIssue(key)\n if (issue === 'empty')\n return buildStorageKeyValidationFailure(field, locale, 'serv_storageKeyRequired')\n if (issue === 'tooLong') {\n return buildStorageKeyValidationFailure(field, locale, 'serv_storageKeyTooLong', {\n max: STORAGE_KEY_MAX_BYTES,\n })\n }\n if (issue === 'characters')\n return buildStorageKeyValidationFailure(field, locale, 'serv_storageKeyIllegalChars')\n if (issue === 'segments')\n return buildStorageKeyValidationFailure(field, locale, 'serv_storageKeyDotSegments')\n return ok(key)\n}\n\nfunction validateStorageKeysOrFail(keys: string[], locale: string): HaiResult<string[]> {\n const parsed = validateInputOrFail(StorageDeleteKeysSchema, keys, locale)\n if (!parsed.success)\n return parsed\n for (const [index, key] of keys.entries()) {\n const keyResult = validateStorageKeyOrFail(key, locale, `keys.${index}`)\n if (!keyResult.success)\n return keyResult\n }\n return ok(keys)\n}\n\n/**\n * 存储资源授权请求;批量操作只有全部资源获准后才会调用存储。\n *\n * @example\n * ```ts\n * import { storage } from '@h-ai/storage'\n * import { createStorageProcedures } from '@h-ai/serv/features/storage'\n *\n * // 宿主已初始化 Storage;用户根目录来自可信 session,含尾斜杠形成边界。\n * const procedures = createStorageProcedures({ storage, authorize: ({ context, keys }) => {\n * const root = `users/${encodeURIComponent(context.session.userId)}/`\n * return keys.length > 0 && keys.every(key => key.startsWith(root))\n * } })\n * // 空列表前缀与相邻用户名前缀均不能匹配此根目录。\n * ```\n */\nexport interface StorageAccessRequest {\n /** 操作类别;策略可分别授予读取、写入或删除权限。 */\n readonly operation: 'download' | 'upload' | 'list' | 'metadata' | 'delete' | 'deleteMany'\n /** 已通过认证的可信请求上下文。 */\n readonly context: AuthenticatedServContext\n /** 单项/批量 key;list 操作仅包含请求的 prefix,未提供 prefix 时为空字符串。 */\n readonly keys: readonly string[]\n}\n\n/**\n * Storage 默认 procedures 依赖。\n *\n * @example\n * ```ts\n * import { storage } from '@h-ai/storage'\n * import { createStorageProcedures } from '@h-ai/serv/features/storage'\n *\n * // 宿主已初始化 Storage;用户根目录来自可信 session,含尾斜杠形成边界。\n * const procedures = createStorageProcedures({ storage, authorize: ({ context, keys }) => {\n * const root = `users/${encodeURIComponent(context.session.userId)}/`\n * return keys.length > 0 && keys.every(key => key.startsWith(root))\n * } })\n * // 空列表前缀与相邻用户名前缀均不能匹配此根目录。\n * ```\n */\nexport interface StorageProcedureDeps {\n readonly storage: StorageFunctions\n /** 必需的资源授权策略;返回 true 才允许执行,缺失策略时默认拒绝。 */\n readonly authorize: (request: StorageAccessRequest) => boolean | Promise<boolean>\n}\n\n/**\n * 内部预签名结果投影,包含短期访问 URL 和可选失效时间。\n *\n * @example\n * ```ts\n * // 模块内部上下文:示例复用当前声明所在模块的实际绑定。\n * function safeUrl(value: PresignedResponse) {\n * return { url: value.url, key: value.key, expiresAt: value.expiresAt }\n * }\n * // URL 是授权后的短期凭据;只返回给已授权调用方,不记录到日志。\n * ```\n */\ninterface PresignedResponse {\n readonly url: string\n readonly key: string\n readonly expiresAt?: Date\n}\n\n/**\n * 创建具有认证、路径校验和资源授权的 Storage procedures。\n *\n * @param deps - 存储服务及必需的资源授权策略。\n * @returns 可挂载至 serv.createApp 的存储 router;拒绝访问返回 FORBIDDEN。\n *\n * @example\n * ```ts\n * import { storage } from '@h-ai/storage'\n * import { createStorageProcedures } from '@h-ai/serv/features/storage'\n *\n * // 宿主已初始化 Storage;用户根目录来自可信 session,含尾斜杠形成边界。\n * const procedures = createStorageProcedures({ storage, authorize: ({ context, keys }) => {\n * const root = `users/${encodeURIComponent(context.session.userId)}/`\n * return keys.length > 0 && keys.every(key => key.startsWith(root))\n * } })\n * // 空列表前缀与相邻用户名前缀均不能匹配此根目录。\n * ```\n */\nexport function createStorageProcedures(deps: StorageProcedureDeps) {\n const { storage } = deps\n\n async function authorize(request: StorageAccessRequest): Promise<HaiResult<void>> {\n if (typeof deps.authorize !== 'function' || await deps.authorize(request) !== true)\n return err(HaiCommonError.FORBIDDEN, servM('serv_errorForbidden', { locale: request.context.locale }))\n return ok(undefined)\n }\n\n return implement(storageContract)\n .context<ServContext>()\n\n .route('presignedUrls.createDownload')\n .auth()\n .handle(async ({ input, context }) => {\n const keyResult = validateStorageKeyOrFail(input.key, context.locale)\n if (!keyResult.success)\n return keyResult\n const access = await authorize({ context, operation: 'download', keys: [keyResult.data] })\n if (!access.success)\n return access\n const expiresIn = input.expiresIn ?? 900\n return toPresignedResult(\n keyResult.data,\n expiresIn,\n await storage.presign.getUrl(keyResult.data, { expiresIn }),\n )\n })\n\n .route('presignedUrls.createUpload')\n .auth()\n .handle(async ({ input, context }) => {\n const keyResult = validateStorageKeyOrFail(input.key, context.locale)\n if (!keyResult.success)\n return keyResult\n const access = await authorize({ context, operation: 'upload', keys: [keyResult.data] })\n if (!access.success)\n return access\n const expiresIn = input.expiresIn ?? 900\n const contentType = input.contentType ?? 'application/octet-stream'\n const { key: _, ...options } = input\n return toPresignedResult(\n keyResult.data,\n expiresIn,\n await storage.presign.putUrl(keyResult.data, { ...options, expiresIn, contentType }),\n )\n })\n\n .route('files.list')\n .auth()\n .handle(async ({ input, context }) => {\n const prefix = input.prefix ?? ''\n if (prefix) {\n const prefixResult = validateStorageKeyOrFail(prefix, context.locale, 'prefix')\n if (!prefixResult.success)\n return prefixResult\n }\n const access = await authorize({ context, operation: 'list', keys: [prefix] })\n if (!access.success)\n return access\n return storage.dir.list(input)\n })\n\n .route('files.getMetadata')\n .auth()\n .handle(async ({ input, context }) => {\n const keyResult = validateStorageKeyOrFail(input.key, context.locale)\n if (!keyResult.success)\n return keyResult\n const access = await authorize({ context, operation: 'metadata', keys: [keyResult.data] })\n if (!access.success)\n return access\n return storage.file.head(keyResult.data)\n })\n\n .route('files.delete')\n .auth()\n .handle(async ({ input, context }) => {\n const keyResult = validateStorageKeyOrFail(input.key, context.locale)\n if (!keyResult.success)\n return keyResult\n const access = await authorize({ context, operation: 'delete', keys: [keyResult.data] })\n if (!access.success)\n return access\n return storage.file.delete(keyResult.data)\n })\n\n .route('files.deleteMany')\n .auth()\n .handle(async ({ input, context }) => {\n const keysResult = validateStorageKeysOrFail(input.keys, context.locale)\n if (!keysResult.success)\n return keysResult\n const access = await authorize({ context, operation: 'deleteMany', keys: keysResult.data })\n if (!access.success)\n return access\n return storage.file.deleteMany(keysResult.data)\n })\n\n .build()\n}\n\nfunction toPresignedResult(\n key: string,\n expiresIn: number | undefined,\n result: HaiResult<string>,\n): HaiResult<PresignedResponse> {\n return mapHaiResult(result, url => ({\n url,\n key,\n expiresAt: expiresIn ? new Date(Date.now() + expiresIn * 1000) : undefined,\n }))\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/features/serv-feature-storage.ts"],"names":[],"mappings":"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","file":"storage.js","sourcesContent":["/**\n * @h-ai/serv — Storage 默认 procedures\n *\n * 基于 `@h-ai/storage` 提供开箱即用的 Storage procedures 实现:预签名 URL、列表、元数据、删除。\n *\n * 所有操作先验证路径,再调用应用提供的资源授权策略;未提供策略时拒绝访问。\n * 策略必须从已认证 session 确定用户/租户范围,不能信任客户端提供的前缀。\n * @module features/serv-feature-storage\n */\n\nimport type { HaiResult } from '@h-ai/core'\nimport type { StorageFunctions } from '@h-ai/storage'\nimport type { ServContext } from '../serv-context.js'\nimport type { ServMessageKey } from '../serv-i18n.js'\nimport type { AuthenticatedServContext } from '../serv-router.js'\nimport { apiContract, StorageDeleteSummarySchema } from '@h-ai/api-contract'\nimport { err, HaiCommonError, ok } from '@h-ai/core'\nimport { getStorageKeyIssue, STORAGE_KEY_MAX_BYTES, StorageDeleteKeysSchema } from '@h-ai/storage/schemas'\nimport { servM } from '../serv-i18n.js'\nimport { implement } from '../serv-router.js'\nimport { validateInputOrFail } from '../serv-validation.js'\nimport { mapHaiResult } from './serv-feature-helpers.js'\n\nconst storageContract = apiContract.storage\n\nfunction buildStorageKeyValidationFailure(\n field: string,\n locale: string,\n messageKey: ServMessageKey,\n params?: Record<string, string | number>,\n): HaiResult<never> {\n const message = servM(messageKey, { locale, params })\n return err(\n HaiCommonError.VALIDATION_ERROR,\n servM('serv_validationFailed', { locale }),\n [{ field, message }],\n )\n}\n\n/**\n * 对业务层再次校验存储 key 是否安全。\n *\n * 与公开 Schema 共用规则,保留业务入口防线;后续仍必须执行授权和 Provider 防逃逸。\n */\nfunction validateStorageKeyOrFail(key: string, locale: string, field: string = 'key'): HaiResult<string> {\n const issue = getStorageKeyIssue(key)\n if (issue === 'empty')\n return buildStorageKeyValidationFailure(field, locale, 'serv_storageKeyRequired')\n if (issue === 'tooLong') {\n return buildStorageKeyValidationFailure(field, locale, 'serv_storageKeyTooLong', {\n max: STORAGE_KEY_MAX_BYTES,\n })\n }\n if (issue === 'characters')\n return buildStorageKeyValidationFailure(field, locale, 'serv_storageKeyIllegalChars')\n if (issue === 'segments')\n return buildStorageKeyValidationFailure(field, locale, 'serv_storageKeyDotSegments')\n return ok(key)\n}\n\nfunction validateStorageKeysOrFail(keys: string[], locale: string): HaiResult<string[]> {\n const parsed = validateInputOrFail(StorageDeleteKeysSchema, keys, locale)\n if (!parsed.success)\n return parsed\n for (const [index, key] of keys.entries()) {\n const keyResult = validateStorageKeyOrFail(key, locale, `keys.${index}`)\n if (!keyResult.success)\n return keyResult\n }\n return ok(keys)\n}\n\n/**\n * 存储资源授权请求;批量操作只有全部资源获准后才会调用存储。\n *\n * @example\n * ```ts\n * import { storage } from '@h-ai/storage'\n * import { createStorageProcedures } from '@h-ai/serv/features/storage'\n *\n * // 宿主已初始化 Storage;用户根目录来自可信 session,含尾斜杠形成边界。\n * const procedures = createStorageProcedures({ storage, authorize: ({ context, keys }) => {\n * const root = `users/${encodeURIComponent(context.session.userId)}/`\n * return keys.length > 0 && keys.every(key => key.startsWith(root))\n * } })\n * // 空列表前缀与相邻用户名前缀均不能匹配此根目录。\n * ```\n */\nexport interface StorageAccessRequest {\n /** 操作类别;策略可分别授予读取、写入或删除权限。 */\n readonly operation: 'download' | 'upload' | 'list' | 'metadata' | 'delete' | 'deleteMany'\n /** 已通过认证的可信请求上下文。 */\n readonly context: AuthenticatedServContext\n /** 单项/批量 key;list 操作仅包含请求的 prefix,未提供 prefix 时为空字符串。 */\n readonly keys: readonly string[]\n}\n\n/**\n * Storage 默认 procedures 依赖。\n *\n * @example\n * ```ts\n * import { storage } from '@h-ai/storage'\n * import { createStorageProcedures } from '@h-ai/serv/features/storage'\n *\n * // 宿主已初始化 Storage;用户根目录来自可信 session,含尾斜杠形成边界。\n * const procedures = createStorageProcedures({ storage, authorize: ({ context, keys }) => {\n * const root = `users/${encodeURIComponent(context.session.userId)}/`\n * return keys.length > 0 && keys.every(key => key.startsWith(root))\n * } })\n * // 空列表前缀与相邻用户名前缀均不能匹配此根目录。\n * ```\n */\nexport interface StorageProcedureDeps {\n readonly storage: StorageFunctions\n /** 必需的资源授权策略;返回 true 才允许执行,缺失策略时默认拒绝。 */\n readonly authorize: (request: StorageAccessRequest) => boolean | Promise<boolean>\n}\n\n/**\n * 内部预签名结果投影,包含短期访问 URL 和可选失效时间。\n *\n * @example\n * ```ts\n * // 模块内部上下文:示例复用当前声明所在模块的实际绑定。\n * function safeUrl(value: PresignedResponse) {\n * return { url: value.url, key: value.key, expiresAt: value.expiresAt }\n * }\n * // URL 是授权后的短期凭据;只返回给已授权调用方,不记录到日志。\n * ```\n */\ninterface PresignedResponse {\n readonly url: string\n readonly key: string\n readonly expiresAt?: Date\n}\n\n/**\n * 创建具有认证、路径校验和资源授权的 Storage procedures。\n *\n * @param deps - 存储服务及必需的资源授权策略。\n * @returns 可挂载至 serv.createApp 的存储 router;拒绝访问返回 FORBIDDEN。\n *\n * @example\n * ```ts\n * import { storage } from '@h-ai/storage'\n * import { createStorageProcedures } from '@h-ai/serv/features/storage'\n *\n * // 宿主已初始化 Storage;用户根目录来自可信 session,含尾斜杠形成边界。\n * const procedures = createStorageProcedures({ storage, authorize: ({ context, keys }) => {\n * const root = `users/${encodeURIComponent(context.session.userId)}/`\n * return keys.length > 0 && keys.every(key => key.startsWith(root))\n * } })\n * // 空列表前缀与相邻用户名前缀均不能匹配此根目录。\n * ```\n */\nexport function createStorageProcedures(deps: StorageProcedureDeps) {\n const { storage } = deps\n\n async function authorize(request: StorageAccessRequest): Promise<HaiResult<void>> {\n if (typeof deps.authorize !== 'function' || await deps.authorize(request) !== true)\n return err(HaiCommonError.FORBIDDEN, servM('serv_errorForbidden', { locale: request.context.locale }))\n return ok(undefined)\n }\n\n return implement(storageContract)\n .context<ServContext>()\n\n .route('presignedUrls.createDownload')\n .auth()\n .handle(async ({ input, context }) => {\n const keyResult = validateStorageKeyOrFail(input.key, context.locale)\n if (!keyResult.success)\n return keyResult\n const access = await authorize({ context, operation: 'download', keys: [keyResult.data] })\n if (!access.success)\n return access\n const expiresIn = input.expiresIn ?? 900\n return toPresignedResult(\n keyResult.data,\n expiresIn,\n await storage.presign.getUrl(keyResult.data, { expiresIn }),\n )\n })\n\n .route('presignedUrls.createUpload')\n .auth()\n .handle(async ({ input, context }) => {\n const keyResult = validateStorageKeyOrFail(input.key, context.locale)\n if (!keyResult.success)\n return keyResult\n const access = await authorize({ context, operation: 'upload', keys: [keyResult.data] })\n if (!access.success)\n return access\n const expiresIn = input.expiresIn ?? 900\n const contentType = input.contentType ?? 'application/octet-stream'\n const { key: _, ...options } = input\n return toPresignedResult(\n keyResult.data,\n expiresIn,\n await storage.presign.putUrl(keyResult.data, { ...options, expiresIn, contentType }),\n )\n })\n\n .route('files.list')\n .auth()\n .handle(async ({ input, context }) => {\n const prefix = input.prefix ?? ''\n if (prefix) {\n const prefixResult = validateStorageKeyOrFail(prefix, context.locale, 'prefix')\n if (!prefixResult.success)\n return prefixResult\n }\n const access = await authorize({ context, operation: 'list', keys: [prefix] })\n if (!access.success)\n return access\n return storage.dir.list(input)\n })\n\n .route('files.getMetadata')\n .auth()\n .handle(async ({ input, context }) => {\n const keyResult = validateStorageKeyOrFail(input.key, context.locale)\n if (!keyResult.success)\n return keyResult\n const access = await authorize({ context, operation: 'metadata', keys: [keyResult.data] })\n if (!access.success)\n return access\n return storage.file.head(keyResult.data)\n })\n\n .route('files.delete')\n .auth()\n .handle(async ({ input, context }) => {\n const keyResult = validateStorageKeyOrFail(input.key, context.locale)\n if (!keyResult.success)\n return keyResult\n const access = await authorize({ context, operation: 'delete', keys: [keyResult.data] })\n if (!access.success)\n return access\n return storage.file.delete(keyResult.data)\n })\n\n .route('files.deleteMany')\n .auth()\n .handle(async ({ input, context }) => {\n const keysResult = validateStorageKeysOrFail(input.keys, context.locale)\n if (!keysResult.success)\n return keysResult\n const access = await authorize({ context, operation: 'deleteMany', keys: keysResult.data })\n if (!access.success)\n return access\n const result = await storage.file.deleteMany(keysResult.data)\n if (result.success)\n return result\n const progress = StorageDeleteSummarySchema.safeParse(result.error.ext?.deleteMany)\n return err({ ...result.error, publicExt: progress.success ? { deleteMany: progress.data } : undefined })\n })\n\n .build()\n}\n\nfunction toPresignedResult(\n key: string,\n expiresIn: number | undefined,\n result: HaiResult<string>,\n): HaiResult<PresignedResponse> {\n return mapHaiResult(result, url => ({\n url,\n key,\n expiresAt: expiresIn ? new Date(Date.now() + expiresIn * 1000) : undefined,\n }))\n}\n"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -1224,6 +1224,7 @@ interface ServValidationFailureBody {
|
|
|
1224
1224
|
readonly error: {
|
|
1225
1225
|
readonly code: string | number;
|
|
1226
1226
|
readonly message: string;
|
|
1227
|
+
readonly traceId?: string;
|
|
1227
1228
|
readonly httpStatus: number;
|
|
1228
1229
|
readonly system: string;
|
|
1229
1230
|
readonly module: string;
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { validateInputOrFail, resolveRequestLocale, localizeZodError } from './chunk-
|
|
2
|
-
import { servM, WILDCARD_ROLE, WILDCARD_PERMISSION, implement, buildHaiErrorBody } from './chunk-
|
|
1
|
+
import { validateInputOrFail, resolveRequestLocale, localizeZodError } from './chunk-WW25756Z.js';
|
|
2
|
+
import { servM, WILDCARD_ROLE, WILDCARD_PERMISSION, implement, buildHaiErrorBody } from './chunk-KR4H56KP.js';
|
|
3
3
|
import process from 'process';
|
|
4
4
|
import { upgradeWebSocket, serve } from '@hono/node-server';
|
|
5
5
|
import { apiContract, AUDIO_WS_PATH, AudioWsClientMessageSchema } from '@h-ai/api-contract';
|
|
@@ -1212,10 +1212,18 @@ var audioWsServers = /* @__PURE__ */ new WeakMap();
|
|
|
1212
1212
|
function createApp(options) {
|
|
1213
1213
|
const http = resolveServHttpConfig(options.http);
|
|
1214
1214
|
const app = new Hono();
|
|
1215
|
+
app.onError((error, c) => {
|
|
1216
|
+
const traceId = core.context.get().traceId ?? core.context.get().requestId ?? resolveRequestId(c.req.header("x-request-id") ?? null);
|
|
1217
|
+
core.logger.error("HTTP handler failed", { traceId, error, method: c.req.method });
|
|
1218
|
+
c.header("x-trace-id", traceId);
|
|
1219
|
+
const safe = core.error.toPublic({ ...HaiCommonError.INTERNAL_ERROR, message: "" }, traceId);
|
|
1220
|
+
return c.json({ success: false, error: safe }, 500);
|
|
1221
|
+
});
|
|
1215
1222
|
app.use("*", async (c, next) => {
|
|
1216
1223
|
const requestId = resolveRequestId(c.req.header("x-request-id") ?? null);
|
|
1217
1224
|
await core.context.run({ requestId, userId: void 0, scopeId: void 0, jobId: void 0 }, () => core.i18n.runWithLocale(resolveRequestLocale(c.req.raw.headers), next));
|
|
1218
1225
|
c.header("x-request-id", requestId);
|
|
1226
|
+
c.header("x-trace-id", requestId);
|
|
1219
1227
|
});
|
|
1220
1228
|
app.notFound((c) => c.json(buildHaiErrorBody(
|
|
1221
1229
|
HaiCommonError.NOT_FOUND,
|
|
@@ -1348,7 +1356,8 @@ async function localizeValidationResponse(response, requestHeaders) {
|
|
|
1348
1356
|
success: false,
|
|
1349
1357
|
error: {
|
|
1350
1358
|
code: HaiCommonError.VALIDATION_ERROR.code,
|
|
1351
|
-
|
|
1359
|
+
traceId: core.context.get().traceId ?? core.context.get().requestId,
|
|
1360
|
+
message: core.error.formatMessage({ message: servM("serv_validationFailed", { locale }), traceId: core.context.get().traceId ?? core.context.get().requestId }),
|
|
1352
1361
|
httpStatus: HaiCommonError.VALIDATION_ERROR.httpStatus,
|
|
1353
1362
|
system: HaiCommonError.VALIDATION_ERROR.system,
|
|
1354
1363
|
module: HaiCommonError.VALIDATION_ERROR.module,
|
|
@@ -1435,7 +1444,7 @@ var DEFAULT_CORS_MAX_AGE = 86400;
|
|
|
1435
1444
|
function cors(config = {}) {
|
|
1436
1445
|
const methods = [...config.methods ?? DEFAULT_CORS_METHODS];
|
|
1437
1446
|
const allowedHeaders = [...config.allowedHeaders ?? DEFAULT_CORS_ALLOWED_HEADERS];
|
|
1438
|
-
const exposedHeaders = [...config.exposedHeaders ?? []];
|
|
1447
|
+
const exposedHeaders = [.../* @__PURE__ */ new Set(["X-Request-Id", "X-Trace-Id", ...config.exposedHeaders ?? []])];
|
|
1439
1448
|
const credentials = config.credentials ?? false;
|
|
1440
1449
|
const maxAge = config.maxAge ?? DEFAULT_CORS_MAX_AGE;
|
|
1441
1450
|
const originConfig = config.origin ?? "*";
|