@playcraft/devkit 1.0.31-beta.11 → 1.0.31-beta.14

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 (101) hide show
  1. package/cli/bin/playable-scripts.js +6 -53
  2. package/cli/commands/build.js +32 -241
  3. package/cli/commands/builds.js +2 -13
  4. package/cli/commands/dev.js +1 -22
  5. package/cli/commands/pack.js +40 -320
  6. package/cli/commands/vite-dev.js +1 -7
  7. package/core/artifacts/emit-fonts.test.js +1 -0
  8. package/core/artifacts/emit.js +4 -98
  9. package/core/artifacts/fflate.js +1 -31
  10. package/core/artifacts/zip.js +1 -39
  11. package/core/batch-build.js +147 -1261
  12. package/core/constants.js +2 -20
  13. package/core/cos-uploader.js +23 -289
  14. package/core/engines/cocos/adapter-vfs-path.test.js +1 -0
  15. package/core/engines/cocos/clean-cache.js +5 -179
  16. package/core/engines/cocos/clean-cache.test.js +1 -75
  17. package/core/engines/cocos/cli-build.js +2 -116
  18. package/core/engines/cocos/cli.js +11 -38
  19. package/core/engines/cocos/constants.js +1 -21
  20. package/core/engines/cocos/creator-cli.js +1 -108
  21. package/core/engines/cocos/dev-server.js +4 -412
  22. package/core/engines/cocos/fs.js +1 -105
  23. package/core/engines/cocos/injects/3x/init.js +19 -438
  24. package/core/engines/cocos/injects/3x/main.js +2 -52
  25. package/core/engines/cocos/injects/libs/pako.js +1 -2
  26. package/core/engines/cocos/mcp-refresh.js +2 -76
  27. package/core/engines/cocos/merge-inline.test.js +1 -0
  28. package/core/engines/cocos/merge.js +9 -148
  29. package/core/engines/cocos/omit-playable-weight.js +10 -0
  30. package/core/engines/cocos/omit-playable-weight.test.js +2 -0
  31. package/core/engines/cocos/pack.js +1 -187
  32. package/core/engines/cocos/preview-cache.js +2 -48
  33. package/core/engines/cocos/preview-cache.test.js +1 -32
  34. package/core/engines/cocos/preview-concat.js +6 -189
  35. package/core/engines/cocos/preview-concat.test.js +1 -73
  36. package/core/engines/cocos/preview-json-hook.js +1 -200
  37. package/core/engines/cocos/preview-json-pack.js +3 -376
  38. package/core/engines/cocos/preview-json-pack.test.js +2 -226
  39. package/core/engines/cocos/preview-proxy.js +1 -132
  40. package/core/engines/cocos/rebundle-preview.js +2 -54
  41. package/core/engines/cocos/strip-social-share.js +3 -115
  42. package/core/engines/cocos/theme-assets.js +2 -161
  43. package/core/engines/cocos/theme-levels.js +1 -0
  44. package/core/engines/cocos/writable-cli.js +2 -248
  45. package/core/engines/cocos/writable-cli.test.js +1 -112
  46. package/core/engines/web/index.js +1 -20
  47. package/core/engines/web/vite.dev.js +17 -322
  48. package/core/engines/web/webpack.build.js +37 -522
  49. package/core/engines/web/webpack.common.js +11 -177
  50. package/core/engines/web/webpack.dev.js +6 -88
  51. package/core/index.js +7 -101
  52. package/core/injectors/apply.js +1 -94
  53. package/core/injectors/check-channel-matrix.js +2 -130
  54. package/core/injectors/spec.js +10 -217
  55. package/core/loaders/gltf-loader.js +28 -74
  56. package/core/options.js +16 -353
  57. package/core/plugins/AdikteevInjectorPlugin.js +4 -26
  58. package/core/plugins/BigoAdsInjectorPlugin.js +4 -21
  59. package/core/plugins/DAPIInjectorPlugin.js +2 -25
  60. package/core/plugins/DebuggerInjectionPlugin.js +3 -31
  61. package/core/plugins/ExitAPIInjectorPlugin.js +3 -56
  62. package/core/plugins/FflateCompressionPlugin.js +160 -307
  63. package/core/plugins/FflateCompressionPlugin.test.js +13 -0
  64. package/core/plugins/FontInjectionWebpackPlugin.js +4 -46
  65. package/core/plugins/LiftoffInjectorPlugin.js +4 -26
  66. package/core/plugins/MRAIDInjectorPlugin.js +2 -24
  67. package/core/plugins/MintegralInjectorPlugin.js +2 -25
  68. package/core/plugins/PangleInjectorPlugin.js +2 -24
  69. package/core/plugins/PlaycraftOrientationInjectorPlugin.js +3 -29
  70. package/core/plugins/SnapchatInjectorPlugin.js +4 -26
  71. package/core/plugins/SocialMediaInjectorPlugin.js +7 -119
  72. package/core/plugins/TikTokInjectorPlugin.js +2 -24
  73. package/core/plugins/UnityInjectorPlugin.js +8 -37
  74. package/core/plugins/ZipPlugin.js +20 -154
  75. package/core/plugins/socialMediaVitePlugin.js +2 -108
  76. package/core/utils/buildDefines.js +2 -30
  77. package/core/utils/buildTemplateString.js +5 -39
  78. package/core/utils/date.js +1 -16
  79. package/core/utils/fontRegistry.js +13 -81
  80. package/core/utils/fontResolver.js +37 -335
  81. package/core/utils/generateAdikteevHtmlWebpackPluginConfig.js +8 -42
  82. package/core/utils/generateBigabidHtmlWebpackPluginConfig.js +3 -30
  83. package/core/utils/generateInMobiHtmlWebpackPluginConfig.js +7 -43
  84. package/core/utils/getPlaycraftOrientationSuffix.js +2 -9
  85. package/core/utils/injectSDKPlugins.js +13 -68
  86. package/core/utils/logOptions.js +5 -46
  87. package/core/utils/mergeOptions.js +2 -21
  88. package/core/utils/obfuscateLevels.js +14 -0
  89. package/core/utils/obfuscateLevels.test.js +10 -0
  90. package/core/utils/parseArgvOptions.js +5 -125
  91. package/core/utils/resolveChannelFold2Zip.js +3 -15
  92. package/core/utils/validateThemeData.js +26 -227
  93. package/core/validators/pre-build-checker.js +25 -287
  94. package/core/validators/tracking-validator.js +40 -441
  95. package/core/validators/tracking-validator.test.js +2 -84
  96. package/core/vite.dev.js +1 -1
  97. package/core/webpack.build.js +1 -1
  98. package/core/webpack.common.js +1 -1
  99. package/core/webpack.dev.js +1 -1
  100. package/package.json +2 -3
  101. package/README.md +0 -262
@@ -1,200 +1 @@
1
- /* playcraft-json-pack:start */
2
- (function () {
3
- var pack = null;
4
- var pending = [];
5
- var packHash = '';
6
-
7
- function resolvePackUrl() {
8
- var src = '';
9
- try {
10
- if (document.currentScript && document.currentScript.src) src = document.currentScript.src;
11
- } catch (err) {}
12
- if (!src) {
13
- try {
14
- var scripts = document.getElementsByTagName('script');
15
- for (var i = scripts.length - 1; i >= 0; --i) {
16
- var candidate = scripts[i].src || '';
17
- if (candidate.indexOf('system.js') !== -1) {
18
- src = candidate;
19
- break;
20
- }
21
- }
22
- } catch (err) {}
23
- }
24
- if (!src) {
25
- try {
26
- var entries = performance.getEntriesByType('resource');
27
- for (var i = entries.length - 1; i >= 0; --i) {
28
- var name = entries[i].name;
29
- if (name.indexOf('/systemjs/system.js') !== -1) {
30
- src = name;
31
- break;
32
- }
33
- }
34
- } catch (err) {}
35
- }
36
- var url = src
37
- ? src.replace(/system\.js(\?.*)?$/, 'playcraft-json-pack.json')
38
- : 'scripting/systemjs/playcraft-json-pack.json';
39
- if (packHash && url.indexOf('?') === -1) url += '?h=' + packHash;
40
- return url;
41
- }
42
-
43
- function uuidFromUrl(url) {
44
- var match = String(url || '').match(
45
- /([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}(?:@[^.\\/?]+)?)(?:\.json)?(?:\?|$)/i,
46
- );
47
- return match ? match[1].toLowerCase() : '';
48
- }
49
-
50
- function extnameUuidFromUrl(url) {
51
- var match = String(url || '').match(
52
- /query-extname\/([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}(?:@[^.\\/?]+)?)(?:\?|$)/i,
53
- );
54
- return match ? match[1].toLowerCase() : '';
55
- }
56
-
57
- function configNameFromUrl(url) {
58
- var match = String(url || '').match(/\/(?:assets|remote)\/([^/]+)\/(?:config|cc\.config)\.json(?:\?|$)/i);
59
- return match ? match[1] : '';
60
- }
61
-
62
- function hasAsset(uuid) {
63
- return !!(uuid && pack && pack.assets && Object.prototype.hasOwnProperty.call(pack.assets, uuid));
64
- }
65
-
66
- function lookup(url) {
67
- if (!pack) return null;
68
- var href = String(url || '');
69
- var extUuid = extnameUuidFromUrl(href);
70
- if (extUuid) {
71
- if (hasAsset(extUuid)) return '.json';
72
- return null;
73
- }
74
- var uuid = uuidFromUrl(href);
75
- if (hasAsset(uuid)) return pack.assets[uuid];
76
- var configName = configNameFromUrl(href);
77
- if (configName && pack.configs && Object.prototype.hasOwnProperty.call(pack.configs, configName)) {
78
- return pack.configs[configName];
79
- }
80
- return null;
81
- }
82
-
83
- function serve(xhr, data) {
84
- var isString = typeof data === 'string';
85
- var text = isString ? data : JSON.stringify(data);
86
- Object.defineProperty(xhr, 'readyState', { configurable: true, get: function () { return 4; } });
87
- Object.defineProperty(xhr, 'status', { configurable: true, get: function () { return 200; } });
88
- Object.defineProperty(xhr, 'response', {
89
- configurable: true,
90
- get: function () { return xhr.responseType === 'json' && !isString ? data : text; },
91
- });
92
- Object.defineProperty(xhr, 'responseText', { configurable: true, get: function () { return text; } });
93
- if (typeof xhr.onreadystatechange === 'function') xhr.onreadystatechange();
94
- if (typeof xhr.onload === 'function') xhr.onload();
95
- }
96
-
97
- function flush() {
98
- var queue = pending.splice(0);
99
- for (var i = 0; i < queue.length; i++) queue[i]();
100
- }
101
-
102
- var xhrOpen = XMLHttpRequest.prototype.open;
103
- var xhrSend = XMLHttpRequest.prototype.send;
104
- var xhrHeader = XMLHttpRequest.prototype.setRequestHeader;
105
-
106
- XMLHttpRequest.prototype.open = function (method, url) {
107
- this.__pcUrl = String(url == null ? '' : url);
108
- this.__pcOpenArgs = arguments;
109
- this.__pcHit = false;
110
- this.__pcWait = false;
111
- if (this.__pcUrl.indexOf('playcraft-json-pack.json') !== -1) {
112
- return xhrOpen.apply(this, arguments);
113
- }
114
- if (pack) {
115
- if (lookup(this.__pcUrl) != null) {
116
- this.__pcHit = true;
117
- return;
118
- }
119
- return xhrOpen.apply(this, arguments);
120
- }
121
- this.__pcWait = true;
122
- };
123
-
124
- XMLHttpRequest.prototype.setRequestHeader = function () {
125
- if (this.__pcHit || this.__pcWait) return;
126
- return xhrHeader.apply(this, arguments);
127
- };
128
-
129
- XMLHttpRequest.prototype.send = function (body) {
130
- var xhr = this;
131
- var url = xhr.__pcUrl;
132
- if (url && String(url).indexOf('playcraft-json-pack.json') !== -1) {
133
- return xhrSend.apply(xhr, arguments);
134
- }
135
- var run = function () {
136
- var data = lookup(url);
137
- if (data != null) {
138
- xhr.__pcHit = true;
139
- serve(xhr, data);
140
- return;
141
- }
142
- if (xhr.__pcWait) xhrOpen.apply(xhr, xhr.__pcOpenArgs || ['GET', url]);
143
- xhrSend.call(xhr, body);
144
- };
145
- if (pack) {
146
- run();
147
- return;
148
- }
149
- pending.push(run);
150
- };
151
-
152
- if (typeof globalThis !== 'undefined' && typeof globalThis.fetch === 'function') {
153
- var nativeFetch = globalThis.fetch.bind(globalThis);
154
- globalThis.fetch = function (input, init) {
155
- var url = typeof input === 'string' ? input : (input && input.url);
156
- if (url && String(url).indexOf('playcraft-json-pack.json') !== -1) {
157
- return nativeFetch.apply(this, arguments);
158
- }
159
- var run = function () {
160
- var data = lookup(url);
161
- if (data != null) {
162
- var isString = typeof data === 'string';
163
- var text = isString ? data : JSON.stringify(data);
164
- return Promise.resolve(new Response(text, {
165
- status: 200,
166
- headers: { 'Content-Type': isString ? 'text/plain' : 'application/json' },
167
- }));
168
- }
169
- return nativeFetch.call(this, input, init);
170
- };
171
- if (pack) return run();
172
- return new Promise(function (resolve, reject) {
173
- pending.push(function () {
174
- Promise.resolve(run()).then(resolve, reject);
175
- });
176
- });
177
- };
178
- }
179
-
180
- if (pack) return;
181
-
182
- var req = new XMLHttpRequest();
183
- req.open('GET', resolvePackUrl(), true);
184
- req.onload = function () {
185
- var text = req.responseText || req.response;
186
- try {
187
- pack = typeof text === 'string' ? JSON.parse(text) : text;
188
- } catch (err) {
189
- pack = null;
190
- }
191
- if (!pack || typeof pack !== 'object') pack = { assets: {}, configs: {} };
192
- flush();
193
- };
194
- req.onerror = function () {
195
- pack = { assets: {}, configs: {} };
196
- flush();
197
- };
198
- req.send(null);
199
- })();
200
- /* playcraft-json-pack:end */
1
+ "use strict";/* playcraft-json-pack:start */(function(){var pack=null;var pending=[];var packHash="";function resolvePackUrl(){var src="";try{if(document.currentScript&&document.currentScript.src)src=document.currentScript.src}catch(err){}if(!src){try{var scripts=document.getElementsByTagName("script");for(var i=scripts.length-1;i>=0;--i){var candidate=scripts[i].src||"";if(candidate.indexOf("system.js")!==-1){src=candidate;break}}}catch(err){}}if(!src){try{var entries=performance.getEntriesByType("resource");for(var i=entries.length-1;i>=0;--i){var name=entries[i].name;if(name.indexOf("/systemjs/system.js")!==-1){src=name;break}}}catch(err){}}var url=src?src.replace(/system\.js(\?.*)?$/,"playcraft-json-pack.json"):"scripting/systemjs/playcraft-json-pack.json";if(packHash&&url.indexOf("?")===-1)url+="?h="+packHash;return url}function uuidFromUrl(url){var match=String(url||"").match(/([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}(?:@[^.\\/?]+)?)(?:\.json)?(?:\?|$)/i);return match?match[1].toLowerCase():""}function extnameUuidFromUrl(url){var match=String(url||"").match(/query-extname\/([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}(?:@[^.\\/?]+)?)(?:\?|$)/i);return match?match[1].toLowerCase():""}function configNameFromUrl(url){var match=String(url||"").match(/\/(?:assets|remote)\/([^/]+)\/(?:config|cc\.config)\.json(?:\?|$)/i);return match?match[1]:""}function hasAsset(uuid){return!!(uuid&&pack&&pack.assets&&Object.prototype.hasOwnProperty.call(pack.assets,uuid))}function lookup(url){if(!pack)return null;var href=String(url||"");var extUuid=extnameUuidFromUrl(href);if(extUuid){if(hasAsset(extUuid))return".json";return null}var uuid=uuidFromUrl(href);if(hasAsset(uuid))return pack.assets[uuid];var configName=configNameFromUrl(href);if(configName&&pack.configs&&Object.prototype.hasOwnProperty.call(pack.configs,configName)){return pack.configs[configName]}return null}function serve(xhr,data){var isString=typeof data==="string";var text=isString?data:JSON.stringify(data);Object.defineProperty(xhr,"readyState",{configurable:true,get:function(){return 4}});Object.defineProperty(xhr,"status",{configurable:true,get:function(){return 200}});Object.defineProperty(xhr,"response",{configurable:true,get:function(){return xhr.responseType==="json"&&!isString?data:text}});Object.defineProperty(xhr,"responseText",{configurable:true,get:function(){return text}});if(typeof xhr.onreadystatechange==="function")xhr.onreadystatechange();if(typeof xhr.onload==="function")xhr.onload()}function flush(){var queue=pending.splice(0);for(var i=0;i<queue.length;i++)queue[i]()}var xhrOpen=XMLHttpRequest.prototype.open;var xhrSend=XMLHttpRequest.prototype.send;var xhrHeader=XMLHttpRequest.prototype.setRequestHeader;XMLHttpRequest.prototype.open=function(method,url){this.__pcUrl=String(url==null?"":url);this.__pcOpenArgs=arguments;this.__pcHit=false;this.__pcWait=false;if(this.__pcUrl.indexOf("playcraft-json-pack.json")!==-1){return xhrOpen.apply(this,arguments)}if(pack){if(lookup(this.__pcUrl)!=null){this.__pcHit=true;return}return xhrOpen.apply(this,arguments)}this.__pcWait=true};XMLHttpRequest.prototype.setRequestHeader=function(){if(this.__pcHit||this.__pcWait)return;return xhrHeader.apply(this,arguments)};XMLHttpRequest.prototype.send=function(body){var xhr=this;var url=xhr.__pcUrl;if(url&&String(url).indexOf("playcraft-json-pack.json")!==-1){return xhrSend.apply(xhr,arguments)}var run=function(){var data=lookup(url);if(data!=null){xhr.__pcHit=true;serve(xhr,data);return}if(xhr.__pcWait)xhrOpen.apply(xhr,xhr.__pcOpenArgs||["GET",url]);xhrSend.call(xhr,body)};if(pack){run();return}pending.push(run)};if(typeof globalThis!=="undefined"&&typeof globalThis.fetch==="function"){var nativeFetch=globalThis.fetch.bind(globalThis);globalThis.fetch=function(input,init){var url=typeof input==="string"?input:input&&input.url;if(url&&String(url).indexOf("playcraft-json-pack.json")!==-1){return nativeFetch.apply(this,arguments)}var run=function(){var data=lookup(url);if(data!=null){var isString=typeof data==="string";var text=isString?data:JSON.stringify(data);return Promise.resolve(new Response(text,{status:200,headers:{"Content-Type":isString?"text/plain":"application/json"}}))}return nativeFetch.call(this,input,init)};if(pack)return run();return new Promise(function(resolve,reject){pending.push(function(){Promise.resolve(run()).then(resolve,reject)})})}}if(pack)return;var req=new XMLHttpRequest;req.open("GET",resolvePackUrl(),true);req.onload=function(){var text=req.responseText||req.response;try{pack=typeof text==="string"?JSON.parse(text):text}catch(err){pack=null}if(!pack||typeof pack!=="object")pack={assets:{},configs:{}};flush()};req.onerror=function(){pack={assets:{},configs:{}};flush()};req.send(null)})();/* playcraft-json-pack:end */
@@ -1,379 +1,6 @@
1
- 'use strict';
2
-
3
- const crypto = require('crypto');
4
- const fs = require('fs');
5
- const http = require('http');
6
- const https = require('https');
7
- const path = require('path');
8
- const { resolveCocosBin } = require('./cli.js');
9
-
10
- const HOOK_START = '/* playcraft-json-pack:start */';
11
- const HOOK_END = '/* playcraft-json-pack:end */';
12
- const PACK_FILE = 'playcraft-json-pack.json';
13
- const UUID_RE = /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}(?:@[0-9a-z]+)?/gi;
14
- const UUID_FILE_RE = /^([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}(?:@.+)?)\.json$/i;
15
- const FALLBACK_MAX_BYTES = 200 * 1024;
16
- const FILE_MAX_BYTES = 5 * 1024 * 1024;
17
-
18
- function systemJsDir(projectRoot) {
19
- return path.join(projectRoot, 'temp/programming/preview/systemjs');
20
- }
21
-
22
- function hookSource() {
23
- return fs.readFileSync(path.join(__dirname, 'preview-json-hook.js'), 'utf8').trim() + '\n';
24
- }
25
-
26
- function uuidFromUrl(url) {
27
- const match = String(url || '').match(
28
- /([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}(?:@[^.\\/?]+)?)(?:\.json)?(?:\?|$)/i,
29
- );
30
- return match ? match[1].toLowerCase() : '';
31
- }
32
-
33
- function configNameFromUrl(url) {
34
- const match = String(url || '').match(/\/(?:assets|remote)\/([^/]+)\/(?:config|cc\.config)\.json(?:\?|$)/i);
35
- return match ? match[1] : '';
36
- }
37
-
38
- function addUuid(set, value) {
39
- if (typeof value !== 'string' || !value) return;
40
- const inner = value.match(/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}(?:@[0-9a-z]+)?/i);
41
- if (inner) set.add(inner[0].toLowerCase());
42
- }
43
-
44
- function collectFromSettings(settings, seeds) {
45
- if (!settings || typeof settings !== 'object') return;
46
- const builtins = settings.engine && settings.engine.builtinAssets;
47
- if (Array.isArray(builtins)) {
48
- for (const uuid of builtins) addUuid(seeds, uuid);
49
- }
50
- addUuid(seeds, settings.launch && settings.launch.launchScene);
51
- addUuid(seeds, settings.launchScene);
52
- const scenes = settings.scenes || (settings.launch && settings.launch.scenes);
53
- if (Array.isArray(scenes)) {
54
- for (const scene of scenes) {
55
- if (scene && typeof scene === 'object') addUuid(seeds, scene.uuid);
56
- else addUuid(seeds, scene);
57
- }
58
- }
59
- }
60
-
61
- function collectFromConfig(config, seeds) {
62
- if (!config || typeof config !== 'object') return;
63
- for (const uuid of config.uuids || []) addUuid(seeds, String(uuid));
64
- for (const uuid of Object.keys(config.paths || {})) addUuid(seeds, uuid);
65
- const scenes = config.scenes || {};
66
- if (typeof scenes === 'object') {
67
- for (const value of Object.values(scenes)) {
68
- if (Array.isArray(value)) {
69
- for (const item of value) addUuid(seeds, String(item));
70
- } else {
71
- addUuid(seeds, String(value));
72
- }
73
- }
74
- }
75
- }
76
-
77
- function parseSettings(text) {
78
- const match = String(text || '').match(/window\._CCSettings\s*=\s*(\{[\s\S]*\});\s*$/);
79
- if (!match) return null;
80
- return JSON.parse(match[1]);
81
- }
82
-
83
- function fetchText(url, timeout = 8000) {
84
- return new Promise((resolve, reject) => {
85
- const client = String(url).startsWith('https:') ? https : http;
86
- const req = client.get(url, { timeout }, (res) => {
87
- const chunks = [];
88
- res.on('data', (chunk) => chunks.push(chunk));
89
- res.on('end', () => {
90
- const body = Buffer.concat(chunks).toString('utf8');
91
- if ((res.statusCode || 0) >= 400) {
92
- reject(new Error(`${res.statusCode} ${url}`));
93
- return;
94
- }
95
- resolve(body);
96
- });
97
- });
98
- req.on('timeout', () => {
99
- req.destroy();
100
- reject(new Error(`timeout ${url}`));
101
- });
102
- req.on('error', reject);
103
- });
104
- }
105
-
106
- function startSceneUuid(projectRoot) {
107
- try {
108
- const cfg = JSON.parse(fs.readFileSync(path.join(projectRoot, 'settings/cocos.config.json'), 'utf8'));
109
- return (
110
- (cfg.builder && cfg.builder.common && cfg.builder.common.startScene) ||
111
- (cfg.builder && cfg.builder.platforms && cfg.builder.platforms['web-mobile'] && cfg.builder.platforms['web-mobile'].startScene) ||
112
- (cfg.builder && cfg.builder.platforms && cfg.builder.platforms['web-desktop'] && cfg.builder.platforms['web-desktop'].startScene) ||
113
- ''
114
- );
115
- } catch {
116
- return '';
117
- }
118
- }
119
-
120
- function resolveEngineLibraryDirs(projectRoot) {
121
- const dirs = [];
122
- const add = (dir) => {
123
- if (dir && fs.existsSync(dir) && !dirs.includes(dir)) dirs.push(dir);
124
- };
125
- if (process.env.COCOS_ENGINE) {
126
- add(path.join(process.env.COCOS_ENGINE, 'editor/library'));
127
- }
128
- if (projectRoot) {
129
- add(path.join(projectRoot, 'temp/cocos-cli/packages/engine/editor/library'));
130
- }
131
- const bin = resolveCocosBin();
132
- const starts = [];
133
- if (bin && path.isAbsolute(bin)) starts.push(bin);
134
- try {
135
- const { execSync } = require('child_process');
136
- const which = execSync('command -v cocos', { encoding: 'utf8' }).trim();
137
- if (which) starts.push(which);
138
- } catch {}
139
- for (const start of starts) {
140
- try {
141
- let current = fs.realpathSync(start);
142
- for (let i = 0; i < 8; i++) {
143
- add(path.join(current, 'packages/engine/editor/library'));
144
- add(path.join(current, 'engine/editor/library'));
145
- add(path.join(current, 'editor/library'));
146
- current = path.dirname(current);
147
- }
148
- } catch {}
149
- }
150
- add('/opt/cocos-cli/packages/engine/editor/library');
151
- add('/usr/local/lib/node_modules/cocos-cli/packages/engine/editor/library');
152
- return dirs;
153
- }
154
-
155
- function libraryDirs(projectRoot, extraDirs) {
156
- const dirs = [];
157
- const projectLib = path.join(projectRoot, 'library');
158
- if (fs.existsSync(projectLib)) dirs.push(projectLib);
159
- for (const dir of extraDirs || resolveEngineLibraryDirs(projectRoot)) {
160
- if (dir && fs.existsSync(dir) && !dirs.includes(dir)) dirs.push(dir);
161
- }
162
- return dirs;
163
- }
164
-
165
- function importJsonUrl(origin, bundle, uuid) {
166
- return `${String(origin).replace(/\/$/, '')}/assets/${bundle}/import/${uuid.slice(0, 2)}/${uuid}.json`;
167
- }
168
-
169
- async function fetchAssetJson(origin, uuid, bundles, fetch) {
170
- for (const bundle of bundles) {
171
- try {
172
- return JSON.parse(await fetch(importJsonUrl(origin, bundle, uuid)));
173
- } catch {}
174
- }
175
- try {
176
- return JSON.parse(await fetch(`${String(origin).replace(/\/$/, '')}/scene/${uuid}.json`));
177
- } catch {}
178
- return null;
179
- }
180
-
181
- async function fillAssetsFromOrigin(assets, seeds, options) {
182
- const origin = options.previewOrigin;
183
- if (!origin) return;
184
- const fetch = options.fetchText || fetchText;
185
- const bundles = Object.keys(options.bundleConfigs || {}).filter(Boolean);
186
- if (!bundles.length) bundles.push('internal', 'main', 'resources');
187
- const queue = [];
188
- const seen = new Set(Object.keys(assets));
189
- for (const uuid of seeds) {
190
- seen.add(uuid);
191
- if (!assets[uuid]) queue.push(uuid);
192
- }
193
- const runOne = async (uuid) => {
194
- if (assets[uuid]) return;
195
- const json = await fetchAssetJson(origin, uuid, bundles, fetch);
196
- if (!json) return;
197
- assets[uuid] = json;
198
- for (const match of JSON.stringify(json).matchAll(UUID_RE)) {
199
- const next = match[0].toLowerCase();
200
- if (seen.has(next)) continue;
201
- seen.add(next);
202
- queue.push(next);
203
- }
204
- };
205
- while (queue.length) {
206
- const batch = queue.splice(0, 10);
207
- await Promise.all(batch.map(runOne));
208
- }
209
- }
210
-
211
- function findLibraryJson(uuid, dirs) {
212
- const name = `${uuid}.json`;
213
- const prefix = uuid.slice(0, 2);
214
- for (const dir of dirs) {
215
- const abs = path.join(dir, prefix, name);
216
- if (fs.existsSync(abs)) return abs;
217
- }
218
- return '';
219
- }
220
-
221
- function scanFallbackUuids(dirs) {
222
- const seeds = new Set();
223
- for (const dir of dirs) {
224
- if (!fs.existsSync(dir)) continue;
225
- for (const bucket of fs.readdirSync(dir)) {
226
- const absBucket = path.join(dir, bucket);
227
- let stat;
228
- try {
229
- stat = fs.statSync(absBucket);
230
- } catch {
231
- continue;
232
- }
233
- if (!stat.isDirectory()) continue;
234
- for (const name of fs.readdirSync(absBucket)) {
235
- const match = name.match(UUID_FILE_RE);
236
- if (!match) continue;
237
- const abs = path.join(absBucket, name);
238
- try {
239
- if (fs.statSync(abs).size > FALLBACK_MAX_BYTES) continue;
240
- } catch {
241
- continue;
242
- }
243
- seeds.add(match[1].toLowerCase());
244
- }
245
- }
246
- }
247
- return seeds;
248
- }
249
-
250
- function closeUuidJson(seeds, dirs) {
251
- const assets = {};
252
- const queue = [...seeds];
253
- const seen = new Set(seeds);
254
- while (queue.length) {
255
- const uuid = queue.pop();
256
- const abs = findLibraryJson(uuid, dirs);
257
- if (!abs) continue;
258
- let stat;
259
- try {
260
- stat = fs.statSync(abs);
261
- } catch {
262
- continue;
263
- }
264
- if (stat.size > FILE_MAX_BYTES) continue;
265
- let json;
266
- try {
267
- json = JSON.parse(fs.readFileSync(abs, 'utf8'));
268
- } catch {
269
- continue;
270
- }
271
- assets[uuid] = json;
272
- const text = JSON.stringify(json);
273
- UUID_RE.lastIndex = 0;
274
- let match;
275
- while ((match = UUID_RE.exec(text))) {
276
- const next = match[0].toLowerCase();
277
- if (seen.has(next)) continue;
278
- seen.add(next);
279
- queue.push(next);
280
- }
281
- }
282
- return assets;
283
- }
284
-
285
- function injectJsonPackHook(projectRoot, packHash, packObject) {
286
- const dir = systemJsDir(projectRoot);
287
- const systemJsPath = path.join(dir, 'system.js');
288
- if (!fs.existsSync(systemJsPath)) return false;
289
- let source = fs.readFileSync(systemJsPath, 'utf8');
290
- const start = source.indexOf(HOOK_START);
291
- const end = source.indexOf(HOOK_END);
292
- if (start !== -1 && end !== -1 && end > start) {
293
- source = `${source.slice(0, start)}${source.slice(end + HOOK_END.length)}`.replace(/^\n/, '');
294
- }
295
- let hook = hookSource();
296
- if (packObject) {
297
- hook = hook.replace('var pack = null;', `var pack = ${JSON.stringify(packObject)};`);
298
- }
299
- if (packHash) {
300
- hook = hook.replace(/var packHash = '';/, `var packHash = ${JSON.stringify(packHash)};`);
301
- }
302
- fs.writeFileSync(systemJsPath, `${hook}${source}`);
303
- return true;
304
- }
305
-
306
- async function loadPreviewMeta(options) {
307
- if (options.settings || options.bundleConfigs) {
308
- return {
309
- settings: options.settings || null,
310
- configs: options.bundleConfigs || {},
311
- };
312
- }
313
- const origin = options.previewOrigin;
314
- if (!origin) return { settings: null, configs: {} };
315
- const fetch = options.fetchText || fetchText;
316
- const settings = parseSettings(await fetch(`${origin.replace(/\/$/, '')}/preview/settings.js`));
317
- const bundles = (settings && settings.assets && settings.assets.projectBundles) || [
318
- 'internal',
319
- 'main',
320
- 'resources',
321
- ];
322
- const configs = {};
323
- for (const name of bundles) {
324
- try {
325
- configs[name] = JSON.parse(await fetch(`${origin.replace(/\/$/, '')}/assets/${name}/config.json`));
326
- } catch {}
327
- }
328
- return { settings, configs };
329
- }
330
-
331
- /**
1
+ "use strict";const crypto=require("crypto");const fs=require("fs");const http=require("http");const https=require("https");const path=require("path");const{resolveCocosEntryPoint}=require("./cli.js");const HOOK_START="/* playcraft-json-pack:start */";const HOOK_END="/* playcraft-json-pack:end */";const PACK_FILE="playcraft-json-pack.json";const UUID_RE=/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}(?:@[0-9a-z]+)?/gi;const UUID_FILE_RE=/^([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}(?:@.+)?)\.json$/i;const FALLBACK_MAX_BYTES=200*1024;const FILE_MAX_BYTES=5*1024*1024;function systemJsDir(projectRoot){return path.join(projectRoot,"temp/programming/preview/systemjs")}function hookSource(){return fs.readFileSync(path.join(__dirname,"preview-json-hook.js"),"utf8").trim()+"\n"}function uuidFromUrl(url){const match=String(url||"").match(/([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}(?:@[^.\\/?]+)?)(?:\.json)?(?:\?|$)/i);return match?match[1].toLowerCase():""}function configNameFromUrl(url){const match=String(url||"").match(/\/(?:assets|remote)\/([^/]+)\/(?:config|cc\.config)\.json(?:\?|$)/i);return match?match[1]:""}function addUuid(set,value){if(typeof value!=="string"||!value)return;const inner=value.match(/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}(?:@[0-9a-z]+)?/i);if(inner)set.add(inner[0].toLowerCase())}function collectFromSettings(settings,seeds){if(!settings||typeof settings!=="object")return;const builtins=settings.engine&&settings.engine.builtinAssets;if(Array.isArray(builtins)){for(const uuid of builtins)addUuid(seeds,uuid)}addUuid(seeds,settings.launch&&settings.launch.launchScene);addUuid(seeds,settings.launchScene);const scenes=settings.scenes||settings.launch&&settings.launch.scenes;if(Array.isArray(scenes)){for(const scene of scenes){if(scene&&typeof scene==="object")addUuid(seeds,scene.uuid);else addUuid(seeds,scene)}}}function collectFromConfig(config,seeds){if(!config||typeof config!=="object")return;for(const uuid of config.uuids||[])addUuid(seeds,String(uuid));for(const uuid of Object.keys(config.paths||{}))addUuid(seeds,uuid);const scenes=config.scenes||{};if(typeof scenes==="object"){for(const value of Object.values(scenes)){if(Array.isArray(value)){for(const item of value)addUuid(seeds,String(item))}else{addUuid(seeds,String(value))}}}}function parseSettings(text){const match=String(text||"").match(/window\._CCSettings\s*=\s*(\{[\s\S]*\});\s*$/);if(!match)return null;return JSON.parse(match[1])}function fetchText(url,timeout=8000){return new Promise((resolve,reject)=>{const client=String(url).startsWith("https:")?https:http;const req=client.get(url,{timeout},res=>{const chunks=[];res.on("data",chunk=>chunks.push(chunk));res.on("end",()=>{const body=Buffer.concat(chunks).toString("utf8");if((res.statusCode||0)>=400){reject(new Error(`${res.statusCode} ${url}`));return}resolve(body)})});req.on("timeout",()=>{req.destroy();reject(new Error(`timeout ${url}`))});req.on("error",reject)})}function startSceneUuid(projectRoot){try{const cfg=JSON.parse(fs.readFileSync(path.join(projectRoot,"settings/cocos.config.json"),"utf8"));return cfg.builder&&cfg.builder.common&&cfg.builder.common.startScene||cfg.builder&&cfg.builder.platforms&&cfg.builder.platforms["web-mobile"]&&cfg.builder.platforms["web-mobile"].startScene||cfg.builder&&cfg.builder.platforms&&cfg.builder.platforms["web-desktop"]&&cfg.builder.platforms["web-desktop"].startScene||""}catch{return""}}function resolveEngineLibraryDirs(projectRoot){const dirs=[];const add=dir=>{if(dir&&fs.existsSync(dir)&&!dirs.includes(dir))dirs.push(dir)};if(process.env.COCOS_ENGINE){add(path.join(process.env.COCOS_ENGINE,"editor/library"))}if(projectRoot){add(path.join(projectRoot,"temp/cocos-cli/packages/engine/editor/library"))}// Windows 上要穿透 npm 的 cocos.cmd shim 才能往上走到 engine/library
2
+ try{const entry=resolveCocosEntryPoint();let current=entry?fs.realpathSync(entry):"";for(let i=0;current&&i<8;i++){add(path.join(current,"packages/engine/editor/library"));add(path.join(current,"engine/editor/library"));add(path.join(current,"editor/library"));const parent=path.dirname(current);current=parent===current?"":parent}}catch{}add("/opt/cocos-cli/packages/engine/editor/library");add("/usr/local/lib/node_modules/cocos-cli/packages/engine/editor/library");return dirs}function libraryDirs(projectRoot,extraDirs){const dirs=[];const projectLib=path.join(projectRoot,"library");if(fs.existsSync(projectLib))dirs.push(projectLib);for(const dir of extraDirs||resolveEngineLibraryDirs(projectRoot)){if(dir&&fs.existsSync(dir)&&!dirs.includes(dir))dirs.push(dir)}return dirs}function importJsonUrl(origin,bundle,uuid){return`${String(origin).replace(/\/$/,"")}/assets/${bundle}/import/${uuid.slice(0,2)}/${uuid}.json`}async function fetchAssetJson(origin,uuid,bundles,fetch){for(const bundle of bundles){try{return JSON.parse(await fetch(importJsonUrl(origin,bundle,uuid)))}catch{}}try{return JSON.parse(await fetch(`${String(origin).replace(/\/$/,"")}/scene/${uuid}.json`))}catch{}return null}async function fillAssetsFromOrigin(assets,seeds,options){const origin=options.previewOrigin;if(!origin)return;const fetch=options.fetchText||fetchText;const bundles=Object.keys(options.bundleConfigs||{}).filter(Boolean);if(!bundles.length)bundles.push("internal","main","resources");const queue=[];const seen=new Set(Object.keys(assets));for(const uuid of seeds){seen.add(uuid);if(!assets[uuid])queue.push(uuid)}const runOne=async uuid=>{if(assets[uuid])return;const json=await fetchAssetJson(origin,uuid,bundles,fetch);if(!json)return;assets[uuid]=json;for(const match of JSON.stringify(json).matchAll(UUID_RE)){const next=match[0].toLowerCase();if(seen.has(next))continue;seen.add(next);queue.push(next)}};while(queue.length){const batch=queue.splice(0,10);await Promise.all(batch.map(runOne))}}function findLibraryJson(uuid,dirs){const name=`${uuid}.json`;const prefix=uuid.slice(0,2);for(const dir of dirs){const abs=path.join(dir,prefix,name);if(fs.existsSync(abs))return abs}return""}function scanFallbackUuids(dirs){const seeds=new Set;for(const dir of dirs){if(!fs.existsSync(dir))continue;for(const bucket of fs.readdirSync(dir)){const absBucket=path.join(dir,bucket);let stat;try{stat=fs.statSync(absBucket)}catch{continue}if(!stat.isDirectory())continue;for(const name of fs.readdirSync(absBucket)){const match=name.match(UUID_FILE_RE);if(!match)continue;const abs=path.join(absBucket,name);try{if(fs.statSync(abs).size>FALLBACK_MAX_BYTES)continue}catch{continue}seeds.add(match[1].toLowerCase())}}}return seeds}function closeUuidJson(seeds,dirs){const assets={};const queue=[...seeds];const seen=new Set(seeds);while(queue.length){const uuid=queue.pop();const abs=findLibraryJson(uuid,dirs);if(!abs)continue;let stat;try{stat=fs.statSync(abs)}catch{continue}if(stat.size>FILE_MAX_BYTES)continue;let json;try{json=JSON.parse(fs.readFileSync(abs,"utf8"))}catch{continue}assets[uuid]=json;const text=JSON.stringify(json);UUID_RE.lastIndex=0;let match;while(match=UUID_RE.exec(text)){const next=match[0].toLowerCase();if(seen.has(next))continue;seen.add(next);queue.push(next)}}return assets}function injectJsonPackHook(projectRoot,packHash,packObject){const dir=systemJsDir(projectRoot);const systemJsPath=path.join(dir,"system.js");if(!fs.existsSync(systemJsPath))return false;let source=fs.readFileSync(systemJsPath,"utf8");const start=source.indexOf(HOOK_START);const end=source.indexOf(HOOK_END);if(start!==-1&&end!==-1&&end>start){source=`${source.slice(0,start)}${source.slice(end+HOOK_END.length)}`.replace(/^\n/,"")}let hook=hookSource();if(packObject){hook=hook.replace("var pack = null;",`var pack = ${JSON.stringify(packObject)};`)}if(packHash){hook=hook.replace(/var packHash = '';/,`var packHash = ${JSON.stringify(packHash)};`)}fs.writeFileSync(systemJsPath,`${hook}${source}`);return true}async function loadPreviewMeta(options){if(options.settings||options.bundleConfigs){return{settings:options.settings||null,configs:options.bundleConfigs||{}}}const origin=options.previewOrigin;if(!origin)return{settings:null,configs:{}};const fetch=options.fetchText||fetchText;const settings=parseSettings(await fetch(`${origin.replace(/\/$/,"")}/preview/settings.js`));const bundles=settings&&settings.assets&&settings.assets.projectBundles||["internal","main","resources"];const configs={};for(const name of bundles){try{configs[name]=JSON.parse(await fetch(`${origin.replace(/\/$/,"")}/assets/${name}/config.json`))}catch{}}return{settings,configs}}/**
332
3
  * Pack preview UUID JSON + bundle configs into one file and intercept XHR
333
4
  * from system.js (before builtin assets load). Official merge_all_json is
334
5
  * builder-only and uses a compiled format preview cannot feed.
335
- */
336
- async function packPreviewJson(projectRoot, options = {}) {
337
- const dirs = libraryDirs(projectRoot, options.engineLibraryDirs);
338
- const { settings, configs } = await loadPreviewMeta(options);
339
- const seeds = new Set();
340
- collectFromSettings(settings, seeds);
341
- for (const config of Object.values(configs || {})) collectFromConfig(config, seeds);
342
- addUuid(seeds, startSceneUuid(projectRoot));
343
- const projectLib = path.join(projectRoot, 'library');
344
- for (const uuid of scanFallbackUuids([projectLib])) seeds.add(uuid);
345
- if (!seeds.size) {
346
- for (const uuid of scanFallbackUuids(dirs)) seeds.add(uuid);
347
- }
348
- const assets = closeUuidJson(seeds, dirs);
349
- await fillAssetsFromOrigin(assets, seeds, { ...options, bundleConfigs: configs });
350
- const pack = { assets, configs: configs || {} };
351
- const json = `${JSON.stringify(pack)}\n`;
352
- const dir = systemJsDir(projectRoot);
353
- fs.mkdirSync(dir, { recursive: true });
354
- const abs = path.join(dir, PACK_FILE);
355
- const tmp = `${abs}.tmp`;
356
- fs.writeFileSync(tmp, json);
357
- fs.renameSync(tmp, abs);
358
- const packHash = crypto.createHash('sha1').update(json).digest('hex').slice(0, 10);
359
- const hooked = injectJsonPackHook(projectRoot, packHash, pack);
360
- return {
361
- files: Object.keys(assets).length,
362
- configs: Object.keys(pack.configs).length,
363
- bytes: Buffer.byteLength(json),
364
- hooked,
365
- pack: `./${PACK_FILE}`,
366
- };
367
- }
368
-
369
- module.exports = {
370
- packPreviewJson,
371
- injectJsonPackHook,
372
- uuidFromUrl,
373
- configNameFromUrl,
374
- parseSettings,
375
- collectFromSettings,
376
- collectFromConfig,
377
- PACK_FILE,
378
- HOOK_START,
379
- };
6
+ */async function packPreviewJson(projectRoot,options={}){const dirs=libraryDirs(projectRoot,options.engineLibraryDirs);const{settings,configs}=await loadPreviewMeta(options);const seeds=new Set;collectFromSettings(settings,seeds);for(const config of Object.values(configs||{}))collectFromConfig(config,seeds);addUuid(seeds,startSceneUuid(projectRoot));const projectLib=path.join(projectRoot,"library");for(const uuid of scanFallbackUuids([projectLib]))seeds.add(uuid);if(!seeds.size){for(const uuid of scanFallbackUuids(dirs))seeds.add(uuid)}const assets=closeUuidJson(seeds,dirs);await fillAssetsFromOrigin(assets,seeds,{...options,bundleConfigs:configs});const pack={assets,configs:configs||{}};const json=`${JSON.stringify(pack)}\n`;const dir=systemJsDir(projectRoot);fs.mkdirSync(dir,{recursive:true});const abs=path.join(dir,PACK_FILE);const tmp=`${abs}.tmp`;fs.writeFileSync(tmp,json);fs.renameSync(tmp,abs);const packHash=crypto.createHash("sha1").update(json).digest("hex").slice(0,10);const hooked=injectJsonPackHook(projectRoot,packHash,pack);return{files:Object.keys(assets).length,configs:Object.keys(pack.configs).length,bytes:Buffer.byteLength(json),hooked,pack:`./${PACK_FILE}`}}module.exports={packPreviewJson,injectJsonPackHook,uuidFromUrl,configNameFromUrl,parseSettings,collectFromSettings,collectFromConfig,PACK_FILE,HOOK_START};