voltra 2.0.0 → 2.1.1

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 (84) hide show
  1. package/build/cjs/config/normalize.js +93 -0
  2. package/build/cjs/config/normalize.js.map +1 -1
  3. package/build/cjs/index.js +5 -2
  4. package/build/cjs/index.js.map +1 -1
  5. package/build/cjs/platforms/android/apply.js +11 -2
  6. package/build/cjs/platforms/android/apply.js.map +1 -1
  7. package/build/cjs/platforms/android/generated.js +152 -130
  8. package/build/cjs/platforms/android/generated.js.map +1 -1
  9. package/build/cjs/platforms/android/gradle.js +120 -0
  10. package/build/cjs/platforms/android/gradle.js.map +1 -0
  11. package/build/cjs/platforms/ios/generated.js +246 -142
  12. package/build/cjs/platforms/ios/generated.js.map +1 -1
  13. package/build/cjs/platforms/ios/xcodeTarget.js +68 -0
  14. package/build/cjs/platforms/ios/xcodeTarget.js.map +1 -1
  15. package/build/cjs/platforms/shared/widgetModule.js +151 -0
  16. package/build/cjs/platforms/shared/widgetModule.js.map +1 -0
  17. package/build/esm/config/normalize.js +93 -0
  18. package/build/esm/config/normalize.js.map +1 -1
  19. package/build/esm/index.js +1 -0
  20. package/build/esm/index.js.map +1 -1
  21. package/build/esm/platforms/android/apply.js +11 -2
  22. package/build/esm/platforms/android/apply.js.map +1 -1
  23. package/build/esm/platforms/android/generated.js +152 -97
  24. package/build/esm/platforms/android/generated.js.map +1 -1
  25. package/build/esm/platforms/android/gradle.js +112 -0
  26. package/build/esm/platforms/android/gradle.js.map +1 -0
  27. package/build/esm/platforms/ios/generated.js +246 -109
  28. package/build/esm/platforms/ios/generated.js.map +1 -1
  29. package/build/esm/platforms/ios/xcodeTarget.js +69 -1
  30. package/build/esm/platforms/ios/xcodeTarget.js.map +1 -1
  31. package/build/esm/platforms/shared/widgetModule.js +111 -0
  32. package/build/esm/platforms/shared/widgetModule.js.map +1 -0
  33. package/build/types/config/normalize.d.ts.map +1 -1
  34. package/build/types/config/types.d.ts +32 -0
  35. package/build/types/config/types.d.ts.map +1 -1
  36. package/build/types/index.d.ts +3 -1
  37. package/build/types/index.d.ts.map +1 -1
  38. package/build/types/platforms/android/apply.d.ts.map +1 -1
  39. package/build/types/platforms/android/generated.d.ts.map +1 -1
  40. package/build/types/platforms/android/gradle.d.ts +18 -0
  41. package/build/types/platforms/android/gradle.d.ts.map +1 -0
  42. package/build/types/platforms/ios/generated.d.ts.map +1 -1
  43. package/build/types/platforms/ios/xcodeTarget.d.ts.map +1 -1
  44. package/build/types/platforms/shared/widgetModule.d.ts +9 -0
  45. package/build/types/platforms/shared/widgetModule.d.ts.map +1 -0
  46. package/package.json +2 -1
  47. package/src/apply/index.ts +309 -0
  48. package/src/apply/preflight.ts +172 -0
  49. package/src/bin.ts +14 -0
  50. package/src/commands/apply.ts +114 -0
  51. package/src/config/defaults.ts +34 -0
  52. package/src/config/load.ts +100 -0
  53. package/src/config/normalize.ts +562 -0
  54. package/src/config/types.ts +317 -0
  55. package/src/cosmiconfig.d.ts +21 -0
  56. package/src/dependencies/platformPackages.ts +75 -0
  57. package/src/discovery/android.ts +233 -0
  58. package/src/discovery/ios.ts +579 -0
  59. package/src/fs/path.ts +25 -0
  60. package/src/fs/readWrite.ts +102 -0
  61. package/src/git/status.ts +205 -0
  62. package/src/index.ts +204 -0
  63. package/src/platforms/android/apply.ts +106 -0
  64. package/src/platforms/android/generated.ts +1284 -0
  65. package/src/platforms/android/gradle.ts +155 -0
  66. package/src/platforms/android/manifest.ts +379 -0
  67. package/src/platforms/ios/apply.ts +139 -0
  68. package/src/platforms/ios/deploymentTarget.ts +47 -0
  69. package/src/platforms/ios/entitlements.ts +146 -0
  70. package/src/platforms/ios/generated.ts +1233 -0
  71. package/src/platforms/ios/mainAppEntitlements.ts +11 -0
  72. package/src/platforms/ios/plist.ts +321 -0
  73. package/src/platforms/ios/podfile.ts +255 -0
  74. package/src/platforms/ios/targetName.ts +11 -0
  75. package/src/platforms/ios/xcode.ts +181 -0
  76. package/src/platforms/ios/xcodeTarget.ts +899 -0
  77. package/src/platforms/shared/widgetModule.ts +153 -0
  78. package/src/reporting/clack.ts +67 -0
  79. package/src/reporting/summary.ts +116 -0
  80. package/src/state/diff.ts +21 -0
  81. package/src/state/files.ts +52 -0
  82. package/src/state/load.ts +66 -0
  83. package/src/state/save.ts +31 -0
  84. package/src/xml2js.d.ts +23 -0
@@ -0,0 +1,47 @@
1
+ export const VOLTRA_MIN_IOS_DEPLOYMENT_TARGET = '16.4'
2
+
3
+ export function compareIOSDeploymentTargets(left: string, right: string): number | undefined {
4
+ const leftParts = parseIOSDeploymentTarget(left)
5
+ const rightParts = parseIOSDeploymentTarget(right)
6
+
7
+ if (!leftParts || !rightParts) {
8
+ return undefined
9
+ }
10
+
11
+ const length = Math.max(leftParts.length, rightParts.length)
12
+
13
+ for (let index = 0; index < length; index += 1) {
14
+ const leftPart = leftParts[index] ?? 0
15
+ const rightPart = rightParts[index] ?? 0
16
+
17
+ if (leftPart > rightPart) {
18
+ return 1
19
+ }
20
+
21
+ if (leftPart < rightPart) {
22
+ return -1
23
+ }
24
+ }
25
+
26
+ return 0
27
+ }
28
+
29
+ export function isIOSDeploymentTargetAtLeast(value: string, minimum: string): boolean | undefined {
30
+ const comparison = compareIOSDeploymentTargets(value, minimum)
31
+ return comparison === undefined ? undefined : comparison >= 0
32
+ }
33
+
34
+ export function maxIOSDeploymentTarget(left: string, right: string): string {
35
+ const comparison = compareIOSDeploymentTargets(left, right)
36
+ return comparison !== undefined && comparison >= 0 ? left : right
37
+ }
38
+
39
+ function parseIOSDeploymentTarget(value: string): number[] | undefined {
40
+ const normalizedValue = value.trim().replace(/^"|"$/g, '').replace(/^'|'$/g, '')
41
+
42
+ if (!/^\d+(?:\.\d+){0,2}$/.test(normalizedValue)) {
43
+ return undefined
44
+ }
45
+
46
+ return normalizedValue.split('.').map((part) => Number(part))
47
+ }
@@ -0,0 +1,146 @@
1
+ import { pathExists, readTextFile, writeTextFile } from '../../fs/readWrite'
2
+ import { toRelativePath } from '../../fs/path'
3
+ import { VoltraCliError } from '../../reporting/summary'
4
+
5
+ import { buildPlistXml, parsePlistFile } from './plist'
6
+ import { resolveMainAppEntitlementsPath } from './mainAppEntitlements'
7
+
8
+ import type { IOSProjectDiscovery } from '../../discovery/ios'
9
+ import type { NormalizedVoltraIOSConfig } from '../../config/types'
10
+ import type { ReportedChange } from '../../reporting/summary'
11
+
12
+ interface PreviousVoltraEntitlementValues {
13
+ appGroupIdentifier?: string
14
+ keychainGroup?: string
15
+ pushNotificationsEnabled: boolean
16
+ }
17
+
18
+ export interface EnsureEntitlementsOptions {
19
+ projectRoot: string
20
+ ios: NormalizedVoltraIOSConfig
21
+ discovery: IOSProjectDiscovery
22
+ }
23
+
24
+ export interface EnsureEntitlementsResult {
25
+ change?: ReportedChange
26
+ }
27
+
28
+ export class IOSEntitlementsMutationError extends VoltraCliError {
29
+ constructor(message: string) {
30
+ super(message, 'VOLTRA_IOS_ENTITLEMENTS_FAILED')
31
+ this.name = 'IOSEntitlementsMutationError'
32
+ }
33
+ }
34
+
35
+ export async function ensureEntitlements(options: EnsureEntitlementsOptions): Promise<EnsureEntitlementsResult> {
36
+ const { projectRoot, ios, discovery } = options
37
+ const entitlementsPath = resolveMainAppEntitlementsPath(discovery)
38
+
39
+ if (!discovery.entitlementsPath) {
40
+ if (!needsEntitlementsMutation(ios)) {
41
+ return {}
42
+ }
43
+ }
44
+
45
+ const entitlements: Record<string, unknown> = (await pathExists(entitlementsPath))
46
+ ? await parsePlistFile(entitlementsPath, 'main app entitlements', createEntitlementsError)
47
+ : {}
48
+ const previousVoltraValues = await readPreviousVoltraEntitlementValues(discovery.infoPlistPath)
49
+
50
+ ensureStringArrayValue(
51
+ entitlements,
52
+ 'com.apple.security.application-groups',
53
+ ios.groupIdentifier,
54
+ previousVoltraValues.appGroupIdentifier
55
+ )
56
+ ensureStringArrayValue(entitlements, 'keychain-access-groups', ios.keychainGroup, previousVoltraValues.keychainGroup)
57
+
58
+ if (ios.enablePushNotifications && entitlements['aps-environment'] === undefined) {
59
+ entitlements['aps-environment'] = 'development'
60
+ } else if (
61
+ !ios.enablePushNotifications &&
62
+ previousVoltraValues.pushNotificationsEnabled &&
63
+ entitlements['aps-environment'] === 'development'
64
+ ) {
65
+ delete entitlements['aps-environment']
66
+ }
67
+
68
+ const nextContent = buildPlistXml(entitlements, createEntitlementsError)
69
+ const change = await writeEntitlementsIfChanged(projectRoot, entitlementsPath, nextContent)
70
+
71
+ return { change }
72
+ }
73
+
74
+ export function needsEntitlementsMutation(ios: NormalizedVoltraIOSConfig): boolean {
75
+ return ios.enablePushNotifications || ios.groupIdentifier !== undefined || ios.keychainGroup !== undefined
76
+ }
77
+
78
+ function ensureStringArrayValue(
79
+ target: Record<string, unknown>,
80
+ key: string,
81
+ nextValue: string | undefined,
82
+ previousOwnedValue: string | undefined
83
+ ): void {
84
+ const existingValues = Array.isArray(target[key])
85
+ ? target[key].filter((value): value is string => typeof value === 'string' && value.length > 0)
86
+ : []
87
+ const dedupedValues = Array.from(new Set(existingValues))
88
+ const filteredValues = previousOwnedValue
89
+ ? dedupedValues.filter((value) => value !== previousOwnedValue)
90
+ : dedupedValues
91
+
92
+ if (nextValue === undefined) {
93
+ if (filteredValues.length === 0) {
94
+ delete target[key]
95
+ return
96
+ }
97
+
98
+ if (filteredValues.length !== existingValues.length) {
99
+ target[key] = filteredValues
100
+ }
101
+
102
+ return
103
+ }
104
+
105
+ // Preserve unrelated user-managed values in shared entitlements.
106
+ // V1 does not attempt to undo historical shared-file mutations.
107
+ if (!filteredValues.includes(nextValue)) {
108
+ filteredValues.push(nextValue)
109
+ }
110
+
111
+ target[key] = filteredValues
112
+ }
113
+
114
+ async function writeEntitlementsIfChanged(
115
+ projectRoot: string,
116
+ entitlementsPath: string,
117
+ nextContent: string
118
+ ): Promise<ReportedChange | undefined> {
119
+ const previousContent = (await pathExists(entitlementsPath)) ? await readTextFile(entitlementsPath) : undefined
120
+
121
+ if (previousContent === nextContent) {
122
+ return undefined
123
+ }
124
+
125
+ await writeTextFile(entitlementsPath, nextContent)
126
+
127
+ return {
128
+ kind: previousContent === undefined ? 'created' : 'updated',
129
+ path: toRelativePath(projectRoot, entitlementsPath),
130
+ }
131
+ }
132
+
133
+ function createEntitlementsError(message: string): IOSEntitlementsMutationError {
134
+ return new IOSEntitlementsMutationError(message)
135
+ }
136
+
137
+ async function readPreviousVoltraEntitlementValues(infoPlistPath: string): Promise<PreviousVoltraEntitlementValues> {
138
+ const infoPlist = await parsePlistFile(infoPlistPath, 'main app Info.plist', createEntitlementsError)
139
+
140
+ return {
141
+ appGroupIdentifier:
142
+ typeof infoPlist.Voltra_AppGroupIdentifier === 'string' ? infoPlist.Voltra_AppGroupIdentifier : undefined,
143
+ keychainGroup: typeof infoPlist.Voltra_KeychainGroup === 'string' ? infoPlist.Voltra_KeychainGroup : undefined,
144
+ pushNotificationsEnabled: infoPlist.Voltra_EnablePushNotifications === true,
145
+ }
146
+ }