react-native-ios-widget 0.0.12 → 0.0.13-beta.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.
@@ -0,0 +1,7 @@
1
+ import ExpoModulesCore
2
+
3
+ public class ReactNativeWidgetExtensionModule: Module {
4
+ public func definition() -> ModuleDefinition {
5
+ Name("ReactNativeWidgetExtension")
6
+ }
7
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-ios-widget",
3
- "version": "0.0.12",
3
+ "version": "0.0.13-beta.2",
4
4
  "description": "Expo config plugin to add widgets to a React Native app",
5
5
  "main": "build/index.js",
6
6
  "types": "build/index.d.ts",
@@ -5,6 +5,7 @@ const withXcode_1 = require("./withXcode");
5
5
  const withWidgetExtensionEntitlements_1 = require("./withWidgetExtensionEntitlements");
6
6
  const withPodfile_1 = require("./withPodfile");
7
7
  const withConfig_1 = require("./withConfig");
8
+ const withWidgetModuleConfig_1 = require("./withWidgetModuleConfig");
8
9
  const withWidget = (config, { enabled = true, deploymentTarget = "14.0", widgetsFolder = "widgets", groupIdentifier, pods = [], targetName = "WidgetsExtension", bundleIdentifier = `${config.ios?.bundleIdentifier}.Widgets`, }) => {
9
10
  const widget = {
10
11
  enabled,
@@ -20,6 +21,7 @@ const withWidget = (config, { enabled = true, deploymentTarget = "14.0", widgets
20
21
  [withWidgetExtensionEntitlements_1.withWidgetExtensionEntitlements, widget],
21
22
  [withPodfile_1.withPodfile, widget],
22
23
  [withConfig_1.withConfig, widget],
24
+ [withWidgetModuleConfig_1.withWidgetModuleConfig, widget],
23
25
  ]);
24
26
  };
25
27
  exports.default = withWidget;
@@ -47,15 +47,13 @@ const getWidgetFiles = (widgetsPath, targetPath, moduleRoot) => {
47
47
  if (!fs.existsSync(targetPath)) {
48
48
  fs.mkdirSync(targetPath, { recursive: true });
49
49
  }
50
- // Ensure moduleRoot directory exists
51
50
  if (!fs.existsSync(moduleRoot)) {
52
51
  fs.mkdirSync(moduleRoot, { recursive: true });
53
52
  }
54
- // Check if Module.swift exists before proceeding
55
53
  const moduleSwiftPath = path.join(widgetsPath, "Module.swift");
56
54
  if (!fs.existsSync(moduleSwiftPath)) {
57
55
  throw new Error(`Module.swift not found at ${moduleSwiftPath}. ` +
58
- `The widgets folder must contain a Module.swift file for the ReactNativeWidgetExtension module to build correctly.`);
56
+ "The widgets folder must contain Module.swift to build ReactNativeWidgetExtension.");
59
57
  }
60
58
  if (fs.lstatSync(widgetsPath).isDirectory()) {
61
59
  const files = fs.readdirSync(widgetsPath);
@@ -90,7 +88,6 @@ const getWidgetFiles = (widgetsPath, targetPath, moduleRoot) => {
90
88
  const source = path.join(widgetsPath, file);
91
89
  copyFileSync(source, targetPath);
92
90
  });
93
- // Copy Module.swift to moduleRoot (package ios directory)
94
91
  copyFileSync(moduleSwiftPath, path.join(moduleRoot, "Module.swift"));
95
92
  // Copy directories
96
93
  widgetFiles.assetDirectories.forEach((directory) => {
@@ -1 +1 @@
1
- {"root":["../src/index.ts","../src/types.ts","../src/withconfig.ts","../src/withpodfile.ts","../src/withwidgetextensionentitlements.ts","../src/withxcode.ts","../src/lib/getwidgetextensionentitlements.ts","../src/lib/getwidgetfiles.ts","../src/xcode/addbuildphases.ts","../src/xcode/addpbxgroup.ts","../src/xcode/addproductfile.ts","../src/xcode/addtargetdependency.ts","../src/xcode/addtopbxnativetargetsection.ts","../src/xcode/addtopbxprojectsection.ts","../src/xcode/addxcconfigurationlist.ts"],"version":"5.9.3"}
1
+ {"root":["../src/index.ts","../src/types.ts","../src/withconfig.ts","../src/withpodfile.ts","../src/withwidgetextensionentitlements.ts","../src/withwidgetmoduleconfig.ts","../src/withxcode.ts","../src/lib/getwidgetextensionentitlements.ts","../src/lib/getwidgetfiles.ts","../src/xcode/addbuildphases.ts","../src/xcode/addpbxgroup.ts","../src/xcode/addproductfile.ts","../src/xcode/addtargetdependency.ts","../src/xcode/addtopbxnativetargetsection.ts","../src/xcode/addtopbxprojectsection.ts","../src/xcode/addxcconfigurationlist.ts"],"errors":true,"version":"5.9.3"}
@@ -0,0 +1,3 @@
1
+ import { ConfigPlugin } from "expo/config-plugins";
2
+ import { WidgetConfig } from "./types";
3
+ export declare const withWidgetModuleConfig: ConfigPlugin<Required<WidgetConfig>>;
@@ -0,0 +1,85 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.withWidgetModuleConfig = void 0;
37
+ const fs = __importStar(require("fs"));
38
+ const path = __importStar(require("path"));
39
+ const withWidgetModuleConfig = (config, { enabled, targetName, widgetsFolder }) => {
40
+ const { platformProjectRoot, projectRoot } = config.modRequest;
41
+ const widgetsPath = path.join(projectRoot, widgetsFolder);
42
+ const moduleRoot = path.join(projectRoot, "node_modules", "react-native-ios-widget", "ios");
43
+ if (!enabled) {
44
+ // When disabled, ensure no module config exists (remove if present)
45
+ const moduleConfigPath = path.join(moduleRoot, "expo-module.config.json");
46
+ if (fs.existsSync(moduleConfigPath)) {
47
+ fs.unlinkSync(moduleConfigPath);
48
+ }
49
+ // Optionally write empty config to explicitly exclude module
50
+ // fs.writeFileSync(
51
+ // moduleConfigPath,
52
+ // JSON.stringify({ platforms: ["ios"], ios: {} }, null, 2)
53
+ // );
54
+ }
55
+ // Conditionally manage expo-module.config.json based on widget enabled state.
56
+ // When widgets are enabled, ensure module config exists and declares ReactNativeWidgetExtensionModule.
57
+ // When disabled, remove or write empty config to exclude module from Expo autolinking.
58
+ const moduleConfigPath = path.join(moduleRoot, "expo-module.config.json");
59
+ const moduleSwiftPath = path.join(widgetsPath, "Module.swift");
60
+ const targetPath = path.join(moduleRoot, "Module.swift");
61
+ if (fs.existsSync(moduleSwiftPath)) {
62
+ // Widgets enabled: copy real Module.swift for CocoaPods
63
+ fs.copyFileSync(moduleSwiftPath, targetPath);
64
+ // Write module config to enable Expo autolinking
65
+ const moduleConfig = {
66
+ platforms: ["ios"],
67
+ ios: {
68
+ modules: ["ReactNativeWidgetExtensionModule"],
69
+ },
70
+ };
71
+ if (!fs.existsSync(moduleConfigPath)) {
72
+ fs.writeFileSync(moduleConfigPath, JSON.stringify(moduleConfig, null, 2));
73
+ }
74
+ }
75
+ else {
76
+ // Widgets disabled: ensure no module config exists (remove empty config if present)
77
+ if (fs.existsSync(moduleConfigPath)) {
78
+ fs.unlinkSync(moduleConfigPath);
79
+ }
80
+ // Write empty config to exclude module from Expo autolinking
81
+ fs.writeFileSync(moduleConfigPath, JSON.stringify({ platforms: ["ios"], ios: {} }, null, 2));
82
+ }
83
+ return config;
84
+ };
85
+ exports.withWidgetModuleConfig = withWidgetModuleConfig;
@@ -35,6 +35,7 @@ var __importStar = (this && this.__importStar) || (function () {
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.withXcode = void 0;
37
37
  const config_plugins_1 = require("expo/config-plugins");
38
+ const fs = __importStar(require("fs"));
38
39
  const path = __importStar(require("path"));
39
40
  const addXCConfigurationList_1 = require("./xcode/addXCConfigurationList");
40
41
  const addProductFile_1 = require("./xcode/addProductFile");
@@ -45,49 +46,87 @@ const addPbxGroup_1 = require("./xcode/addPbxGroup");
45
46
  const addBuildPhases_1 = require("./xcode/addBuildPhases");
46
47
  const getWidgetFiles_1 = require("./lib/getWidgetFiles");
47
48
  const withXcode = (config, { enabled, targetName, bundleIdentifier, deploymentTarget, widgetsFolder }) => {
48
- return (0, config_plugins_1.withXcodeProject)(config, (config) => {
49
- const { platformProjectRoot, projectRoot } = config.modRequest;
50
- if (!enabled) {
49
+ return (0, config_plugins_1.withDangerousMod)(config, [
50
+ "ios",
51
+ (config) => {
52
+ const { platformProjectRoot, projectRoot } = config.modRequest;
53
+ const widgetsPath = path.join(projectRoot, widgetsFolder);
54
+ const moduleRoot = path.join(projectRoot, "node_modules", "react-native-ios-widget", "ios");
55
+ if (!enabled) {
56
+ ensureModuleSwift(widgetsPath, moduleRoot);
57
+ return config;
58
+ }
59
+ const targetPath = path.join(platformProjectRoot, targetName);
60
+ const widgetFiles = (0, getWidgetFiles_1.getWidgetFiles)(widgetsPath, targetPath, moduleRoot);
61
+ const xcodeProject = config.modResults;
62
+ const marketingVersion = config.version;
63
+ const xCConfigurationList = (0, addXCConfigurationList_1.addXCConfigurationList)(xcodeProject, {
64
+ targetName,
65
+ currentProjectVersion: config.ios.buildNumber || "1",
66
+ bundleIdentifier,
67
+ deploymentTarget,
68
+ marketingVersion,
69
+ });
70
+ const groupName = "Embed Foundation Extensions";
71
+ const productFile = (0, addProductFile_1.addProductFile)(xcodeProject, {
72
+ targetName,
73
+ groupName,
74
+ });
75
+ const targetUuid = xcodeProject.generateUuid();
76
+ const target = (0, addToPbxNativeTargetSection_1.addToPbxNativeTargetSection)(xcodeProject, {
77
+ targetName,
78
+ targetUuid,
79
+ productFile,
80
+ xCConfigurationList,
81
+ });
82
+ (0, addToPbxProjectSection_1.addToPbxProjectSection)(xcodeProject, target);
83
+ (0, addTargetDependency_1.addTargetDependency)(xcodeProject, target);
84
+ (0, addBuildPhases_1.addBuildPhases)(xcodeProject, {
85
+ targetUuid,
86
+ groupName,
87
+ productFile,
88
+ widgetFiles,
89
+ });
90
+ (0, addPbxGroup_1.addPbxGroup)(xcodeProject, {
91
+ targetName,
92
+ widgetFiles,
93
+ });
51
94
  return config;
52
95
  }
53
- const widgetsPath = path.join(projectRoot, widgetsFolder);
54
- const targetPath = path.join(platformProjectRoot, targetName);
55
- const moduleRoot = path.join(projectRoot, "node_modules", "react-native-ios-widget", "ios");
56
- const widgetFiles = (0, getWidgetFiles_1.getWidgetFiles)(widgetsPath, targetPath, moduleRoot);
57
- const xcodeProject = config.modResults;
58
- const marketingVersion = config.version;
59
- const xCConfigurationList = (0, addXCConfigurationList_1.addXCConfigurationList)(xcodeProject, {
60
- targetName,
61
- currentProjectVersion: config.ios.buildNumber || "1",
62
- bundleIdentifier,
63
- deploymentTarget,
64
- marketingVersion,
65
- });
66
- const groupName = "Embed Foundation Extensions";
67
- const productFile = (0, addProductFile_1.addProductFile)(xcodeProject, {
68
- targetName,
69
- groupName,
70
- });
71
- const targetUuid = xcodeProject.generateUuid();
72
- const target = (0, addToPbxNativeTargetSection_1.addToPbxNativeTargetSection)(xcodeProject, {
73
- targetName,
74
- targetUuid,
75
- productFile,
76
- xCConfigurationList,
77
- });
78
- (0, addToPbxProjectSection_1.addToPbxProjectSection)(xcodeProject, target);
79
- (0, addTargetDependency_1.addTargetDependency)(xcodeProject, target);
80
- (0, addBuildPhases_1.addBuildPhases)(xcodeProject, {
81
- targetUuid,
82
- groupName,
83
- productFile,
84
- widgetFiles,
85
- });
86
- (0, addPbxGroup_1.addPbxGroup)(xcodeProject, {
87
- targetName,
88
- widgetFiles,
89
- });
90
- return config;
91
- });
96
+ ]);
92
97
  };
93
98
  exports.withXcode = withXcode;
99
+ const ensureModuleSwift = (widgetsPath, moduleRoot) => {
100
+ // Ensure pod source dir exists for Module.swift.
101
+ if (!fs.existsSync(moduleRoot)) {
102
+ fs.mkdirSync(moduleRoot, { recursive: true });
103
+ }
104
+ // Conditionally manage expo-module.config.json based on widget enabled state.
105
+ // When widgets are enabled, ensure module config exists and declares ReactNativeWidgetExtensionModule.
106
+ // When disabled, remove or write empty config to exclude module from Expo autolinking.
107
+ const moduleConfigPath = path.join(moduleRoot, "expo-module.config.json");
108
+ const moduleSwiftPath = path.join(widgetsPath, "Module.swift");
109
+ const targetPath = path.join(moduleRoot, "Module.swift");
110
+ if (fs.existsSync(moduleSwiftPath)) {
111
+ // Widgets enabled: copy real Module.swift for CocoaPods
112
+ fs.copyFileSync(moduleSwiftPath, targetPath);
113
+ // Write module config to enable Expo autolinking
114
+ const moduleConfig = {
115
+ platforms: ["ios"],
116
+ ios: {
117
+ modules: ["ReactNativeWidgetExtensionModule"],
118
+ },
119
+ };
120
+ if (!fs.existsSync(moduleConfigPath)) {
121
+ fs.writeFileSync(moduleConfigPath, JSON.stringify(moduleConfig, null, 2));
122
+ }
123
+ }
124
+ else {
125
+ // Widgets disabled: ensure no module config exists (remove empty config if present)
126
+ if (fs.existsSync(moduleConfigPath)) {
127
+ fs.unlinkSync(moduleConfigPath);
128
+ }
129
+ // Write empty config to exclude module from Expo autolinking
130
+ fs.writeFileSync(moduleConfigPath, JSON.stringify({ platforms: ["ios"], ios: {} }, null, 2));
131
+ }
132
+ };
@@ -26,17 +26,15 @@ export const getWidgetFiles = (
26
26
  fs.mkdirSync(targetPath, { recursive: true });
27
27
  }
28
28
 
29
- // Ensure moduleRoot directory exists
30
29
  if (!fs.existsSync(moduleRoot)) {
31
30
  fs.mkdirSync(moduleRoot, { recursive: true });
32
31
  }
33
32
 
34
- // Check if Module.swift exists before proceeding
35
33
  const moduleSwiftPath = path.join(widgetsPath, "Module.swift");
36
34
  if (!fs.existsSync(moduleSwiftPath)) {
37
35
  throw new Error(
38
36
  `Module.swift not found at ${moduleSwiftPath}. ` +
39
- `The widgets folder must contain a Module.swift file for the ReactNativeWidgetExtension module to build correctly.`
37
+ "The widgets folder must contain Module.swift to build ReactNativeWidgetExtension."
40
38
  );
41
39
  }
42
40
 
@@ -73,7 +71,6 @@ export const getWidgetFiles = (
73
71
  copyFileSync(source, targetPath);
74
72
  });
75
73
 
76
- // Copy Module.swift to moduleRoot (package ios directory)
77
74
  copyFileSync(moduleSwiftPath, path.join(moduleRoot, "Module.swift"));
78
75
 
79
76
  // Copy directories
@@ -1,4 +1,5 @@
1
1
  import { ConfigPlugin, withXcodeProject } from "expo/config-plugins";
2
+ import * as fs from "fs";
2
3
  import * as path from "path";
3
4
 
4
5
  import { addXCConfigurationList } from "./xcode/addXCConfigurationList";
@@ -18,18 +19,20 @@ export const withXcode: ConfigPlugin<Required<WidgetConfig>> = (
18
19
  return withXcodeProject(config, (config) => {
19
20
  const { platformProjectRoot, projectRoot } = config.modRequest;
20
21
 
21
- if (!enabled) {
22
- return config;
23
- }
24
-
25
22
  const widgetsPath = path.join(projectRoot, widgetsFolder);
26
- const targetPath = path.join(platformProjectRoot, targetName);
27
23
  const moduleRoot = path.join(
28
24
  projectRoot,
29
25
  "node_modules",
30
26
  "react-native-ios-widget",
31
27
  "ios"
32
28
  );
29
+
30
+ if (!enabled) {
31
+ ensureModuleSwift(widgetsPath, moduleRoot);
32
+ return config;
33
+ }
34
+
35
+ const targetPath = path.join(platformProjectRoot, targetName);
33
36
  const widgetFiles = getWidgetFiles(widgetsPath, targetPath, moduleRoot);
34
37
 
35
38
  const xcodeProject = config.modResults;
@@ -75,3 +78,34 @@ export const withXcode: ConfigPlugin<Required<WidgetConfig>> = (
75
78
  return config;
76
79
  });
77
80
  };
81
+
82
+ const ensureModuleSwift = (widgetsPath: string, moduleRoot: string) => {
83
+ // Ensure the pod source dir exists for Module.swift.
84
+ if (!fs.existsSync(moduleRoot)) {
85
+ fs.mkdirSync(moduleRoot, { recursive: true });
86
+ }
87
+
88
+ // Prefer the real Module.swift from widgets if it exists.
89
+ const moduleSwiftPath = path.join(widgetsPath, "Module.swift");
90
+ const targetPath = path.join(moduleRoot, "Module.swift");
91
+ if (fs.existsSync(moduleSwiftPath)) {
92
+ fs.copyFileSync(moduleSwiftPath, targetPath);
93
+ return;
94
+ }
95
+
96
+ // If widgets are disabled and no real Module.swift exists, write a stub
97
+ // so CocoaPods still builds a Swift module and avoids import errors.
98
+ if (!fs.existsSync(targetPath)) {
99
+ const stubModule = [
100
+ "import ExpoModulesCore",
101
+ "",
102
+ "public class ReactNativeWidgetExtensionModule: Module {",
103
+ " public func definition() -> ModuleDefinition {",
104
+ ' Name("ReactNativeWidgetExtension")',
105
+ " }",
106
+ "}",
107
+ "",
108
+ ].join("\n");
109
+ fs.writeFileSync(targetPath, stubModule);
110
+ }
111
+ };