react-native-config-ultimate 0.0.7 → 0.1.0

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.
Files changed (152) hide show
  1. package/android/gradle.properties +6 -0
  2. package/android/rnuc.yaml +1 -0
  3. package/lib/commonjs/NativeUltimateConfig.js +20 -0
  4. package/lib/commonjs/NativeUltimateConfig.js.map +1 -0
  5. package/lib/commonjs/bin.spec.js +50 -0
  6. package/lib/commonjs/bin.spec.js.map +1 -0
  7. package/lib/commonjs/cli.js +143 -0
  8. package/lib/commonjs/cli.js.map +1 -0
  9. package/lib/commonjs/cli.spec.js +190 -0
  10. package/lib/commonjs/cli.spec.js.map +1 -0
  11. package/lib/commonjs/flatten.js +23 -0
  12. package/lib/commonjs/flatten.js.map +1 -0
  13. package/lib/commonjs/flatten.spec.js +32 -0
  14. package/lib/commonjs/flatten.spec.js.map +1 -0
  15. package/lib/commonjs/index.js +34 -0
  16. package/lib/commonjs/index.js.map +1 -0
  17. package/lib/commonjs/load-env.js +86 -0
  18. package/lib/commonjs/load-env.js.map +1 -0
  19. package/lib/commonjs/load-env.spec.js +257 -0
  20. package/lib/commonjs/load-env.spec.js.map +1 -0
  21. package/lib/commonjs/main.js +36 -0
  22. package/lib/commonjs/main.js.map +1 -0
  23. package/lib/commonjs/main.spec.js +228 -0
  24. package/lib/commonjs/main.spec.js.map +1 -0
  25. package/lib/commonjs/package.json +1 -0
  26. package/lib/commonjs/render-env.js +90 -0
  27. package/lib/commonjs/render-env.js.map +1 -0
  28. package/lib/commonjs/render-env.spec.js +397 -0
  29. package/lib/commonjs/render-env.spec.js.map +1 -0
  30. package/lib/commonjs/resolve-env.js +30 -0
  31. package/lib/commonjs/resolve-env.js.map +1 -0
  32. package/lib/commonjs/resolve-env.spec.js +31 -0
  33. package/lib/commonjs/resolve-env.spec.js.map +1 -0
  34. package/lib/commonjs/templates/ConfigValues.h.handlebars +24 -0
  35. package/lib/commonjs/templates/index.d.ts.handlebars +18 -0
  36. package/lib/commonjs/templates/index.web.js.handlebars +1 -0
  37. package/lib/commonjs/templates/override.js.handlebars +16 -0
  38. package/lib/commonjs/templates/rncu.xcconfig.handlebars +4 -0
  39. package/lib/commonjs/templates/rncu.yaml.handlebars +7 -0
  40. package/lib/commonjs/validate-env.js +63 -0
  41. package/lib/commonjs/validate-env.js.map +1 -0
  42. package/lib/commonjs/validate-env.spec.js +325 -0
  43. package/lib/commonjs/validate-env.spec.js.map +1 -0
  44. package/lib/commonjs/write-env.js +80 -0
  45. package/lib/commonjs/write-env.js.map +1 -0
  46. package/lib/commonjs/write-env.spec.js +115 -0
  47. package/lib/commonjs/write-env.spec.js.map +1 -0
  48. package/lib/module/NativeUltimateConfig.js +16 -0
  49. package/lib/module/NativeUltimateConfig.js.map +1 -0
  50. package/lib/module/bin.spec.js +49 -0
  51. package/lib/module/bin.spec.js.map +1 -0
  52. package/lib/module/cli.js +136 -0
  53. package/lib/module/cli.js.map +1 -0
  54. package/lib/module/cli.spec.js +190 -0
  55. package/lib/module/cli.spec.js.map +1 -0
  56. package/lib/module/flatten.js +18 -0
  57. package/lib/module/flatten.js.map +1 -0
  58. package/lib/module/flatten.spec.js +31 -0
  59. package/lib/module/flatten.spec.js.map +1 -0
  60. package/lib/module/index.js +30 -0
  61. package/lib/module/index.js.map +1 -0
  62. package/lib/module/load-env.js +81 -0
  63. package/lib/module/load-env.js.map +1 -0
  64. package/lib/module/load-env.spec.js +257 -0
  65. package/lib/module/load-env.spec.js.map +1 -0
  66. package/lib/module/main.js +31 -0
  67. package/lib/module/main.js.map +1 -0
  68. package/lib/module/main.spec.js +224 -0
  69. package/lib/module/main.spec.js.map +1 -0
  70. package/lib/module/render-env.js +84 -0
  71. package/lib/module/render-env.js.map +1 -0
  72. package/lib/module/render-env.spec.js +396 -0
  73. package/lib/module/render-env.spec.js.map +1 -0
  74. package/lib/module/resolve-env.js +26 -0
  75. package/lib/module/resolve-env.js.map +1 -0
  76. package/lib/module/resolve-env.spec.js +30 -0
  77. package/lib/module/resolve-env.spec.js.map +1 -0
  78. package/lib/module/templates/ConfigValues.h.handlebars +24 -0
  79. package/lib/module/templates/index.d.ts.handlebars +18 -0
  80. package/lib/module/templates/index.web.js.handlebars +1 -0
  81. package/lib/module/templates/override.js.handlebars +16 -0
  82. package/lib/module/templates/rncu.xcconfig.handlebars +4 -0
  83. package/lib/module/templates/rncu.yaml.handlebars +7 -0
  84. package/lib/module/validate-env.js +59 -0
  85. package/lib/module/validate-env.js.map +1 -0
  86. package/lib/module/validate-env.spec.js +325 -0
  87. package/lib/module/validate-env.spec.js.map +1 -0
  88. package/lib/module/write-env.js +75 -0
  89. package/lib/module/write-env.js.map +1 -0
  90. package/lib/module/write-env.spec.js +115 -0
  91. package/lib/module/write-env.spec.js.map +1 -0
  92. package/lib/typescript/src/NativeUltimateConfig.d.ts +18 -0
  93. package/lib/typescript/src/NativeUltimateConfig.d.ts.map +1 -0
  94. package/lib/typescript/src/bin.spec.d.ts +2 -0
  95. package/lib/typescript/src/bin.spec.d.ts.map +1 -0
  96. package/lib/typescript/src/cli.d.ts +2 -0
  97. package/lib/typescript/src/cli.d.ts.map +1 -0
  98. package/lib/typescript/src/cli.spec.d.ts +14 -0
  99. package/lib/typescript/src/cli.spec.d.ts.map +1 -0
  100. package/lib/typescript/src/flatten.d.ts +8 -0
  101. package/lib/typescript/src/flatten.d.ts.map +1 -0
  102. package/lib/typescript/src/flatten.spec.d.ts +2 -0
  103. package/lib/typescript/src/flatten.spec.d.ts.map +1 -0
  104. package/lib/typescript/src/index.d.ts +6 -0
  105. package/lib/typescript/src/index.d.ts.map +1 -0
  106. package/lib/typescript/src/load-env.d.ts +23 -0
  107. package/lib/typescript/src/load-env.d.ts.map +1 -0
  108. package/lib/typescript/src/load-env.spec.d.ts +6 -0
  109. package/lib/typescript/src/load-env.spec.d.ts.map +1 -0
  110. package/lib/typescript/src/main.d.ts +12 -0
  111. package/lib/typescript/src/main.d.ts.map +1 -0
  112. package/lib/typescript/src/main.spec.d.ts +2 -0
  113. package/lib/typescript/src/main.spec.d.ts.map +1 -0
  114. package/lib/typescript/src/render-env.d.ts +11 -0
  115. package/lib/typescript/src/render-env.d.ts.map +1 -0
  116. package/lib/typescript/src/render-env.spec.d.ts +2 -0
  117. package/lib/typescript/src/render-env.spec.d.ts.map +1 -0
  118. package/lib/typescript/src/resolve-env.d.ts +35 -0
  119. package/lib/typescript/src/resolve-env.d.ts.map +1 -0
  120. package/lib/typescript/src/resolve-env.spec.d.ts +2 -0
  121. package/lib/typescript/src/resolve-env.spec.d.ts.map +1 -0
  122. package/lib/typescript/src/validate-env.d.ts +10 -0
  123. package/lib/typescript/src/validate-env.d.ts.map +1 -0
  124. package/lib/typescript/src/validate-env.spec.d.ts +2 -0
  125. package/lib/typescript/src/validate-env.spec.d.ts.map +1 -0
  126. package/lib/typescript/src/write-env.d.ts +13 -0
  127. package/lib/typescript/src/write-env.d.ts.map +1 -0
  128. package/lib/typescript/src/write-env.spec.d.ts +9 -0
  129. package/lib/typescript/src/write-env.spec.d.ts.map +1 -0
  130. package/package.json +84 -52
  131. package/src/NativeUltimateConfig.ts +1 -2
  132. package/src/cli.ts +158 -0
  133. package/src/flatten.ts +26 -0
  134. package/src/index.ts +37 -0
  135. package/src/load-env.ts +81 -0
  136. package/src/main.ts +39 -0
  137. package/src/render-env.ts +111 -0
  138. package/src/resolve-env.ts +45 -0
  139. package/src/validate-env.ts +71 -0
  140. package/src/write-env.ts +74 -0
  141. package/bin.js +0 -5
  142. package/index.js +0 -28
  143. package/override.js +0 -1
  144. package/src/NativeUltimateConfig.js +0 -4
  145. package/src/cli.js +0 -176
  146. package/src/flatten.js +0 -22
  147. package/src/load-env.js +0 -107
  148. package/src/main.js +0 -34
  149. package/src/render-env.js +0 -113
  150. package/src/resolve-env.js +0 -12
  151. package/src/validate-env.js +0 -59
  152. package/src/write-env.js +0 -102
@@ -0,0 +1 @@
1
+ {"version":3,"file":"load-env.d.ts","sourceRoot":"","sources":["../../../src/load-env.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAiB7C;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,CAAC,OAAO,UAAU,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,OAAO,CAqCzE"}
@@ -0,0 +1,6 @@
1
+ declare const mockReadFileSync: jest.Mock<any, any, any>;
2
+ declare const mockParse: jest.Mock<any, any, any>;
3
+ declare const mockExpand: jest.Mock<any, any, any>;
4
+ declare const mockYaml: jest.Mock<any, any, any>;
5
+ declare const load_env: (paths: string | string[]) => Record<string, unknown>;
6
+ //# sourceMappingURL=load-env.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"load-env.spec.d.ts","sourceRoot":"","sources":["../../../src/load-env.spec.ts"],"names":[],"mappings":"AAAA,QAAA,MAAM,gBAAgB,0BAAY,CAAC;AAGnC,QAAA,MAAM,SAAS,0BAAY,CAAC;AAG5B,QAAA,MAAM,UAAU,0BAAY,CAAC;AAG7B,QAAA,MAAM,QAAQ,0BAAY,CAAC;AAI3B,QAAA,MAAM,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,KAAK,MAAM,CAAC,MAAM,EAAE,OAAO,CACrC,CAAC"}
@@ -0,0 +1,12 @@
1
+ import type { RC } from './resolve-env';
2
+ /**
3
+ * Main build-time pipeline:
4
+ * load → resolve (on_env hook) → validate (schema) → flatten → render → write
5
+ *
6
+ * @param project_root Root of the React Native project
7
+ * @param lib_root Root of the react-native-config-ultimate install
8
+ * @param env_file Path(s) to env file(s). Multiple files are merged (last wins).
9
+ * @param rc Optional RC config from `.rncurc.js`
10
+ */
11
+ export default function main(project_root: string, lib_root: string, env_file: string | string[], rc?: RC): Promise<void>;
12
+ //# sourceMappingURL=main.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../../src/main.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,EAAE,EAAW,MAAM,eAAe,CAAC;AAGjD;;;;;;;;GAQG;AACH,wBAA8B,IAAI,CAChC,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,EAC3B,EAAE,CAAC,EAAE,EAAE,GACN,OAAO,CAAC,IAAI,CAAC,CAcf"}
@@ -0,0 +1,2 @@
1
+ export declare const files_to_assert: string[];
2
+ //# sourceMappingURL=main.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.spec.d.ts","sourceRoot":"","sources":["../../../src/main.spec.ts"],"names":[],"mappings":"AAcA,eAAO,MAAM,eAAe,UAO3B,CAAC"}
@@ -0,0 +1,11 @@
1
+ import type { FlatConfig } from './flatten';
2
+ import type { RC } from './resolve-env';
3
+ import type { FileMap } from './write-env';
4
+ interface PlatformEnv {
5
+ ios: FlatConfig;
6
+ android: FlatConfig;
7
+ web: FlatConfig;
8
+ }
9
+ export default function render_env(project_root: string, lib_root: string, env: PlatformEnv, rc?: RC): FileMap;
10
+ export {};
11
+ //# sourceMappingURL=render-env.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render-env.d.ts","sourceRoot":"","sources":["../../../src/render-env.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAoE3C,UAAU,WAAW;IACnB,GAAG,EAAE,UAAU,CAAC;IAChB,OAAO,EAAE,UAAU,CAAC;IACpB,GAAG,EAAE,UAAU,CAAC;CACjB;AAED,MAAM,CAAC,OAAO,UAAU,UAAU,CAChC,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,WAAW,EAChB,EAAE,CAAC,EAAE,EAAE,GACN,OAAO,CAyBT"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=render-env.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render-env.spec.d.ts","sourceRoot":"","sources":["../../../src/render-env.spec.ts"],"names":[],"mappings":""}
@@ -0,0 +1,35 @@
1
+ export type EnvData = Record<string, unknown>;
2
+ /**
3
+ * Schema definition for a single environment variable.
4
+ * Used in `.rncurc.js` to validate env vars at build time.
5
+ *
6
+ * @example
7
+ * module.exports = {
8
+ * schema: {
9
+ * API_URL: { type: 'string', required: true },
10
+ * TIMEOUT_MS: { type: 'number', required: true },
11
+ * DEBUG: { type: 'boolean', required: false },
12
+ * ENV_NAME: { type: 'string', required: true, pattern: '^(dev|staging|prod)$' },
13
+ * }
14
+ * };
15
+ */
16
+ export interface SchemaField {
17
+ /** Expected type. Strings are always accepted as-is; number/boolean validate parsability. */
18
+ type: 'string' | 'number' | 'boolean';
19
+ /** If true, build fails when this var is missing or empty. Default: false. */
20
+ required?: boolean;
21
+ /** Optional regex pattern the value must match (applied to string representation). */
22
+ pattern?: string;
23
+ }
24
+ export type Schema = Record<string, SchemaField>;
25
+ export interface RC {
26
+ on_env?: (env: EnvData) => unknown;
27
+ js_override?: boolean;
28
+ /**
29
+ * Optional schema for build-time validation of env vars.
30
+ * Validated after `on_env` runs (so the hook can add/transform vars before validation).
31
+ */
32
+ schema?: Schema;
33
+ }
34
+ export default function resolve_env(env: EnvData, rc?: RC): Promise<EnvData>;
35
+ //# sourceMappingURL=resolve-env.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve-env.d.ts","sourceRoot":"","sources":["../../../src/resolve-env.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAE9C;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,WAAW;IAC1B,6FAA6F;IAC7F,IAAI,EAAE,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAAC;IACtC,8EAA8E;IAC9E,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,sFAAsF;IACtF,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;AAEjD,MAAM,WAAW,EAAE;IACjB,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC;IACnC,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAA8B,WAAW,CAAC,GAAG,EAAE,OAAO,EAAE,EAAE,CAAC,EAAE,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAOjF"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=resolve-env.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve-env.spec.d.ts","sourceRoot":"","sources":["../../../src/resolve-env.spec.ts"],"names":[],"mappings":""}
@@ -0,0 +1,10 @@
1
+ import type { EnvData, Schema } from './resolve-env';
2
+ /**
3
+ * Validate env data against a schema defined in `.rncurc.js`.
4
+ * Called after `on_env` so the hook can add/transform vars before validation.
5
+ *
6
+ * Throws with a human-readable error listing ALL failures at once
7
+ * (not just the first one), so users can fix everything in one pass.
8
+ */
9
+ export declare function validate_env(env: EnvData, schema: Schema): void;
10
+ //# sourceMappingURL=validate-env.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate-env.d.ts","sourceRoot":"","sources":["../../../src/validate-env.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAIrD;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CA2D/D"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=validate-env.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate-env.spec.d.ts","sourceRoot":"","sources":["../../../src/validate-env.spec.ts"],"names":[],"mappings":""}
@@ -0,0 +1,13 @@
1
+ export type FileMap = Record<string, string>;
2
+ /**
3
+ * Atomically write all generated files.
4
+ *
5
+ * Strategy: write each file to a temp path first, then rename (atomic on POSIX).
6
+ * If any write fails, we abort before committing any renames so the project
7
+ * is never left in a partially-written state.
8
+ *
9
+ * On Windows, `fs.renameSync` across drives may fail — in that case we fall
10
+ * back to a direct `writeFileSync` (best-effort, still better than nothing).
11
+ */
12
+ export default function write_env(files: FileMap): void;
13
+ //# sourceMappingURL=write-env.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"write-env.d.ts","sourceRoot":"","sources":["../../../src/write-env.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAE7C;;;;;;;;;GASG;AACH,MAAM,CAAC,OAAO,UAAU,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAyDtD"}
@@ -0,0 +1,9 @@
1
+ declare const mockWriteFileSync: jest.Mock<any, any, any>;
2
+ declare const mockRenameSync: jest.Mock<any, any, any>;
3
+ declare const mockUnlinkSync: jest.Mock<any, any, any>;
4
+ declare const mockCopyFileSync: jest.Mock<any, any, any>;
5
+ declare const mockMkdirSync: jest.Mock<any, any, any>;
6
+ declare const write_env: (env: Record<string, string>) => void;
7
+ /** Returns the temp file path used for a given destination. */
8
+ declare function tmp_for(dest: string): string;
9
+ //# sourceMappingURL=write-env.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"write-env.spec.d.ts","sourceRoot":"","sources":["../../../src/write-env.spec.ts"],"names":[],"mappings":"AACA,QAAA,MAAM,iBAAiB,0BAAY,CAAC;AACpC,QAAA,MAAM,cAAc,0BAAY,CAAC;AACjC,QAAA,MAAM,cAAc,0BAAY,CAAC;AACjC,QAAA,MAAM,gBAAgB,0BAAY,CAAC;AACnC,QAAA,MAAM,aAAa,0BAAY,CAAC;AAahC,QAAA,MAAM,SAAS,EAAE,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,IAAqC,CAAC;AAIxF,+DAA+D;AAC/D,iBAAS,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAGrC"}
package/package.json CHANGED
@@ -1,59 +1,53 @@
1
1
  {
2
2
  "name": "react-native-config-ultimate",
3
3
  "title": "React Native Config Ultimate",
4
- "version": "0.0.7",
4
+ "version": "0.1.0",
5
5
  "description": "Config that works. A community-maintained fork of react-native-ultimate-config.",
6
- "main": "index.js",
7
- "module": "index.js",
8
- "react-native": "index.js",
9
- "source": "index.ts",
10
- "browser": "index.web.js",
11
- "types": "index.d.ts",
6
+ "main": "./lib/commonjs/index.js",
7
+ "module": "./lib/module/index.js",
8
+ "types": "./lib/typescript/src/index.d.ts",
9
+ "react-native": "./src/index.ts",
10
+ "source": "./src/index.ts",
12
11
  "exports": {
13
12
  ".": {
14
- "react-native": "./index.js",
15
- "import": "./index.js",
16
- "require": "./index.js",
17
- "default": "./index.js"
18
- }
13
+ "react-native": "./src/index.ts",
14
+ "source": "./src/index.ts",
15
+ "types": "./lib/typescript/src/index.d.ts",
16
+ "default": "./lib/module/index.js"
17
+ },
18
+ "./package.json": "./package.json"
19
19
  },
20
20
  "files": [
21
- "bin.js",
22
- "index.js",
23
- "index.d.ts",
24
- "index.web.js",
25
- "src/*.js",
26
- "!src/*.spec.js",
27
- "src/NativeUltimateConfig.ts",
28
- "src/templates",
29
- "override.js",
30
- "ios/UltimateConfig.{h,mm}",
31
- "ios/ConfigValues.h",
32
- "ios/UltimateConfig.xcodeproj/project.pbxproj",
33
- "android/src",
34
- "android/build.gradle",
35
- "android/rncu.gradle",
36
- "react-native-config-ultimate.podspec"
21
+ "src",
22
+ "lib",
23
+ "android",
24
+ "ios",
25
+ "*.podspec",
26
+ "!src/**/*.spec.ts",
27
+ "!src/test_outputs",
28
+ "!ios/build",
29
+ "!android/build",
30
+ "!android/gradle",
31
+ "!android/gradlew",
32
+ "!android/gradlew.bat",
33
+ "!android/local.properties",
34
+ "!**/__tests__",
35
+ "!**/__fixtures__",
36
+ "!**/__mocks__",
37
+ "!**/.*"
37
38
  ],
38
39
  "scripts": {
39
- "build": "tsc",
40
+ "example": "yarn workspace react-native-config-ultimate-example",
41
+ "build": "bob build && node -e \"const fs=require('fs');const f='lib/commonjs/cli.js';const c=fs.readFileSync(f,'utf8');if(!c.startsWith('#!')){fs.writeFileSync(f,'#!/usr/bin/env node\\n'+c)}\"",
42
+ "clean": "del-cli android/build example/android/build example/android/app/build example/ios/build lib",
43
+ "prepare": "npm run build",
44
+ "prepack": "printf '#error \"react-native-config-ultimate: ConfigValues.h not generated. Run: npx rncu .env from your project root before building iOS.\\n\"' > ios/ConfigValues.h",
40
45
  "typecheck": "tsc --noEmit",
41
- "pretest": "tsc",
42
46
  "test": "jest",
43
- "prepack": "printf '#error \"react-native-config-ultimate: ConfigValues.h not generated. Run: npx rncu .env from your project root before building iOS.\\n\"' > ios/ConfigValues.h && echo 'module.exports = {};' > override.js",
44
- "lint": "eslint src/**/*.ts index.ts --max-warnings=0",
45
- "format": "prettier --write src/**/*.ts index.ts"
47
+ "lint": "eslint \"src/**/*.{js,ts,tsx}\" --max-warnings=0"
46
48
  },
47
49
  "bin": {
48
- "rncu": "./bin.js"
49
- },
50
- "repository": {
51
- "type": "git",
52
- "url": "git+https://github.com/javier545dev/react-native-config-ultimate.git"
53
- },
54
- "homepage": "https://github.com/javier545dev/react-native-config-ultimate#readme",
55
- "bugs": {
56
- "url": "https://github.com/javier545dev/react-native-config-ultimate/issues"
50
+ "rncu": "./lib/commonjs/cli.js"
57
51
  },
58
52
  "keywords": [
59
53
  "react-native",
@@ -76,6 +70,10 @@
76
70
  "new-architecture",
77
71
  "turbomodules"
78
72
  ],
73
+ "repository": {
74
+ "type": "git",
75
+ "url": "git+https://github.com/javier545dev/react-native-config-ultimate.git"
76
+ },
79
77
  "author": {
80
78
  "name": "Javier Fuentes",
81
79
  "email": "javierfuentes545@gmail.com"
@@ -88,26 +86,40 @@
88
86
  }
89
87
  ],
90
88
  "license": "MIT",
91
- "peerDependencies": {
92
- "react-native": ">=0.73.0 <1.0.x"
89
+ "bugs": {
90
+ "url": "https://github.com/javier545dev/react-native-config-ultimate/issues"
91
+ },
92
+ "homepage": "https://github.com/javier545dev/react-native-config-ultimate#readme",
93
+ "publishConfig": {
94
+ "registry": "https://registry.npmjs.org/"
93
95
  },
94
96
  "devDependencies": {
97
+ "@eslint/compat": "^1.3.2",
98
+ "@eslint/eslintrc": "^3.3.1",
99
+ "@eslint/js": "^9.35.0",
100
+ "@react-native/babel-preset": "0.83.0",
101
+ "@react-native/eslint-config": "0.83.0",
95
102
  "@types/jest": "^29.5.0",
96
103
  "@types/js-yaml": "^4.0.9",
97
104
  "@types/node": "^20.0.0",
105
+ "@types/react": "^19.2.0",
98
106
  "@types/yargs": "^17.0.35",
99
- "@typescript-eslint/eslint-plugin": "^8.20.0",
100
- "@typescript-eslint/parser": "^8.20.0",
101
- "eslint": "^9.17.0",
107
+ "del-cli": "^6.0.0",
108
+ "eslint": "^9.35.0",
109
+ "eslint-config-prettier": "^10.1.8",
110
+ "eslint-plugin-prettier": "^5.5.4",
102
111
  "jest": "^29.7.0",
103
112
  "prettier": "^3.4.2",
104
- "react": "^19.0.0",
105
- "react-native": "0.79.5",
113
+ "react": "19.2.0",
114
+ "react-native": "0.83.0",
115
+ "react-native-builder-bob": "^0.40.18",
106
116
  "ts-jest": "^29.2.0",
107
- "typescript": "^5.5.4"
117
+ "turbo": "^2.5.6",
118
+ "typescript": "^5.9.2"
108
119
  },
109
- "engines": {
110
- "node": ">= 18.0.0"
120
+ "peerDependencies": {
121
+ "react": "*",
122
+ "react-native": "*"
111
123
  },
112
124
  "dependencies": {
113
125
  "chokidar": "4.0.3",
@@ -117,6 +129,19 @@
117
129
  "js-yaml": "^4",
118
130
  "yargs": "^17"
119
131
  },
132
+ "workspaces": [
133
+ "example"
134
+ ],
135
+ "packageManager": "yarn@4.11.0",
136
+ "react-native-builder-bob": {
137
+ "source": "src",
138
+ "output": "lib",
139
+ "targets": [
140
+ "commonjs",
141
+ "module",
142
+ "typescript"
143
+ ]
144
+ },
120
145
  "codegenConfig": {
121
146
  "name": "RNUltimateConfigSpec",
122
147
  "type": "modules",
@@ -124,5 +149,12 @@
124
149
  "android": {
125
150
  "javaPackageName": "com.reactnativeultimateconfig"
126
151
  }
152
+ },
153
+ "prettier": {
154
+ "quoteProps": "consistent",
155
+ "singleQuote": true,
156
+ "tabWidth": 2,
157
+ "trailingComma": "es5",
158
+ "useTabs": false
127
159
  }
128
160
  }
@@ -9,8 +9,7 @@
9
9
  * - getAll() returns all config values as a JSON-encoded string, which Codegen handles perfectly
10
10
  * - This gives us a working TurboModule binding for New Architecture
11
11
  */
12
- import type { TurboModule } from 'react-native/Libraries/TurboModule/RCTExport';
13
- import { TurboModuleRegistry } from 'react-native';
12
+ import { TurboModuleRegistry, type TurboModule } from 'react-native';
14
13
 
15
14
  export interface Spec extends TurboModule {
16
15
  // Returns all config values as a JSON-encoded string.
package/src/cli.ts ADDED
@@ -0,0 +1,158 @@
1
+ import yargs from 'yargs';
2
+ import * as path from 'path';
3
+ import * as fs from 'fs';
4
+ import { watch } from 'chokidar';
5
+ import main from './main';
6
+ import type { RC } from './resolve-env';
7
+
8
+ /**
9
+ * Load the RC file fresh on every call (clears require cache so
10
+ * changes to .rncurc.js are picked up during --watch mode).
11
+ */
12
+ function load_rc(rc_file: string): RC | undefined {
13
+ if (!fs.existsSync(rc_file)) return undefined;
14
+ delete require.cache[require.resolve(rc_file)];
15
+ // eslint-disable-next-line @typescript-eslint/no-var-requires, @typescript-eslint/no-require-imports
16
+ return require(rc_file) as RC;
17
+ }
18
+
19
+ function log(msg: string): void {
20
+ process.stdout.write(`[rncu] ${msg}\n`);
21
+ }
22
+
23
+ function log_err(msg: string): void {
24
+ process.stderr.write(`[rncu] ✗ ${msg}\n`);
25
+ }
26
+
27
+ export default async function cli(): Promise<void> {
28
+ const argv = await yargs(process.argv.slice(2))
29
+ .option('projectRoot', {
30
+ type: 'string',
31
+ default: process.cwd(),
32
+ description: 'Root directory of the React Native project',
33
+ })
34
+ .option('libRoot', {
35
+ type: 'string',
36
+ description:
37
+ 'Root directory of react-native-config-ultimate ' +
38
+ '(defaults to <projectRoot>/node_modules/react-native-config-ultimate)',
39
+ })
40
+ .option('watch', {
41
+ alias: 'w',
42
+ type: 'boolean',
43
+ default: false,
44
+ description:
45
+ 'Watch env file(s) for changes and regenerate automatically. ' +
46
+ 'Note: changes to native vars (iOS xcconfig, Android BuildConfig) ' +
47
+ 'still require a full native rebuild.',
48
+ })
49
+ .usage('Usage: $0 <env-file> [env-file2 ...] [options]')
50
+ .help()
51
+ .parseAsync();
52
+
53
+ const project_root = argv.projectRoot;
54
+
55
+ /**
56
+ * Resolve the library root directory.
57
+ *
58
+ * Priority:
59
+ * 1. --libRoot flag (explicit override)
60
+ * 2. Conventional path <projectRoot>/node_modules/react-native-config-ultimate
61
+ * — used when the directory exists (standard install, or bin.spec.ts integration test).
62
+ * 3. require.resolve() — handles npm workspaces hoisting, pnpm, Yarn PnP,
63
+ * and any layout where the package is hoisted above projectRoot.
64
+ * 4. Fall back to conventional path even if it doesn't exist yet
65
+ * (write-env.ts will create the directories on first run).
66
+ */
67
+ const lib_root: string = (() => {
68
+ if (argv.libRoot) return argv.libRoot;
69
+
70
+ const conventional = path.join(project_root, 'node_modules', 'react-native-config-ultimate');
71
+
72
+ // If the directory already exists at the conventional location, use it.
73
+ // This handles standard installs and the integration test temp-dir setup.
74
+ if (fs.existsSync(conventional)) return conventional;
75
+
76
+ // Otherwise, try require.resolve to handle hoisted workspaces.
77
+ try {
78
+ const pkg_json = require.resolve('react-native-config-ultimate/package.json', {
79
+ paths: [project_root],
80
+ });
81
+ return path.dirname(pkg_json);
82
+ } catch {
83
+ // Last resort: return the conventional path and let write-env create it.
84
+ return conventional;
85
+ }
86
+ })();
87
+
88
+ // Accept one or more positional env file paths.
89
+ // Multiple files are merged left-to-right (last file wins for conflicting keys).
90
+ const env_files = argv._.map(String);
91
+
92
+ // Validate env files exist before running anything.
93
+ const missing_files = env_files.filter((f) => !fs.existsSync(f));
94
+ if (missing_files.length > 0) {
95
+ for (const f of missing_files) {
96
+ log_err(`env file not found: ${f}`);
97
+ }
98
+ process.exit(1);
99
+ }
100
+
101
+ const rc_file = path.resolve(project_root, '.rncurc.js');
102
+
103
+ // Helper: run the full pipeline once, returning duration in ms.
104
+ // Never throws — errors are caught and logged so watch mode stays alive.
105
+ async function run(changed_path?: string): Promise<void> {
106
+ if (changed_path) {
107
+ log(`${changed_path} changed → regenerating...`);
108
+ }
109
+ const start = Date.now();
110
+ try {
111
+ const rc = load_rc(rc_file);
112
+ await main(project_root, lib_root, env_files, rc);
113
+ if (changed_path) {
114
+ log(`✓ done in ${Date.now() - start}ms`);
115
+ }
116
+ } catch (err) {
117
+ log_err(err instanceof Error ? err.message : String(err));
118
+ }
119
+ }
120
+
121
+ // Initial run (always runs, throws on error in non-watch mode).
122
+ if (!argv.watch) {
123
+ const rc = load_rc(rc_file);
124
+ await main(project_root, lib_root, env_files, rc);
125
+ return;
126
+ }
127
+
128
+ // --watch mode ────────────────────────────────────────────────────────────
129
+ // Initial run (errors are caught — we still want to start watching).
130
+ await run();
131
+
132
+ // Files to watch: env files + RC file (if it exists).
133
+ const files_to_watch = [...env_files, ...(fs.existsSync(rc_file) ? [rc_file] : [])];
134
+
135
+ const watcher = watch(files_to_watch, {
136
+ ignoreInitial: true,
137
+ persistent: true,
138
+ });
139
+
140
+ log(
141
+ `watching: ${files_to_watch.join(', ')}\n` +
142
+ `[rncu] ⚠ native vars (xcconfig/BuildConfig) require a full rebuild to take effect`
143
+ );
144
+
145
+ watcher.on('change', (p) => void run(p));
146
+ watcher.on('add', (p) => void run(p));
147
+
148
+ // Keep the process alive (chokidar persistent:true already does this,
149
+ // but stdin.resume makes it explicit and survives edge cases).
150
+ process.stdin.resume();
151
+
152
+ // Graceful shutdown on Ctrl+C.
153
+ process.on('SIGINT', () => {
154
+ process.stdout.write('\n');
155
+ log('stopping...');
156
+ void watcher.close().then(() => process.exit(0));
157
+ });
158
+ }
package/src/flatten.ts ADDED
@@ -0,0 +1,26 @@
1
+ import assert from 'assert';
2
+
3
+ type Platform = 'ios' | 'android' | 'web';
4
+ export type ConfigValue = string | number | boolean;
5
+ export type PerPlatformValue = Partial<Record<Platform, ConfigValue>>;
6
+ export type EnvConfig = Record<string, ConfigValue | PerPlatformValue>;
7
+ export type FlatConfig = Record<string, ConfigValue | undefined>;
8
+
9
+ const VALID_PLATFORMS: Platform[] = ['ios', 'android', 'web'];
10
+
11
+ export default function flatten(config: EnvConfig, platform: Platform): FlatConfig {
12
+ assert(config && typeof config === 'object', 'Config should be non-null object');
13
+ assert(
14
+ VALID_PLATFORMS.includes(platform),
15
+ '`platform` should one of: ' + VALID_PLATFORMS.join(', ')
16
+ );
17
+ const result: FlatConfig = {};
18
+ for (const [key, value] of Object.entries(config)) {
19
+ if (value && typeof value === 'object') {
20
+ result[key] = (value as PerPlatformValue)[platform];
21
+ } else {
22
+ result[key] = value as ConfigValue;
23
+ }
24
+ }
25
+ return result;
26
+ }
package/src/index.ts ADDED
@@ -0,0 +1,37 @@
1
+ import { TurboModuleRegistry, NativeModules } from 'react-native';
2
+ import type { Spec } from './NativeUltimateConfig';
3
+
4
+ export type ConfigValue = string | number | boolean;
5
+ export type { Spec } from './NativeUltimateConfig';
6
+
7
+ type Config = Record<string, ConfigValue>;
8
+
9
+ // override.js is dynamically generated by the rncu CLI at the package root.
10
+ // It contains platform-specific overrides. Do not commit override.js to git.
11
+ // eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires
12
+ const override: Config = require('../override');
13
+
14
+ // New Architecture: TurboModules are accessed via TurboModuleRegistry.
15
+ // The spec exposes getAll(): string — returns config values as JSON.
16
+ // Old Architecture: constants are exposed directly on NativeModules via constantsToExport.
17
+ const turboModule = TurboModuleRegistry.get<Spec>('UltimateConfig');
18
+
19
+ let nativeConstants: Config;
20
+
21
+ if (turboModule != null && typeof turboModule.getAll === 'function') {
22
+ // New Arch: call getAll() and parse JSON
23
+ try {
24
+ const raw = turboModule.getAll();
25
+ nativeConstants = JSON.parse(raw) as Config;
26
+ } catch {
27
+ nativeConstants = {};
28
+ }
29
+ } else {
30
+ // Old Arch / interop bridge: constants are properties on NativeModules.UltimateConfig
31
+ nativeConstants = (NativeModules.UltimateConfig as Config | undefined) ?? {};
32
+ }
33
+
34
+ export default {
35
+ ...nativeConstants,
36
+ ...override,
37
+ } as Config;