@arcblock/payment-service 1.29.1 → 1.29.2

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/dist/drivers.js CHANGED
@@ -339,6 +339,84 @@ var init_queue = __esm({
339
339
  }
340
340
  });
341
341
 
342
+ // ../../blocklets/core/api/src/libs/env.ts
343
+ function readConfig(key) {
344
+ const injected = activeConfig?.[key];
345
+ if (injected !== void 0 && injected !== null) return String(injected);
346
+ const fromEnv = process.env[key];
347
+ return fromEnv === void 0 ? void 0 : fromEnv;
348
+ }
349
+ var import_env, activeConfig, tenantModeRaw, blockletAppPid, env_default;
350
+ var init_env = __esm({
351
+ "../../blocklets/core/api/src/libs/env.ts"() {
352
+ "use strict";
353
+ import_env = require("@blocklet/sdk/lib/env");
354
+ tenantModeRaw = () => readConfig("PAYMENT_TENANT_MODE");
355
+ blockletAppPid = () => readConfig("BLOCKLET_APP_PID");
356
+ env_default = {
357
+ ...import_env.env
358
+ };
359
+ }
360
+ });
361
+
362
+ // ../../blocklets/core/api/src/libs/tenant.ts
363
+ var tenant_exports = {};
364
+ __export(tenant_exports, {
365
+ INVALID_TENANT_TABLE: () => INVALID_TENANT_TABLE,
366
+ TENANT_CONTEXT_MISSING: () => TENANT_CONTEXT_MISSING,
367
+ TENANT_HOST_UNRESOLVED: () => TENANT_HOST_UNRESOLVED,
368
+ TENANT_MISMATCH: () => TENANT_MISMATCH,
369
+ TenantError: () => TenantError,
370
+ assertValidInstanceDid: () => assertValidInstanceDid,
371
+ getDefaultInstanceDid: () => getDefaultInstanceDid,
372
+ getTenantMode: () => getTenantMode,
373
+ resolveRowTenant: () => resolveRowTenant,
374
+ setDefaultInstanceDid: () => setDefaultInstanceDid
375
+ });
376
+ function getTenantMode() {
377
+ return tenantModeRaw() === "multi" ? "multi" : "single";
378
+ }
379
+ function setDefaultInstanceDid(did) {
380
+ if (did !== void 0) assertValidInstanceDid(did);
381
+ overrideDefaultInstanceDid = did;
382
+ }
383
+ function getDefaultInstanceDid() {
384
+ const did = overrideDefaultInstanceDid || blockletAppPid() || "";
385
+ if (!did) {
386
+ throw new TenantError(TENANT_CONTEXT_MISSING, "app DID is not configured for this deployment");
387
+ }
388
+ return did;
389
+ }
390
+ function resolveRowTenant(row) {
391
+ const fromRow = row?.instance_did;
392
+ if (fromRow) return fromRow;
393
+ if (getTenantMode() === "single") return getDefaultInstanceDid();
394
+ throw new TenantError(TENANT_CONTEXT_MISSING, "row has no tenant and deployment is in multi mode");
395
+ }
396
+ function assertValidInstanceDid(instanceDid) {
397
+ if (typeof instanceDid !== "string" || !/^\S{3,}$/.test(instanceDid)) {
398
+ throw new TenantError(TENANT_CONTEXT_MISSING, `invalid instanceDid: ${JSON.stringify(instanceDid)}`);
399
+ }
400
+ }
401
+ var TENANT_CONTEXT_MISSING, TENANT_MISMATCH, INVALID_TENANT_TABLE, TENANT_HOST_UNRESOLVED, TenantError, overrideDefaultInstanceDid;
402
+ var init_tenant = __esm({
403
+ "../../blocklets/core/api/src/libs/tenant.ts"() {
404
+ "use strict";
405
+ init_env();
406
+ TENANT_CONTEXT_MISSING = "TENANT_CONTEXT_MISSING";
407
+ TENANT_MISMATCH = "TENANT_MISMATCH";
408
+ INVALID_TENANT_TABLE = "INVALID_TENANT_TABLE";
409
+ TENANT_HOST_UNRESOLVED = "TENANT_HOST_UNRESOLVED";
410
+ TenantError = class extends Error {
411
+ constructor(code, message) {
412
+ super(message);
413
+ this.name = "TenantError";
414
+ this.code = code;
415
+ }
416
+ };
417
+ }
418
+ });
419
+
342
420
  // ../../blocklets/core/api/src/libs/drivers/cron.ts
343
421
  function parseField(field, min, max) {
344
422
  if (field === "*") return null;
@@ -387,6 +465,37 @@ function shouldRunInWindow(cronExpr, date) {
387
465
  function createCronRegistry(kind) {
388
466
  const jobs = [];
389
467
  let onErrorHandler;
468
+ const selfSchedule = kind === "node-cron";
469
+ let scheduler = null;
470
+ const stopScheduler = () => {
471
+ if (!scheduler) return;
472
+ for (const job of Object.values(scheduler.jobs)) {
473
+ try {
474
+ job.stop();
475
+ } catch {
476
+ }
477
+ }
478
+ scheduler = null;
479
+ };
480
+ const startScheduler = () => {
481
+ stopScheduler();
482
+ if (!selfSchedule || jobs.length === 0) return;
483
+ const mod = require("@abtnode/cron");
484
+ const init = mod.init ?? mod.default?.init;
485
+ const { getTenantMode: getTenantMode2 } = (init_tenant(), __toCommonJS(tenant_exports));
486
+ const isMulti = getTenantMode2() === "multi";
487
+ scheduler = init({
488
+ context: {},
489
+ jobs: jobs.map((j) => ({
490
+ name: j.name,
491
+ time: j.time,
492
+ fn: j.fn,
493
+ options: isMulti ? { ...j.options || {}, runOnInit: false } : j.options || {}
494
+ })),
495
+ onError: onErrorHandler ?? (() => {
496
+ })
497
+ });
498
+ };
390
499
  return {
391
500
  kind,
392
501
  register(next, onError) {
@@ -395,9 +504,24 @@ function createCronRegistry(kind) {
395
504
  for (const job of next || []) {
396
505
  if (job.name && job.time && typeof job.fn === "function") jobs.push(job);
397
506
  }
507
+ startScheduler();
398
508
  },
399
509
  addJob(name, time, fn, options) {
400
510
  jobs.push({ name, time, fn, options });
511
+ if (selfSchedule && scheduler) {
512
+ try {
513
+ scheduler.addJob(name, time, fn, options || {});
514
+ } catch (err) {
515
+ onErrorHandler?.(err, name);
516
+ }
517
+ }
518
+ },
519
+ stop() {
520
+ stopScheduler();
521
+ },
522
+ dispose() {
523
+ stopScheduler();
524
+ jobs.length = 0;
401
525
  },
402
526
  async runDue(now = /* @__PURE__ */ new Date()) {
403
527
  const ran = [];
@@ -490,49 +614,6 @@ var init_sql_migrations = __esm({
490
614
  }
491
615
  });
492
616
 
493
- // ../../blocklets/core/api/src/libs/env.ts
494
- function readConfig(key) {
495
- const injected = activeConfig?.[key];
496
- if (injected !== void 0 && injected !== null) return String(injected);
497
- const fromEnv = process.env[key];
498
- return fromEnv === void 0 ? void 0 : fromEnv;
499
- }
500
- var import_env, activeConfig, blockletAppPid, env_default;
501
- var init_env = __esm({
502
- "../../blocklets/core/api/src/libs/env.ts"() {
503
- "use strict";
504
- import_env = require("@blocklet/sdk/lib/env");
505
- blockletAppPid = () => readConfig("BLOCKLET_APP_PID");
506
- env_default = {
507
- ...import_env.env
508
- };
509
- }
510
- });
511
-
512
- // ../../blocklets/core/api/src/libs/tenant.ts
513
- function getDefaultInstanceDid() {
514
- const did = overrideDefaultInstanceDid || blockletAppPid() || "";
515
- if (!did) {
516
- throw new TenantError(TENANT_CONTEXT_MISSING, "app DID is not configured for this deployment");
517
- }
518
- return did;
519
- }
520
- var TENANT_CONTEXT_MISSING, TenantError, overrideDefaultInstanceDid;
521
- var init_tenant = __esm({
522
- "../../blocklets/core/api/src/libs/tenant.ts"() {
523
- "use strict";
524
- init_env();
525
- TENANT_CONTEXT_MISSING = "TENANT_CONTEXT_MISSING";
526
- TenantError = class extends Error {
527
- constructor(code, message) {
528
- super(message);
529
- this.name = "TenantError";
530
- this.code = code;
531
- }
532
- };
533
- }
534
- });
535
-
536
617
  // ../../blocklets/core/api/src/libs/drivers/identity.ts
537
618
  function createDefaultIdentityDriver() {
538
619
  return {
package/dist/index.d.ts CHANGED
@@ -20,6 +20,9 @@ export type TenancySlot = {
20
20
  instanceDid: string;
21
21
  } | {
22
22
  mode: 'multi';
23
+ /** D6 (optional): enumerate all known tenant instanceDids so start()
24
+ * bootstraps each at startup. Absent => host bootstraps per tenant. */
25
+ listInstanceDids?: () => Promise<string[]> | string[];
23
26
  };
24
27
  export interface PaymentCoreSlots {
25
28
  config: Record<string, any>;
@@ -37,12 +40,36 @@ export interface PaymentCoreLifecycle {
37
40
  start: () => Promise<void>;
38
41
  stop: () => Promise<void>;
39
42
  }
43
+ /** Options for svc.http.fetch — basePath is stripped to reach the internal /api/*. */
44
+ export interface PaymentFetchOptions {
45
+ /** the host's mount prefix (e.g. "/.well-known/payment"); stripped, no alias special-case */
46
+ basePath?: string;
47
+ }
40
48
  export interface PaymentCoreService {
41
- /** (req, res) handler — mount under the host's prefix (lazy: node app shell) */
49
+ /**
50
+ * Phase 4 (express→hono): the full node HONO app (was express.Express). Mount
51
+ * under the host's prefix; built lazily (node app shell). Typed `any` so this
52
+ * package's .d.ts stays free of a hono type dependency — the runtime value is a
53
+ * `hono` instance.
54
+ */
42
55
  handler: any;
43
- /** embeddable HTTP surface — `resourceRoutes` for hosts owning their own shell */
56
+ /** embeddable HTTP surface for hosts owning their own shell */
44
57
  http: {
58
+ /**
59
+ * Phase 4 (express→hono): the resource routes as a HONO app (was
60
+ * express.Router) — `/api/healthz` + the migrated domains. A host (CF worker)
61
+ * mounts it via `app.route('/', resourceRoutes)`. Typed `any` (see `handler`).
62
+ */
45
63
  resourceRoutes: any;
64
+ /**
65
+ * D5: Web-Fetch entry over the FULL node hono app. A Fetch-native host
66
+ * (arc-node) forwards a Web Request under {basePath} and gets a Web Response
67
+ * — base-strip, raw-body (Stripe webhook signature), originalUrl, multi
68
+ * Set-Cookie / redirect passthrough handled inside (lazy Node adapter). The
69
+ * host writes zero express/req-res bridge. Node-only: a workerd host that
70
+ * mounts `resourceRoutes` must never call this.
71
+ */
72
+ fetch: (request: Request, opts?: PaymentFetchOptions) => Promise<Response>;
46
73
  };
47
74
  rpc: {
48
75
  entitlements: {
@@ -57,5 +84,12 @@ export interface PaymentCoreService {
57
84
  };
58
85
  };
59
86
  lifecycle: PaymentCoreLifecycle;
87
+ /**
88
+ * D6 — idempotent per-tenant bootstrap (currency logos, overdraft prices,
89
+ * exchange-rate-health schedule, per-tenant integrations) run inside the
90
+ * tenant context. Multi-mode hosts MUST call this per tenant; single mode
91
+ * bootstraps the default tenant from lifecycle.start automatically.
92
+ */
93
+ bootstrapTenant: (instanceDid: string) => Promise<void>;
60
94
  }
61
95
  export declare function createEmbeddedPaymentService(slots: PaymentCoreSlots): PaymentCoreService;