@truewatchtech/cocos-sdk 0.1.0-alpha.3

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 (169) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +51 -0
  3. package/THIRD_PARTY_NOTICES +5 -0
  4. package/bin/cli.cjs +130 -0
  5. package/creator2/package.json +4 -0
  6. package/creator3/package.json +5 -0
  7. package/dist/creator2/core/auto-tracking.d.ts +35 -0
  8. package/dist/creator2/core/auto-tracking.d.ts.map +1 -0
  9. package/dist/creator2/core/auto-tracking.js +337 -0
  10. package/dist/creator2/core/auto-tracking.js.map +1 -0
  11. package/dist/creator2/core/client.d.ts +74 -0
  12. package/dist/creator2/core/client.d.ts.map +1 -0
  13. package/dist/creator2/core/client.js +176 -0
  14. package/dist/creator2/core/client.js.map +1 -0
  15. package/dist/creator2/core/index.d.ts +3 -0
  16. package/dist/creator2/core/index.d.ts.map +1 -0
  17. package/dist/creator2/core/index.js +6 -0
  18. package/dist/creator2/core/index.js.map +1 -0
  19. package/dist/creator2/core/modules.d.ts +159 -0
  20. package/dist/creator2/core/modules.d.ts.map +1 -0
  21. package/dist/creator2/core/modules.js +319 -0
  22. package/dist/creator2/core/modules.js.map +1 -0
  23. package/dist/creator2/core/replay-budget.d.ts +28 -0
  24. package/dist/creator2/core/replay-budget.d.ts.map +1 -0
  25. package/dist/creator2/core/replay-budget.js +113 -0
  26. package/dist/creator2/core/replay-budget.js.map +1 -0
  27. package/dist/creator2/core/replay-diagnostics.d.ts +36 -0
  28. package/dist/creator2/core/replay-diagnostics.d.ts.map +1 -0
  29. package/dist/creator2/core/replay-diagnostics.js +40 -0
  30. package/dist/creator2/core/replay-diagnostics.js.map +1 -0
  31. package/dist/creator2/core/replay-encoding.d.ts +31 -0
  32. package/dist/creator2/core/replay-encoding.d.ts.map +1 -0
  33. package/dist/creator2/core/replay-encoding.js +63 -0
  34. package/dist/creator2/core/replay-encoding.js.map +1 -0
  35. package/dist/creator2/core/replay-pixels.d.ts +3 -0
  36. package/dist/creator2/core/replay-pixels.d.ts.map +1 -0
  37. package/dist/creator2/core/replay-pixels.js +16 -0
  38. package/dist/creator2/core/replay-pixels.js.map +1 -0
  39. package/dist/creator2/core/replay-privacy.d.ts +15 -0
  40. package/dist/creator2/core/replay-privacy.d.ts.map +1 -0
  41. package/dist/creator2/core/replay-privacy.js +36 -0
  42. package/dist/creator2/core/replay-privacy.js.map +1 -0
  43. package/dist/creator2/core/replay.d.ts +97 -0
  44. package/dist/creator2/core/replay.d.ts.map +1 -0
  45. package/dist/creator2/core/replay.js +578 -0
  46. package/dist/creator2/core/replay.js.map +1 -0
  47. package/dist/creator2/core/transport.d.ts +16 -0
  48. package/dist/creator2/core/transport.d.ts.map +1 -0
  49. package/dist/creator2/core/transport.js +33 -0
  50. package/dist/creator2/core/transport.js.map +1 -0
  51. package/dist/creator2/core/types.d.ts +260 -0
  52. package/dist/creator2/core/types.d.ts.map +1 -0
  53. package/dist/creator2/core/types.js +3 -0
  54. package/dist/creator2/core/types.js.map +1 -0
  55. package/dist/creator2/core/validation.d.ts +14 -0
  56. package/dist/creator2/core/validation.d.ts.map +1 -0
  57. package/dist/creator2/core/validation.js +81 -0
  58. package/dist/creator2/core/validation.js.map +1 -0
  59. package/dist/creator2/core/version.d.ts +9 -0
  60. package/dist/creator2/core/version.d.ts.map +1 -0
  61. package/dist/creator2/core/version.js +14 -0
  62. package/dist/creator2/core/version.js.map +1 -0
  63. package/dist/creator2/creator2/auto.d.ts +9 -0
  64. package/dist/creator2/creator2/auto.d.ts.map +1 -0
  65. package/dist/creator2/creator2/auto.js +65 -0
  66. package/dist/creator2/creator2/auto.js.map +1 -0
  67. package/dist/creator2/creator2/capture.d.ts +17 -0
  68. package/dist/creator2/creator2/capture.d.ts.map +1 -0
  69. package/dist/creator2/creator2/capture.js +175 -0
  70. package/dist/creator2/creator2/capture.js.map +1 -0
  71. package/dist/creator2/creator2/index.d.ts +12 -0
  72. package/dist/creator2/creator2/index.d.ts.map +1 -0
  73. package/dist/creator2/creator2/index.js +41 -0
  74. package/dist/creator2/creator2/index.js.map +1 -0
  75. package/dist/creator2/creator2/transport.d.ts +7 -0
  76. package/dist/creator2/creator2/transport.d.ts.map +1 -0
  77. package/dist/creator2/creator2/transport.js +34 -0
  78. package/dist/creator2/creator2/transport.js.map +1 -0
  79. package/dist/creator3/core/auto-tracking.d.ts +35 -0
  80. package/dist/creator3/core/auto-tracking.d.ts.map +1 -0
  81. package/dist/creator3/core/auto-tracking.js +247 -0
  82. package/dist/creator3/core/auto-tracking.js.map +1 -0
  83. package/dist/creator3/core/client.d.ts +74 -0
  84. package/dist/creator3/core/client.d.ts.map +1 -0
  85. package/dist/creator3/core/client.js +158 -0
  86. package/dist/creator3/core/client.js.map +1 -0
  87. package/dist/creator3/core/index.d.ts +3 -0
  88. package/dist/creator3/core/index.d.ts.map +1 -0
  89. package/dist/creator3/core/index.js +2 -0
  90. package/dist/creator3/core/index.js.map +1 -0
  91. package/dist/creator3/core/modules.d.ts +159 -0
  92. package/dist/creator3/core/modules.d.ts.map +1 -0
  93. package/dist/creator3/core/modules.js +293 -0
  94. package/dist/creator3/core/modules.js.map +1 -0
  95. package/dist/creator3/core/replay-budget.d.ts +28 -0
  96. package/dist/creator3/core/replay-budget.d.ts.map +1 -0
  97. package/dist/creator3/core/replay-budget.js +105 -0
  98. package/dist/creator3/core/replay-budget.js.map +1 -0
  99. package/dist/creator3/core/replay-diagnostics.d.ts +36 -0
  100. package/dist/creator3/core/replay-diagnostics.d.ts.map +1 -0
  101. package/dist/creator3/core/replay-diagnostics.js +36 -0
  102. package/dist/creator3/core/replay-diagnostics.js.map +1 -0
  103. package/dist/creator3/core/replay-encoding.d.ts +31 -0
  104. package/dist/creator3/core/replay-encoding.d.ts.map +1 -0
  105. package/dist/creator3/core/replay-encoding.js +62 -0
  106. package/dist/creator3/core/replay-encoding.js.map +1 -0
  107. package/dist/creator3/core/replay-pixels.d.ts +3 -0
  108. package/dist/creator3/core/replay-pixels.d.ts.map +1 -0
  109. package/dist/creator3/core/replay-pixels.js +13 -0
  110. package/dist/creator3/core/replay-pixels.js.map +1 -0
  111. package/dist/creator3/core/replay-privacy.d.ts +15 -0
  112. package/dist/creator3/core/replay-privacy.d.ts.map +1 -0
  113. package/dist/creator3/core/replay-privacy.js +33 -0
  114. package/dist/creator3/core/replay-privacy.js.map +1 -0
  115. package/dist/creator3/core/replay.d.ts +97 -0
  116. package/dist/creator3/core/replay.d.ts.map +1 -0
  117. package/dist/creator3/core/replay.js +520 -0
  118. package/dist/creator3/core/replay.js.map +1 -0
  119. package/dist/creator3/core/transport.d.ts +16 -0
  120. package/dist/creator3/core/transport.d.ts.map +1 -0
  121. package/dist/creator3/core/transport.js +27 -0
  122. package/dist/creator3/core/transport.js.map +1 -0
  123. package/dist/creator3/core/types.d.ts +260 -0
  124. package/dist/creator3/core/types.d.ts.map +1 -0
  125. package/dist/creator3/core/types.js +2 -0
  126. package/dist/creator3/core/types.js.map +1 -0
  127. package/dist/creator3/core/validation.d.ts +14 -0
  128. package/dist/creator3/core/validation.d.ts.map +1 -0
  129. package/dist/creator3/core/validation.js +75 -0
  130. package/dist/creator3/core/validation.js.map +1 -0
  131. package/dist/creator3/core/version.d.ts +9 -0
  132. package/dist/creator3/core/version.d.ts.map +1 -0
  133. package/dist/creator3/core/version.js +11 -0
  134. package/dist/creator3/core/version.js.map +1 -0
  135. package/dist/creator3/creator3/auto.d.ts +9 -0
  136. package/dist/creator3/creator3/auto.d.ts.map +1 -0
  137. package/dist/creator3/creator3/auto.js +73 -0
  138. package/dist/creator3/creator3/auto.js.map +1 -0
  139. package/dist/creator3/creator3/capture.d.ts +17 -0
  140. package/dist/creator3/creator3/capture.d.ts.map +1 -0
  141. package/dist/creator3/creator3/capture.js +119 -0
  142. package/dist/creator3/creator3/capture.js.map +1 -0
  143. package/dist/creator3/creator3/index.d.ts +12 -0
  144. package/dist/creator3/creator3/index.d.ts.map +1 -0
  145. package/dist/creator3/creator3/index.js +23 -0
  146. package/dist/creator3/creator3/index.js.map +1 -0
  147. package/dist/creator3/creator3/replay-render-cycle.d.ts +9 -0
  148. package/dist/creator3/creator3/replay-render-cycle.d.ts.map +1 -0
  149. package/dist/creator3/creator3/replay-render-cycle.js +12 -0
  150. package/dist/creator3/creator3/replay-render-cycle.js.map +1 -0
  151. package/dist/creator3/creator3/transport.d.ts +8 -0
  152. package/dist/creator3/creator3/transport.d.ts.map +1 -0
  153. package/dist/creator3/creator3/transport.js +24 -0
  154. package/dist/creator3/creator3/transport.js.map +1 -0
  155. package/dist/creator3/package.json +1 -0
  156. package/extensions/creator2/install-native.cjs +333 -0
  157. package/extensions/creator2/main.js +23 -0
  158. package/extensions/creator2/package.json +6 -0
  159. package/extensions/creator3/dist/builder.js +9 -0
  160. package/extensions/creator3/dist/hooks.js +70 -0
  161. package/extensions/creator3/dist/main.js +4 -0
  162. package/extensions/creator3/install-native.cjs +333 -0
  163. package/extensions/creator3/package.json +10 -0
  164. package/native/android/src/main/java/com/ft/sdk/cocos/FTCocosBridge.java +532 -0
  165. package/native/android/src/main/java/com/ft/sdk/cocos/FTCocosBridgeProvider.java +70 -0
  166. package/native/ios/FTCocosBridge.h +10 -0
  167. package/native/ios/FTCocosBridge.m +470 -0
  168. package/native/ios/FTCocosBridge.podspec +18 -0
  169. package/package.json +60 -0
@@ -0,0 +1,293 @@
1
+ import { requireText, samplingRate } from './validation.js';
2
+ import { FT_COCOS_SDK_BRIDGE_INFO, FT_COCOS_SDK_BRIDGE_INFO_KEY, FT_COCOS_SDK_VERSION, FT_COCOS_SDK_VERSION_KEY, } from './version.js';
3
+ export class FTSDKOwnership {
4
+ constructor() {
5
+ this.mode = 'unclaimed';
6
+ }
7
+ claimStandalone() {
8
+ if (this.mode === 'native-host') {
9
+ throw new Error('The native host owns SDK initialization in Hybrid mode');
10
+ }
11
+ this.mode = 'standalone';
12
+ }
13
+ claimNativeHost() {
14
+ if (this.mode === 'standalone') {
15
+ throw new Error('Standalone initialization and native-host attachment are mutually exclusive');
16
+ }
17
+ this.mode = 'native-host';
18
+ }
19
+ releaseNativeHost() {
20
+ if (this.mode === 'native-host')
21
+ this.mode = 'unclaimed';
22
+ }
23
+ releaseStandalone() {
24
+ if (this.mode === 'standalone')
25
+ this.mode = 'unclaimed';
26
+ }
27
+ assertNativeHostDoesNotOwnSDK() {
28
+ if (this.mode === 'native-host') {
29
+ throw new Error('The native host owns the native SDK in Hybrid mode');
30
+ }
31
+ }
32
+ }
33
+ function compact(value) {
34
+ const source = value;
35
+ const result = {};
36
+ Object.keys(value).forEach((key) => {
37
+ if (source[key] !== undefined)
38
+ result[key] = source[key];
39
+ });
40
+ return result;
41
+ }
42
+ function withBridgeInfo(attributes) {
43
+ return {
44
+ [FT_COCOS_SDK_BRIDGE_INFO_KEY]: FT_COCOS_SDK_BRIDGE_INFO,
45
+ ...(attributes || {}),
46
+ };
47
+ }
48
+ /** Base SDK lifecycle and user identity operations. */
49
+ export class FTMobileAgent {
50
+ constructor(transport, ownership = new FTSDKOwnership()) {
51
+ this.transport = transport;
52
+ this.ownership = ownership;
53
+ }
54
+ /**
55
+ * Initializes the native SDK connection.
56
+ *
57
+ * Supply either `datakitUrl`, or both `datawayUrl` and `clientToken`.
58
+ *
59
+ * @param config - Base SDK connection and service settings.
60
+ */
61
+ start(config) {
62
+ if (!config.datakitUrl && !(config.datawayUrl && config.clientToken)) {
63
+ throw new TypeError('Configure datakitUrl or datawayUrl with clientToken');
64
+ }
65
+ this.ownership.claimStandalone();
66
+ this.transport.invoke('sdk.configure', compact({
67
+ ...config,
68
+ globalContext: {
69
+ ...(config.globalContext || {}),
70
+ [FT_COCOS_SDK_VERSION_KEY]: FT_COCOS_SDK_VERSION,
71
+ },
72
+ }));
73
+ }
74
+ /**
75
+ * Binds a user identity to data collected after this call.
76
+ *
77
+ * @param user - A user ID or a structured user record.
78
+ */
79
+ bindUser(user) {
80
+ this.transport.invoke('sdk.bindUser', typeof user === 'string' ? { userId: requireText(user, 'userId') } : user);
81
+ }
82
+ /** Removes the currently bound user identity. */
83
+ unbindUser() {
84
+ this.transport.invoke('sdk.unbindUser');
85
+ }
86
+ /** Shuts down a standalone native SDK instance. */
87
+ shutdown() {
88
+ this.ownership.assertNativeHostDoesNotOwnSDK();
89
+ this.transport.invoke('sdk.shutdown');
90
+ this.ownership.releaseStandalone();
91
+ }
92
+ }
93
+ /** Manual Real User Monitoring operations. */
94
+ export class FTRUM {
95
+ constructor(transport, ownership = new FTSDKOwnership()) {
96
+ this.transport = transport;
97
+ this.ownership = ownership;
98
+ }
99
+ /**
100
+ * Enables RUM with the supplied native and Cocos settings.
101
+ *
102
+ * @param config - RUM application IDs, sampling, and native tracking options.
103
+ */
104
+ start(config) {
105
+ samplingRate(config.sampleRate, 'rum.sampleRate');
106
+ samplingRate(config.sessionOnErrorSampleRate, 'rum.sessionOnErrorSampleRate');
107
+ this.ownership.claimStandalone();
108
+ this.transport.invoke('rum.configure', compact(config));
109
+ }
110
+ /**
111
+ * Starts a RUM view.
112
+ *
113
+ * @param name - Application-defined view name.
114
+ * @param attributes - Optional attributes attached to the view.
115
+ */
116
+ startView(name, attributes) {
117
+ this.transport.invoke('rum.startView', {
118
+ name: requireText(name, 'view name'),
119
+ attributes: withBridgeInfo(attributes),
120
+ });
121
+ }
122
+ /**
123
+ * Stops the currently active RUM view.
124
+ *
125
+ * @param attributes - Optional attributes attached when the view stops.
126
+ */
127
+ stopView(attributes) {
128
+ this.transport.invoke('rum.stopView', { attributes: withBridgeInfo(attributes) });
129
+ }
130
+ /**
131
+ * Records a completed RUM action.
132
+ *
133
+ * @param name - Application-defined action name.
134
+ * @param type - Action category. @defaultValue `'click'`
135
+ * @param attributes - Optional attributes attached to the action.
136
+ */
137
+ addAction(name, type = 'click', attributes) {
138
+ this.transport.invoke('rum.addAction', {
139
+ name: requireText(name, 'action name'),
140
+ type: requireText(type, 'action type'),
141
+ attributes: withBridgeInfo(attributes),
142
+ });
143
+ }
144
+ /**
145
+ * Starts a RUM action whose completion is detected by the native SDK.
146
+ *
147
+ * @param name - Application-defined action name.
148
+ * @param type - Action category. @defaultValue `'click'`
149
+ * @param attributes - Optional attributes attached to the action.
150
+ */
151
+ startAction(name, type = 'click', attributes) {
152
+ this.transport.invoke('rum.startAction', {
153
+ name: requireText(name, 'action name'),
154
+ type: requireText(type, 'action type'),
155
+ attributes: withBridgeInfo(attributes),
156
+ });
157
+ }
158
+ /**
159
+ * Records an application error.
160
+ *
161
+ * @param message - Human-readable error message.
162
+ * @param stack - Error stack or diagnostic details.
163
+ * @param type - Application-defined error category. @defaultValue `'cocos_error'`
164
+ * @param state - Application state when the error occurred. @defaultValue `'run'`
165
+ * @param attributes - Optional attributes attached to the error.
166
+ */
167
+ addError(message, stack, type = 'cocos_error', state = 'run', attributes) {
168
+ this.transport.invoke('rum.addError', {
169
+ message,
170
+ stack,
171
+ type,
172
+ state,
173
+ attributes: withBridgeInfo(attributes),
174
+ });
175
+ }
176
+ /**
177
+ * Records a long task.
178
+ *
179
+ * @param stack - Stack or diagnostic details for the task.
180
+ * @param durationNs - Task duration in nanoseconds.
181
+ * @param attributes - Optional attributes attached to the task.
182
+ */
183
+ addLongTask(stack, durationNs, attributes) {
184
+ this.transport.invoke('rum.addLongTask', {
185
+ stack,
186
+ durationNs,
187
+ attributes: withBridgeInfo(attributes),
188
+ });
189
+ }
190
+ /**
191
+ * Starts tracking a resource using an application-defined correlation key.
192
+ *
193
+ * @param key - Key reused by subsequent calls for this resource.
194
+ * @param attributes - Optional attributes attached to the resource.
195
+ */
196
+ startResource(key, attributes) {
197
+ this.transport.invoke('rum.startResource', {
198
+ key: requireText(key, 'resource key'),
199
+ attributes: withBridgeInfo(attributes),
200
+ });
201
+ }
202
+ /**
203
+ * Stops timing a resource previously started with {@link startResource}.
204
+ *
205
+ * @param key - Key passed to {@link startResource}.
206
+ * @param attributes - Optional attributes attached when timing stops.
207
+ */
208
+ stopResource(key, attributes) {
209
+ this.transport.invoke('rum.stopResource', {
210
+ key: requireText(key, 'resource key'),
211
+ attributes: withBridgeInfo(attributes),
212
+ });
213
+ }
214
+ /**
215
+ * Adds request, response, and optional timing details to a tracked resource.
216
+ *
217
+ * @param key - Key passed to {@link startResource} and {@link stopResource}.
218
+ * @param content - Request and response details safe to collect.
219
+ * @param metrics - Optional network timing metrics.
220
+ */
221
+ addResource(key, content, metrics) {
222
+ this.transport.invoke('rum.addResource', {
223
+ key: requireText(key, 'resource key'),
224
+ content,
225
+ metrics,
226
+ });
227
+ }
228
+ }
229
+ /** Manual logging operations. */
230
+ export class FTLogger {
231
+ constructor(transport, ownership = new FTSDKOwnership()) {
232
+ this.transport = transport;
233
+ this.ownership = ownership;
234
+ }
235
+ /**
236
+ * Enables the native logger.
237
+ *
238
+ * @param config - Logger sampling, filtering, and cache settings.
239
+ */
240
+ start(config) {
241
+ samplingRate(config.sampleRate, 'logger.sampleRate');
242
+ this.ownership.claimStandalone();
243
+ this.transport.invoke('logger.configure', compact(config));
244
+ }
245
+ /**
246
+ * Writes a custom log entry.
247
+ *
248
+ * @param content - Log message.
249
+ * @param level - Log severity. @defaultValue `'info'`
250
+ * @param attributes - Optional attributes attached to the log.
251
+ */
252
+ log(content, level = 'info', attributes) {
253
+ this.transport.invoke('logger.log', {
254
+ content,
255
+ level,
256
+ attributes: withBridgeInfo(attributes),
257
+ });
258
+ }
259
+ }
260
+ /** Distributed-tracing operations. */
261
+ export class FTTrace {
262
+ constructor(transport, ownership = new FTSDKOwnership()) {
263
+ this.transport = transport;
264
+ this.ownership = ownership;
265
+ }
266
+ /**
267
+ * Enables distributed tracing.
268
+ *
269
+ * @param config - Trace sampling and propagation settings.
270
+ */
271
+ start(config) {
272
+ samplingRate(config.sampleRate, 'trace.sampleRate');
273
+ this.ownership.claimStandalone();
274
+ this.transport.invoke('trace.configure', compact(config));
275
+ }
276
+ /**
277
+ * Returns propagation headers for an outgoing request.
278
+ *
279
+ * Pass the same `resourceKey` used for manual RUM resource tracking to link
280
+ * the request with its trace.
281
+ *
282
+ * @param url - Absolute outgoing request URL.
283
+ * @param resourceKey - Optional key used for manual RUM resource tracking.
284
+ * @returns Headers to merge into the outgoing request.
285
+ */
286
+ getHeaders(url, resourceKey) {
287
+ return this.transport.invoke('trace.getHeaders', {
288
+ url: requireText(url, 'url'),
289
+ resourceKey,
290
+ }) || {};
291
+ }
292
+ }
293
+ //# sourceMappingURL=modules.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"modules.js","sourceRoot":"","sources":["../../../../../src/core/modules.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ import type { FTResolvedReplayImagePolicy } from './validation.js';
2
+ export declare const REPLAY_KEY_FRAME_BURST_BYTES: number;
3
+ export interface FTReplayCaptureDecision {
4
+ allowed: boolean;
5
+ compressionQuality: number;
6
+ maxImageDimension: number;
7
+ maxFrameBytes: number;
8
+ usedBytes: number;
9
+ priority: boolean;
10
+ reason?: 'budget' | 'throttle';
11
+ }
12
+ /** Rolling image budget. Segment and pointer bytes intentionally remain outside this controller. */
13
+ export declare class FTReplayBudget {
14
+ private readonly policy;
15
+ private entries;
16
+ private lastCaptureAttempt;
17
+ private burstKeys;
18
+ private pressure;
19
+ constructor(policy: FTResolvedReplayImagePolicy);
20
+ reset(): void;
21
+ decide(timestamp: number, priorityKey?: string): FTReplayCaptureDecision;
22
+ record(timestamp: number, byteSize: number, priorityKey?: string): void;
23
+ usedBytes(timestamp: number): number;
24
+ private prune;
25
+ private decision;
26
+ private updatePressure;
27
+ }
28
+ //# sourceMappingURL=replay-budget.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"replay-budget.d.ts","sourceRoot":"","sources":["../../../../../src/core/replay-budget.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,iBAAiB,CAAC;AAInE,eAAO,MAAM,4BAA4B,QAAa,CAAC;AAOvD,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,OAAO,CAAC;IACjB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,QAAQ,GAAG,UAAU,CAAC;CAChC;AAED,oGAAoG;AACpG,qBAAa,cAAc;IAMb,OAAO,CAAC,QAAQ,CAAC,MAAM;IALnC,OAAO,CAAC,OAAO,CAA6B;IAC5C,OAAO,CAAC,kBAAkB,CAAqB;IAC/C,OAAO,CAAC,SAAS,CAAgB;IACjC,OAAO,CAAC,QAAQ,CAA4D;gBAE/C,MAAM,EAAE,2BAA2B;IAEhE,KAAK,IAAI,IAAI;IAOb,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,uBAAuB;IA+BxE,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI;IAUvE,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM;IAKpC,OAAO,CAAC,KAAK;IAKb,OAAO,CAAC,QAAQ;IA2BhB,OAAO,CAAC,cAAc;CA0BvB"}
@@ -0,0 +1,105 @@
1
+ const WINDOW_MS = 60000;
2
+ const THROTTLED_CAPTURE_INTERVAL_MS = 2000;
3
+ export const REPLAY_KEY_FRAME_BURST_BYTES = 100 * 1024;
4
+ /** Rolling image budget. Segment and pointer bytes intentionally remain outside this controller. */
5
+ export class FTReplayBudget {
6
+ constructor(policy) {
7
+ this.policy = policy;
8
+ this.entries = [];
9
+ this.burstKeys = [];
10
+ this.pressure = 'normal';
11
+ }
12
+ reset() {
13
+ this.entries = [];
14
+ this.lastCaptureAttempt = undefined;
15
+ this.burstKeys = [];
16
+ this.pressure = 'normal';
17
+ }
18
+ decide(timestamp, priorityKey) {
19
+ const used = this.usedBytes(timestamp);
20
+ const ratio = used / this.policy.maxBytesPerMinute;
21
+ this.updatePressure(ratio);
22
+ const hasBurst = priorityKey !== undefined && !this.burstKeys.includes(priorityKey);
23
+ if (ratio >= 1 && !hasBurst)
24
+ return this.decision(false, 0, used, hasBurst, 'budget');
25
+ if (this.policy.adaptiveCapture
26
+ && this.pressure !== 'normal'
27
+ && this.lastCaptureAttempt !== undefined
28
+ && timestamp - this.lastCaptureAttempt < THROTTLED_CAPTURE_INTERVAL_MS
29
+ && !hasBurst) {
30
+ return this.decision(false, 0, used, hasBurst, 'throttle');
31
+ }
32
+ this.lastCaptureAttempt = timestamp;
33
+ const normalRemaining = Math.max(0, this.policy.maxBytesPerMinute - used);
34
+ const available = normalRemaining + (hasBurst ? REPLAY_KEY_FRAME_BURST_BYTES : 0);
35
+ const frameLimit = hasBurst
36
+ ? Math.min(Math.max(this.policy.maxFrameBytes, REPLAY_KEY_FRAME_BURST_BYTES), available)
37
+ : Math.min(this.policy.maxFrameBytes, available);
38
+ return this.decision(frameLimit >= 1024, frameLimit, used, hasBurst, frameLimit >= 1024 ? undefined : 'budget');
39
+ }
40
+ record(timestamp, byteSize, priorityKey) {
41
+ if (!Number.isFinite(byteSize) || byteSize <= 0)
42
+ return;
43
+ this.prune(timestamp);
44
+ this.entries.push({ timestamp, byteSize: Math.round(byteSize) });
45
+ if (priorityKey && !this.burstKeys.includes(priorityKey)) {
46
+ this.burstKeys.push(priorityKey);
47
+ if (this.burstKeys.length > 64)
48
+ this.burstKeys.shift();
49
+ }
50
+ }
51
+ usedBytes(timestamp) {
52
+ this.prune(timestamp);
53
+ return this.entries.reduce((total, entry) => total + entry.byteSize, 0);
54
+ }
55
+ prune(timestamp) {
56
+ const cutoff = timestamp - WINDOW_MS;
57
+ while (this.entries.length > 0 && this.entries[0].timestamp <= cutoff)
58
+ this.entries.shift();
59
+ }
60
+ decision(allowed, maxFrameBytes, usedBytes, priority, reason) {
61
+ const degraded = this.policy.adaptiveCapture
62
+ && (this.pressure === 'degraded' || this.pressure === 'paused');
63
+ return {
64
+ allowed,
65
+ compressionQuality: degraded
66
+ ? Math.max(0.25, Math.round(this.policy.compressionQuality * 0.75 * 100) / 100)
67
+ : this.policy.compressionQuality,
68
+ maxImageDimension: degraded
69
+ ? Math.min(this.policy.maxImageDimension, Math.max(240, Math.floor(this.policy.maxImageDimension * 0.75)))
70
+ : this.policy.maxImageDimension,
71
+ maxFrameBytes: Math.max(0, Math.floor(maxFrameBytes)),
72
+ usedBytes,
73
+ priority,
74
+ ...(reason ? { reason } : {}),
75
+ };
76
+ }
77
+ updatePressure(ratio) {
78
+ if (!this.policy.adaptiveCapture) {
79
+ this.pressure = 'normal';
80
+ return;
81
+ }
82
+ if (ratio >= 1) {
83
+ this.pressure = 'paused';
84
+ return;
85
+ }
86
+ if (ratio >= 0.9) {
87
+ this.pressure = 'degraded';
88
+ return;
89
+ }
90
+ if (this.pressure === 'paused' || this.pressure === 'degraded') {
91
+ if (ratio >= 0.8) {
92
+ this.pressure = 'degraded';
93
+ return;
94
+ }
95
+ }
96
+ if (ratio >= 0.75) {
97
+ this.pressure = 'throttled';
98
+ return;
99
+ }
100
+ if (this.pressure === 'throttled' && ratio >= 0.65)
101
+ return;
102
+ this.pressure = 'normal';
103
+ }
104
+ }
105
+ //# sourceMappingURL=replay-budget.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"replay-budget.js","sourceRoot":"","sources":["../../../../../src/core/replay-budget.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ export type FTReplaySkipReason = 'dedupe' | 'approx_static' | 'throttle' | 'budget' | 'busy' | 'error';
2
+ export type FTReplayDiagnosticEvent = {
3
+ type: 'capture_attempt';
4
+ timestamp: number;
5
+ usedBytes: number;
6
+ maxBytesPerMinute: number;
7
+ } | {
8
+ type: 'capture_skipped';
9
+ timestamp: number;
10
+ reason: FTReplaySkipReason;
11
+ } | {
12
+ type: 'image_saved';
13
+ timestamp: number;
14
+ byteSize: number;
15
+ width: number;
16
+ height: number;
17
+ mimeType?: string;
18
+ priority: boolean;
19
+ byteSizeSource: 'native' | 'frame_limit_estimate';
20
+ } | {
21
+ type: 'segment_encoded';
22
+ timestamp: number;
23
+ byteSize: number;
24
+ recordCount: number;
25
+ pointerRecordCount: number;
26
+ hasImage: boolean;
27
+ } | {
28
+ type: 'pointer_received';
29
+ timestamp: number;
30
+ eventType: 'down' | 'up' | 'move';
31
+ } | {
32
+ type: 'replay_stopped';
33
+ timestamp: number;
34
+ };
35
+ export declare function replayUtf8ByteLength(value: string): number;
36
+ //# sourceMappingURL=replay-diagnostics.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"replay-diagnostics.d.ts","sourceRoot":"","sources":["../../../../../src/core/replay-diagnostics.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,kBAAkB,GAC1B,QAAQ,GACR,eAAe,GACf,UAAU,GACV,QAAQ,GACR,MAAM,GACN,OAAO,CAAC;AAEZ,MAAM,MAAM,uBAAuB,GAC/B;IAAE,IAAI,EAAE,iBAAiB,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,iBAAiB,EAAE,MAAM,CAAA;CAAE,GAC5F;IAAE,IAAI,EAAE,iBAAiB,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,kBAAkB,CAAA;CAAE,GAC1E;IACA,IAAI,EAAE,aAAa,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;IAClB,cAAc,EAAE,QAAQ,GAAG,sBAAsB,CAAC;CACnD,GACC;IACA,IAAI,EAAE,iBAAiB,CAAC;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,QAAQ,EAAE,OAAO,CAAC;CACnB,GACC;IAAE,IAAI,EAAE,kBAAkB,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAAA;CAAE,GAClF;IAAE,IAAI,EAAE,gBAAgB,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC;AAmBlD,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAiB1D"}
@@ -0,0 +1,36 @@
1
+ /** @internal Benchmark-only observer hook. Production builds leave it unset. */
2
+ export function emitReplayDiagnostic(event) {
3
+ const observer = globalThis.__FT_COCOS_REPLAY_BENCHMARK_OBSERVER__;
4
+ if (typeof observer !== 'function')
5
+ return;
6
+ try {
7
+ observer(event);
8
+ }
9
+ catch (_a) {
10
+ // Diagnostics must never affect capture, storage, or upload behavior.
11
+ }
12
+ }
13
+ export function replayUtf8ByteLength(value) {
14
+ let bytes = 0;
15
+ for (let index = 0; index < value.length; index += 1) {
16
+ const code = value.charCodeAt(index);
17
+ if (code < 0x80)
18
+ bytes += 1;
19
+ else if (code < 0x800)
20
+ bytes += 2;
21
+ else if (code >= 0xd800 && code <= 0xdbff && index + 1 < value.length) {
22
+ const low = value.charCodeAt(index + 1);
23
+ if (low >= 0xdc00 && low <= 0xdfff) {
24
+ bytes += 4;
25
+ index += 1;
26
+ }
27
+ else {
28
+ bytes += 3;
29
+ }
30
+ }
31
+ else
32
+ bytes += 3;
33
+ }
34
+ return bytes;
35
+ }
36
+ //# sourceMappingURL=replay-diagnostics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"replay-diagnostics.js","sourceRoot":"","sources":["../../../../../src/core/replay-diagnostics.ts"],"names":[],"mappings":"AAsCA,gFAAgF;AAChF,MAAM,UAAU,oBAAoB,CAAC,KAA8B;IACjE,MAAM,QAAQ,GAAI,UAAuC,CAAC,sCAAsC,CAAC;IACjG,IAAI,OAAO,QAAQ,KAAK,UAAU;QAAE,OAAO;IAC3C,IAAI,CAAC;QACH,QAAQ,CAAC,KAAK,CAAC,CAAC;IAClB,CAAC;IAAC,WAAM,CAAC;QACP,sEAAsE;IACxE,CAAC;AACH,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,KAAa;IAChD,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,KAAK,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QACrD,MAAM,IAAI,GAAG,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;QACrC,IAAI,IAAI,GAAG,IAAI;YAAE,KAAK,IAAI,CAAC,CAAC;aACvB,IAAI,IAAI,GAAG,KAAK;YAAE,KAAK,IAAI,CAAC,CAAC;aAC7B,IAAI,IAAI,IAAI,MAAM,IAAI,IAAI,IAAI,MAAM,IAAI,KAAK,GAAG,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC;YACtE,MAAM,GAAG,GAAG,KAAK,CAAC,UAAU,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;YACxC,IAAI,GAAG,IAAI,MAAM,IAAI,GAAG,IAAI,MAAM,EAAE,CAAC;gBACnC,KAAK,IAAI,CAAC,CAAC;gBACX,KAAK,IAAI,CAAC,CAAC;YACb,CAAC;iBAAM,CAAC;gBACN,KAAK,IAAI,CAAC,CAAC;YACb,CAAC;QACH,CAAC;;YAAM,KAAK,IAAI,CAAC,CAAC;IACpB,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -0,0 +1,31 @@
1
+ import type { FTRUMContext } from './types.js';
2
+ export interface FTReplayImageRecord {
3
+ context: FTRUMContext;
4
+ resourceId: string;
5
+ width: number;
6
+ height: number;
7
+ mimeType?: `image/${string}`;
8
+ timestamp: number;
9
+ contextChanged: boolean;
10
+ pointerEvents?: FTReplayPointerRecord[];
11
+ }
12
+ export interface FTReplayPointerRecord {
13
+ eventType: 'down' | 'up' | 'move';
14
+ pointerId: number;
15
+ x: number;
16
+ y: number;
17
+ timestamp: number;
18
+ }
19
+ export interface FTReplayPointerRecords {
20
+ context: FTRUMContext;
21
+ pointerEvents: FTReplayPointerRecord[];
22
+ }
23
+ export declare function encodeReplayImageRecord(input: FTReplayImageRecord): {
24
+ segment: string;
25
+ recordCount: number;
26
+ };
27
+ export declare function encodeReplayPointerRecords(input: FTReplayPointerRecords): {
28
+ segment: string;
29
+ recordCount: number;
30
+ };
31
+ //# sourceMappingURL=replay-encoding.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"replay-encoding.d.ts","sourceRoot":"","sources":["../../../../../src/core/replay-encoding.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,YAAY,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,OAAO,CAAC;IACxB,aAAa,CAAC,EAAE,qBAAqB,EAAE,CAAC;CACzC;AAED,MAAM,WAAW,qBAAqB;IACpC,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAAC;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,YAAY,CAAC;IACtB,aAAa,EAAE,qBAAqB,EAAE,CAAC;CACxC;AAED,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,mBAAmB,GAAG;IACnE,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;CACrB,CAiCA;AAED,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,sBAAsB,GAAG;IACzE,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;CACrB,CAMA"}
@@ -0,0 +1,62 @@
1
+ export function encodeReplayImageRecord(input) {
2
+ var _a;
3
+ const wireframe = {
4
+ id: 1,
5
+ type: 'image',
6
+ x: 0,
7
+ y: 0,
8
+ width: input.width,
9
+ height: input.height,
10
+ base64: null,
11
+ border: null,
12
+ clip: null,
13
+ isEmpty: false,
14
+ ...(input.mimeType ? { mimeType: input.mimeType } : {}),
15
+ resourceId: input.resourceId,
16
+ shapeStyle: null,
17
+ };
18
+ const records = [];
19
+ if (input.contextChanged) {
20
+ records.push({ type: 4, data: { width: input.width, height: input.height }, timestamp: input.timestamp }, { type: 6, data: { has_focus: true }, timestamp: input.timestamp });
21
+ }
22
+ records.push({
23
+ type: 10,
24
+ data: { wireframes: [wireframe] },
25
+ timestamp: input.timestamp,
26
+ });
27
+ records.push(...((_a = input.pointerEvents) === null || _a === void 0 ? void 0 : _a.map(pointerRecord)) || []);
28
+ return {
29
+ segment: encodeEnvelope(input.context, records),
30
+ recordCount: records.length,
31
+ };
32
+ }
33
+ export function encodeReplayPointerRecords(input) {
34
+ const records = input.pointerEvents.map(pointerRecord);
35
+ return {
36
+ segment: encodeEnvelope(input.context, records),
37
+ recordCount: records.length,
38
+ };
39
+ }
40
+ function pointerRecord(pointer) {
41
+ return {
42
+ type: 11,
43
+ data: {
44
+ source: 9,
45
+ pointerEventType: pointer.eventType,
46
+ pointerType: 'touch',
47
+ pointerId: pointer.pointerId,
48
+ x: pointer.x,
49
+ y: pointer.y,
50
+ },
51
+ timestamp: pointer.timestamp,
52
+ };
53
+ }
54
+ function encodeEnvelope(context, records) {
55
+ return JSON.stringify({
56
+ records,
57
+ applicationID: context.applicationId,
58
+ sessionID: context.sessionId,
59
+ viewID: context.viewId,
60
+ });
61
+ }
62
+ //# sourceMappingURL=replay-encoding.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"replay-encoding.js","sourceRoot":"","sources":["../../../../../src/core/replay-encoding.ts"],"names":[],"mappings":"AA0BA,MAAM,UAAU,uBAAuB,CAAC,KAA0B;;IAIhE,MAAM,SAAS,GAAG;QAChB,EAAE,EAAE,CAAC;QACL,IAAI,EAAE,OAAO;QACb,CAAC,EAAE,CAAC;QACJ,CAAC,EAAE,CAAC;QACJ,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,MAAM,EAAE,IAAI;QACZ,MAAM,EAAE,IAAI;QACZ,IAAI,EAAE,IAAI;QACV,OAAO,EAAE,KAAK;QACd,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACvD,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,UAAU,EAAE,IAAI;KACjB,CAAC;IACF,MAAM,OAAO,GAAc,EAAE,CAAC;IAC9B,IAAI,KAAK,CAAC,cAAc,EAAE,CAAC;QACzB,OAAO,CAAC,IAAI,CACV,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,EAC3F,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,CACnE,CAAC;IACJ,CAAC;IACD,OAAO,CAAC,IAAI,CAAC;QACX,IAAI,EAAE,EAAE;QACR,IAAI,EAAE,EAAE,UAAU,EAAE,CAAC,SAAS,CAAC,EAAE;QACjC,SAAS,EAAE,KAAK,CAAC,SAAS;KAC3B,CAAC,CAAC;IACH,OAAO,CAAC,IAAI,CAAC,GAAG,CAAA,MAAA,KAAK,CAAC,aAAa,0CAAE,GAAG,CAAC,aAAa,CAAC,KAAI,EAAE,CAAC,CAAC;IAC/D,OAAO;QACL,OAAO,EAAE,cAAc,CAAC,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC;QAC/C,WAAW,EAAE,OAAO,CAAC,MAAM;KAC5B,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,0BAA0B,CAAC,KAA6B;IAItE,MAAM,OAAO,GAAG,KAAK,CAAC,aAAa,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;IACvD,OAAO;QACL,OAAO,EAAE,cAAc,CAAC,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC;QAC/C,WAAW,EAAE,OAAO,CAAC,MAAM;KAC5B,CAAC;AACJ,CAAC;AAED,SAAS,aAAa,CAAC,OAA8B;IACnD,OAAO;QACL,IAAI,EAAE,EAAE;QACR,IAAI,EAAE;YACJ,MAAM,EAAE,CAAC;YACT,gBAAgB,EAAE,OAAO,CAAC,SAAS;YACnC,WAAW,EAAE,OAAO;YACpB,SAAS,EAAE,OAAO,CAAC,SAAS;YAC5B,CAAC,EAAE,OAAO,CAAC,CAAC;YACZ,CAAC,EAAE,OAAO,CAAC,CAAC;SACb;QACD,SAAS,EAAE,OAAO,CAAC,SAAS;KAC7B,CAAC;AACJ,CAAC;AAED,SAAS,cAAc,CAAC,OAAqB,EAAE,OAAkB;IAC/D,OAAO,IAAI,CAAC,SAAS,CAAC;QACpB,OAAO;QACP,aAAa,EAAE,OAAO,CAAC,aAAa;QACpC,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,MAAM,EAAE,OAAO,CAAC,MAAM;KACvB,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,3 @@
1
+ /** Converts tightly packed RGBA pixels from bottom-left to top-left row order. */
2
+ export declare function flipRgbaRows(bytes: Uint8Array, width: number, height: number): void;
3
+ //# sourceMappingURL=replay-pixels.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"replay-pixels.d.ts","sourceRoot":"","sources":["../../../../../src/core/replay-pixels.ts"],"names":[],"mappings":"AAAA,kFAAkF;AAClF,wBAAgB,YAAY,CAAC,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAUnF"}
@@ -0,0 +1,13 @@
1
+ /** Converts tightly packed RGBA pixels from bottom-left to top-left row order. */
2
+ export function flipRgbaRows(bytes, width, height) {
3
+ const rowSize = width * 4;
4
+ const swap = new Uint8Array(rowSize);
5
+ for (let top = 0, bottom = height - 1; top < bottom; top += 1, bottom -= 1) {
6
+ const topOffset = top * rowSize;
7
+ const bottomOffset = bottom * rowSize;
8
+ swap.set(bytes.subarray(topOffset, topOffset + rowSize));
9
+ bytes.copyWithin(topOffset, bottomOffset, bottomOffset + rowSize);
10
+ bytes.set(swap, bottomOffset);
11
+ }
12
+ }
13
+ //# sourceMappingURL=replay-pixels.js.map