Skip to content

Commit 6502e7d

Browse files
committed
chore: align with PR #33364
1 parent 4dee522 commit 6502e7d

3 files changed

Lines changed: 108 additions & 83 deletions

File tree

packages/devextreme/project.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -728,8 +728,7 @@
728728
"executor": "devextreme-nx-infra-plugin:compress",
729729
"options": {
730730
"files": [
731-
"./artifacts/js/vectormap-utils/dx.vectormaputils.debug.js",
732-
"./artifacts/js/vectormap-utils/dx.vectormaputils.node.js"
731+
"./artifacts/js/vectormap-utils/dx.vectormaputils.debug.js"
733732
],
734733
"mode": "beautify",
735734
"eulaUrl": "https://js.devexpress.com/Licensing/"

packages/nx-infra-plugin/src/executors/vectormap/executor.e2e.spec.ts

Lines changed: 22 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -5,26 +5,23 @@ import { VectormapExecutorSchema } from './schema';
55
import { createTempDir, cleanupTempDir, createMockContext } from '../../utils/test-utils';
66
import { writeFileText, readFileText } from '../../utils';
77

8-
const BROWSER_SOURCE = 'function browserUtil() { return "browser"; }';
9-
10-
const NODE_SOURCE = `
11-
var path = require('path');
12-
var fs = require('fs');
13-
function processFiles(src, opts, cb) {
14-
var files = fs.readdirSync(path.resolve(src)).filter(function(f) { return f.endsWith('.shp'); });
15-
files.forEach(function(f) {
16-
var name = path.basename(f, '.shp');
17-
fs.writeFileSync(path.resolve(opts.output, name + '.js'), name + ' = {};');
18-
});
19-
cb();
20-
}
21-
exports.processFiles = processFiles;
8+
const BROWSER_SOURCE = `
9+
exports.parse = function(input, options) {
10+
return {
11+
type: 'FeatureCollection',
12+
features: [{
13+
precision: options.precision,
14+
firstShpByte: input.shp && input.shp.byteLength > 0
15+
? new Uint8Array(input.shp)[0]
16+
: 0,
17+
}],
18+
};
19+
};
2220
`;
2321

2422
const SETTINGS_JSON = JSON.stringify({
2523
commonFiles: ['common'],
2624
browser: { fileName: 'dx.vectormaputils', files: ['browser'] },
27-
node: { fileName: 'dx.vectormaputils.node', files: ['node'] },
2825
});
2926

3027
const UTILS_TEMPLATE =
@@ -38,9 +35,8 @@ async function setupProject(tempDir: string): Promise<string> {
3835
const srcDir = path.join(proj, 'js', 'viz', 'vector_map.utils');
3936
fs.mkdirSync(srcDir, { recursive: true });
4037
await writeFileText(path.join(srcDir, '_settings.json'), SETTINGS_JSON);
41-
await writeFileText(path.join(srcDir, 'common.js'), '// shared code');
38+
await writeFileText(path.join(srcDir, 'common.js'), '');
4239
await writeFileText(path.join(srcDir, 'browser.js'), BROWSER_SOURCE);
43-
await writeFileText(path.join(srcDir, 'node.js'), NODE_SOURCE);
4440

4541
const templatesDir = path.join(proj, 'build', 'templates');
4642
fs.mkdirSync(templatesDir, { recursive: true });
@@ -49,9 +45,12 @@ async function setupProject(tempDir: string): Promise<string> {
4945

5046
const sourcesDir = path.join(proj, 'build', 'vectormap-sources');
5147
fs.mkdirSync(sourcesDir, { recursive: true });
52-
await writeFileText(path.join(sourcesDir, '_settings.js'), 'module.exports = { isQuiet: true };');
53-
fs.writeFileSync(path.join(sourcesDir, 'world.shp'), Buffer.alloc(0));
54-
fs.writeFileSync(path.join(sourcesDir, 'usa.shp'), Buffer.alloc(0));
48+
await writeFileText(path.join(sourcesDir, '_settings.js'), 'module.exports = { precision: 4 };');
49+
50+
fs.writeFileSync(path.join(sourcesDir, 'world.shp'), Buffer.from([1, 2, 3]));
51+
fs.writeFileSync(path.join(sourcesDir, 'world.dbf'), Buffer.from([0]));
52+
fs.writeFileSync(path.join(sourcesDir, 'usa.shp'), Buffer.from([4, 5, 6]));
53+
fs.writeFileSync(path.join(sourcesDir, 'usa.dbf'), Buffer.from([0]));
5554

5655
await writeFileText(path.join(proj, 'package.json'), '{"name":"test","version":"1.0.0"}');
5756
return proj;
@@ -98,19 +97,17 @@ describe('VectormapExecutor E2E', () => {
9897

9998
expect(fs.existsSync(path.join(utilsDir, 'dx.vectormaputils.debug.js'))).toBe(true);
10099
expect(fs.existsSync(path.join(utilsDir, 'dx.vectormaputils.js'))).toBe(true);
101-
expect(fs.existsSync(path.join(utilsDir, 'dx.vectormaputils.node.js'))).toBe(true);
102100

103101
const debug = await readFileText(path.join(utilsDir, 'dx.vectormaputils.debug.js'));
104102
expect(debug).toContain('factory(exports)');
105-
106-
const node = await readFileText(path.join(utilsDir, 'dx.vectormaputils.node.js'));
107-
expect(node).toContain('exports.processFiles');
108-
expect(node).not.toContain('factory(exports)');
103+
expect(debug).toContain('exports.parse');
109104

110105
const dataFiles = fs.readdirSync(dataDir).filter((f) => f.endsWith('.js'));
111106
expect(dataFiles.length).toBe(2);
112107
const worldData = await readFileText(path.join(dataDir, 'world.js'));
113108
expect(worldData).toContain('sources.');
114109
expect(worldData).toContain('"use strict"');
110+
expect(worldData).toContain('"precision":4');
111+
expect(worldData).toContain('"firstShpByte":1');
115112
}, 30000);
116113
});

packages/nx-infra-plugin/src/executors/vectormap/executor.ts

Lines changed: 85 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -15,18 +15,32 @@ import {
1515
interface UtilsSettings {
1616
commonFiles: string[];
1717
browser: { fileName: string; files: string[] };
18-
node: { fileName: string; files: string[] };
1918
}
2019

2120
interface VariantConfig {
2221
name: string;
2322
files: string[];
2423
fileName: string;
2524
suffix: string;
26-
wrapUmd: boolean;
2725
}
2826

27+
interface ParsedRegion {
28+
name: string;
29+
data: unknown;
30+
}
31+
32+
type ParseFn = (
33+
input: { shp: ArrayBuffer; dbf: ArrayBuffer },
34+
options: { precision: number },
35+
) => unknown;
36+
2937
const USE_STRICT_HEADER = '"use strict";\n\n';
38+
const DEBUG_SUFFIX = '.debug';
39+
const DEFAULT_PRECISION = 4;
40+
41+
function toArrayBuffer(buffer: Buffer): ArrayBuffer {
42+
return buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength);
43+
}
3044

3145
async function buildUtilsVariant(
3246
variant: VariantConfig,
@@ -40,12 +54,10 @@ async function buildUtilsVariant(
4054
const content = await readFileText(filePath);
4155
contents.push(content);
4256
}
43-
let bundle = contents.join('\n');
57+
const concatenated = contents.join('\n');
4458

45-
if (variant.wrapUmd) {
46-
const compiled = _.template(utilsTemplate);
47-
bundle = compiled({ data: bundle });
48-
}
59+
const compiled = _.template(utilsTemplate);
60+
let bundle = compiled({ data: concatenated });
4961

5062
bundle = ensureTrailingNewline(normalizeEol(bundle));
5163

@@ -58,32 +70,24 @@ async function buildUtils(
5870
settingsFile: string,
5971
utilsTemplatePath: string,
6072
outDir: string,
61-
): Promise<{ nodeUtilPath: string }> {
73+
): Promise<{ debugBundlePath: string }> {
6274
const settingsPath = path.join(sourceDir, settingsFile);
6375
const settings: UtilsSettings = JSON.parse(await readFileText(settingsPath));
6476
const utilsTemplate = await readFileText(utilsTemplatePath);
6577

78+
const browserFiles = [...settings.commonFiles, ...settings.browser.files];
6679
const variants: VariantConfig[] = [
6780
{
6881
name: 'browser-debug',
69-
files: [...settings.commonFiles, ...settings.browser.files],
82+
files: browserFiles,
7083
fileName: settings.browser.fileName,
71-
suffix: '.debug',
72-
wrapUmd: true,
84+
suffix: DEBUG_SUFFIX,
7385
},
7486
{
7587
name: 'browser-prod',
76-
files: [...settings.commonFiles, ...settings.browser.files],
88+
files: browserFiles,
7789
fileName: settings.browser.fileName,
7890
suffix: '',
79-
wrapUmd: true,
80-
},
81-
{
82-
name: 'node',
83-
files: [...settings.commonFiles, ...settings.node.files],
84-
fileName: settings.node.fileName,
85-
suffix: '',
86-
wrapUmd: false,
8791
},
8892
];
8993

@@ -94,12 +98,56 @@ async function buildUtils(
9498
await buildUtilsVariant(variant, sourceDir, utilsTemplate, outDir);
9599
}
96100

97-
const nodeUtilPath = path.join(outDir, `${settings.node.fileName}.js`);
98-
return { nodeUtilPath };
101+
const debugBundlePath = path.join(outDir, `${settings.browser.fileName}${DEBUG_SUFFIX}.js`);
102+
return { debugBundlePath };
103+
}
104+
105+
function parseShapefiles(parse: ParseFn, sourcesDir: string, precision: number): ParsedRegion[] {
106+
const shpFiles = fs
107+
.readdirSync(sourcesDir)
108+
.filter((f) => path.extname(f).toLowerCase() === '.shp')
109+
.map((f) => path.basename(f, '.shp'));
110+
111+
const regions: ParsedRegion[] = [];
112+
for (const name of shpFiles) {
113+
const shpBuffer = fs.readFileSync(path.join(sourcesDir, `${name}.shp`));
114+
const dbfBuffer = fs.readFileSync(path.join(sourcesDir, `${name}.dbf`));
115+
116+
const data = parse(
117+
{ shp: toArrayBuffer(shpBuffer), dbf: toArrayBuffer(dbfBuffer) },
118+
{ precision },
119+
);
120+
121+
if (!data) {
122+
throw new Error(
123+
`Vectormap: parse() returned no data for "${name}". `
124+
+ `Check that "${name}.shp" and "${name}.dbf" are valid shapefiles.`,
125+
);
126+
}
127+
128+
regions.push({ name, data });
129+
}
130+
131+
return regions;
132+
}
133+
134+
async function writeRegionModules(
135+
regions: ParsedRegion[],
136+
dataTemplate: string,
137+
outDir: string,
138+
): Promise<void> {
139+
const compiled = _.template(dataTemplate);
140+
141+
for (const { name, data } of regions) {
142+
const rawData = `${name} = ${JSON.stringify(data)};`;
143+
let wrapped = USE_STRICT_HEADER + compiled({ data: rawData });
144+
wrapped = ensureTrailingNewline(normalizeEol(wrapped));
145+
await writeFileText(path.join(outDir, `${name}.js`), wrapped);
146+
}
99147
}
100148

101149
async function buildData(
102-
nodeUtilPath: string,
150+
debugBundlePath: string,
103151
sourcesDir: string,
104152
sourcesSettingsFile: string,
105153
dataTemplatePath: string,
@@ -108,43 +156,25 @@ async function buildData(
108156
): Promise<void> {
109157
const dataTemplate = await readFileText(dataTemplatePath);
110158

111-
const resolvedUtilPath = path.resolve(nodeUtilPath);
159+
const resolvedUtilPath = path.resolve(debugBundlePath);
112160
delete require.cache[require.resolve(resolvedUtilPath)];
113-
const { processFiles } = require(resolvedUtilPath);
161+
const { parse } = require(resolvedUtilPath) as { parse: ParseFn };
114162

115163
const resolvedSourcesDir = path.resolve(projectRoot, sourcesDir);
116164
const resolvedOutDir = path.resolve(projectRoot, outDir);
165+
const resolvedSettingsPath = path.resolve(resolvedSourcesDir, sourcesSettingsFile);
117166

118-
await ensureDir(resolvedOutDir);
167+
delete require.cache[require.resolve(resolvedSettingsPath)];
168+
const sourcesSettings = require(resolvedSettingsPath) as { precision?: number };
169+
const precision =
170+
sourcesSettings.precision !== undefined && sourcesSettings.precision >= 0
171+
? Math.round(sourcesSettings.precision)
172+
: DEFAULT_PRECISION;
119173

120-
await new Promise<void>((resolve, reject) => {
121-
try {
122-
processFiles(
123-
resolvedSourcesDir,
124-
{
125-
output: resolvedOutDir,
126-
settings: path.resolve(resolvedSourcesDir, sourcesSettingsFile),
127-
},
128-
() => {
129-
resolve();
130-
},
131-
);
132-
} catch (error) {
133-
reject(error);
134-
}
135-
});
136-
137-
const files = fs.readdirSync(resolvedOutDir).filter((f) => f.endsWith('.js'));
138-
const compiled = _.template(dataTemplate);
174+
await ensureDir(resolvedOutDir);
139175

140-
for (const file of files) {
141-
const filePath = path.join(resolvedOutDir, file);
142-
const rawData = await readFileText(filePath);
143-
let wrapped = compiled({ data: rawData });
144-
wrapped = USE_STRICT_HEADER + wrapped;
145-
wrapped = ensureTrailingNewline(normalizeEol(wrapped));
146-
await writeFileText(filePath, wrapped);
147-
}
176+
const regions = parseShapefiles(parse, resolvedSourcesDir, precision);
177+
await writeRegionModules(regions, dataTemplate, resolvedOutDir);
148178
}
149179

150180
const runExecutor: PromiseExecutor<VectormapExecutorSchema> = async (options, context) => {
@@ -167,17 +197,16 @@ const runExecutor: PromiseExecutor<VectormapExecutorSchema> = async (options, co
167197

168198
try {
169199
logger.verbose('Phase 1: Building vectormap utilities...');
170-
const { nodeUtilPath } = await buildUtils(
200+
const { debugBundlePath } = await buildUtils(
171201
resolvedSourceDir,
172202
settingsFile,
173203
resolvedUtilsTemplatePath,
174204
resolvedUtilsOutDir,
175205
);
176206

177207
logger.verbose('Phase 2: Building vectormap data...');
178-
179208
await buildData(
180-
nodeUtilPath,
209+
debugBundlePath,
181210
sourcesDir,
182211
sourcesSettingsFile,
183212
resolvedDataTemplatePath,

0 commit comments

Comments
 (0)