@cloudcare/cocos-sdk 0.1.0-alpha.5 → 0.1.0-alpha.6
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.
- package/README.md +13 -1
- package/bin/cli.cjs +40 -21
- package/bin/legacy-asset-hashes.json +27 -0
- package/bin/managed-assets.cjs +67 -0
- package/dist/creator2/core/client.d.ts +23 -7
- package/dist/creator2/core/client.d.ts.map +1 -1
- package/dist/creator2/core/client.js +74 -28
- package/dist/creator2/core/client.js.map +1 -1
- package/dist/creator2/core/index.d.ts +1 -1
- package/dist/creator2/core/index.d.ts.map +1 -1
- package/dist/creator2/core/index.js.map +1 -1
- package/dist/creator2/core/plugin-api.d.ts +15 -0
- package/dist/creator2/core/plugin-api.d.ts.map +1 -0
- package/dist/creator2/core/plugin-api.js +3 -0
- package/dist/creator2/core/plugin-api.js.map +1 -0
- package/dist/creator2/core/types.d.ts +0 -78
- package/dist/creator2/core/types.d.ts.map +1 -1
- package/dist/creator2/core/validation.d.ts +0 -11
- package/dist/creator2/core/validation.d.ts.map +1 -1
- package/dist/creator2/core/validation.js +0 -63
- package/dist/creator2/core/validation.js.map +1 -1
- package/dist/creator2/core/version.d.ts +1 -1
- package/dist/creator2/core/version.js +1 -1
- package/dist/creator2/creator2/auto.d.ts +1 -3
- package/dist/creator2/creator2/auto.d.ts.map +1 -1
- package/dist/creator2/creator2/auto.js +0 -25
- package/dist/creator2/creator2/auto.js.map +1 -1
- package/dist/creator2/creator2/index.d.ts +0 -7
- package/dist/creator2/creator2/index.d.ts.map +1 -1
- package/dist/creator2/creator2/index.js +1 -13
- package/dist/creator2/creator2/index.js.map +1 -1
- package/dist/creator2/creator2/transport.d.ts +0 -1
- package/dist/creator2/creator2/transport.d.ts.map +1 -1
- package/dist/creator2/creator2/transport.js +0 -4
- package/dist/creator2/creator2/transport.js.map +1 -1
- package/dist/creator3/core/client.d.ts +23 -7
- package/dist/creator3/core/client.d.ts.map +1 -1
- package/dist/creator3/core/client.js +72 -28
- package/dist/creator3/core/client.js.map +1 -1
- package/dist/creator3/core/index.d.ts +1 -1
- package/dist/creator3/core/index.d.ts.map +1 -1
- package/dist/creator3/core/index.js.map +1 -1
- package/dist/creator3/core/plugin-api.d.ts +15 -0
- package/dist/creator3/core/plugin-api.d.ts.map +1 -0
- package/dist/creator3/core/plugin-api.js +2 -0
- package/dist/creator3/core/plugin-api.js.map +1 -0
- package/dist/creator3/core/types.d.ts +0 -78
- package/dist/creator3/core/types.d.ts.map +1 -1
- package/dist/creator3/core/validation.d.ts +0 -11
- package/dist/creator3/core/validation.d.ts.map +1 -1
- package/dist/creator3/core/validation.js +0 -61
- package/dist/creator3/core/validation.js.map +1 -1
- package/dist/creator3/core/version.d.ts +1 -1
- package/dist/creator3/core/version.js +1 -1
- package/dist/creator3/creator3/auto.d.ts +1 -3
- package/dist/creator3/creator3/auto.d.ts.map +1 -1
- package/dist/creator3/creator3/auto.js +1 -26
- package/dist/creator3/creator3/auto.js.map +1 -1
- package/dist/creator3/creator3/index.d.ts +0 -7
- package/dist/creator3/creator3/index.d.ts.map +1 -1
- package/dist/creator3/creator3/index.js +1 -12
- package/dist/creator3/creator3/index.js.map +1 -1
- package/dist/creator3/creator3/transport.d.ts +0 -1
- package/dist/creator3/creator3/transport.d.ts.map +1 -1
- package/dist/creator3/creator3/transport.js +0 -4
- package/dist/creator3/creator3/transport.js.map +1 -1
- package/extensions/creator2/install-native.cjs +52 -30
- package/extensions/creator2/install-spm.cjs +16 -8
- package/extensions/creator2/legacy-asset-hashes.json +27 -0
- package/extensions/creator2/managed-assets.cjs +67 -0
- package/extensions/creator3/install-native.cjs +52 -30
- package/extensions/creator3/install-spm.cjs +16 -8
- package/extensions/creator3/legacy-asset-hashes.json +27 -0
- package/extensions/creator3/managed-assets.cjs +67 -0
- package/native/android/src/main/java/com/ft/sdk/cocos/FTBridgeTransport.java +85 -0
- package/native/android/src/main/java/com/ft/sdk/cocos/FTCocosBridge.java +2 -192
- package/native/android/src/main/java/com/ft/sdk/cocos/FTCocosBridgeModules.java +9 -0
- package/native/android/src/main/java/com/ft/sdk/cocos/FTCocosBridgeProvider.java +1 -1
- package/native/ios/FTCocosBridge.m +0 -202
- package/native/ios/FTCocosBridge.podspec +2 -3
- package/native/ios/Package.swift +1 -2
- package/package.json +10 -5
- package/plugin-api/package.json +4 -0
- package/components/creator2/ReplayPrivacy.ts +0 -23
- package/components/creator3/ReplayPrivacy.ts +0 -25
- package/dist/creator2/core/replay-async-transport.d.ts +0 -4
- package/dist/creator2/core/replay-async-transport.d.ts.map +0 -1
- package/dist/creator2/core/replay-async-transport.js +0 -67
- package/dist/creator2/core/replay-async-transport.js.map +0 -1
- package/dist/creator2/core/replay-budget.d.ts +0 -28
- package/dist/creator2/core/replay-budget.d.ts.map +0 -1
- package/dist/creator2/core/replay-budget.js +0 -113
- package/dist/creator2/core/replay-budget.js.map +0 -1
- package/dist/creator2/core/replay-diagnostics.d.ts +0 -36
- package/dist/creator2/core/replay-diagnostics.d.ts.map +0 -1
- package/dist/creator2/core/replay-diagnostics.js +0 -40
- package/dist/creator2/core/replay-diagnostics.js.map +0 -1
- package/dist/creator2/core/replay-encoding.d.ts +0 -31
- package/dist/creator2/core/replay-encoding.d.ts.map +0 -1
- package/dist/creator2/core/replay-encoding.js +0 -63
- package/dist/creator2/core/replay-encoding.js.map +0 -1
- package/dist/creator2/core/replay-file.d.ts +0 -5
- package/dist/creator2/core/replay-file.d.ts.map +0 -1
- package/dist/creator2/core/replay-file.js +0 -101
- package/dist/creator2/core/replay-file.js.map +0 -1
- package/dist/creator2/core/replay-pixels.d.ts +0 -3
- package/dist/creator2/core/replay-pixels.d.ts.map +0 -1
- package/dist/creator2/core/replay-pixels.js +0 -16
- package/dist/creator2/core/replay-pixels.js.map +0 -1
- package/dist/creator2/core/replay-privacy-nodes.d.ts +0 -14
- package/dist/creator2/core/replay-privacy-nodes.d.ts.map +0 -1
- package/dist/creator2/core/replay-privacy-nodes.js +0 -18
- package/dist/creator2/core/replay-privacy-nodes.js.map +0 -1
- package/dist/creator2/core/replay-privacy.d.ts +0 -15
- package/dist/creator2/core/replay-privacy.d.ts.map +0 -1
- package/dist/creator2/core/replay-privacy.js +0 -36
- package/dist/creator2/core/replay-privacy.js.map +0 -1
- package/dist/creator2/core/replay.d.ts +0 -99
- package/dist/creator2/core/replay.d.ts.map +0 -1
- package/dist/creator2/core/replay.js +0 -611
- package/dist/creator2/core/replay.js.map +0 -1
- package/dist/creator2/creator2/capture.d.ts +0 -17
- package/dist/creator2/creator2/capture.d.ts.map +0 -1
- package/dist/creator2/creator2/capture.js +0 -168
- package/dist/creator2/creator2/capture.js.map +0 -1
- package/dist/creator3/core/replay-async-transport.d.ts +0 -4
- package/dist/creator3/core/replay-async-transport.d.ts.map +0 -1
- package/dist/creator3/core/replay-async-transport.js +0 -16
- package/dist/creator3/core/replay-async-transport.js.map +0 -1
- package/dist/creator3/core/replay-budget.d.ts +0 -28
- package/dist/creator3/core/replay-budget.d.ts.map +0 -1
- package/dist/creator3/core/replay-budget.js +0 -105
- package/dist/creator3/core/replay-budget.js.map +0 -1
- package/dist/creator3/core/replay-diagnostics.d.ts +0 -36
- package/dist/creator3/core/replay-diagnostics.d.ts.map +0 -1
- package/dist/creator3/core/replay-diagnostics.js +0 -36
- package/dist/creator3/core/replay-diagnostics.js.map +0 -1
- package/dist/creator3/core/replay-encoding.d.ts +0 -31
- package/dist/creator3/core/replay-encoding.d.ts.map +0 -1
- package/dist/creator3/core/replay-encoding.js +0 -62
- package/dist/creator3/core/replay-encoding.js.map +0 -1
- package/dist/creator3/core/replay-file.d.ts +0 -5
- package/dist/creator3/core/replay-file.d.ts.map +0 -1
- package/dist/creator3/core/replay-file.js +0 -31
- package/dist/creator3/core/replay-file.js.map +0 -1
- package/dist/creator3/core/replay-pixels.d.ts +0 -3
- package/dist/creator3/core/replay-pixels.d.ts.map +0 -1
- package/dist/creator3/core/replay-pixels.js +0 -13
- package/dist/creator3/core/replay-pixels.js.map +0 -1
- package/dist/creator3/core/replay-privacy-nodes.d.ts +0 -14
- package/dist/creator3/core/replay-privacy-nodes.d.ts.map +0 -1
- package/dist/creator3/core/replay-privacy-nodes.js +0 -15
- package/dist/creator3/core/replay-privacy-nodes.js.map +0 -1
- package/dist/creator3/core/replay-privacy.d.ts +0 -15
- package/dist/creator3/core/replay-privacy.d.ts.map +0 -1
- package/dist/creator3/core/replay-privacy.js +0 -33
- package/dist/creator3/core/replay-privacy.js.map +0 -1
- package/dist/creator3/core/replay.d.ts +0 -99
- package/dist/creator3/core/replay.d.ts.map +0 -1
- package/dist/creator3/core/replay.js +0 -534
- package/dist/creator3/core/replay.js.map +0 -1
- package/dist/creator3/creator3/capture.d.ts +0 -17
- package/dist/creator3/creator3/capture.d.ts.map +0 -1
- package/dist/creator3/creator3/capture.js +0 -112
- package/dist/creator3/creator3/capture.js.map +0 -1
- package/dist/creator3/creator3/replay-render-cycle.d.ts +0 -9
- package/dist/creator3/creator3/replay-render-cycle.d.ts.map +0 -1
- package/dist/creator3/creator3/replay-render-cycle.js +0 -12
- package/dist/creator3/creator3/replay-render-cycle.js.map +0 -1
- package/native/android/src/main/java/com/ft/sdk/cocos/FTCocosReplayImageJobs.java +0 -55
- package/native/ios/FTCocosReplayImageJobs.h +0 -11
- package/native/ios/FTCocosReplayImageJobs.m +0 -54
- package/native/shared/FTReplayFileBridge.h +0 -62
- package/native/shared/FTReplayFileWorker.h +0 -88
|
@@ -2,22 +2,11 @@ import { FTDefaultAutoTracking } from '../core/auto-tracking.js';
|
|
|
2
2
|
import { FTCocosSDK } from '../core/client.js';
|
|
3
3
|
import { FTLogger, FTRUM, FTTrace } from '../core/modules.js';
|
|
4
4
|
import { FTCreator3TrackingHooks } from './auto.js';
|
|
5
|
-
import { FTCreator3CanvasCapture } from './capture.js';
|
|
6
5
|
import { FTCreator3Transport } from './transport.js';
|
|
7
6
|
const transport = new FTCreator3Transport();
|
|
8
|
-
const capture = new FTCreator3CanvasCapture();
|
|
9
7
|
const hooks = new FTCreator3TrackingHooks();
|
|
10
8
|
const autoTracking = new FTDefaultAutoTracking(new FTRUM(transport), new FTLogger(transport), new FTTrace(transport), hooks);
|
|
11
9
|
/** Shared SDK entry point for Cocos Creator 3.x applications. */
|
|
12
|
-
export const guanceSdk = new FTCocosSDK(transport,
|
|
13
|
-
/**
|
|
14
|
-
* Selects the Cocos Creator 3 camera used to capture Session Replay frames.
|
|
15
|
-
* Call this after the camera is available and before starting Replay.
|
|
16
|
-
*
|
|
17
|
-
* @param camera - Active Cocos `Camera` component.
|
|
18
|
-
*/
|
|
19
|
-
export function setReplayCamera(camera) {
|
|
20
|
-
capture.setCamera(camera);
|
|
21
|
-
}
|
|
10
|
+
export const guanceSdk = new FTCocosSDK(transport, autoTracking, 'creator3');
|
|
22
11
|
export * from '../core/index.js';
|
|
23
12
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/creator3/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,EAAE,uBAAuB,EAAE,MAAM,WAAW,CAAC;AACpD,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/creator3/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,EAAE,uBAAuB,EAAE,MAAM,WAAW,CAAC;AACpD,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAErD,MAAM,SAAS,GAAG,IAAI,mBAAmB,EAAE,CAAC;AAC5C,MAAM,KAAK,GAAG,IAAI,uBAAuB,EAAE,CAAC;AAC5C,MAAM,YAAY,GAAG,IAAI,qBAAqB,CAC5C,IAAI,KAAK,CAAC,SAAS,CAAC,EACpB,IAAI,QAAQ,CAAC,SAAS,CAAC,EACvB,IAAI,OAAO,CAAC,SAAS,CAAC,EACtB,KAAK,CACN,CAAC;AAEF,iEAAiE;AACjE,MAAM,CAAC,MAAM,SAAS,GAAG,IAAI,UAAU,CAAC,SAAS,EAAE,YAAY,EAAE,UAAU,CAAC,CAAC;AAE7E,cAAc,kBAAkB,CAAC"}
|
|
@@ -2,7 +2,6 @@ import { type FTNativeTransport } from '../core/transport.js';
|
|
|
2
2
|
import type { FTValue } from '../core/types.js';
|
|
3
3
|
export declare class FTCreator3Transport implements FTNativeTransport {
|
|
4
4
|
readonly platform: 'android' | 'ios' | 'unsupported';
|
|
5
|
-
invokeAsync<T = FTValue>(method: string, payload?: unknown): Promise<T | undefined>;
|
|
6
5
|
constructor();
|
|
7
6
|
invoke<T = FTValue>(method: string, payload?: unknown): T | undefined;
|
|
8
7
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../../../../../src/creator3/transport.ts"],"names":[],"mappings":"AAEA,OAAO,EAA0B,KAAK,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACtF,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../../../../../src/creator3/transport.ts"],"names":[],"mappings":"AAEA,OAAO,EAA0B,KAAK,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACtF,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAEhD,qBAAa,mBAAoB,YAAW,iBAAiB;IAC3D,QAAQ,CAAC,QAAQ,EAAE,SAAS,GAAG,KAAK,GAAG,aAAa,CAAC;;IAYrD,MAAM,CAAC,CAAC,GAAG,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,CAAC,GAAG,SAAS;CActE"}
|
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
import { native, sys } from 'cc';
|
|
2
2
|
import { NATIVE } from 'cc/env';
|
|
3
3
|
import { parseTransportResponse } from '../core/transport.js';
|
|
4
|
-
import { invokeReplayAsync } from '../core/replay-async-transport.js';
|
|
5
4
|
export class FTCreator3Transport {
|
|
6
|
-
invokeAsync(method, payload) {
|
|
7
|
-
return invokeReplayAsync(this, method, payload);
|
|
8
|
-
}
|
|
9
5
|
constructor() {
|
|
10
6
|
this.platform = !NATIVE
|
|
11
7
|
? 'unsupported'
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transport.js","sourceRoot":"","sources":["../../../../../src/creator3/transport.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,IAAI,CAAC;AACjC,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EAAE,sBAAsB,EAA0B,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"transport.js","sourceRoot":"","sources":["../../../../../src/creator3/transport.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,IAAI,CAAC;AACjC,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EAAE,sBAAsB,EAA0B,MAAM,sBAAsB,CAAC;AAGtF,MAAM,OAAO,mBAAmB;IAG9B;QACE,IAAI,CAAC,QAAQ,GAAG,CAAC,MAAM;YACrB,CAAC,CAAC,aAAa;YACf,CAAC,CAAC,GAAG,CAAC,EAAE,KAAK,GAAG,CAAC,EAAE,CAAC,OAAO;gBACzB,CAAC,CAAC,SAAS;gBACX,CAAC,CAAC,GAAG,CAAC,EAAE,KAAK,GAAG,CAAC,EAAE,CAAC,GAAG;oBACrB,CAAC,CAAC,KAAK;oBACP,CAAC,CAAC,aAAa,CAAC;IACxB,CAAC;IAED,MAAM,CAAc,MAAc,EAAE,OAAiB;QACnD,IAAI,IAAI,CAAC,QAAQ,KAAK,aAAa;YAAE,OAAO,SAAS,CAAC;QACtD,MAAM,IAAI,GAAG,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QACpE,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,KAAK,SAAS;YACrC,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,gBAAgB,CAChC,gCAAgC,EAChC,QAAQ,EACR,0DAA0D,EAC1D,MAAM,EACN,IAAI,CACL;YACH,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,gBAAgB,CAAC,eAAe,EAAE,iBAAiB,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;QACzF,OAAO,sBAAsB,CAAI,GAAG,CAAC,CAAC;IACxC,CAAC;CACF"}
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
const fs = require('fs');
|
|
4
4
|
const path = require('path');
|
|
5
5
|
const { execFileSync } = require('child_process');
|
|
6
|
+
const { syncManagedDirectory } = require('./managed-assets.cjs');
|
|
6
7
|
|
|
7
8
|
const BEGIN = '/* COCOS_SDK_BEGIN */';
|
|
8
9
|
const END = '/* COCOS_SDK_END */';
|
|
@@ -28,14 +29,32 @@ function installNative(buildRoot, extensionRoot, logger = console) {
|
|
|
28
29
|
logger.warn(`[cocos-sdk] Native bridge not found at ${nativeSource}`);
|
|
29
30
|
return;
|
|
30
31
|
}
|
|
32
|
+
const replayDescriptor = path.join(extensionRoot, 'replay-integration.json');
|
|
33
|
+
const replay = fs.existsSync(replayDescriptor) ? JSON.parse(fs.readFileSync(replayDescriptor, 'utf8')) : null;
|
|
34
|
+
const installedFile = path.join(extensionRoot, 'sdk-integration.json');
|
|
35
|
+
const installed = fs.existsSync(installedFile) ? JSON.parse(fs.readFileSync(installedFile, 'utf8')) : null;
|
|
36
|
+
if (installed?.replay && !replay) throw new Error('[cocos-sdk] Replay assets are missing. Run guance-cocos install --replay.');
|
|
37
|
+
if (replay && (replay.schemaVersion !== 1 || !installed || replay.baseVersion !== installed.version || replay.version !== installed.version || replay.iosSdkVersion !== '1.6.8-alpha.5')) {
|
|
38
|
+
throw new Error('[cocos-sdk] Replay native integration version does not match the base SDK. Reinstall matching packages.');
|
|
39
|
+
}
|
|
40
|
+
const replaySource = path.join(extensionRoot, 'replay-native');
|
|
31
41
|
const buildNative = path.join(buildRoot, 'cocos-sdk-native');
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
.forEach((file) => patchReplayFileBridge(file, replayHeader));
|
|
42
|
+
const sources = [{ root: nativeSource }];
|
|
43
|
+
if (replay) sources.push({ root: replaySource, prefix: 'replay/' });
|
|
44
|
+
if (dependencyManager === 'spm') {
|
|
45
|
+
sources.push({ root: path.join(nativeSource, 'ios'), prefix: 'FTCocosBridge/' });
|
|
46
|
+
if (replay) sources.push({ root: path.join(replaySource, 'ios'), prefix: 'FTCocosReplayBridge/' });
|
|
38
47
|
}
|
|
48
|
+
const modules = 'android/src/main/java/com/ft/sdk/cocos/FTCocosBridgeModules.java';
|
|
49
|
+
const dispatcher = fs.readFileSync(path.join(nativeSource, modules), 'utf8');
|
|
50
|
+
const configuredDispatcher = replay ? dispatcher.replace(
|
|
51
|
+
' return "{',
|
|
52
|
+
' if ("session-replay".equals(endpoint)) return FTCocosReplayBridge.invokeLocal(method, payload);\n return "{',
|
|
53
|
+
) : dispatcher;
|
|
54
|
+
syncManagedDirectory(buildNative, sources, { [modules]: configuredDispatcher });
|
|
55
|
+
const files = findFiles(buildRoot, 7);
|
|
56
|
+
const replayHeader = replay ? path.join(buildNative, 'replay', 'shared', 'FTReplayFileBridge.h') : null;
|
|
57
|
+
findReplayEntryFiles(files).forEach(file => patchReplayFileBridge(file, replayHeader));
|
|
39
58
|
const gradlePropertiesFiles = files.filter((file) => path.basename(file) === 'gradle.properties');
|
|
40
59
|
const gradleFiles = uniqueFiles([
|
|
41
60
|
...files.filter((file) => /(?:^|\/)app\/build\.gradle$/.test(normalize(file))),
|
|
@@ -50,7 +69,6 @@ function installNative(buildRoot, extensionRoot, logger = console) {
|
|
|
50
69
|
.filter((project) => project.target);
|
|
51
70
|
if (dependencyManager === 'spm' && iosApplicationProjects.length > 0) {
|
|
52
71
|
migrateManagedPods(podfiles, logger);
|
|
53
|
-
copyDirectory(path.join(nativeSource, 'ios'), path.join(buildNative, 'FTCocosBridge'));
|
|
54
72
|
}
|
|
55
73
|
if (dependencyManager === 'cocoapods' && podfiles.length === 0) {
|
|
56
74
|
iosApplicationProjects.forEach(({ projectFile, target }) => {
|
|
@@ -63,14 +81,18 @@ function installNative(buildRoot, extensionRoot, logger = console) {
|
|
|
63
81
|
iosApplicationProjects.forEach(({ projectFile, target }) => {
|
|
64
82
|
patchCocos2IosConfiguration(projectFile, target);
|
|
65
83
|
if (dependencyManager === 'spm') {
|
|
66
|
-
require('./install-spm.cjs')
|
|
67
|
-
|
|
84
|
+
const spm = require('./install-spm.cjs');
|
|
85
|
+
if (!replay) spm.removeSwiftPackages(projectFile, ['FTCocosReplayBridge']);
|
|
86
|
+
spm.installSwiftPackage(projectFile, path.join(buildNative, 'FTCocosBridge'), 'FTCocosBridge', target);
|
|
87
|
+
if (replay) spm.installSwiftPackage(projectFile, path.join(buildNative, 'FTCocosReplayBridge'), 'FTCocosReplayBridge', target);
|
|
88
|
+
} else if (fs.readFileSync(projectFile, 'utf8').includes('XCLocalSwiftPackageReference')
|
|
89
|
+
|| fs.existsSync(path.join(path.dirname(projectFile), 'cocos-sdk-spm.json'))) {
|
|
68
90
|
require('./install-spm.cjs').removeSwiftPackages(projectFile);
|
|
69
91
|
}
|
|
70
92
|
});
|
|
71
|
-
gradleFiles.forEach((file) => patchGradle(file, buildNative));
|
|
93
|
+
gradleFiles.forEach((file) => patchGradle(file, buildNative, replay));
|
|
72
94
|
gradlePropertiesFiles.forEach(patchGradleProperties);
|
|
73
|
-
if (dependencyManager === 'cocoapods') podfiles.forEach((file) => patchPodfile(file, buildNative));
|
|
95
|
+
if (dependencyManager === 'cocoapods') podfiles.forEach((file) => patchPodfile(file, buildNative, replay));
|
|
74
96
|
logger.info(
|
|
75
97
|
`[cocos-sdk] Installed native bridge (${gradleFiles.length} Android, ${dependencyManager === 'spm' ? iosApplicationProjects.length : podfiles.length} iOS project files; iOS: ${dependencyManager}).`,
|
|
76
98
|
);
|
|
@@ -85,6 +107,12 @@ function patchReplayFileBridge(file, header) {
|
|
|
85
107
|
// Creator 3 shares Game.cpp across iOS/Android builds. Keep its include stable
|
|
86
108
|
// when another platform's build directory is cleaned or regenerated.
|
|
87
109
|
const sharedDirectory = path.join(path.dirname(file), 'cocos-sdk-replay');
|
|
110
|
+
if (!header) {
|
|
111
|
+
const next = original.replace(markedPattern(includeBegin, includeEnd), '').replace(markedPattern(initBegin, initEnd), '');
|
|
112
|
+
if (fs.existsSync(sharedDirectory)) syncManagedDirectory(sharedDirectory, []);
|
|
113
|
+
if (next !== original) fs.writeFileSync(file, next);
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
88
116
|
const include = `${includeBegin}\n#include "cocos-sdk-replay/FTReplayFileBridge.h"\n${includeEnd}`;
|
|
89
117
|
const init = `${initBegin}\n ft_cocos::installReplayFileBridge();\n ${initEnd}\n `;
|
|
90
118
|
let next = original;
|
|
@@ -100,7 +128,7 @@ function patchReplayFileBridge(file, header) {
|
|
|
100
128
|
next = markedPattern(includeBegin, includeEnd).test(next)
|
|
101
129
|
? next.replace(markedPattern(includeBegin, includeEnd), include)
|
|
102
130
|
: `${include}\n${next}`;
|
|
103
|
-
|
|
131
|
+
syncManagedDirectory(sharedDirectory, [{ root: path.dirname(header) }]);
|
|
104
132
|
if (next !== original) fs.writeFileSync(file, next);
|
|
105
133
|
}
|
|
106
134
|
|
|
@@ -251,12 +279,14 @@ function compareVersions(left, right) {
|
|
|
251
279
|
return 0;
|
|
252
280
|
}
|
|
253
281
|
|
|
254
|
-
function patchGradle(file, nativeRoot) {
|
|
282
|
+
function patchGradle(file, nativeRoot, replay) {
|
|
255
283
|
const javaDir = normalize(path.join(nativeRoot, 'android', 'src', 'main', 'java'));
|
|
284
|
+
const javaDirs = [javaDir];
|
|
285
|
+
if (replay) javaDirs.push(normalize(path.join(nativeRoot, 'replay', 'android', 'src', 'main', 'java')));
|
|
256
286
|
replaceMarkedBlock(file, [
|
|
257
287
|
BEGIN,
|
|
258
288
|
'android {',
|
|
259
|
-
` sourceSets { main.java.srcDirs += ['${escapeGroovy(
|
|
289
|
+
` sourceSets { main.java.srcDirs += [${javaDirs.map(dir => `'${escapeGroovy(dir)}'`).join(', ')}] }`,
|
|
260
290
|
'}',
|
|
261
291
|
'repositories {',
|
|
262
292
|
" maven { url 'https://mvnrepo.guance.com/repository/maven-releases' }",
|
|
@@ -264,21 +294,22 @@ function patchGradle(file, nativeRoot) {
|
|
|
264
294
|
'dependencies {',
|
|
265
295
|
" implementation 'com.cloudcare.ft.mobile.sdk.tracker.agent:ft-sdk:1.7.6-alpha03'",
|
|
266
296
|
" implementation 'com.cloudcare.ft.mobile.sdk.tracker.agent:ft-native:1.1.3'",
|
|
267
|
-
|
|
297
|
+
...(replay ? [` implementation '${escapeGroovy(replay.androidReplay)}'`] : []),
|
|
268
298
|
" implementation 'com.google.code.gson:gson:2.10.1'",
|
|
269
299
|
" implementation platform('org.jetbrains.kotlin:kotlin-bom:1.8.22')",
|
|
270
300
|
" implementation 'androidx.appcompat:appcompat:1.1.0'",
|
|
271
|
-
|
|
301
|
+
...(replay ? [` implementation '${escapeGroovy(replay.androidFragment)}'`] : []),
|
|
272
302
|
'}',
|
|
273
303
|
END,
|
|
274
304
|
].join('\n'), BEGIN, END, [[LEGACY_BEGIN, LEGACY_END]]);
|
|
275
305
|
}
|
|
276
306
|
|
|
277
|
-
function patchPodfile(file, nativeRoot) {
|
|
307
|
+
function patchPodfile(file, nativeRoot, replay) {
|
|
278
308
|
const iosDir = normalize(path.join(nativeRoot, 'ios'));
|
|
279
309
|
const block = [
|
|
280
310
|
POD_BEGIN,
|
|
281
311
|
`pod 'FTCocosBridge', :path => '${escapeRuby(iosDir)}'`,
|
|
312
|
+
...(replay ? [`pod 'FTCocosReplayBridge', :path => '${escapeRuby(normalize(path.join(nativeRoot, 'replay', 'ios')))}'`] : []),
|
|
282
313
|
POD_END,
|
|
283
314
|
].join('\n');
|
|
284
315
|
const original = fs.readFileSync(file, 'utf8');
|
|
@@ -308,7 +339,8 @@ function replaceIndentedMarkedBlock(contents, begin, end, block) {
|
|
|
308
339
|
|
|
309
340
|
function findIosApplicationTarget(projectFile) {
|
|
310
341
|
const contents = fs.readFileSync(projectFile, 'utf8');
|
|
311
|
-
if (contents.includes('COCOS_SDK_XCODE_PROJECT')
|
|
342
|
+
if (contents.includes('COCOS_SDK_XCODE_PROJECT')
|
|
343
|
+
|| fs.existsSync(path.join(path.dirname(projectFile), 'cocos-sdk-spm.json'))) {
|
|
312
344
|
const { readProject, applicationTarget } = require('./install-spm.cjs');
|
|
313
345
|
return applicationTarget(readProject(projectFile))?.[1].name || null;
|
|
314
346
|
}
|
|
@@ -366,16 +398,6 @@ function markedPattern(begin, end) {
|
|
|
366
398
|
return new RegExp(`${escapeRegExp(begin)}[\\s\\S]*?${escapeRegExp(end)}`, 'm');
|
|
367
399
|
}
|
|
368
400
|
|
|
369
|
-
function copyDirectory(source, destination) {
|
|
370
|
-
fs.mkdirSync(destination, { recursive: true });
|
|
371
|
-
for (const entry of fs.readdirSync(source, { withFileTypes: true })) {
|
|
372
|
-
const from = path.join(source, entry.name);
|
|
373
|
-
const to = path.join(destination, entry.name);
|
|
374
|
-
if (entry.isDirectory()) copyDirectory(from, to);
|
|
375
|
-
else fs.copyFileSync(from, to);
|
|
376
|
-
}
|
|
377
|
-
}
|
|
378
|
-
|
|
379
401
|
function findFiles(root, maxDepth) {
|
|
380
402
|
const result = [];
|
|
381
403
|
function visit(directory, depth) {
|
|
@@ -425,14 +447,14 @@ function migrateManagedPods(podfiles, logger) {
|
|
|
425
447
|
[POD_BEGIN, POD_END], [LEGACY_POD_BEGIN, LEGACY_POD_END], [LEGACY_BEGIN, LEGACY_END],
|
|
426
448
|
['# COCOS_HYBRID_SAMPLE_BEGIN', '# COCOS_HYBRID_SAMPLE_END'],
|
|
427
449
|
]) next = next.replace(markedPattern(begin, end), '');
|
|
428
|
-
if (/^\s*pod\s+['"](?:FTCocosBridge|HybridSampleHost|GuanceSDK)(?:\/[^'"]*)?['"]/m.test(next)) {
|
|
450
|
+
if (/^\s*pod\s+['"](?:FTCocosBridge|FTCocosReplayBridge|HybridSampleHost|GuanceSDK)(?:\/[^'"]*)?['"]/m.test(next)) {
|
|
429
451
|
throw new Error(`[cocos-sdk] Remove the manually declared native SDK Pod from ${file} before switching to SPM.`);
|
|
430
452
|
}
|
|
431
453
|
if (next !== original) fs.writeFileSync(file, next);
|
|
432
454
|
const directory = path.dirname(file);
|
|
433
455
|
const existingLock = path.join(directory, 'Podfile.lock');
|
|
434
456
|
const hasSDKPods = fs.existsSync(existingLock)
|
|
435
|
-
&& /^\s*- (?:FTCocosBridge|HybridSampleHost|GuanceSDK)(?:\/|\s|:)/m.test(fs.readFileSync(existingLock, 'utf8'));
|
|
457
|
+
&& /^\s*- (?:FTCocosBridge|FTCocosReplayBridge|HybridSampleHost|GuanceSDK)(?:\/|\s|:)/m.test(fs.readFileSync(existingLock, 'utf8'));
|
|
436
458
|
if (next === original && !hasSDKPods) continue;
|
|
437
459
|
if (fs.existsSync(path.join(directory, 'Podfile.lock')) || fs.existsSync(path.join(directory, 'Pods'))) {
|
|
438
460
|
logger.info('[cocos-sdk] Updating existing Pods integration for the SPM switch.');
|
|
@@ -145,11 +145,11 @@ function preserveCmakeIntegration(projectFile, project, entry) {
|
|
|
145
145
|
if (!fs.existsSync(stateFile) || fs.readFileSync(stateFile, 'utf8') !== serialized) fs.writeFileSync(stateFile, serialized);
|
|
146
146
|
}
|
|
147
147
|
|
|
148
|
-
function removeSwiftPackages(projectFile) {
|
|
148
|
+
function removeSwiftPackages(projectFile, productNames = ['FTCocosBridge', 'FTCocosReplayBridge', 'HybridSampleHost']) {
|
|
149
149
|
const project = readProject(projectFile);
|
|
150
150
|
const objects = project.objects;
|
|
151
151
|
const removed = new Set();
|
|
152
|
-
for (const productName of
|
|
152
|
+
for (const productName of productNames) {
|
|
153
153
|
const packageID = identifier(`package:${productName}`);
|
|
154
154
|
if (!objects[packageID]) continue;
|
|
155
155
|
removed.add(packageID);
|
|
@@ -159,23 +159,31 @@ function removeSwiftPackages(projectFile) {
|
|
|
159
159
|
removed.add(identifier(`framework:${id}:${productName}`));
|
|
160
160
|
}
|
|
161
161
|
}
|
|
162
|
-
if (!removed.size) return;
|
|
163
162
|
for (const id of removed) delete objects[id];
|
|
164
163
|
for (const object of Object.values(objects)) {
|
|
165
164
|
for (const key of ['packageReferences', 'packageProductDependencies', 'files']) {
|
|
166
165
|
if (Array.isArray(object[key])) object[key] = object[key].filter((id) => !removed.has(id));
|
|
167
166
|
}
|
|
168
|
-
|
|
167
|
+
|
|
169
168
|
}
|
|
170
169
|
const stateFile = path.join(path.dirname(projectFile), 'cocos-sdk-spm.json');
|
|
171
170
|
if (fs.existsSync(stateFile)) {
|
|
172
171
|
const state = JSON.parse(fs.readFileSync(stateFile, 'utf8'));
|
|
173
|
-
|
|
174
|
-
|
|
172
|
+
state.packages = state.packages.filter(item => !productNames.includes(item.productName));
|
|
173
|
+
if (state.packages.length) {
|
|
174
|
+
fs.writeFileSync(stateFile, `${JSON.stringify(state, null, 2)}\n`);
|
|
175
|
+
} else {
|
|
176
|
+
for (const [id, settings] of Object.entries(state.buildLocations)) {
|
|
177
|
+
if (objects[id]) Object.assign(objects[id].buildSettings ||= {}, settings);
|
|
178
|
+
}
|
|
179
|
+
for (const object of Object.values(objects)) {
|
|
180
|
+
if (object.isa === 'PBXShellScriptBuildPhase') object.shellScript = (object.shellScript || '').replace(restorePattern, '');
|
|
181
|
+
}
|
|
182
|
+
fs.unlinkSync(stateFile);
|
|
183
|
+
fs.rmSync(path.join(path.dirname(projectFile), 'cocos-sdk-spm.cjs'), { force: true });
|
|
175
184
|
}
|
|
176
|
-
fs.unlinkSync(stateFile);
|
|
177
|
-
fs.rmSync(path.join(path.dirname(projectFile), 'cocos-sdk-spm.cjs'), { force: true });
|
|
178
185
|
}
|
|
186
|
+
|
|
179
187
|
writeProject(projectFile, project);
|
|
180
188
|
}
|
|
181
189
|
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
[
|
|
2
|
+
"058341971ed42ddfde76c28ce19fcc0bba5020fec1f7e1c613c7bda7d2df7677",
|
|
3
|
+
"11ee16e609096ccfe90b17f61d87ab65275a39df4bef6f8c29577e7395aa00f8",
|
|
4
|
+
"15338071a78f1505265cc8efbdc9628e9362f7a2c9fc00989d57461126f8f3f5",
|
|
5
|
+
"1a51af27d68cdf0bf3ce709c9cd60f9b8a2d7defd46d06896ce9a916e1dfc767",
|
|
6
|
+
"2caa0d3d542f5cca0b6b7f3aa2851c7e296b08fce286202a844b52920b1f6dc0",
|
|
7
|
+
"3189144de638b936e14d64ddbf9d4c95e95146ceecc357021473ca8adcc757d1",
|
|
8
|
+
"48ff77a12a7b9b59172f5470a642f23e4c61e9f7e10ee6d9d3f4f41377d696ac",
|
|
9
|
+
"4d2dcd924f1073b8a6fb94d342bee33a281f93c19302104be172e5de9981b3f0",
|
|
10
|
+
"51c71e12df61cfe7e75c3d97080e31a398fbea8719a3e964cec5dd332df1202c",
|
|
11
|
+
"5f33108f27f38836214f2c11badd7bb76ba9ec090f9d5b1490834a9257976939",
|
|
12
|
+
"85ad9622480d954c33a4f9442a391f6d3d9d617a2f1261e5ad769170c6e9cf12",
|
|
13
|
+
"86cf732195aad676898520192ac8aa878267877dc09f85fcf425279d8badc9b8",
|
|
14
|
+
"910792f383c25cd46ddc7d851080a687fa532a93d605fb709b7baff9bb2789cf",
|
|
15
|
+
"95bdc516c4e1b72833af3bec13b18e3c2ac6ae83de284c3f711e97765ed1b461",
|
|
16
|
+
"a748564f0bba03effbf4aa381308f60eedcb618cbd2a37e1c67cdbee596e9ceb",
|
|
17
|
+
"a8a57b5892e7a5063078d561fce790b44d900d2bb3869e43ed4c4de82f1f62ed",
|
|
18
|
+
"cd03df57f7861d19b0a8e0a97e8aff1fa08e5c26d4f43152743968245632535b",
|
|
19
|
+
"d26fb42c6bee416eaf29bc2ed8579edc7a28ca3d0e18433dcb8abea11fac9920",
|
|
20
|
+
"d2d171e4ef1777facdb6fe665105372ea2e6452028d4c32f5e2ccc74dacc8850",
|
|
21
|
+
"d538d9eebaf181687ebf8537fc6ce7c8fae59fa424daeb45c3f900a8e210ecfc",
|
|
22
|
+
"df8e3014e583d60922cd1b7f7f16964c433b260a7e1a7e6c285cb08ce2d9e7e4",
|
|
23
|
+
"e70ca2a537cec56f8424ff4d551c1e97af133938fc7ba863a3944859dcfd194d",
|
|
24
|
+
"f0211acbaaa312bd5a4478bba81fa98293c855692ceca69f141600ff991c5904",
|
|
25
|
+
"f09f9b35ddfb17a7c4e4439384afae93ded6ee0285e778ad013d320cfc880cab",
|
|
26
|
+
"fa88198c5434613ff5ab2d44dce6e7eb8b825085b5b498402810eb144cf81f96"
|
|
27
|
+
]
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const path = require('path');
|
|
4
|
+
const { createHash } = require('crypto');
|
|
5
|
+
const legacyHashes = new Set(require('./legacy-asset-hashes.json'));
|
|
6
|
+
// Older combined installations predate the ownership manifest. Never leave a
|
|
7
|
+
// locally modified obsolete Replay bridge compiling beside the new bridge.
|
|
8
|
+
const legacyReplayNames = new Set(['FTCocosReplayImageJobs.java', 'FTCocosReplayImageJobs.h', 'FTCocosReplayImageJobs.m', 'FTReplayFileBridge.h', 'FTReplayFileWorker.h']);
|
|
9
|
+
const manifestName = '.cocos-sdk-managed.json';
|
|
10
|
+
const hash = bytes => createHash('sha256').update(bytes).digest('hex');
|
|
11
|
+
|
|
12
|
+
function files(root) {
|
|
13
|
+
const result = [];
|
|
14
|
+
if (!fs.existsSync(root)) return result;
|
|
15
|
+
function visit(directory) {
|
|
16
|
+
for (const entry of fs.readdirSync(directory, { withFileTypes: true })) {
|
|
17
|
+
if (entry.name === manifestName || entry.name === '.DS_Store') continue;
|
|
18
|
+
const file = path.join(directory, entry.name);
|
|
19
|
+
if (entry.isSymbolicLink()) throw new Error(`[cocos-sdk] Refusing to copy symbolic link: ${file}`);
|
|
20
|
+
if (entry.isDirectory()) visit(file);
|
|
21
|
+
else result.push(path.relative(root, file).split(path.sep).join('/'));
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
visit(root);
|
|
25
|
+
return result;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** Reconciles only files written by the SDK, preserving unrelated project assets. */
|
|
29
|
+
function syncManagedDirectory(destination, sources, overrides = {}) {
|
|
30
|
+
const desired = new Map();
|
|
31
|
+
for (const { root, prefix = '' } of sources) {
|
|
32
|
+
if (!fs.existsSync(root)) throw new Error(`[cocos-sdk] Missing package assets: ${root}`);
|
|
33
|
+
for (const file of files(root)) desired.set(prefix + file, fs.readFileSync(path.join(root, file)));
|
|
34
|
+
}
|
|
35
|
+
for (const [file, content] of Object.entries(overrides)) desired.set(file, Buffer.from(content));
|
|
36
|
+
const manifest = path.join(destination, manifestName);
|
|
37
|
+
const previous = fs.existsSync(manifest) ? JSON.parse(fs.readFileSync(manifest, 'utf8')) : {};
|
|
38
|
+
const existing = files(destination);
|
|
39
|
+
const remove = [];
|
|
40
|
+
// Check every conflict before writing or deleting any managed file.
|
|
41
|
+
for (const file of existing) {
|
|
42
|
+
const digest = hash(fs.readFileSync(path.join(destination, file)));
|
|
43
|
+
const old = previous[file];
|
|
44
|
+
const next = desired.get(file);
|
|
45
|
+
const legacy = legacyHashes.has(digest);
|
|
46
|
+
if (!next && !old && !legacy && legacyReplayNames.has(path.basename(file))) {
|
|
47
|
+
throw new Error(`[cocos-sdk] Preserve or reconcile modified legacy Replay asset before reinstalling: ${path.join(destination, file)}`);
|
|
48
|
+
}
|
|
49
|
+
if ((old || next) && digest !== old && !legacy && (!next || digest !== hash(next))) {
|
|
50
|
+
throw new Error(`[cocos-sdk] Preserve or reconcile modified SDK asset before reinstalling: ${path.join(destination, file)}`);
|
|
51
|
+
}
|
|
52
|
+
if (!next && (old || legacy) && !file.endsWith('.meta')) remove.push(file);
|
|
53
|
+
}
|
|
54
|
+
fs.mkdirSync(destination, { recursive: true });
|
|
55
|
+
for (const file of remove) fs.unlinkSync(path.join(destination, file));
|
|
56
|
+
const nextManifest = {};
|
|
57
|
+
for (const [file, content] of desired) {
|
|
58
|
+
const target = path.resolve(destination, file);
|
|
59
|
+
if (!target.startsWith(path.resolve(destination) + path.sep)) throw new Error('Invalid SDK asset path');
|
|
60
|
+
fs.mkdirSync(path.dirname(target), { recursive: true });
|
|
61
|
+
if (!fs.existsSync(target) || hash(fs.readFileSync(target)) !== hash(content)) fs.writeFileSync(target, content);
|
|
62
|
+
nextManifest[file] = hash(content);
|
|
63
|
+
}
|
|
64
|
+
fs.writeFileSync(manifest, `${JSON.stringify(nextManifest, null, 2)}\n`);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
module.exports = { syncManagedDirectory };
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
const fs = require('fs');
|
|
4
4
|
const path = require('path');
|
|
5
5
|
const { execFileSync } = require('child_process');
|
|
6
|
+
const { syncManagedDirectory } = require('./managed-assets.cjs');
|
|
6
7
|
|
|
7
8
|
const BEGIN = '/* COCOS_SDK_BEGIN */';
|
|
8
9
|
const END = '/* COCOS_SDK_END */';
|
|
@@ -28,14 +29,32 @@ function installNative(buildRoot, extensionRoot, logger = console) {
|
|
|
28
29
|
logger.warn(`[cocos-sdk] Native bridge not found at ${nativeSource}`);
|
|
29
30
|
return;
|
|
30
31
|
}
|
|
32
|
+
const replayDescriptor = path.join(extensionRoot, 'replay-integration.json');
|
|
33
|
+
const replay = fs.existsSync(replayDescriptor) ? JSON.parse(fs.readFileSync(replayDescriptor, 'utf8')) : null;
|
|
34
|
+
const installedFile = path.join(extensionRoot, 'sdk-integration.json');
|
|
35
|
+
const installed = fs.existsSync(installedFile) ? JSON.parse(fs.readFileSync(installedFile, 'utf8')) : null;
|
|
36
|
+
if (installed?.replay && !replay) throw new Error('[cocos-sdk] Replay assets are missing. Run guance-cocos install --replay.');
|
|
37
|
+
if (replay && (replay.schemaVersion !== 1 || !installed || replay.baseVersion !== installed.version || replay.version !== installed.version || replay.iosSdkVersion !== '1.6.8-alpha.5')) {
|
|
38
|
+
throw new Error('[cocos-sdk] Replay native integration version does not match the base SDK. Reinstall matching packages.');
|
|
39
|
+
}
|
|
40
|
+
const replaySource = path.join(extensionRoot, 'replay-native');
|
|
31
41
|
const buildNative = path.join(buildRoot, 'cocos-sdk-native');
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
.forEach((file) => patchReplayFileBridge(file, replayHeader));
|
|
42
|
+
const sources = [{ root: nativeSource }];
|
|
43
|
+
if (replay) sources.push({ root: replaySource, prefix: 'replay/' });
|
|
44
|
+
if (dependencyManager === 'spm') {
|
|
45
|
+
sources.push({ root: path.join(nativeSource, 'ios'), prefix: 'FTCocosBridge/' });
|
|
46
|
+
if (replay) sources.push({ root: path.join(replaySource, 'ios'), prefix: 'FTCocosReplayBridge/' });
|
|
38
47
|
}
|
|
48
|
+
const modules = 'android/src/main/java/com/ft/sdk/cocos/FTCocosBridgeModules.java';
|
|
49
|
+
const dispatcher = fs.readFileSync(path.join(nativeSource, modules), 'utf8');
|
|
50
|
+
const configuredDispatcher = replay ? dispatcher.replace(
|
|
51
|
+
' return "{',
|
|
52
|
+
' if ("session-replay".equals(endpoint)) return FTCocosReplayBridge.invokeLocal(method, payload);\n return "{',
|
|
53
|
+
) : dispatcher;
|
|
54
|
+
syncManagedDirectory(buildNative, sources, { [modules]: configuredDispatcher });
|
|
55
|
+
const files = findFiles(buildRoot, 7);
|
|
56
|
+
const replayHeader = replay ? path.join(buildNative, 'replay', 'shared', 'FTReplayFileBridge.h') : null;
|
|
57
|
+
findReplayEntryFiles(files).forEach(file => patchReplayFileBridge(file, replayHeader));
|
|
39
58
|
const gradlePropertiesFiles = files.filter((file) => path.basename(file) === 'gradle.properties');
|
|
40
59
|
const gradleFiles = uniqueFiles([
|
|
41
60
|
...files.filter((file) => /(?:^|\/)app\/build\.gradle$/.test(normalize(file))),
|
|
@@ -50,7 +69,6 @@ function installNative(buildRoot, extensionRoot, logger = console) {
|
|
|
50
69
|
.filter((project) => project.target);
|
|
51
70
|
if (dependencyManager === 'spm' && iosApplicationProjects.length > 0) {
|
|
52
71
|
migrateManagedPods(podfiles, logger);
|
|
53
|
-
copyDirectory(path.join(nativeSource, 'ios'), path.join(buildNative, 'FTCocosBridge'));
|
|
54
72
|
}
|
|
55
73
|
if (dependencyManager === 'cocoapods' && podfiles.length === 0) {
|
|
56
74
|
iosApplicationProjects.forEach(({ projectFile, target }) => {
|
|
@@ -63,14 +81,18 @@ function installNative(buildRoot, extensionRoot, logger = console) {
|
|
|
63
81
|
iosApplicationProjects.forEach(({ projectFile, target }) => {
|
|
64
82
|
patchCocos2IosConfiguration(projectFile, target);
|
|
65
83
|
if (dependencyManager === 'spm') {
|
|
66
|
-
require('./install-spm.cjs')
|
|
67
|
-
|
|
84
|
+
const spm = require('./install-spm.cjs');
|
|
85
|
+
if (!replay) spm.removeSwiftPackages(projectFile, ['FTCocosReplayBridge']);
|
|
86
|
+
spm.installSwiftPackage(projectFile, path.join(buildNative, 'FTCocosBridge'), 'FTCocosBridge', target);
|
|
87
|
+
if (replay) spm.installSwiftPackage(projectFile, path.join(buildNative, 'FTCocosReplayBridge'), 'FTCocosReplayBridge', target);
|
|
88
|
+
} else if (fs.readFileSync(projectFile, 'utf8').includes('XCLocalSwiftPackageReference')
|
|
89
|
+
|| fs.existsSync(path.join(path.dirname(projectFile), 'cocos-sdk-spm.json'))) {
|
|
68
90
|
require('./install-spm.cjs').removeSwiftPackages(projectFile);
|
|
69
91
|
}
|
|
70
92
|
});
|
|
71
|
-
gradleFiles.forEach((file) => patchGradle(file, buildNative));
|
|
93
|
+
gradleFiles.forEach((file) => patchGradle(file, buildNative, replay));
|
|
72
94
|
gradlePropertiesFiles.forEach(patchGradleProperties);
|
|
73
|
-
if (dependencyManager === 'cocoapods') podfiles.forEach((file) => patchPodfile(file, buildNative));
|
|
95
|
+
if (dependencyManager === 'cocoapods') podfiles.forEach((file) => patchPodfile(file, buildNative, replay));
|
|
74
96
|
logger.info(
|
|
75
97
|
`[cocos-sdk] Installed native bridge (${gradleFiles.length} Android, ${dependencyManager === 'spm' ? iosApplicationProjects.length : podfiles.length} iOS project files; iOS: ${dependencyManager}).`,
|
|
76
98
|
);
|
|
@@ -85,6 +107,12 @@ function patchReplayFileBridge(file, header) {
|
|
|
85
107
|
// Creator 3 shares Game.cpp across iOS/Android builds. Keep its include stable
|
|
86
108
|
// when another platform's build directory is cleaned or regenerated.
|
|
87
109
|
const sharedDirectory = path.join(path.dirname(file), 'cocos-sdk-replay');
|
|
110
|
+
if (!header) {
|
|
111
|
+
const next = original.replace(markedPattern(includeBegin, includeEnd), '').replace(markedPattern(initBegin, initEnd), '');
|
|
112
|
+
if (fs.existsSync(sharedDirectory)) syncManagedDirectory(sharedDirectory, []);
|
|
113
|
+
if (next !== original) fs.writeFileSync(file, next);
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
88
116
|
const include = `${includeBegin}\n#include "cocos-sdk-replay/FTReplayFileBridge.h"\n${includeEnd}`;
|
|
89
117
|
const init = `${initBegin}\n ft_cocos::installReplayFileBridge();\n ${initEnd}\n `;
|
|
90
118
|
let next = original;
|
|
@@ -100,7 +128,7 @@ function patchReplayFileBridge(file, header) {
|
|
|
100
128
|
next = markedPattern(includeBegin, includeEnd).test(next)
|
|
101
129
|
? next.replace(markedPattern(includeBegin, includeEnd), include)
|
|
102
130
|
: `${include}\n${next}`;
|
|
103
|
-
|
|
131
|
+
syncManagedDirectory(sharedDirectory, [{ root: path.dirname(header) }]);
|
|
104
132
|
if (next !== original) fs.writeFileSync(file, next);
|
|
105
133
|
}
|
|
106
134
|
|
|
@@ -251,12 +279,14 @@ function compareVersions(left, right) {
|
|
|
251
279
|
return 0;
|
|
252
280
|
}
|
|
253
281
|
|
|
254
|
-
function patchGradle(file, nativeRoot) {
|
|
282
|
+
function patchGradle(file, nativeRoot, replay) {
|
|
255
283
|
const javaDir = normalize(path.join(nativeRoot, 'android', 'src', 'main', 'java'));
|
|
284
|
+
const javaDirs = [javaDir];
|
|
285
|
+
if (replay) javaDirs.push(normalize(path.join(nativeRoot, 'replay', 'android', 'src', 'main', 'java')));
|
|
256
286
|
replaceMarkedBlock(file, [
|
|
257
287
|
BEGIN,
|
|
258
288
|
'android {',
|
|
259
|
-
` sourceSets { main.java.srcDirs += ['${escapeGroovy(
|
|
289
|
+
` sourceSets { main.java.srcDirs += [${javaDirs.map(dir => `'${escapeGroovy(dir)}'`).join(', ')}] }`,
|
|
260
290
|
'}',
|
|
261
291
|
'repositories {',
|
|
262
292
|
" maven { url 'https://mvnrepo.guance.com/repository/maven-releases' }",
|
|
@@ -264,21 +294,22 @@ function patchGradle(file, nativeRoot) {
|
|
|
264
294
|
'dependencies {',
|
|
265
295
|
" implementation 'com.cloudcare.ft.mobile.sdk.tracker.agent:ft-sdk:1.7.6-alpha03'",
|
|
266
296
|
" implementation 'com.cloudcare.ft.mobile.sdk.tracker.agent:ft-native:1.1.3'",
|
|
267
|
-
|
|
297
|
+
...(replay ? [` implementation '${escapeGroovy(replay.androidReplay)}'`] : []),
|
|
268
298
|
" implementation 'com.google.code.gson:gson:2.10.1'",
|
|
269
299
|
" implementation platform('org.jetbrains.kotlin:kotlin-bom:1.8.22')",
|
|
270
300
|
" implementation 'androidx.appcompat:appcompat:1.1.0'",
|
|
271
|
-
|
|
301
|
+
...(replay ? [` implementation '${escapeGroovy(replay.androidFragment)}'`] : []),
|
|
272
302
|
'}',
|
|
273
303
|
END,
|
|
274
304
|
].join('\n'), BEGIN, END, [[LEGACY_BEGIN, LEGACY_END]]);
|
|
275
305
|
}
|
|
276
306
|
|
|
277
|
-
function patchPodfile(file, nativeRoot) {
|
|
307
|
+
function patchPodfile(file, nativeRoot, replay) {
|
|
278
308
|
const iosDir = normalize(path.join(nativeRoot, 'ios'));
|
|
279
309
|
const block = [
|
|
280
310
|
POD_BEGIN,
|
|
281
311
|
`pod 'FTCocosBridge', :path => '${escapeRuby(iosDir)}'`,
|
|
312
|
+
...(replay ? [`pod 'FTCocosReplayBridge', :path => '${escapeRuby(normalize(path.join(nativeRoot, 'replay', 'ios')))}'`] : []),
|
|
282
313
|
POD_END,
|
|
283
314
|
].join('\n');
|
|
284
315
|
const original = fs.readFileSync(file, 'utf8');
|
|
@@ -308,7 +339,8 @@ function replaceIndentedMarkedBlock(contents, begin, end, block) {
|
|
|
308
339
|
|
|
309
340
|
function findIosApplicationTarget(projectFile) {
|
|
310
341
|
const contents = fs.readFileSync(projectFile, 'utf8');
|
|
311
|
-
if (contents.includes('COCOS_SDK_XCODE_PROJECT')
|
|
342
|
+
if (contents.includes('COCOS_SDK_XCODE_PROJECT')
|
|
343
|
+
|| fs.existsSync(path.join(path.dirname(projectFile), 'cocos-sdk-spm.json'))) {
|
|
312
344
|
const { readProject, applicationTarget } = require('./install-spm.cjs');
|
|
313
345
|
return applicationTarget(readProject(projectFile))?.[1].name || null;
|
|
314
346
|
}
|
|
@@ -366,16 +398,6 @@ function markedPattern(begin, end) {
|
|
|
366
398
|
return new RegExp(`${escapeRegExp(begin)}[\\s\\S]*?${escapeRegExp(end)}`, 'm');
|
|
367
399
|
}
|
|
368
400
|
|
|
369
|
-
function copyDirectory(source, destination) {
|
|
370
|
-
fs.mkdirSync(destination, { recursive: true });
|
|
371
|
-
for (const entry of fs.readdirSync(source, { withFileTypes: true })) {
|
|
372
|
-
const from = path.join(source, entry.name);
|
|
373
|
-
const to = path.join(destination, entry.name);
|
|
374
|
-
if (entry.isDirectory()) copyDirectory(from, to);
|
|
375
|
-
else fs.copyFileSync(from, to);
|
|
376
|
-
}
|
|
377
|
-
}
|
|
378
|
-
|
|
379
401
|
function findFiles(root, maxDepth) {
|
|
380
402
|
const result = [];
|
|
381
403
|
function visit(directory, depth) {
|
|
@@ -425,14 +447,14 @@ function migrateManagedPods(podfiles, logger) {
|
|
|
425
447
|
[POD_BEGIN, POD_END], [LEGACY_POD_BEGIN, LEGACY_POD_END], [LEGACY_BEGIN, LEGACY_END],
|
|
426
448
|
['# COCOS_HYBRID_SAMPLE_BEGIN', '# COCOS_HYBRID_SAMPLE_END'],
|
|
427
449
|
]) next = next.replace(markedPattern(begin, end), '');
|
|
428
|
-
if (/^\s*pod\s+['"](?:FTCocosBridge|HybridSampleHost|GuanceSDK)(?:\/[^'"]*)?['"]/m.test(next)) {
|
|
450
|
+
if (/^\s*pod\s+['"](?:FTCocosBridge|FTCocosReplayBridge|HybridSampleHost|GuanceSDK)(?:\/[^'"]*)?['"]/m.test(next)) {
|
|
429
451
|
throw new Error(`[cocos-sdk] Remove the manually declared native SDK Pod from ${file} before switching to SPM.`);
|
|
430
452
|
}
|
|
431
453
|
if (next !== original) fs.writeFileSync(file, next);
|
|
432
454
|
const directory = path.dirname(file);
|
|
433
455
|
const existingLock = path.join(directory, 'Podfile.lock');
|
|
434
456
|
const hasSDKPods = fs.existsSync(existingLock)
|
|
435
|
-
&& /^\s*- (?:FTCocosBridge|HybridSampleHost|GuanceSDK)(?:\/|\s|:)/m.test(fs.readFileSync(existingLock, 'utf8'));
|
|
457
|
+
&& /^\s*- (?:FTCocosBridge|FTCocosReplayBridge|HybridSampleHost|GuanceSDK)(?:\/|\s|:)/m.test(fs.readFileSync(existingLock, 'utf8'));
|
|
436
458
|
if (next === original && !hasSDKPods) continue;
|
|
437
459
|
if (fs.existsSync(path.join(directory, 'Podfile.lock')) || fs.existsSync(path.join(directory, 'Pods'))) {
|
|
438
460
|
logger.info('[cocos-sdk] Updating existing Pods integration for the SPM switch.');
|