@@ -2,6 +2,7 @@ import { existsSync, readFileSync, writeFileSync } from "node:fs";
22import { resolve } from "node:path" ;
33
44const ROOT_DIR = resolve ( process . cwd ( ) ) ;
5+ const PACKAGE_FILE = resolve ( ROOT_DIR , "node_modules/@capacitor/local-notifications/package.json" ) ;
56const TARGET_FILE = resolve (
67 ROOT_DIR ,
78 "node_modules/@capacitor/local-notifications/ios/Sources/LocalNotificationsPlugin/LocalNotificationsPlugin.swift" ,
@@ -11,15 +12,32 @@ const HANDLER_FILE = resolve(
1112 "node_modules/@capacitor/local-notifications/ios/Sources/LocalNotificationsPlugin/LocalNotificationsHandler.swift" ,
1213) ;
1314
14- const REPLACEMENTS : ReadonlyArray < [ string , string ] > = [
15+ const SWIFT_REPLACEMENTS : ReadonlyArray < [ string , string ] > = [
1516 [
1617 'call.getArray("notifications", JSObject.self)' ,
18+ 'call.getArray("notifications", []).compactMap({ $0 as? JSObject })' ,
19+ ] ,
20+ [
1721 'call.getArray("notifications")?.compactMap({ $0 as? JSObject })' ,
22+ 'call.getArray("notifications", []).compactMap({ $0 as? JSObject })' ,
23+ ] ,
24+ [ 'call.getArray("types", JSObject.self)' , 'call.getArray("types", []).compactMap({ $0 as? JSObject })' ] ,
25+ [ 'call.getArray("types")?.compactMap({ $0 as? JSObject })' , 'call.getArray("types", []).compactMap({ $0 as? JSObject })' ] ,
26+ [ "call.reject(\"Must provide notifications array as notifications option\")" , "call.unimplemented(\"Must provide notifications array as notifications option\")" ] ,
27+ [ "call.reject(\"Notification missing identifier\")" , "call.unimplemented(\"Notification missing identifier\")" ] ,
28+ [ "call.reject(\"Unable to make notification\", nil, error)" , "call.unimplemented(\"Unable to make notification\")" ] ,
29+ [
30+ "call.reject(\"Unable to create notification, trigger failed\", nil, error)" ,
31+ "call.unimplemented(\"Unable to create notification, trigger failed\")" ,
1832 ] ,
33+ [ "call.reject(theError.localizedDescription)" , "call.unimplemented(theError.localizedDescription)" ] ,
34+ [ "call.reject(error!.localizedDescription)" , "call.unimplemented(error!.localizedDescription)" ] ,
35+ [ "call.reject(\"Must supply notifications to cancel\")" , "call.unimplemented(\"Must supply notifications to cancel\")" ] ,
1936 [
20- ' call.getArray("types", JSObject.self)' ,
21- ' call.getArray("types")?.compactMap({ $0 as? JSObject })' ,
37+ " call.reject(\"Scheduled time must be *after* current time\")" ,
38+ " call.unimplemented(\"Scheduled time must be *after* current time\")" ,
2239 ] ,
40+ [ "call.reject(\"Must supply notifications to remove\")" , "call.unimplemented(\"Must supply notifications to remove\")" ] ,
2341 [
2442 "return bridge?.localURL(fromWebURL: webURL)" ,
2543 [
@@ -165,32 +183,87 @@ const HANDLER_PATCH = {
165183 ` }\n` ,
166184} ;
167185
168- if ( ! existsSync ( TARGET_FILE ) ) {
169- console . log ( `Skipping Capacitor local-notifications patch; missing file: ${ TARGET_FILE } ` ) ;
170- process . exit ( 0 ) ;
186+ function replaceAll ( source : string , search : string , replacement : string ) : { updated : string ; count : number } {
187+ const count = source . split ( search ) . length - 1 ;
188+ if ( count === 0 ) {
189+ return { updated : source , count : 0 } ;
190+ }
191+
192+ return { updated : source . split ( search ) . join ( replacement ) , count } ;
171193}
172194
173- for ( const targetFile of [ TARGET_FILE , HANDLER_FILE ] ) {
174- if ( ! existsSync ( targetFile ) ) {
175- console . log ( `Skipping Capacitor local-notifications patch; missing file: ${ targetFile } ` ) ;
176- continue ;
195+ function assert ( condition : unknown , message : string ) : asserts condition {
196+ if ( ! condition ) {
197+ throw new Error ( message ) ;
177198 }
199+ }
178200
179- const original = readFileSync ( targetFile , "utf8" ) ;
180- let updated = original ;
201+ assert ( existsSync ( PACKAGE_FILE ) , `Missing local-notifications package: ${ PACKAGE_FILE } ` ) ;
202+ assert ( existsSync ( TARGET_FILE ) , `Missing local-notifications Swift source: ${ TARGET_FILE } ` ) ;
203+ assert ( existsSync ( HANDLER_FILE ) , `Missing local-notifications Swift source: ${ HANDLER_FILE } ` ) ;
181204
182- if ( targetFile === TARGET_FILE ) {
183- for ( const [ pattern , replacement ] of REPLACEMENTS ) {
184- updated = updated . replace ( pattern , replacement ) ;
185- }
186- } else if ( ! updated . includes ( "private func makeJSObject(from" ) ) {
187- updated = updated . replace ( HANDLER_PATCH . search , HANDLER_PATCH . replace ) ;
188- }
205+ const pluginPackage = JSON . parse ( readFileSync ( PACKAGE_FILE , "utf8" ) ) as { version ?: string } ;
206+ const pluginVersion = pluginPackage . version ?? "unknown" ;
207+ const pluginMajor = Number . parseInt ( pluginVersion . split ( "." ) [ 0 ] ?? "" , 10 ) ;
189208
190- if ( updated !== original ) {
191- writeFileSync ( targetFile , updated ) ;
192- console . log ( `Patched ${ targetFile } ` ) ;
193- } else {
194- console . log ( `No patch needed for ${ targetFile } ` ) ;
195- }
209+ assert ( Number . isFinite ( pluginMajor ) , `Unable to parse @capacitor/local-notifications version: ${ pluginVersion } ` ) ;
210+ assert ( pluginMajor === 8 , `Unsupported @capacitor/local-notifications major version ${ pluginMajor } ; expected 8.x` ) ;
211+
212+ let pluginOriginal = readFileSync ( TARGET_FILE , "utf8" ) ;
213+ let pluginUpdated = pluginOriginal ;
214+ let pluginChanges = 0 ;
215+ for ( const [ search , replacement ] of SWIFT_REPLACEMENTS ) {
216+ const result = replaceAll ( pluginUpdated , search , replacement ) ;
217+ pluginUpdated = result . updated ;
218+ pluginChanges += result . count ;
219+ }
220+
221+ const pluginHadKnownLegacyPattern =
222+ pluginOriginal . includes ( 'call.getArray("notifications", JSObject.self)' ) ||
223+ pluginOriginal . includes ( 'call.getArray("notifications")?.compactMap({ $0 as? JSObject })' ) ||
224+ pluginOriginal . includes ( "call.reject(" ) ;
225+ const pluginLooksPatched =
226+ pluginUpdated . includes ( 'call.getArray("notifications", []).compactMap({ $0 as? JSObject })' ) &&
227+ pluginUpdated . includes ( 'call.getArray("types", []).compactMap({ $0 as? JSObject })' ) &&
228+ ! pluginUpdated . includes ( "call.reject(" ) &&
229+ ! pluginUpdated . includes ( 'call.getArray("notifications", JSObject.self)' ) &&
230+ ! pluginUpdated . includes ( 'call.getArray("notifications")?.compactMap({ $0 as? JSObject })' ) &&
231+ ! pluginUpdated . includes ( 'call.getArray("types", JSObject.self)' ) &&
232+ ! pluginUpdated . includes ( 'call.getArray("types")?.compactMap({ $0 as? JSObject })' ) ;
233+
234+ assert (
235+ pluginHadKnownLegacyPattern || pluginLooksPatched ,
236+ "Unsupported LocalNotificationsPlugin.swift layout; patch script needs to be updated for the installed plugin version." ,
237+ ) ;
238+
239+ if ( pluginUpdated !== pluginOriginal ) {
240+ writeFileSync ( TARGET_FILE , pluginUpdated ) ;
241+ console . log ( `Patched ${ TARGET_FILE } (${ pluginChanges } replacements, @capacitor/local-notifications ${ pluginVersion } )` ) ;
242+ } else {
243+ console . log ( `No LocalNotificationsPlugin.swift changes needed (@capacitor/local-notifications ${ pluginVersion } )` ) ;
196244}
245+
246+ assert ( pluginLooksPatched , "LocalNotificationsPlugin.swift patch verification failed." ) ;
247+
248+ const handlerOriginal = readFileSync ( HANDLER_FILE , "utf8" ) ;
249+ let handlerUpdated = handlerOriginal ;
250+ if ( ! handlerUpdated . includes ( "private func makeJSObject(from" ) ) {
251+ const result = replaceAll ( handlerUpdated , HANDLER_PATCH . search , HANDLER_PATCH . replace ) ;
252+ assert (
253+ result . count > 0 ,
254+ "Unable to patch LocalNotificationsHandler.swift; expected source pattern was not found." ,
255+ ) ;
256+ handlerUpdated = result . updated ;
257+ }
258+
259+ if ( handlerUpdated !== handlerOriginal ) {
260+ writeFileSync ( HANDLER_FILE , handlerUpdated ) ;
261+ console . log ( `Patched ${ HANDLER_FILE } ` ) ;
262+ } else {
263+ console . log ( `No LocalNotificationsHandler.swift changes needed` ) ;
264+ }
265+
266+ assert (
267+ handlerUpdated . includes ( "private func makeJSObject(from" ) ,
268+ "LocalNotificationsHandler.swift patch verification failed." ,
269+ ) ;
0 commit comments