fix(voip-push): dynamic import @parse/node-apn — nitro bundler bricht statisches Tracing (Class extends Module-namespace)
This commit is contained in:
parent
57e0a23021
commit
848b517d22
@ -10,15 +10,13 @@ export default defineNitroConfig({
|
||||
// Default-publicAssets greift nicht zuverlässig wenn srcDir auf "server" zeigt.
|
||||
publicAssets: [{ baseURL: "/", dir: "../public", maxAge: 60 * 60 }],
|
||||
|
||||
// Supabase + @parse/node-apn + imapflow als external deps — nicht bundlen.
|
||||
// node-apn + imapflow nutzen CJS-extends/inherits-Patterns, die brechen beim
|
||||
// Bundlen zu ESM ("Class extends value [object Module] is not a constructor
|
||||
// or null" / "superCtor.prototype must be of type object"). Müssen als externe
|
||||
// node_modules-Requires bleiben.
|
||||
// Supabase + imapflow als external deps — nicht bundlen.
|
||||
// imapflow nutzt CJS-inherits-Pattern, bricht beim Bundlen zu ESM
|
||||
// ("superCtor.prototype must be of type object"). @parse/node-apn wird
|
||||
// in services/voip-push.ts via dynamic import geladen (vermeidet das gleiche
|
||||
// Problem ohne Externalize-Eintrag).
|
||||
externals: {
|
||||
inline: [
|
||||
/^(?!@supabase\/supabase-js)(?!@parse\/node-apn)(?!imapflow)/,
|
||||
],
|
||||
inline: [/^(?!@supabase\/supabase-js)(?!imapflow)/],
|
||||
},
|
||||
|
||||
imports: {
|
||||
|
||||
@ -17,14 +17,22 @@
|
||||
* Wenn ENV-Vars fehlen: Service no-op (kein Error, nur Log-Warnung beim ersten Send).
|
||||
* → Macht reguläre Pushes nicht kaputt wenn das VoIP-Setup noch unfertig ist.
|
||||
*/
|
||||
import apn from "@parse/node-apn";
|
||||
import fs from "node:fs";
|
||||
|
||||
let provider: apn.Provider | null = null;
|
||||
// node-apn dynamisch laden (await import statt static import). Grund: nitro/rollup
|
||||
// bricht beim Bundlen von node-apn → undici → `Class extends value [object Module]`
|
||||
// at push.mjs. Dynamic import wird nicht statisch getraced, lädt Modul zur Laufzeit
|
||||
// aus node_modules wo es korrekt als CJS funktioniert.
|
||||
type ApnModule = typeof import("@parse/node-apn");
|
||||
type ApnProvider = InstanceType<ApnModule["Provider"]>;
|
||||
type ApnNotification = InstanceType<ApnModule["Notification"]>;
|
||||
|
||||
let apnMod: ApnModule | null = null;
|
||||
let provider: ApnProvider | null = null;
|
||||
let initialized = false;
|
||||
let topic: string | null = null;
|
||||
|
||||
function getProvider(): apn.Provider | null {
|
||||
async function getProvider(): Promise<ApnProvider | null> {
|
||||
if (initialized) return provider;
|
||||
initialized = true;
|
||||
|
||||
@ -45,8 +53,13 @@ function getProvider(): apn.Provider | null {
|
||||
}
|
||||
|
||||
try {
|
||||
// Dynamic import — vermeidet bundler statisches Tracing.
|
||||
const mod = (await import("@parse/node-apn")) as unknown as ApnModule & {
|
||||
default?: ApnModule;
|
||||
};
|
||||
apnMod = mod.default ?? mod;
|
||||
topic = tpc;
|
||||
provider = new apn.Provider({
|
||||
provider = new apnMod.Provider({
|
||||
pfx: p12Path,
|
||||
passphrase: p12Pass,
|
||||
production,
|
||||
@ -84,10 +97,10 @@ export interface VoIPCallPayload {
|
||||
* @returns true bei Erfolg (oder no-op wenn Service disabled), false bei Fehler.
|
||||
*/
|
||||
export async function sendVoIPPush(payload: VoIPCallPayload): Promise<boolean> {
|
||||
const p = getProvider();
|
||||
if (!p || !topic) return true; // no-op, regulärer Push übernimmt
|
||||
const p = await getProvider();
|
||||
if (!p || !topic || !apnMod) return true; // no-op, regulärer Push übernimmt
|
||||
|
||||
const note = new apn.Notification();
|
||||
const note: ApnNotification = new apnMod.Notification();
|
||||
note.topic = topic;
|
||||
note.expiry = 0; // sofort verwerfen wenn Device unreachable
|
||||
note.priority = 10;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user