Skip to content

Commit

Permalink
chore(tile-converter): i3s-server tests (#2563)
Browse files Browse the repository at this point in the history
  • Loading branch information
belom88 authored Jul 24, 2023
1 parent d02c8ff commit 1dabc14
Show file tree
Hide file tree
Showing 25 changed files with 443 additions and 151 deletions.
1 change: 0 additions & 1 deletion modules/i3s/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ export type {
Histogram,
ValueCount,
BuildingSceneSublayer,
DATA_TYPE,
OperationalLayer,
TextureSetDefinitionFormats
} from './types';
Expand Down
29 changes: 14 additions & 15 deletions modules/i3s/src/lib/parsers/constants.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
import GL from '@luma.gl/constants';
import {DATA_TYPE} from '../../types';

export function getConstructorForDataFormat(dataType: string) {
switch (dataType) {
case DATA_TYPE.UInt8:
case 'UInt8':
return Uint8Array;
case DATA_TYPE.UInt16:
case 'UInt16':
return Uint16Array;
case DATA_TYPE.UInt32:
case 'UInt32':
return Uint32Array;
case DATA_TYPE.Float32:
case 'Float32':
return Float32Array;
case DATA_TYPE.UInt64:
case 'UInt64':
return Float64Array;
default:
throw new Error(`parse i3s tile content: unknown type of data: ${dataType}`);
Expand All @@ -32,18 +31,18 @@ export const GL_TYPE_MAP: {[key: string]: number} = {
*/
export function sizeOf(dataType: string): number {
switch (dataType) {
case DATA_TYPE.UInt8:
case 'UInt8':
return 1;
case DATA_TYPE.UInt16:
case DATA_TYPE.Int16:
case 'UInt16':
case 'Int16':
return 2;
case DATA_TYPE.UInt32:
case DATA_TYPE.Int32:
case DATA_TYPE.Float32:
case 'UInt32':
case 'Int32':
case 'Float32':
return 4;
case DATA_TYPE.UInt64:
case DATA_TYPE.Int64:
case DATA_TYPE.Float64:
case 'UInt64':
case 'Int64':
case 'Float64':
return 8;
default:
throw new Error(`parse i3s tile content: unknown size of data: ${dataType}`);
Expand Down
2 changes: 1 addition & 1 deletion modules/i3s/src/lib/parsers/parse-slpk/slpk-archieve.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ const PATH_DESCRIPTIONS: {test: RegExp; extensions: string[]}[] = [
extensions: ['.json.gz']
},
{
test: /^nodes\/\d+$/,
test: /^nodes\/(\d+|root)$/,
extensions: ['/3dNodeIndexDocument.json.gz']
},
{
Expand Down
65 changes: 25 additions & 40 deletions modules/i3s/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,6 @@ import type {Matrix4, Quaternion, Vector3} from '@math.gl/core';
import type {TypedArray, MeshAttribute, TextureLevel} from '@loaders.gl/schema';
import {Tile3D, Tileset3D} from '@loaders.gl/tiles';

export enum DATA_TYPE {
UInt8 = 'UInt8',
UInt16 = 'UInt16',
UInt32 = 'UInt32',
UInt64 = 'UInt64',
Int16 = 'Int16',
Int32 = 'Int32',
Int64 = 'Int64',
Float32 = 'Float32',
Float64 = 'Float64'
}

export type COLOR = [number, number, number, number];

/**
Expand Down Expand Up @@ -690,20 +678,24 @@ type Domain = {
* spec - https://github.com/Esri/i3s-spec/blob/master/docs/1.8/store.cmn.md
*/
type Store = {
id: string | number;
id?: string | number;
profile: string;
version: number | string;
resourcePattern: string[];
rootNode: string;
extent: number[];
indexCRS: string;
vertexCRS: string;
normalReferenceFrame: string;
attributeEncoding: string;
textureEncoding: string[];
lodType: string;
lodModel: string;
resourcePattern?: string[];
rootNode?: string;
extent?: number[];
indexCRS?: string;
vertexCRS?: string;
normalReferenceFrame?: string;
lodType?: string;
lodModel?: string;
defaultGeometrySchema: DefaultGeometrySchema;
nidEncoding?: string;
textureEncoding?: string[];
featureEncoding?: string;
geometryEncoding?: string;
attributeEncoding?: string;
indexingScheme?: string;
};
/**
* Spec - https://github.com/Esri/i3s-spec/blob/master/docs/1.8/defaultGeometrySchema.cmn.md
Expand All @@ -726,15 +718,15 @@ type DefaultGeometrySchema = {
export type HeaderAttribute = {
property: HeaderAttributeProperty.vertexCount | HeaderAttributeProperty.featureCount | string;
type:
| DATA_TYPE.UInt8
| DATA_TYPE.UInt16
| DATA_TYPE.UInt32
| DATA_TYPE.UInt64
| DATA_TYPE.Int16
| DATA_TYPE.Int32
| DATA_TYPE.Int64
| DATA_TYPE.Float32
| DATA_TYPE.Float64;
| 'UInt8'
| 'UInt16'
| 'UInt32'
| 'UInt64'
| 'Int16'
| 'Int32'
| 'Int64'
| 'Float32'
| 'Float64';
};
export enum HeaderAttributeProperty {
vertexCount = 'vertexCount',
Expand All @@ -749,14 +741,7 @@ export type VertexAttribute = {
};
export type GeometryAttribute = {
byteOffset?: number;
valueType:
| DATA_TYPE.UInt8
| DATA_TYPE.UInt16
| DATA_TYPE.Int16
| DATA_TYPE.Int32
| DATA_TYPE.Int64
| DATA_TYPE.Float32
| DATA_TYPE.Float64;
valueType: 'UInt8' | 'UInt16' | 'Int16' | 'Int32' | 'Int64' | 'Float32' | 'Float64';
valuesPerElement: number;
};
export type I3SMeshAttributes = {
Expand Down
6 changes: 5 additions & 1 deletion modules/tile-converter/src/i3s-server/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,14 @@ import express from 'express';
import path from 'path';
import logger from 'morgan';
import cors from 'cors';
import {loadArchive} from './controllers/slpk-controller';

const I3S_LAYER_PATH = process.env.I3sLayerPath || ''; // eslint-disable-line no-process-env, no-undef
const FULL_LAYER_PATH = path.join(process.cwd(), I3S_LAYER_PATH); // eslint-disable-line no-undef
loadArchive(FULL_LAYER_PATH);

const indexRouter = require('./routes/index');

const I3S_LAYER_PATH = process.env.I3sLayerPath || ''; // eslint-disable-line no-process-env, no-undef
export const app = express();

app.use(logger('dev'));
Expand Down
94 changes: 14 additions & 80 deletions modules/tile-converter/src/i3s-server/bin/www.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,25 @@
#!/usr/bin/env node

/**
* Module dependencies.
*/

import {app} from '../app';
import debugFactory from 'debug';
import https from 'https';
import http from 'http';
import fs from 'fs';
import path from 'path';
import {formErrorHandler, formListeningHandler, normalizePort} from '../utils/server-utils';

const debug = debugFactory('i3s-server:server');

/**
* Get port from environment and store in Express.
*/

const httpPort = normalizePort(process.env.PORT || '80'); // eslint-disable-line no-process-env, no-undef
const httpsPort = normalizePort(process.env.HTTPS_PORT || '443'); // eslint-disable-line no-process-env, no-undef

/**
* Create HTTP server.
*/
/** Get port from environment and store in Express. */
const httpPort = normalizePort(process.env.PORT || '80');
if (httpPort === false) {
console.error(`Incorrect HTTP port`);
process.exit(1);
}
const httpsPort = normalizePort(process.env.HTTPS_PORT || '443');
if (httpsPort === false) {
console.error(`Incorrect HTTPs port`);
process.exit(1);
}

/** Create HTTP server. */
const options = {
key: fs.readFileSync(path.join(__dirname, '../certs/key.pem')),
cert: fs.readFileSync(path.join(__dirname, '../certs/cert.pem'))
Expand All @@ -32,73 +28,11 @@ const options = {
const httpServer = http.createServer(app);
const httpsServer = https.createServer(options, app);

/**
* Listen on provided port, on all network interfaces.
*/

/** Listen on provided port, on all network interfaces. */
httpServer.listen(httpPort);
httpServer.on('error', formErrorHandler(httpPort));
httpServer.on('listening', formListeningHandler(httpServer));

httpsServer.listen(httpsPort);
httpsServer.on('error', formErrorHandler(httpsPort));
httpsServer.on('listening', formListeningHandler(httpsServer));

/**
* Normalize a port into a number, string, or false.
*/

function normalizePort(val) {
const chkPort = parseInt(val, 10);

if (isNaN(chkPort)) {
// named pipe
return val;
}

if (chkPort >= 0) {
// port number
return chkPort;
}

return false;
}

/**
* Event listener for HTTP/HTTPS server "error" event.
*/

function formErrorHandler(optionalPort) {
return function onError(error) {
if (error.syscall !== 'listen') {
throw error;
}

const bind = typeof global.port === 'string' ? `Pipe ${optionalPort}` : `Port ${optionalPort}`;

// handle specific listen errors with friendly messages
switch (error.code) {
case 'EACCES':
console.error(`${bind} requires elevated privileges`); // eslint-disable-line no-console, no-undef
process.exit(1); // eslint-disable-line no-process-exit, no-undef
break;
case 'EADDRINUSE':
console.error(`${bind} is already in use`); // eslint-disable-line no-console, no-undef
process.exit(1); // eslint-disable-line no-process-exit, no-undef
break;
default:
throw error;
}
};
}

/**
* Event listener for HTTP/HTTPS server "listening" event.
*/
function formListeningHandler(optionalServer) {
return function onListening() {
const addr = optionalServer.address();
const bind = typeof addr === 'string' ? `pipe ${addr}` : `port ${addr.port}`;
debug(`Listening on ${bind}`);
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,16 @@ import fs from 'fs';

const {promises} = fs;

const I3S_LAYER_PATH = process.env.I3sLayerPath || ''; // eslint-disable-line no-process-env, no-undef
const FULL_LAYER_PATH = path.join(process.cwd(), I3S_LAYER_PATH); // eslint-disable-line no-undef
const I3S_LAYER_PATH = process.env.I3sLayerPath || '';

export async function getFileNameByUrl(url) {
/**
* Get local file name by input HTTP URL
* @param url - I3S HTTP service url
* @returns - local file name
*/
export async function getFileNameByUrl(url: string): Promise<string | null> {
const extensions = ['json', 'bin', 'jpg', 'jpeg', 'png', 'bin.dds', 'ktx2'];
const FULL_LAYER_PATH = path.join(process.cwd(), I3S_LAYER_PATH);
for (const ext of extensions) {
const fileName = `${FULL_LAYER_PATH}${url}/index.${ext}`;
try {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,25 @@
import '@loaders.gl/polyfills';
import {parseSLPK} from '@loaders.gl/i3s';
import {FileHandleProvider} from '@loaders.gl/tile-converter';
import path from 'path';

let slpkArchive;

const loadArchive = async (fullLayerPath) => {
/**
* Open SLPK file for reading and load HASH file
* @param fullLayerPath - full path to SLPK file
*/
export const loadArchive = async (fullLayerPath: string): Promise<void> => {
slpkArchive = await parseSLPK(await FileHandleProvider.from(fullLayerPath));
};

const I3S_LAYER_PATH = process.env.I3sLayerPath || ''; // eslint-disable-line no-process-env, no-undef
const FULL_LAYER_PATH = path.join(process.cwd(), I3S_LAYER_PATH); // eslint-disable-line no-undef

loadArchive(FULL_LAYER_PATH);

export async function getFileByUrl(url) {
/**
* Get a file from SLPK
* @param url - I3S HTTP URL
* @returns - file content
*/
export async function getFileByUrl(url: string) {
const trimmedPath = /^\/?(.*)\/?$/.exec(url);
let uncompressedFile;
let uncompressedFile: Buffer | null = null;
if (trimmedPath) {
try {
uncompressedFile = Buffer.from(await slpkArchive.getFile(trimmedPath[1], 'http'));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
import {SceneLayer3D} from '@loaders.gl/i3s';
import {v4 as uuidv4} from 'uuid';

export const createSceneServer = (name, layer) => {
/**
* Create `/SceneServer` response
* @param name - service name, custom user-friendly name of the service
* @param layer - I3S layer JSON
* @returns reponse JSON for `/SceneServer` route
*/
export const createSceneServer = (name: string, layer: SceneLayer3D) => {
return {
serviceItemId: uuidv4().replace(/-/gi, ''),
serviceName: name,
Expand Down
Loading

0 comments on commit 1dabc14

Please sign in to comment.