@lynxship/cli 0.1.19 → 0.1.21

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 (193) hide show
  1. package/README.md +66 -5
  2. package/dist/android/signing.d.ts +16 -0
  3. package/dist/android/signing.d.ts.map +1 -0
  4. package/dist/android/signing.js +131 -0
  5. package/dist/android/types.d.ts +12 -0
  6. package/dist/android/types.d.ts.map +1 -0
  7. package/dist/android/types.js +1 -0
  8. package/dist/android-build.d.ts +4 -13
  9. package/dist/android-build.d.ts.map +1 -1
  10. package/dist/android-build.js +14 -133
  11. package/dist/android-toolchain/inspection.d.ts +3 -0
  12. package/dist/android-toolchain/inspection.d.ts.map +1 -0
  13. package/dist/android-toolchain/inspection.js +122 -0
  14. package/dist/android-toolchain/probes.d.ts +23 -0
  15. package/dist/android-toolchain/probes.d.ts.map +1 -0
  16. package/dist/android-toolchain/probes.js +183 -0
  17. package/dist/android-toolchain/types.d.ts +20 -0
  18. package/dist/android-toolchain/types.d.ts.map +1 -0
  19. package/dist/android-toolchain/types.js +1 -0
  20. package/dist/android-toolchain.d.ts +4 -20
  21. package/dist/android-toolchain.d.ts.map +1 -1
  22. package/dist/android-toolchain.js +4 -300
  23. package/dist/app-config.d.ts +25 -0
  24. package/dist/app-config.d.ts.map +1 -0
  25. package/dist/app-config.js +106 -0
  26. package/dist/bundle-build.d.ts.map +1 -1
  27. package/dist/bundle-build.js +11 -0
  28. package/dist/cli.d.ts +3 -0
  29. package/dist/cli.d.ts.map +1 -0
  30. package/dist/cli.js +66 -0
  31. package/dist/commands/build-execution.d.ts +41 -0
  32. package/dist/commands/build-execution.d.ts.map +1 -0
  33. package/dist/commands/build-execution.js +182 -0
  34. package/dist/commands/configuration.d.ts +19 -0
  35. package/dist/commands/configuration.d.ts.map +1 -0
  36. package/dist/commands/configuration.js +174 -0
  37. package/dist/commands/development.d.ts +22 -0
  38. package/dist/commands/development.d.ts.map +1 -0
  39. package/dist/commands/development.js +132 -0
  40. package/dist/commands/device.d.ts +3 -0
  41. package/dist/commands/device.d.ts.map +1 -0
  42. package/dist/commands/device.js +86 -0
  43. package/dist/commands/doctor.d.ts +18 -0
  44. package/dist/commands/doctor.d.ts.map +1 -0
  45. package/dist/commands/doctor.js +320 -0
  46. package/dist/commands/help.d.ts +2 -0
  47. package/dist/commands/help.d.ts.map +1 -0
  48. package/dist/commands/help.js +118 -0
  49. package/dist/commands/i18n.d.ts +14 -0
  50. package/dist/commands/i18n.d.ts.map +1 -0
  51. package/dist/commands/i18n.js +88 -0
  52. package/dist/commands/logs.d.ts +3 -0
  53. package/dist/commands/logs.d.ts.map +1 -0
  54. package/dist/commands/logs.js +51 -0
  55. package/dist/commands/metadata.d.ts +3 -0
  56. package/dist/commands/metadata.d.ts.map +1 -0
  57. package/dist/commands/metadata.js +45 -0
  58. package/dist/commands/ota.d.ts +28 -0
  59. package/dist/commands/ota.d.ts.map +1 -0
  60. package/dist/commands/ota.js +203 -0
  61. package/dist/commands/project.d.ts +14 -0
  62. package/dist/commands/project.d.ts.map +1 -0
  63. package/dist/commands/project.js +122 -0
  64. package/dist/commands/remote-build.d.ts +35 -0
  65. package/dist/commands/remote-build.d.ts.map +1 -0
  66. package/dist/commands/remote-build.js +73 -0
  67. package/dist/commands/submit.d.ts +27 -0
  68. package/dist/commands/submit.d.ts.map +1 -0
  69. package/dist/commands/submit.js +92 -0
  70. package/dist/ecosystem.d.ts +9 -0
  71. package/dist/ecosystem.d.ts.map +1 -0
  72. package/dist/ecosystem.js +95 -0
  73. package/dist/frameworks.d.ts.map +1 -1
  74. package/dist/frameworks.js +5 -1
  75. package/dist/guidance/catalog.d.ts +3 -0
  76. package/dist/guidance/catalog.d.ts.map +1 -0
  77. package/dist/guidance/catalog.js +504 -0
  78. package/dist/guidance/types.d.ts +10 -0
  79. package/dist/guidance/types.d.ts.map +1 -0
  80. package/dist/guidance/types.js +1 -0
  81. package/dist/guidance.d.ts +2 -9
  82. package/dist/guidance.d.ts.map +1 -1
  83. package/dist/guidance.js +1 -502
  84. package/dist/i18n/discovery.d.ts +14 -0
  85. package/dist/i18n/discovery.d.ts.map +1 -0
  86. package/dist/i18n/discovery.js +106 -0
  87. package/dist/i18n/plan.d.ts +12 -0
  88. package/dist/i18n/plan.d.ts.map +1 -0
  89. package/dist/i18n/plan.js +95 -0
  90. package/dist/i18n/setup.d.ts +11 -0
  91. package/dist/i18n/setup.d.ts.map +1 -0
  92. package/dist/i18n/setup.js +47 -0
  93. package/dist/i18n/types.d.ts +17 -0
  94. package/dist/i18n/types.d.ts.map +1 -0
  95. package/dist/i18n/types.js +1 -0
  96. package/dist/index.d.ts +1 -1
  97. package/dist/index.d.ts.map +1 -1
  98. package/dist/index.js +4 -2069
  99. package/dist/ios/assets.d.ts +19 -0
  100. package/dist/ios/assets.d.ts.map +1 -0
  101. package/dist/ios/assets.js +128 -0
  102. package/dist/ios/production-build.d.ts +6 -0
  103. package/dist/ios/production-build.d.ts.map +1 -0
  104. package/dist/ios/production-build.js +200 -0
  105. package/dist/ios/project.d.ts +4 -0
  106. package/dist/ios/project.d.ts.map +1 -0
  107. package/dist/ios/project.js +43 -0
  108. package/dist/ios/simulator-build.d.ts +8 -0
  109. package/dist/ios/simulator-build.d.ts.map +1 -0
  110. package/dist/ios/simulator-build.js +188 -0
  111. package/dist/ios/simulator.d.ts +5 -0
  112. package/dist/ios/simulator.d.ts.map +1 -0
  113. package/dist/ios/simulator.js +60 -0
  114. package/dist/ios/types.d.ts +14 -0
  115. package/dist/ios/types.d.ts.map +1 -0
  116. package/dist/ios/types.js +1 -0
  117. package/dist/ios-build.d.ts +4 -37
  118. package/dist/ios-build.d.ts.map +1 -1
  119. package/dist/ios-build.js +3 -575
  120. package/dist/ios-host.d.ts.map +1 -1
  121. package/dist/ios-toolchain/inspection.d.ts +4 -0
  122. package/dist/ios-toolchain/inspection.d.ts.map +1 -0
  123. package/dist/ios-toolchain/inspection.js +211 -0
  124. package/dist/ios-toolchain/probes.d.ts +24 -0
  125. package/dist/ios-toolchain/probes.d.ts.map +1 -0
  126. package/dist/ios-toolchain/probes.js +127 -0
  127. package/dist/ios-toolchain/types.d.ts +17 -0
  128. package/dist/ios-toolchain/types.d.ts.map +1 -0
  129. package/dist/ios-toolchain/types.js +1 -0
  130. package/dist/ios-toolchain.d.ts +3 -18
  131. package/dist/ios-toolchain.d.ts.map +1 -1
  132. package/dist/ios-toolchain.js +1 -333
  133. package/dist/plugins/contracts.d.ts +28 -0
  134. package/dist/plugins/contracts.d.ts.map +1 -0
  135. package/dist/plugins/contracts.js +1 -0
  136. package/dist/plugins/discovery.d.ts +19 -0
  137. package/dist/plugins/discovery.d.ts.map +1 -0
  138. package/dist/plugins/discovery.js +250 -0
  139. package/dist/plugins/native-operations.d.ts +28 -0
  140. package/dist/plugins/native-operations.d.ts.map +1 -0
  141. package/dist/plugins/native-operations.js +217 -0
  142. package/dist/plugins/operations.d.ts +9 -0
  143. package/dist/plugins/operations.d.ts.map +1 -0
  144. package/dist/plugins/operations.js +76 -0
  145. package/dist/plugins/validation.d.ts +9 -0
  146. package/dist/plugins/validation.d.ts.map +1 -0
  147. package/dist/plugins/validation.js +52 -0
  148. package/dist/plugins.d.ts +3 -34
  149. package/dist/plugins.d.ts.map +1 -1
  150. package/dist/plugins.js +2 -595
  151. package/dist/process-runner.d.ts +4 -0
  152. package/dist/process-runner.d.ts.map +1 -1
  153. package/dist/process-runner.js +14 -0
  154. package/dist/remote.d.ts +22 -1
  155. package/dist/remote.d.ts.map +1 -1
  156. package/dist/remote.js +141 -2
  157. package/dist/rspeedy-app-config.d.ts +4 -0
  158. package/dist/rspeedy-app-config.d.ts.map +1 -0
  159. package/dist/rspeedy-app-config.js +32 -0
  160. package/dist/runtime/args.d.ts +3 -0
  161. package/dist/runtime/args.d.ts.map +1 -0
  162. package/dist/runtime/args.js +11 -0
  163. package/dist/runtime/build-commands.d.ts +3 -0
  164. package/dist/runtime/build-commands.d.ts.map +1 -0
  165. package/dist/runtime/build-commands.js +282 -0
  166. package/dist/runtime/context.d.ts +63 -0
  167. package/dist/runtime/context.d.ts.map +1 -0
  168. package/dist/runtime/context.js +179 -0
  169. package/dist/runtime/early-commands.d.ts +4 -0
  170. package/dist/runtime/early-commands.d.ts.map +1 -0
  171. package/dist/runtime/early-commands.js +284 -0
  172. package/dist/runtime/project.d.ts +8 -0
  173. package/dist/runtime/project.d.ts.map +1 -0
  174. package/dist/runtime/project.js +38 -0
  175. package/dist/runtime/state.d.ts +47 -0
  176. package/dist/runtime/state.d.ts.map +1 -0
  177. package/dist/runtime/state.js +33 -0
  178. package/dist/secure-store/backends.d.ts +20 -0
  179. package/dist/secure-store/backends.d.ts.map +1 -0
  180. package/dist/secure-store/backends.js +248 -0
  181. package/dist/secure-store/types.d.ts +27 -0
  182. package/dist/secure-store/types.d.ts.map +1 -0
  183. package/dist/secure-store/types.js +1 -0
  184. package/dist/secure-store.d.ts +2 -26
  185. package/dist/secure-store.d.ts.map +1 -1
  186. package/dist/secure-store.js +3 -245
  187. package/dist/ui/components.d.ts.map +1 -1
  188. package/dist/ui/components.js +2 -1
  189. package/package.json +7 -4
  190. package/templates/android-host/app/build.gradle +1 -0
  191. package/templates/android-host/app/src/main/java/template/MainActivity.java +98 -3
  192. package/templates/ios-host/__IOS_TARGET_NAME__/DemoLynxProvider.swift +26 -16
  193. package/templates/ios-host/__IOS_TARGET_NAME__/ViewController.swift +107 -19
@@ -0,0 +1 @@
1
+ {"version":3,"file":"native-operations.d.ts","sourceRoot":"","sources":["../../src/plugins/native-operations.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EACL,KAAK,iBAAiB,EACtB,KAAK,4BAA4B,EACjC,KAAK,UAAU,EACf,KAAK,wBAAwB,EAC7B,KAAK,mBAAmB,EAExB,KAAK,oBAAoB,EACzB,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACrB,KAAK,oBAAoB,EAC1B,MAAM,sBAAsB,CAAC;AAG9B,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,mBAAmB,CAAC;CAChC;AAED,iBAAS,yBAAyB,CAAC,YAAY,EAAE;IAC/C,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,KAAK,CAAC,EAAE,iBAAiB,CAAC;IAC1B,MAAM,CAAC,EAAE,SAAS,mBAAmB,EAAE,CAAC;IACxC,QAAQ,CAAC,EAAE,oBAAoB,CAAC;IAChC,SAAS,CAAC,EAAE,SAAS,oBAAoB,EAAE,CAAC;IAC5C,KAAK,CAAC,EAAE,SAAS,4BAA4B,EAAE,CAAC;CACjD,GAAG,gBAAgB,EAAE,CASrB;AAYD,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,wBAAwB,EAChC,YAAY,EAAE,OAAO,GACpB,OAAO,CAAC,YAAY,IAAI;IACzB,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,KAAK,CAAC,EAAE,iBAAiB,CAAC;IAC1B,MAAM,CAAC,EAAE,SAAS,mBAAmB,EAAE,CAAC;IACxC,QAAQ,CAAC,EAAE,oBAAoB,CAAC;IAChC,SAAS,CAAC,EAAE,SAAS,oBAAoB,EAAE,CAAC;IAC5C,KAAK,CAAC,EAAE,SAAS,4BAA4B,EAAE,CAAC;CACjD,CAsHA;AAED,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,wBAAwB,EAChC,YAAY,EAAE,UAAU,CAAC,OAAO,yBAAyB,CAAC,CAAC,CAAC,CAAC,GAC5D,IAAI,CAeN;AAUD,wBAAsB,sBAAsB,CAC1C,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,oBAAoB,EAC3B,QAAQ,EAAE,QAAQ,GACjB,OAAO,CAAC,gBAAgB,GAAG,SAAS,CAAC,CAiCvC;AAyCD,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,SAAS,oBAAoB,EAAE,GAC1C,IAAI,CAoBN;AAED,wBAAsB,+BAA+B,CACnD,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,SAAS,oBAAoB,EAAE,EAC3C,QAAQ,EAAE,QAAQ,GACjB,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAmC7B"}
@@ -0,0 +1,217 @@
1
+ import { existsSync } from "node:fs";
2
+ import { mkdir, readFile, rm, writeFile } from "node:fs/promises";
3
+ import { dirname } from "node:path";
4
+ import { appliesToPlatform, mergeJson, safeProjectFile } from "./discovery.js";
5
+ function permissionForContribution(contribution) {
6
+ const required = [];
7
+ if (contribution.config)
8
+ required.push("config:write");
9
+ if (contribution.build)
10
+ required.push("build:metadata");
11
+ if (contribution.native?.length)
12
+ required.push("native:write");
13
+ if (contribution.autolink)
14
+ required.push("autolink:metadata");
15
+ if (contribution.templates?.length)
16
+ required.push("template:register");
17
+ if (contribution.cloud?.length)
18
+ required.push("cloud:provider");
19
+ return required;
20
+ }
21
+ function capabilityForPermission(permission) {
22
+ return permission.split(":")[0];
23
+ }
24
+ function isJsonObject(value) {
25
+ return Boolean(value && typeof value === "object" && !Array.isArray(value));
26
+ }
27
+ export function assertPluginContribution(plugin, contribution) {
28
+ if (!isJsonObject(contribution))
29
+ throw new Error(`Plugin '${plugin.name}' returned an invalid contribution object`);
30
+ if (contribution.config !== undefined && !isJsonObject(contribution.config))
31
+ throw new Error(`Plugin '${plugin.name}' returned an invalid config contribution`);
32
+ if (contribution.native !== undefined && !Array.isArray(contribution.native))
33
+ throw new Error(`Plugin '${plugin.name}' returned an invalid native contribution`);
34
+ for (const operation of contribution.native ?? []) {
35
+ if (!isJsonObject(operation))
36
+ throw new Error(`Plugin '${plugin.name}' returned an invalid native operation`);
37
+ if (!["all", "android", "ios", "harmonyos", "web", "desktop"].includes(String(operation.platform)) ||
38
+ typeof operation.file !== "string" ||
39
+ operation.file.length === 0 ||
40
+ !["ensure-text", "append-text", "replace-text", "json-merge"].includes(String(operation.operation)))
41
+ throw new Error(`Plugin '${plugin.name}' returned an invalid native operation`);
42
+ if ((operation.operation === "ensure-text" ||
43
+ operation.operation === "append-text") &&
44
+ typeof operation.text !== "string")
45
+ throw new Error(`Plugin '${plugin.name}' returned an invalid text operation`);
46
+ if (operation.operation === "replace-text" &&
47
+ (typeof operation.from !== "string" || typeof operation.to !== "string"))
48
+ throw new Error(`Plugin '${plugin.name}' returned an invalid replacement operation`);
49
+ if (operation.operation === "json-merge" && !isJsonObject(operation.value))
50
+ throw new Error(`Plugin '${plugin.name}' returned an invalid JSON merge operation`);
51
+ }
52
+ if (contribution.autolink !== undefined) {
53
+ if (!isJsonObject(contribution.autolink))
54
+ throw new Error(`Plugin '${plugin.name}' returned an invalid Autolink contribution`);
55
+ for (const key of ["packageNames", "capabilities"]) {
56
+ const value = contribution.autolink[key];
57
+ if (value !== undefined &&
58
+ (!Array.isArray(value) ||
59
+ !value.every((item) => typeof item === "string")))
60
+ throw new Error(`Plugin '${plugin.name}' returned invalid Autolink metadata`);
61
+ }
62
+ }
63
+ if (contribution.build !== undefined) {
64
+ if (!isJsonObject(contribution.build))
65
+ throw new Error(`Plugin '${plugin.name}' returned an invalid build contribution`);
66
+ for (const key of [
67
+ "requiredTools",
68
+ "artifactExtensions",
69
+ "notes",
70
+ ]) {
71
+ const value = contribution.build[key];
72
+ if (value !== undefined &&
73
+ (!Array.isArray(value) ||
74
+ !value.every((item) => typeof item === "string")))
75
+ throw new Error(`Plugin '${plugin.name}' returned invalid build metadata`);
76
+ }
77
+ }
78
+ for (const template of Array.isArray(contribution.templates)
79
+ ? contribution.templates
80
+ : []) {
81
+ if (!isJsonObject(template) ||
82
+ typeof template.id !== "string" ||
83
+ typeof template.displayName !== "string" ||
84
+ typeof template.source !== "string")
85
+ throw new Error(`Plugin '${plugin.name}' returned an invalid template contribution`);
86
+ }
87
+ for (const integration of Array.isArray(contribution.cloud)
88
+ ? contribution.cloud
89
+ : []) {
90
+ if (!isJsonObject(integration) ||
91
+ typeof integration.id !== "string" ||
92
+ typeof integration.displayName !== "string" ||
93
+ !Array.isArray(integration.capabilities) ||
94
+ !integration.capabilities.every((item) => ["build", "artifacts", "updates", "submit"].includes(String(item))))
95
+ throw new Error(`Plugin '${plugin.name}' returned an invalid cloud contribution`);
96
+ }
97
+ }
98
+ export function assertPluginPermissions(plugin, contribution) {
99
+ const missing = permissionForContribution(contribution).filter((permission) => !plugin.permissions.includes(permission));
100
+ const missingCapabilities = permissionForContribution(contribution)
101
+ .map(capabilityForPermission)
102
+ .filter((capability) => !plugin.capabilities.includes(capability));
103
+ if (missing.length)
104
+ throw new Error(`Plugin '${plugin.name}' returned contributions without declaring permission(s): ${missing.join(", ")}`);
105
+ if (missingCapabilities.length)
106
+ throw new Error(`Plugin '${plugin.name}' returned contributions without declaring capability(ies): ${[...new Set(missingCapabilities)].join(", ")}`);
107
+ }
108
+ async function mergeJsonFile(file, value) {
109
+ const current = JSON.parse(await readFile(file, "utf8"));
110
+ await writeFile(file, `${JSON.stringify(mergeJson(current, value), null, 2)}\n`);
111
+ }
112
+ export async function inspectNativeOperation(root, owned, platform) {
113
+ const operation = owned.operation;
114
+ if (!appliesToPlatform([operation.platform], platform))
115
+ return undefined;
116
+ const file = safeProjectFile(root, operation.file);
117
+ const current = existsSync(file) ? await readFile(file, "utf8") : "";
118
+ let changed = false;
119
+ if (operation.operation === "json-merge") {
120
+ if (!existsSync(file))
121
+ throw new Error(`Plugin JSON target does not exist: ${operation.file}`);
122
+ const merged = `${JSON.stringify(mergeJson(JSON.parse(current), operation.value), null, 2)}\n`;
123
+ changed = merged !== current;
124
+ }
125
+ else if (operation.operation === "ensure-text") {
126
+ changed = !current.includes(operation.text);
127
+ }
128
+ else if (operation.operation === "append-text") {
129
+ changed = !current.includes(operation.text);
130
+ }
131
+ else if (operation.operation === "replace-text") {
132
+ if (!current.includes(operation.from))
133
+ throw new Error(`Plugin replacement target was not found in ${operation.file}`);
134
+ changed = current.replace(operation.from, operation.to) !== current;
135
+ }
136
+ return {
137
+ plugin: owned.plugin,
138
+ platform,
139
+ file: operation.file,
140
+ operation: operation.operation,
141
+ changed,
142
+ };
143
+ }
144
+ async function applyNativeOperation(root, operation, platform) {
145
+ if (!appliesToPlatform([operation.platform], platform))
146
+ return;
147
+ const file = safeProjectFile(root, operation.file);
148
+ await mkdir(dirname(file), { recursive: true });
149
+ if (operation.operation === "json-merge") {
150
+ if (!existsSync(file))
151
+ throw new Error(`Plugin JSON target does not exist: ${operation.file}`);
152
+ await mergeJsonFile(file, operation.value);
153
+ return;
154
+ }
155
+ const current = existsSync(file) ? await readFile(file, "utf8") : "";
156
+ if (operation.operation === "ensure-text") {
157
+ if (!current.includes(operation.text))
158
+ await writeFile(file, `${current}${current && !current.endsWith("\n") ? "\n" : ""}${operation.text}\n`);
159
+ return;
160
+ }
161
+ if (operation.operation === "append-text") {
162
+ if (current.includes(operation.text))
163
+ return;
164
+ await writeFile(file, `${current}${current && !current.endsWith("\n") ? "\n" : ""}${operation.text}\n`);
165
+ return;
166
+ }
167
+ if (operation.operation !== "replace-text")
168
+ return;
169
+ if (!current.includes(operation.from))
170
+ throw new Error(`Plugin replacement target was not found in ${operation.file}`);
171
+ await writeFile(file, current.replace(operation.from, operation.to));
172
+ }
173
+ export function assertNativeConflicts(root, operations) {
174
+ const seen = new Map();
175
+ for (const owned of operations) {
176
+ const file = safeProjectFile(root, owned.operation.file);
177
+ const previous = seen.get(file);
178
+ if (!previous) {
179
+ seen.set(file, owned);
180
+ continue;
181
+ }
182
+ const currentOperation = owned.operation;
183
+ const previousOperation = previous.operation;
184
+ if (currentOperation.operation === "replace-text" &&
185
+ previousOperation.operation === "replace-text" &&
186
+ currentOperation.from === previousOperation.from)
187
+ throw new Error(`Conflicting or duplicate LynxShip plugins '${previous.plugin}' and '${owned.plugin}' both replace '${currentOperation.from}' in ${currentOperation.file}`);
188
+ }
189
+ }
190
+ export async function applyNativeOperationsAtomically(root, operations, platform) {
191
+ assertNativeConflicts(root, operations);
192
+ const backups = new Map();
193
+ for (const owned of operations) {
194
+ if (!appliesToPlatform([owned.operation.platform], platform))
195
+ continue;
196
+ const file = safeProjectFile(root, owned.operation.file);
197
+ if (!backups.has(file))
198
+ backups.set(file, existsSync(file) ? await readFile(file, "utf8") : undefined);
199
+ }
200
+ try {
201
+ const changes = (await Promise.all(operations.map((operation) => inspectNativeOperation(root, operation, platform)))).filter((change) => Boolean(change));
202
+ for (const owned of operations)
203
+ await applyNativeOperation(root, owned.operation, platform);
204
+ return changes;
205
+ }
206
+ catch (error) {
207
+ for (const [file, content] of backups) {
208
+ if (content === undefined)
209
+ await rm(file, { force: true });
210
+ else {
211
+ await mkdir(dirname(file), { recursive: true });
212
+ await writeFile(file, content);
213
+ }
214
+ }
215
+ throw new Error(`${error instanceof Error ? error.message : String(error)}; native plugin changes were rolled back`);
216
+ }
217
+ }
@@ -0,0 +1,9 @@
1
+ import type { Platform } from "@lynxship/contracts";
2
+ import type { LynxShipConfig } from "../config.js";
3
+ import type { PluginApplication } from "./contracts.js";
4
+ export declare function applyProjectPlugins(root: string, config: LynxShipConfig, target: {
5
+ platform: Platform;
6
+ profile: string;
7
+ mode?: "plan" | "apply";
8
+ }): Promise<PluginApplication>;
9
+ //# sourceMappingURL=operations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"operations.d.ts","sourceRoot":"","sources":["../../src/plugins/operations.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAUpD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAQnD,OAAO,KAAK,EAAE,iBAAiB,EAAgB,MAAM,gBAAgB,CAAC;AAWtE,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,cAAc,EACtB,MAAM,EAAE;IAAE,QAAQ,EAAE,QAAQ,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE,GACvE,OAAO,CAAC,iBAAiB,CAAC,CAqF5B"}
@@ -0,0 +1,76 @@
1
+ import { appliesToPlatform, mergeJson, pluginReference, pluginReferences, resolvePlugin, } from "./discovery.js";
2
+ import { applyNativeOperationsAtomically, assertNativeConflicts, assertPluginContribution, assertPluginPermissions, inspectNativeOperation, } from "./native-operations.js";
3
+ export async function applyProjectPlugins(root, config, target) {
4
+ const references = pluginReferences(config);
5
+ const resolved = [];
6
+ for (const reference of references)
7
+ resolved.push(await resolvePlugin(root, reference));
8
+ const report = {
9
+ configured: references.length,
10
+ plugins: resolved.map((plugin) => plugin.info),
11
+ };
12
+ const invalid = report.plugins.find((plugin) => plugin.status !== "ready");
13
+ if (invalid)
14
+ throw new Error(`LynxShip plugin '${invalid.name}' is invalid: ${invalid.reason}`);
15
+ let effectiveConfig = JSON.parse(JSON.stringify(config));
16
+ const applied = [];
17
+ const templates = [];
18
+ const cloud = [];
19
+ const build = [];
20
+ const autolink = [];
21
+ const operations = [];
22
+ for (let index = 0; index < resolved.length; index += 1) {
23
+ const plugin = resolved[index];
24
+ const reference = references[index];
25
+ if (!plugin?.definition || !reference)
26
+ continue;
27
+ if (!appliesToPlatform(plugin.definition.platforms, target.platform))
28
+ continue;
29
+ const options = pluginReference(reference).options;
30
+ const context = {
31
+ rootDir: root,
32
+ platform: target.platform,
33
+ profile: target.profile,
34
+ mode: target.mode ?? "apply",
35
+ projectId: config.projectId,
36
+ config: effectiveConfig,
37
+ options,
38
+ };
39
+ const contribution = await plugin.definition.apply(context);
40
+ if (!contribution) {
41
+ applied.push(plugin.info.name);
42
+ continue;
43
+ }
44
+ assertPluginContribution(plugin.definition, contribution);
45
+ assertPluginPermissions(plugin.definition, contribution);
46
+ if (contribution.config)
47
+ effectiveConfig = mergeJson(effectiveConfig, contribution.config);
48
+ for (const operation of contribution.native ?? [])
49
+ operations.push({ plugin: plugin.info.name, operation });
50
+ if (contribution.autolink)
51
+ autolink.push(contribution.autolink);
52
+ templates.push(...(contribution.templates ?? []));
53
+ cloud.push(...(contribution.cloud ?? []));
54
+ if (contribution.build)
55
+ build.push(contribution.build);
56
+ applied.push(plugin.info.name);
57
+ }
58
+ let changes;
59
+ if (target.mode === "plan") {
60
+ assertNativeConflicts(root, operations);
61
+ changes = (await Promise.all(operations.map((operation) => inspectNativeOperation(root, operation, target.platform)))).filter((change) => Boolean(change));
62
+ }
63
+ else {
64
+ changes = await applyNativeOperationsAtomically(root, operations, target.platform);
65
+ }
66
+ return {
67
+ config: effectiveConfig,
68
+ report,
69
+ applied,
70
+ templates,
71
+ cloud,
72
+ build,
73
+ autolink,
74
+ changes,
75
+ };
76
+ }
@@ -0,0 +1,9 @@
1
+ import { LYNXSHIP_PLUGIN_API_VERSION, type LynxShipPluginDefinition, type PluginCapability, type PluginPermission } from "@lynxship/plugin-api";
2
+ export { LYNXSHIP_PLUGIN_API_VERSION };
3
+ export declare const KNOWN_CAPABILITIES: readonly PluginCapability[];
4
+ export declare const KNOWN_PERMISSIONS: readonly PluginPermission[];
5
+ export declare function capabilities(value: unknown): PluginCapability[];
6
+ export declare function permissions(value: unknown): PluginPermission[];
7
+ export declare function isKnownList(value: unknown, allowed: readonly string[]): value is readonly string[];
8
+ export declare function validPluginDefinition(value: unknown): value is LynxShipPluginDefinition;
9
+ //# sourceMappingURL=validation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../src/plugins/validation.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,2BAA2B,EAC3B,KAAK,wBAAwB,EAC7B,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACtB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAE,2BAA2B,EAAE,CAAC;AAEvC,eAAO,MAAM,kBAAkB,EAAE,SAAS,gBAAgB,EAOzD,CAAC;AAEF,eAAO,MAAM,iBAAiB,EAAE,SAAS,gBAAgB,EAOxD,CAAC;AAEF,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,gBAAgB,EAAE,CAK/D;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,gBAAgB,EAAE,CAK9D;AAED,wBAAgB,WAAW,CACzB,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,SAAS,MAAM,EAAE,GACzB,KAAK,IAAI,SAAS,MAAM,EAAE,CAQ5B;AAED,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,OAAO,GACb,KAAK,IAAI,wBAAwB,CAoBnC"}
@@ -0,0 +1,52 @@
1
+ import { LYNXSHIP_PLUGIN_API_VERSION, } from "@lynxship/plugin-api";
2
+ export { LYNXSHIP_PLUGIN_API_VERSION };
3
+ export const KNOWN_CAPABILITIES = [
4
+ "config",
5
+ "build",
6
+ "native",
7
+ "autolink",
8
+ "template",
9
+ "cloud",
10
+ ];
11
+ export const KNOWN_PERMISSIONS = [
12
+ "config:write",
13
+ "build:metadata",
14
+ "native:write",
15
+ "autolink:metadata",
16
+ "template:register",
17
+ "cloud:provider",
18
+ ];
19
+ export function capabilities(value) {
20
+ if (!Array.isArray(value))
21
+ return [];
22
+ return value.filter((candidate) => KNOWN_CAPABILITIES.includes(candidate));
23
+ }
24
+ export function permissions(value) {
25
+ if (!Array.isArray(value))
26
+ return [];
27
+ return value.filter((candidate) => KNOWN_PERMISSIONS.includes(candidate));
28
+ }
29
+ export function isKnownList(value, allowed) {
30
+ return (Array.isArray(value) &&
31
+ value.every((candidate) => typeof candidate === "string" && allowed.includes(candidate)));
32
+ }
33
+ export function validPluginDefinition(value) {
34
+ if (!value || typeof value !== "object")
35
+ return false;
36
+ const definition = value;
37
+ return (definition.apiVersion === LYNXSHIP_PLUGIN_API_VERSION &&
38
+ typeof definition.name === "string" &&
39
+ definition.name.length > 0 &&
40
+ isKnownList(definition.capabilities, KNOWN_CAPABILITIES) &&
41
+ isKnownList(definition.permissions, KNOWN_PERMISSIONS) &&
42
+ (definition.platforms === undefined ||
43
+ isKnownList(definition.platforms, [
44
+ "all",
45
+ "android",
46
+ "ios",
47
+ "harmonyos",
48
+ "web",
49
+ "desktop",
50
+ ])) &&
51
+ typeof definition.apply === "function");
52
+ }
package/dist/plugins.d.ts CHANGED
@@ -1,35 +1,4 @@
1
- import type { Platform } from "@lynxship/contracts";
2
- import { type BuildContribution, type CloudIntegrationContribution, type PluginCapability, type AutolinkContribution, type PluginPermission, type PluginPlanChange, type TemplateContribution } from "@lynxship/plugin-api";
3
- import type { LynxShipConfig } from "./config.js";
4
- export interface ProjectPluginInfo {
5
- name: string;
6
- version?: string;
7
- packagePath?: string;
8
- entry?: string;
9
- apiVersion?: number;
10
- capabilities: PluginCapability[];
11
- permissions: PluginPermission[];
12
- status: "ready" | "missing" | "invalid";
13
- reason: string;
14
- }
15
- export interface PluginReport {
16
- configured: number;
17
- plugins: ProjectPluginInfo[];
18
- }
19
- export interface PluginApplication {
20
- config: LynxShipConfig;
21
- report: PluginReport;
22
- applied: string[];
23
- templates: TemplateContribution[];
24
- cloud: CloudIntegrationContribution[];
25
- build: BuildContribution[];
26
- changes: PluginPlanChange[];
27
- autolink: AutolinkContribution[];
28
- }
29
- export declare function inspectProjectPlugins(root: string, config: LynxShipConfig): Promise<PluginReport>;
30
- export declare function applyProjectPlugins(root: string, config: LynxShipConfig, target: {
31
- platform: Platform;
32
- profile: string;
33
- mode?: "plan" | "apply";
34
- }): Promise<PluginApplication>;
1
+ export type { PluginApplication, PluginReport, ProjectPluginInfo, } from "./plugins/contracts.js";
2
+ export { inspectProjectPlugins } from "./plugins/discovery.js";
3
+ export { applyProjectPlugins } from "./plugins/operations.js";
35
4
  //# sourceMappingURL=plugins.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"plugins.d.ts","sourceRoot":"","sources":["../src/plugins.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAEL,KAAK,iBAAiB,EACtB,KAAK,4BAA4B,EAKjC,KAAK,gBAAgB,EAErB,KAAK,oBAAoB,EACzB,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EAGrB,KAAK,oBAAoB,EAC1B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAclD,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,gBAAgB,EAAE,CAAC;IACjC,WAAW,EAAE,gBAAgB,EAAE,CAAC;IAChC,MAAM,EAAE,OAAO,GAAG,SAAS,GAAG,SAAS,CAAC;IACxC,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,iBAAiB,EAAE,CAAC;CAC9B;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,cAAc,CAAC;IACvB,MAAM,EAAE,YAAY,CAAC;IACrB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,SAAS,EAAE,oBAAoB,EAAE,CAAC;IAClC,KAAK,EAAE,4BAA4B,EAAE,CAAC;IACtC,KAAK,EAAE,iBAAiB,EAAE,CAAC;IAC3B,OAAO,EAAE,gBAAgB,EAAE,CAAC;IAC5B,QAAQ,EAAE,oBAAoB,EAAE,CAAC;CAClC;AAqUD,wBAAsB,qBAAqB,CACzC,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,cAAc,GACrB,OAAO,CAAC,YAAY,CAAC,CAQvB;AA+XD,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,cAAc,EACtB,MAAM,EAAE;IAAE,QAAQ,EAAE,QAAQ,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE,GACvE,OAAO,CAAC,iBAAiB,CAAC,CAqF5B"}
1
+ {"version":3,"file":"plugins.d.ts","sourceRoot":"","sources":["../src/plugins.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,iBAAiB,EACjB,YAAY,EACZ,iBAAiB,GAClB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAE/D,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC"}