APIs

Show:
"use strict";

const fs = require("fs");
const path = require("path");
const assert = require("node-opcua-assert").assert;

const normalize_require_file = require("node-opcua-utils").normalize_require_file;

const debugLog = require("node-opcua-debug").make_debugLog(__filename);
const doDebug = require("node-opcua-debug").checkDebugFlag(__filename);

/**
 * @module opcua.miscellaneous
 * @class Factory
 * @static
 */


require("node-opcua-factory/src/factories_basic_type");


const produce_code = require("./factory_code_generator").produce_code;

const get_class_javascript_filename = require("./factory_code_generator").get_class_javascript_filename;

exports.verbose = false;

function get_caller_source_filename() {
    // let's find source code where schema file is described
    // to do make change this
    // the line has the following shape:
    //      'at blah (/home/toto/myfile.js:53:34)'
    const err = new Error();
    const re = /.*\((.*):[0-9]*:[0-9]*\)/g;
    const schema_file = re.exec(err.stack.split("\n")[3])[1];
    return schema_file;
}

/**
 * register a new object type from a schema
 * @method registerObject
 * @param schema
 * @param optional_folder {String}
 * @return {Function} the object constructor.
 */
function registerObject(schema, optional_folder) {
    let schema_file;
    let schema_name;
    let code;
    let local_schema_file;

    if (typeof schema === "string") {

        // we expect <schema>|<hint>
        const hint_schema = schema.split("|");
        if (hint_schema.length === 1) {
            // no hint provided
            const caller_folder = get_caller_source_filename();

            const default_hint = path.join(path.dirname(caller_folder),"schemas");
            hint_schema.unshift(default_hint);

            optional_folder =  path.join(path.dirname(caller_folder),"_generated_");

        }

        const folder_hint = hint_schema[0];
        schema = hint_schema[1];

        schema_name = schema + "_Schema";
        schema_file = path.join(folder_hint, schema + "_schema.js");
        local_schema_file = schema_file;

        schema = require(local_schema_file)[schema_name];

    } else {

        schema_file = get_caller_source_filename();
        local_schema_file = schema_file;

        if (!optional_folder) {
            console.log(" MIGRATED OLD SCHEME FILE ".red, schema, schema_file);
        }
    }

    assert(schema.generate_source === undefined);

    schema_name = schema.name + "_Schema";

    const generated_source = get_class_javascript_filename(schema.name, optional_folder);

    const generated_source_exists = fs.existsSync(generated_source);

    let schema_file_is_newer = false;
    let code_generator_is_newer = false;

    if (generated_source_exists) {
        const generated_source_mtime = new Date(fs.statSync(generated_source).mtime).getTime();
        const schema_file_mtime = new Date(fs.statSync(local_schema_file).mtime).getTime();
        schema_file_is_newer = (generated_source_mtime <= schema_file_mtime );
        const code_generator_script = path.join(__dirname,"factory_code_generator.js");
        assert(fs.existsSync(code_generator_script), "cannot get code generator");
        const code_generator_script_mtime = new Date(fs.statSync(code_generator_script).mtime).getTime();
        code_generator_is_newer = (generated_source_mtime <= code_generator_script_mtime );
    }
    const generated_source_is_outdated = (!generated_source_exists || code_generator_is_newer || schema_file_is_newer);

    if (generated_source_is_outdated) {
        debugLog(" generated_source_is_outdated ", schema.name, " to ", generated_source);
        if (exports.verbose) {
            console.log(" generating ", schema.name, " in ", generated_source);
        }
        code = produce_code(schema_file, schema_name, generated_source);
    }
    schema.generate_source = generated_source;

    const local_generated_source = normalize_require_file(__dirname, generated_source);
    return require(local_generated_source)[schema.name];
}

exports.registerObject = registerObject;

exports.unregisterObject = function (schema,folder) {

    assert(folder,"#unregisterObject: a folder must be provided");
    const generate_source = get_class_javascript_filename(schema.name,folder);
    if (fs.existsSync(generate_source)) {
        fs.unlinkSync(generate_source);
        assert(!fs.existsSync(generate_source));
    }
};