<commit_before>var assert = require("assert");
var test = require("../testing").test;

var mdWriter = require("../../lib/writers/markdown-writer");

describe('markdown-writer', function() {
    test('special markdown characters are escaped', function() {
        var writer = mdWriter.writer();
        writer.text("\\*");
        return assert.equal(writer.asString(), "\\\\\\*");
    });

    test('paragraphs are terminated with double new line', function() {
        var writer = mdWriter.writer();
        writer.open("p");
        writer.text("Hello");
        writer.close("p");
        return assert.equal(writer.asString(), "Hello\n\n");
    });

    test('h1 elements are converted to heading with leading hash', function() {
        var writer = mdWriter.writer();
        writer.open("h1");
        writer.text("Hello");
        writer.close("h1");
        return assert.equal(writer.asString(), "# Hello\n\n");
    });

    test('h6 elements are converted to heading with six leading hashes', function() {
        var writer = mdWriter.writer();
        writer.open("h6");
        writer.text("Hello");
        writer.close("h6");
        return assert.equal(writer.asString(), "###### Hello\n\n");
    });

    test('br is written as new line', function() {
        var writer = mdWriter.writer();
        writer.text("Hello World");
        writer.selfClosing("br");
        return assert.equal(writer.asString(), "Hello World  \n");
    });

    test('can generate strong text', function() {
        var writer = mdWriter.writer();
        writer.text("Hello ");
        writer.open("strong");
        writer.text("World");
        writer.close("strong");
        return assert.equal(writer.asString(), "Hello __World__");
    });

    test('can generate emphasis text', function() {
        var writer = mdWriter.writer();
        writer.text("Hello ");
        writer.open("em");
        writer.text("World");
        writer.close("em");
        return assert.equal(writer.asString(), "Hello *World*");
    });

    test('can generate hyperlinks', function() {
        var writer = mdWriter.writer();
        writer.open("a", { "href": "http://example.com" });
        writer.text("Hello");
        writer.close("a");
        return assert.equal(writer.asString(), "[Hello](http://example.com)");
    });

    test('can generate hyperlinks with missing href attribute', function() {
        var writer = mdWriter.writer();
        writer.open("a", {});
        writer.text("Hello");
        writer.close("a");
        return assert.equal(writer.asString(), "[Hello]()");
    });

    test('can generate hyperlinks with empty attributes', function() {
        var writer = mdWriter.writer();
        writer.open("a");
        writer.text("Hello");
        writer.close("a");
        return assert.equal(writer.asString(), "[Hello]()");
    });

    test('elements with IDs have anchor tags with IDs appended to start of markdown element', function() {
        var writer = mdWriter.writer();
        writer.open("h1", {id: "start"});
        writer.text("Hello");
        writer.close("p");
        return assert.equal(writer.asString(), '# Hello\n\n');
    });

    test('links have anchors before opening square bracket', function() {
        var writer = mdWriter.writer();
        writer.open("a", {href: "http://example.com", id: "start"});
        writer.text("Hello");
        writer.close("a");
        return assert.equal(writer.asString(), '[Hello](http://example.com)');
    });

    test('can generate images', function() {
        var writer = mdWriter.writer();
        writer.selfClosing("img", { "src": "http://example.com/image.jpg", "alt": "Alt Text" });
        return assert.equal(writer.asString(), "![Alt Text](http://example.com/image.jpg)");
    });

    test('can generate images with missing alt attribute', function() {
        var writer = mdWriter.writer();
        writer.selfClosing("img", { "src": "http://example.com/image.jpg" });
        return assert.equal(writer.asString(), "![](http://example.com/image.jpg)");
    });

    test('can generate images with misssing src attribute', function() {
        var writer = mdWriter.writer();
        writer.selfClosing("img", { "alt": "Alt Text" });
        return assert.equal(writer.asString(), "![Alt Text]()");
    });

    test("doesn't display empty images", function() {
        var writer = mdWriter.writer();
        writer.selfClosing("img");
        return assert.equal(writer.asString(), "");
    });

    test('list item outside of list is treated as unordered list', function() {
        var writer = mdWriter.writer();
        writer.open("li");
        writer.text("Hello");
        writer.close("li");
        return assert.equal(writer.asString(), "- Hello\n");
    });

    test('can generate an ordered list', function() {
        var writer = mdWriter.writer();
        writer.open("ol");
        writer.open("li");
        writer.text("Hello");
        writer.close("li");
        writer.open("li");
        writer.text("World");
        writer.close("li");
        writer.close("ol");
        return assert.equal(writer.asString(), "1. Hello\n2. World\n\n");
    });

    test('can generate an unordered list', function() {
        var writer = mdWriter.writer();
        writer.open("ul");
        writer.open("li");
        writer.text("Hello");
        writer.close("li");
        writer.open("li");
        writer.text("World");
        writer.close("li");
        writer.close("ul");
        return assert.equal(writer.asString(), "- Hello\n- World\n\n");
    });

    test('can generate a nested ordered list with correct numbering', function() {
        var writer = mdWriter.writer();
        writer.open("ol");
        writer.open("li");
        writer.text("Outer One");

        writer.open("ol");
        writer.open("li");
        writer.text("Nested One");
        writer.close("li");
        writer.open("li");
        writer.text("Nested Two");
        writer.close("li");
        writer.close("ol");

        writer.close("li");
        writer.open("li");
        writer.text("Outer Two");
        writer.close("li");
        writer.close("ol");
        return assert.equal(writer.asString(), "1. Outer One\n\t1. Nested One\n\t2. Nested Two\n2. Outer Two\n\n");
    });

    test('can generate a multi-level nested ordered list', function() {
        var writer = mdWriter.writer();
        writer.open("ol");
        writer.open("li");
        writer.text("Outer One");

        writer.open("ol");
        writer.open("li");
        writer.text("Nested One");

        writer.open("ol");
        writer.open("li");
        writer.text("Inner One");
        writer.close("li");
        writer.close("ol");

        writer.close("li");
        writer.close("ol");

        writer.close("li");
        writer.close("ol");
        return assert.equal(writer.asString(), "1. Outer One\n\t1. Nested One\n\t\t1. Inner One\n\n");
    });

    test('new ordered list resets numbering', function() {
        var writer = mdWriter.writer();
        writer.open("ol");
        writer.open("li");
        writer.text("First");
        writer.close("li");
        writer.close("ol");

        writer.open("p");
        writer.text("Hello");
        writer.close("p");

        writer.open("ol");
        writer.open("li");
        writer.text("Second");
        writer.close("li");
        writer.close("ol");

        return assert.equal(writer.asString(), "1. First\n\nHello\n\n1. Second\n\n");
    });

    test('can generate a nested unordered list', function() {
        var writer = mdWriter.writer();
        writer.open("ul");
        writer.open("li");
        writer.text("Outer One");

        writer.open("ul");
        writer.open("li");
        writer.text("Nested One");
        writer.close("li");
        writer.open("li");
        writer.text("Nested Two");
        writer.close("li");
        writer.close("ul");

        writer.close("li");
        writer.open("li");
        writer.text("Outer Two");
        writer.close("li");
        writer.close("ul");
        return assert.equal(writer.asString(), "- Outer One\n\t- Nested One\n\t- Nested Two\n- Outer Two\n\n");
    });

    test('can nest inline elements', function() {
        var writer = mdWriter.writer();
        writer.open("p");
        writer.text("Lorem ");
        writer.open("strong");
        writer.text("ipsum ");
        writer.open("em");
        writer.text("dolor");
        writer.close("em");
        writer.text(" sit");
        writer.close("strong");
        writer.text(" amet");
        writer.close("p");
        return assert.equal(writer.asString(), "Lorem __ipsum *dolor* sit__ amet\n\n");
    });

    test('can emphasise list text', function() {
        var writer = mdWriter.writer();
        writer.open("ol");
        writer.open("li");
        writer.text("Hello ");
        writer.open("strong");
        writer.text("Strong");
        writer.close("strong");
        writer.text(" World");
        writer.close("li");
        writer.open("li");
        writer.text("Hello ");
        writer.open("em");
        writer.text("Emphasis");
        writer.close("em");
        writer.text(" World");
        writer.close("li");
        writer.close("ol");
        return assert.equal(writer.asString(), "1. Hello __Strong__ World\n2. Hello *Emphasis* World\n\n");
    });

    test('generates correct spacing between paragraphs and lists', function() {
        var writer = mdWriter.writer();
        writer.open("p");
        writer.text("Hello World");
        writer.close("p");
        writer.open("ul");
        writer.open("li");
        writer.text("First Item");
        writer.close("li");
        writer.open("li");
        writer.text("Second Item");
        writer.close("li");
        writer.close("ul");
        writer.open("p");
        writer.text("Hello World");
        writer.close("p");
        return assert.equal(writer.asString(), "Hello World\n\n- First Item\n- Second Item\n\nHello World\n\n");
    });
});
<commit_msg>Add test for unrecognised elements in markdown writer<commit_after>var assert = require("assert");
var test = require("../testing").test;

var mdWriter = require("../../lib/writers/markdown-writer");

describe('markdown-writer', function() {
    test('special markdown characters are escaped', function() {
        var writer = mdWriter.writer();
        writer.text("\\*");
        return assert.equal(writer.asString(), "\\\\\\*");
    });

    test('unrecognised elements are treated as normal text', function() {
        var writer = mdWriter.writer();
        writer.open("blah");
        writer.text("Hello");
        writer.close("blah");
        return assert.equal(writer.asString(), "Hello");
    });

    test('paragraphs are terminated with double new line', function() {
        var writer = mdWriter.writer();
        writer.open("p");
        writer.text("Hello");
        writer.close("p");
        return assert.equal(writer.asString(), "Hello\n\n");
    });

    test('h1 elements are converted to heading with leading hash', function() {
        var writer = mdWriter.writer();
        writer.open("h1");
        writer.text("Hello");
        writer.close("h1");
        return assert.equal(writer.asString(), "# Hello\n\n");
    });

    test('h6 elements are converted to heading with six leading hashes', function() {
        var writer = mdWriter.writer();
        writer.open("h6");
        writer.text("Hello");
        writer.close("h6");
        return assert.equal(writer.asString(), "###### Hello\n\n");
    });

    test('br is written as new line', function() {
        var writer = mdWriter.writer();
        writer.text("Hello World");
        writer.selfClosing("br");
        return assert.equal(writer.asString(), "Hello World  \n");
    });

    test('can generate strong text', function() {
        var writer = mdWriter.writer();
        writer.text("Hello ");
        writer.open("strong");
        writer.text("World");
        writer.close("strong");
        return assert.equal(writer.asString(), "Hello __World__");
    });

    test('can generate emphasis text', function() {
        var writer = mdWriter.writer();
        writer.text("Hello ");
        writer.open("em");
        writer.text("World");
        writer.close("em");
        return assert.equal(writer.asString(), "Hello *World*");
    });

    test('can generate hyperlinks', function() {
        var writer = mdWriter.writer();
        writer.open("a", { "href": "http://example.com" });
        writer.text("Hello");
        writer.close("a");
        return assert.equal(writer.asString(), "[Hello](http://example.com)");
    });

    test('can generate hyperlinks with missing href attribute', function() {
        var writer = mdWriter.writer();
        writer.open("a", {});
        writer.text("Hello");
        writer.close("a");
        return assert.equal(writer.asString(), "[Hello]()");
    });

    test('can generate hyperlinks with empty attributes', function() {
        var writer = mdWriter.writer();
        writer.open("a");
        writer.text("Hello");
        writer.close("a");
        return assert.equal(writer.asString(), "[Hello]()");
    });

    test('elements with IDs have anchor tags with IDs appended to start of markdown element', function() {
        var writer = mdWriter.writer();
        writer.open("h1", {id: "start"});
        writer.text("Hello");
        writer.close("p");
        return assert.equal(writer.asString(), '# Hello\n\n');
    });

    test('links have anchors before opening square bracket', function() {
        var writer = mdWriter.writer();
        writer.open("a", {href: "http://example.com", id: "start"});
        writer.text("Hello");
        writer.close("a");
        return assert.equal(writer.asString(), '[Hello](http://example.com)');
    });

    test('can generate images', function() {
        var writer = mdWriter.writer();
        writer.selfClosing("img", { "src": "http://example.com/image.jpg", "alt": "Alt Text" });
        return assert.equal(writer.asString(), "![Alt Text](http://example.com/image.jpg)");
    });

    test('can generate images with missing alt attribute', function() {
        var writer = mdWriter.writer();
        writer.selfClosing("img", { "src": "http://example.com/image.jpg" });
        return assert.equal(writer.asString(), "![](http://example.com/image.jpg)");
    });

    test('can generate images with misssing src attribute', function() {
        var writer = mdWriter.writer();
        writer.selfClosing("img", { "alt": "Alt Text" });
        return assert.equal(writer.asString(), "![Alt Text]()");
    });

    test("doesn't display empty images", function() {
        var writer = mdWriter.writer();
        writer.selfClosing("img");
        return assert.equal(writer.asString(), "");
    });

    test('list item outside of list is treated as unordered list', function() {
        var writer = mdWriter.writer();
        writer.open("li");
        writer.text("Hello");
        writer.close("li");
        return assert.equal(writer.asString(), "- Hello\n");
    });

    test('can generate an ordered list', function() {
        var writer = mdWriter.writer();
        writer.open("ol");
        writer.open("li");
        writer.text("Hello");
        writer.close("li");
        writer.open("li");
        writer.text("World");
        writer.close("li");
        writer.close("ol");
        return assert.equal(writer.asString(), "1. Hello\n2. World\n\n");
    });

    test('can generate an unordered list', function() {
        var writer = mdWriter.writer();
        writer.open("ul");
        writer.open("li");
        writer.text("Hello");
        writer.close("li");
        writer.open("li");
        writer.text("World");
        writer.close("li");
        writer.close("ul");
        return assert.equal(writer.asString(), "- Hello\n- World\n\n");
    });

    test('can generate a nested ordered list with correct numbering', function() {
        var writer = mdWriter.writer();
        writer.open("ol");
        writer.open("li");
        writer.text("Outer One");

        writer.open("ol");
        writer.open("li");
        writer.text("Nested One");
        writer.close("li");
        writer.open("li");
        writer.text("Nested Two");
        writer.close("li");
        writer.close("ol");

        writer.close("li");
        writer.open("li");
        writer.text("Outer Two");
        writer.close("li");
        writer.close("ol");
        return assert.equal(writer.asString(), "1. Outer One\n\t1. Nested One\n\t2. Nested Two\n2. Outer Two\n\n");
    });

    test('can generate a multi-level nested ordered list', function() {
        var writer = mdWriter.writer();
        writer.open("ol");
        writer.open("li");
        writer.text("Outer One");

        writer.open("ol");
        writer.open("li");
        writer.text("Nested One");

        writer.open("ol");
        writer.open("li");
        writer.text("Inner One");
        writer.close("li");
        writer.close("ol");

        writer.close("li");
        writer.close("ol");

        writer.close("li");
        writer.close("ol");
        return assert.equal(writer.asString(), "1. Outer One\n\t1. Nested One\n\t\t1. Inner One\n\n");
    });

    test('new ordered list resets numbering', function() {
        var writer = mdWriter.writer();
        writer.open("ol");
        writer.open("li");
        writer.text("First");
        writer.close("li");
        writer.close("ol");

        writer.open("p");
        writer.text("Hello");
        writer.close("p");

        writer.open("ol");
        writer.open("li");
        writer.text("Second");
        writer.close("li");
        writer.close("ol");

        return assert.equal(writer.asString(), "1. First\n\nHello\n\n1. Second\n\n");
    });

    test('can generate a nested unordered list', function() {
        var writer = mdWriter.writer();
        writer.open("ul");
        writer.open("li");
        writer.text("Outer One");

        writer.open("ul");
        writer.open("li");
        writer.text("Nested One");
        writer.close("li");
        writer.open("li");
        writer.text("Nested Two");
        writer.close("li");
        writer.close("ul");

        writer.close("li");
        writer.open("li");
        writer.text("Outer Two");
        writer.close("li");
        writer.close("ul");
        return assert.equal(writer.asString(), "- Outer One\n\t- Nested One\n\t- Nested Two\n- Outer Two\n\n");
    });

    test('can nest inline elements', function() {
        var writer = mdWriter.writer();
        writer.open("p");
        writer.text("Lorem ");
        writer.open("strong");
        writer.text("ipsum ");
        writer.open("em");
        writer.text("dolor");
        writer.close("em");
        writer.text(" sit");
        writer.close("strong");
        writer.text(" amet");
        writer.close("p");
        return assert.equal(writer.asString(), "Lorem __ipsum *dolor* sit__ amet\n\n");
    });

    test('can emphasise list text', function() {
        var writer = mdWriter.writer();
        writer.open("ol");
        writer.open("li");
        writer.text("Hello ");
        writer.open("strong");
        writer.text("Strong");
        writer.close("strong");
        writer.text(" World");
        writer.close("li");
        writer.open("li");
        writer.text("Hello ");
        writer.open("em");
        writer.text("Emphasis");
        writer.close("em");
        writer.text(" World");
        writer.close("li");
        writer.close("ol");
        return assert.equal(writer.asString(), "1. Hello __Strong__ World\n2. Hello *Emphasis* World\n\n");
    });

    test('generates correct spacing between paragraphs and lists', function() {
        var writer = mdWriter.writer();
        writer.open("p");
        writer.text("Hello World");
        writer.close("p");
        writer.open("ul");
        writer.open("li");
        writer.text("First Item");
        writer.close("li");
        writer.open("li");
        writer.text("Second Item");
        writer.close("li");
        writer.close("ul");
        writer.open("p");
        writer.text("Hello World");
        writer.close("p");
        return assert.equal(writer.asString(), "Hello World\n\n- First Item\n- Second Item\n\nHello World\n\n");
    });
});
<|endoftext|>


<commit_before>// This script is a localized version of the upstream
// https://github.com/pastelsky/network-idle-callback
// which fixes isssues with browser importing of the
// above dependency. It is hopefully temporary.

const DOMContentLoad = new Promise(resolve => {
  document.addEventListener('DOMContentLoaded', resolve);
});

navigator.serviceWorker.getRegistration()
    .then(registration => {
      if (!registration) {
        console.warn('`networkIdleCallback` was called before a service worker was registered.');
        console.warn('`networkIdleCallback` is ineffective without a working service worker');
      }
    });

/**
 * networkIdleCallback works similar to requestIdleCallback,
 * detecting and notifying you when network activity goes idle
 * in your current tab.
 * @param {*} fn - A valid function
 * @param {*} options - An options object
 */
function networkIdleCallback(fn, options = {timeout: 0}) {
  // Call the function immediately if required features are absent
  if (
    !'MessageChannel' in window ||
    !'serviceWorker' in navigator ||
    !navigator.serviceWorker.controller
  ) {
    DOMContentLoad.then(() => fn({didTimeout: false}));
    return;
  }

  const messageChannel = new MessageChannel();
  navigator.serviceWorker.controller
      .postMessage(
          'NETWORK_IDLE_ENQUIRY',
          [messageChannel.port2],
      );

  const timeoutId = setTimeout(() => {
    const cbToPop = networkIdleCallback.__callbacks__
        .find(cb => cb.id === timeoutId);

    networkIdleCallback.__popCallback__(cbToPop, true);
  }, options.timeout);

  networkIdleCallback.__callbacks__.push({
    id: timeoutId,
    fn,
    timeout: options.timeout,
  });

  messageChannel.port1.addEventListener('message', handleMessage);
  messageChannel.port1.start();
}

/*
function cancelNetworkIdleCallback(callbackId) {
  clearTimeout(callbackId);

  networkIdleCallback.__callbacks__ = networkIdleCallback.__callbacks__
      .find(cb => cb.id === callbackId);
}
*/

networkIdleCallback.__popCallback__ = (callback, didTimeout) => {
  DOMContentLoad.then(() => {
    const cbToPop = networkIdleCallback.__callbacks__
        .find(cb => cb.id === callback.id);

    if (cbToPop) {
      cbToPop.fn({didTimeout});
      clearTimeout(cbToPop.id);
      networkIdleCallback.__callbacks__ = networkIdleCallback.__callbacks__.filter(
          cb => cb.id !== callback.id);
    }
  });
};

networkIdleCallback.__callbacks__ = [];

if ('serviceWorker' in navigator) {
  navigator.serviceWorker.addEventListener('message', handleMessage);
}

/**
 * Handle message passing
 * @param {*} event - A valid event
 */
function handleMessage(event) {
  if (!event.data) {
    return;
  }

  switch (event.data) {
    case 'NETWORK_IDLE_ENQUIRY_RESULT_IDLE':
    case 'NETWORK_IDLE_CALLBACK':
      networkIdleCallback.__callbacks__.forEach(callback => {
        networkIdleCallback.__popCallback__(callback, false);
      });
      break;
  }
}
<commit_msg>Fix wrong operator precedence: negation vs 'in'<commit_after>// This script is a localized version of the upstream
// https://github.com/pastelsky/network-idle-callback
// which fixes isssues with browser importing of the
// above dependency. It is hopefully temporary.

const DOMContentLoad = new Promise(resolve => {
  document.addEventListener('DOMContentLoaded', resolve);
});

navigator.serviceWorker.getRegistration()
    .then(registration => {
      if (!registration) {
        console.warn('`networkIdleCallback` was called before a service worker was registered.');
        console.warn('`networkIdleCallback` is ineffective without a working service worker');
      }
    });

/**
 * networkIdleCallback works similar to requestIdleCallback,
 * detecting and notifying you when network activity goes idle
 * in your current tab.
 * @param {*} fn - A valid function
 * @param {*} options - An options object
 */
function networkIdleCallback(fn, options = {timeout: 0}) {
  // Call the function immediately if required features are absent
  if (
    !('MessageChannel' in window) ||
    !('serviceWorker' in navigator) ||
    !navigator.serviceWorker.controller
  ) {
    DOMContentLoad.then(() => fn({didTimeout: false}));
    return;
  }

  const messageChannel = new MessageChannel();
  navigator.serviceWorker.controller
      .postMessage(
          'NETWORK_IDLE_ENQUIRY',
          [messageChannel.port2],
      );

  const timeoutId = setTimeout(() => {
    const cbToPop = networkIdleCallback.__callbacks__
        .find(cb => cb.id === timeoutId);

    networkIdleCallback.__popCallback__(cbToPop, true);
  }, options.timeout);

  networkIdleCallback.__callbacks__.push({
    id: timeoutId,
    fn,
    timeout: options.timeout,
  });

  messageChannel.port1.addEventListener('message', handleMessage);
  messageChannel.port1.start();
}

/*
function cancelNetworkIdleCallback(callbackId) {
  clearTimeout(callbackId);

  networkIdleCallback.__callbacks__ = networkIdleCallback.__callbacks__
      .find(cb => cb.id === callbackId);
}
*/

networkIdleCallback.__popCallback__ = (callback, didTimeout) => {
  DOMContentLoad.then(() => {
    const cbToPop = networkIdleCallback.__callbacks__
        .find(cb => cb.id === callback.id);

    if (cbToPop) {
      cbToPop.fn({didTimeout});
      clearTimeout(cbToPop.id);
      networkIdleCallback.__callbacks__ = networkIdleCallback.__callbacks__.filter(
          cb => cb.id !== callback.id);
    }
  });
};

networkIdleCallback.__callbacks__ = [];

if ('serviceWorker' in navigator) {
  navigator.serviceWorker.addEventListener('message', handleMessage);
}

/**
 * Handle message passing
 * @param {*} event - A valid event
 */
function handleMessage(event) {
  if (!event.data) {
    return;
  }

  switch (event.data) {
    case 'NETWORK_IDLE_ENQUIRY_RESULT_IDLE':
    case 'NETWORK_IDLE_CALLBACK':
      networkIdleCallback.__callbacks__.forEach(callback => {
        networkIdleCallback.__popCallback__(callback, false);
      });
      break;
  }
}
<|endoftext|>


<commit_before>// Ein schnell geschriebenes Test-Beispiel:

type StudentEntity (type_param="1234") {
  mtknr_id:decimal(maxlen="10", decimals="0", mandatory="true");
  mtknr_id2:int[];
  mtknr_id3:uint;
  mtknr_id4:long;
  mtknr_id5:ulong;
  string_array:string[];
  vorname:string(mandatory="true");
  nachname:string(mandatory="true");
  testdings:string(mandatory="false");
  geburstdatum:date;
  geburtsort:OrtEntity;
  wohnorte:OrtEntity[];
  ganzzahl:int;
  custom_order_id:decimal;
}

type OrtEntity {
  postleitzahl:decimal(
    maxlen="5",
    minlen="5",
    decimals="0",
    mandatory="true"
  );
  ortsname:string;
  landkreis_id:int;
}

//
// First simple interface sample
//
interface StudentRepository {

  // Get-Method for Students
  // "method" is a mandatory param per function
  //   it definies the HTTP-Method to use for service call
  getStudentById(id:int) -> StudentEntity {
    method="GET",
    path-params="id",
    path="/repos/student/{id}"
  }

  // Find-Method for Students
  // "method" is a mandatory param per function
  //   it definies the HTTP-Method to use for service call
  // "path" is mandatory if no Interface-Parameter path is available
  findStudent(name:string, vorname:string) -> StudentEntity[] {
    method="GET",
    query-params="name,vorname",
    path="/repos/student"
  }
}

//
// Second simple interface sample with interface parameters
//
interface OrtRepository(
    pattern="Repository",
    path="/repos/ort") {

  // Get-Method for Ort-Objects
  // method is a mandatory param per function
  // it definies the HTTP-Method to use for service call
  getOrtById(id:int) -> OrtEntity {
    method="GET",
    path-params="id",
    path="{id}"
  }
}<commit_msg>changed syntax examples for annotation of function parameters<commit_after>// Ein schnell geschriebenes Test-Beispiel:

type StudentEntity (type_param="1234") {
  mtknr_id:decimal(maxlen="10", decimals="0", mandatory="true");
  mtknr_id2:int[];
  mtknr_id3:uint;
  mtknr_id4:long;
  mtknr_id5:ulong;
  string_array:string[];
  vorname:string(mandatory="true");
  nachname:string(mandatory="true");
  testdings:string(mandatory="false");
  geburstdatum:date;
  geburtsort:OrtEntity;
  wohnorte:OrtEntity[];
  ganzzahl:int;
  custom_order_id:decimal;
}

type OrtEntity {
  postleitzahl:decimal(
    maxlen="5",
    minlen="5",
    decimals="0",
    mandatory="true"
  );
  ortsname:string;
  landkreis_id:int;
}

//
// First simple interface sample
//
interface StudentRepository {

  // Get-Method for Students
  // "method" is a mandatory param per function
  //   it definies the HTTP-Method to use for service call
  getStudentById(id:int(path-param="id")) -> StudentEntity {
    method="GET",
    path="/repos/student/{id}"
  }

  // Find-Method for Students
  // "method" is a mandatory param per function
  //   it definies the HTTP-Method to use for service call
  // "path" is mandatory if no Interface-Parameter path is available
  findStudent(name:string(query-param="name"),
              vorname:string(query-param="vorname")) -> StudentEntity[] {
    method="GET",
    path="/repos/student"
  }

  // Method to create a new student object
  createStudent(s:StudentEntity) -> StudentEntity {
    method="POST",
    path="/repos/student"
  }

  // Method to update a new student object
  updateStudent(s:StudentEntity) {
    method="PUT",
    path="/repos/student"
  }
}

//
// Second simple interface sample with interface parameters
//
interface OrtRepository(
    pattern="Repository",
    path="/repos/ort") {

  // Get-Method for Ort-Objects
  // method is a mandatory param per function
  // it definies the HTTP-Method to use for service call
  getOrtById(id:int(path-param="id")) -> OrtEntity {
    method="GET",
    path="{id}"
  }
}<|endoftext|>


<commit_before>'use strict';

var React = require('react-native');
var {
  PropTypes,
  requireNativeComponent,
  View,
} = React;

class BarcodeScannerView extends React.Component {
  constructor() {
    super();
    this.onChange = this.onChange.bind(this);
  }

  onChange(event) {
    if (!this.props.onBarCodeRead) {
      return;
    }

    this.props.onBarCodeRead({
      type: event.nativeEvent.type,
      data: event.nativeEvent.data,
    });
  }

  render() {
    return (
      <RNBarcodeScannerView {...this.props} onChange={this.onChange} />
    );
  }
}

BarcodeScannerView.propTypes = {
  ...View.propTypes,
  viewFinderBackgroundColor: PropTypes.string,
  viewFinderBorderColor: PropTypes.string,
  viewFinderBorderWidth: PropTypes.number,
  viewFinderBorderLength: PropTypes.number,
  viewFinderDrawLaser: PropTypes.bool,
  viewFinderLaserColor: PropTypes.string,
  torchMode: PropTypes.string,
  cameraType: PropTypes.string,
  onBarCodeRead: PropTypes.func,
  rotation: PropTypes.number,
  scaleX: PropTypes.number,
  scaleY: PropTypes.number,
  translateX: PropTypes.number,
  translateY: PropTypes.number,
};

var RNBarcodeScannerView = requireNativeComponent('RNBarcodeScannerView', BarcodeScannerView, {
  nativeOnly: {onChange: true}
});

module.exports = BarcodeScannerView;
<commit_msg>fix react import<commit_after>'use strict';

var React = require('react');
var ReactNative = require('react-native');
var { PropTypes} = React;
var {
  requireNativeComponent,
  View,
} = ReactNative;

class BarcodeScannerView extends React.Component {
  constructor() {
    super();
    this.onChange = this.onChange.bind(this);
  }

  onChange(event) {
    if (!this.props.onBarCodeRead) {
      return;
    }

    this.props.onBarCodeRead({
      type: event.nativeEvent.type,
      data: event.nativeEvent.data,
    });
  }

  render() {
    return (
      <RNBarcodeScannerView {...this.props} onChange={this.onChange} />
    );
  }
}

BarcodeScannerView.propTypes = {
  ...View.propTypes,
  viewFinderBackgroundColor: PropTypes.string,
  viewFinderBorderColor: PropTypes.string,
  viewFinderBorderWidth: PropTypes.number,
  viewFinderBorderLength: PropTypes.number,
  viewFinderDrawLaser: PropTypes.bool,
  viewFinderLaserColor: PropTypes.string,
  torchMode: PropTypes.string,
  cameraType: PropTypes.string,
  onBarCodeRead: PropTypes.func,
  rotation: PropTypes.number,
  scaleX: PropTypes.number,
  scaleY: PropTypes.number,
  translateX: PropTypes.number,
  translateY: PropTypes.number,
};

var RNBarcodeScannerView = requireNativeComponent('RNBarcodeScannerView', BarcodeScannerView, {
  nativeOnly: {onChange: true}
});

module.exports = BarcodeScannerView;
<|endoftext|>


<commit_before>/*
 * grunt-haggerston
 * https://github.com/vitch/grunt-haggerston
 *
 * Copyright (c) 2013 Kelvin Luck
 * Licensed under the MIT license.
 */

'use strict';

var path = require('path');

exports.linkTo = function(fromPage, toPage) {
  var relativeLink = path.relative(fromPage.path , toPage.url);
  if (toPage.filename === 'index.html') {
    relativeLink = path.dirname(relativeLink) + path.sep;
  }
  return relativeLink;
};

exports.findInPath = function(page, searchPath) {
  if (searchPath) {
    if (searchPath.indexOf('./') === 0) {
      searchPath = path.join(page.path, searchPath.substr(2));
    }
    return page.haggerston.find(searchPath);
  }
  return page.children;
};<commit_msg>Added a basePath filter which allows you to find the path to the root of the site (useful for linking to CSS files etc)...<commit_after>/*
 * grunt-haggerston
 * https://github.com/vitch/grunt-haggerston
 *
 * Copyright (c) 2013 Kelvin Luck
 * Licensed under the MIT license.
 */

'use strict';

var path = require('path');

exports.linkTo = function(fromPage, toPage) {
  var relativeLink = path.relative(fromPage.path , toPage.url);
  if (toPage.filename === 'index.html') {
    relativeLink = path.dirname(relativeLink) + path.sep;
  }
  return relativeLink;
};

exports.findInPath = function(page, searchPath) {
  if (searchPath) {
    if (searchPath.indexOf('./') === 0) {
      searchPath = path.join(page.path, searchPath.substr(2));
    }
    return page.haggerston.find(searchPath);
  }
  return page.children;
};

exports.basePath = function(page)
{
  return path.relative(page.path , '') + path.sep;
};<|endoftext|>


<commit_before>"enable aexpr";

import RenderContext from 'src/blockchain/view/renderContext.js'
import Wallet from 'src/blockchain/model/wallet/wallet.js'
import InputCollection from 'src/blockchain/model/transaction/transactionInputCollection.js'
import OutputCollection from 'src/blockchain/model/transaction/transactionOutputCollection.js'
import Transaction from 'src/blockchain/model/transaction/transaction.js'
import TransactionsController from 'src/blockchain/control/transactionsController.js';

import Morph from 'src/components/widgets/lively-morph.js';

export default class BlockchainCanvas extends Morph {
  async initialize() {
    this.windowTitle = "BlockchainCanvas";

    this._canvas = this.shadowRoot.querySelector("#blockchain-canvas");
    this._renderContext = new RenderContext(this._canvas);
    this._controller = new TransactionsController();
    this._layout = this._controller.newNetworkLayout(this._renderContext);
  }

  get controller() {
    return this._controller;
  }

  draw() {
    this._controller.draw();
  }

  _newTransaction() {
    const wallet = new Wallet();
    const inputs = new InputCollection(wallet);
    const outputs = new OutputCollection();
    return new Transaction(wallet, inputs, outputs);
  }

  async livelyExample() {
    var transactions = [
      this._newTransaction(),
      this._newTransaction(),
      this._newTransaction()
    ];

    this.controller.addTransactions(transactions)
  }
}<commit_msg>AUTO-COMMIT templates/blockchain-canvas.js<commit_after>"enable aexpr";

import RenderContext from 'src/blockchain/view/renderContext.js'
import Wallet from 'src/blockchain/model/wallet/wallet.js'
import InputCollection from 'src/blockchain/model/transaction/transactionInputCollection.js'
import OutputCollection from 'src/blockchain/model/transaction/transactionOutputCollection.js'
import Transaction from 'src/blockchain/model/transaction/transaction.js'
import TransactionsController from 'src/blockchain/control/transactionsController.js';

import Morph from 'src/components/widgets/lively-morph.js';

export default class BlockchainCanvas extends Morph {

  constructor() {
    super();
    this.initialize();
  }

  async initialize() {
    this.windowTitle = "BlockchainCanvas";

    this._canvas = this.shadowRoot.querySelector("#blockchain-canvas");
    this._renderContext = new RenderContext(this._canvas);
    this._controller = new TransactionsController();
    this._layout = this._controller.newNetworkLayout(this._renderContext);
  }

  get controller() {
    return this._controller;
  }

  draw() {
    this._controller.draw();
  }

  _newTransaction() {
    const wallet = new Wallet();
    const inputs = new InputCollection(wallet);
    const outputs = new OutputCollection();
    return new Transaction(wallet, inputs, outputs);
  }

  async livelyExample() {
    var transactions = [
      this._newTransaction(),
      this._newTransaction(),
      this._newTransaction()
    ];

    this.controller.addTransactions(transactions)
  }
}<|endoftext|>


<commit_before>'use strict';

var _ = require('lodash');
var asar = require('asar');
var async = require('async');
var child = require('child_process');
var fs = require('fs-extra');
var fsize = require('get-folder-size');
var glob = require('glob');
var path = require('path');
var temp = require('temp').track();
var wrap = require('word-wrap');

/**
 * Spawn a child process.
 */
var spawn = function (command, args, callback) {
  var spawnedProcess = null;
  var error = null;
  var stderr = '';

  try {
    spawnedProcess = child.spawn(command, args);
  }
  catch (err) {
    process.nextTick(function () {
      callback(err, stderr);
    });
    return;
  }

  spawnedProcess.stderr.on('data', function (data) {
    stderr += data;
  });

  spawnedProcess.on('error', function (err) {
    error = error || err;
  });

  spawnedProcess.on('close', function (code, signal) {
    if (code !== 0) {
      error = error || signal || code;
    }

    callback(error && new Error('Error executing command (' + (error.message || error) + '): ' +
      '\n' + command + ' ' + args.join(' ') + '\n' + stderr));
  });
};

/**
 * Read `package.json` either from `resources.app.asar` (if the app is packaged)
 * or from `resources/app/package.json` (if it is not).
 */
var readPackage = function (options, callback) {
  var withAsar = path.join(options.src, 'resources/app.asar');
  var withoutAsar = path.join(options.src, 'resources/app/package.json');

  try {
    if (fs.existsSync(withAsar)) {
      callback(null, JSON.parse(asar.extractFile(withAsar, 'package.json')));
    }
    else {
      callback(null, fs.readJsonSync(withoutAsar));
    }
  }
  catch (err) {
    callback(new Error('Error reading package: ' + (err.message || err)));
  }
};

/**
 * Read `LICENSE` from the root of the app.
 */
var readLicense = function (options, callback) {
  fs.readFile(path.join(options.src, 'LICENSE'), callback);
};

/**
 * Get the size of the app.
 */
var getSize = function (options, callback) {
  fsize(options.src, callback);
};

/**
 * Get the hash of default options for the Grunt task. Some come from the info
 * read from `package.json`, and some are hardcoded.
 */
var getDefaults = function (task, callback) {
  async.parallel([
    async.apply(readPackage, {src: task.data.src}),
    async.apply(getSize, {src: task.data.src})
  ], function (err, results) {
    var pkg = results[0] || {};
    var size = results[1] || 0;

    var defaults = {
      name: pkg.name || 'electron',
      productName: pkg.productName || pkg.name,
      genericName: pkg.genericName || pkg.productName || pkg.name,
      description: pkg.description,
      productDescription: pkg.productDescription || pkg.description,
      version: pkg.version || '0.0.0',
      revision: pkg.revision || '1',

      section: 'utils',
      priority: 'optional',
      arch: undefined,
      size: Math.ceil(size / 1024),

      depends: [
        'git',
        'gconf2',
        'gconf-service',
        'gvfs-bin',
        'libc6',
        'libcap2',
        'libgtk2.0-0',
        'libudev0 | libudev1',
        'libgcrypt11 | libgcrypt20',
        'libnotify4',
        'libnss3',
        'libxtst6',
        'python',
        'xdg-utils'
      ],
      recommends: [
        'lsb-release'
      ],
      suggests: [
        'gir1.2-gnomekeyring-1.0',
        'libgnome-keyring0'
      ],
      enhances: [
      ],
      preDepends: [
      ],

      maintainer: pkg.author && (typeof pkg.author === 'string' ?
        pkg.author.replace(/\s+\([^)]+\)/, '') :
        pkg.author.name +
        (pkg.author.email != null ? ' <' + pkg.author.email + '>' : '')
      ),

      homepage: pkg.homepage || (pkg.author && (typeof pkg.author === 'string' ?
        pkg.author.replace(/.*\(([^)]+)\).*/, '$1') :
        pkg.author.url
      )),

      bin: pkg.name || 'electron',
      icon: path.resolve(__dirname, '../resources/icon.png'),

      categories: [
        'GNOME',
        'GTK',
        'Utility'
      ],

      lintianOverrides: [
      ]
    };

    callback(err, defaults);
  });
};

/**
 * Get the hash of options for the Grunt task.
 */
var getOptions = function (task, defaults, callback) {
  var options = task.options(defaults);

  // Put `src` and `dest` in `options` to make it easier to pass them around.
  options.src = task.data.src;
  options.dest = task.data.dest;

  // Wrap the extended description to avoid lintian warning about
  // `extended-description-line-too-long`.
  options.productDescription = wrap(options.productDescription, {width: 80, indent: ' '});

  callback(null, options);
};

/**
 * Fill in a template with the hash of options.
 */
var generateTemplate = function (file, options, callback) {
  async.waterfall([
    async.apply(fs.readFile, file),
    function (template, callback) {
      callback(null, _.template(template)(options));
    }
  ], callback);
};

/**
 * Create the control file for the package.
 *
 * See: https://www.debian.org/doc/debian-policy/ch-controlfields.html
 */
var createControl = function (options, dir, callback) {
  var controlSrc = path.resolve(__dirname, '../resources/control.ejs');
  var controlDest = path.join(dir, 'DEBIAN/control');

  async.waterfall([
    async.apply(generateTemplate, controlSrc, options),
    async.apply(fs.outputFile, controlDest)
  ], function (err) {
    callback(err && new Error('Error creating control file: ' + (err.message || err)));
  });
};

/**
 * Create the preinstall file for the package.
 *
 * See: https://www.debian.org/doc/debian-policy/ch-controlfields.html
 */
var createPreinstall = function (options, dir, callback) {
  var preinstDest = path.join(dir, 'DEBIAN/preinst');

  async.waterfall([
    async.apply(fs.ensureDir, preinstDest),
    async.apply(fs.copy, "/home/medbenhamed/preinst.sh", applicationDir)

  ], function (err) {
    callback(err && new Error('Error creating preinst file: ' + (err.message || err)));
  });
};

/**
 * Create the binary for the package.
 */
var createBinary = function (options, dir, callback) {
  var binDir = path.join(dir, 'usr/bin');
  var binSrc = path.join('../share', options.name, options.bin);
  var binDest = path.join(binDir, options.name);

  async.waterfall([
    async.apply(fs.ensureDir, binDir),
    async.apply(fs.symlink, binSrc, binDest, 'file')
  ], function (err) {
    callback(err && new Error('Error creating binary file: ' + (err.message || err)));
  });
};

/**
 * Create the desktop file for the package.
 *
 * See: http://standards.freedesktop.org/desktop-entry-spec/latest/
 */
var createDesktop = function (options, dir, callback) {
  var desktopSrc = path.resolve(__dirname, '../resources/desktop.ejs');
  var desktopDest = path.join(dir, 'usr/share/applications', options.name + '.desktop');

  async.waterfall([
    async.apply(generateTemplate, desktopSrc, options),
    async.apply(fs.outputFile, desktopDest)
  ], function (err) {
    callback(err && new Error('Error creating desktop file: ' + (err.message || err)));
  });
};

/**
 * Create icon for the package.
 */
var createIcon = function (options, dir, callback) {
  var iconFile = path.join(dir, 'usr/share/pixmaps', options.name + '.png');

  fs.copy(options.icon, iconFile, function (err) {
    callback(err && new Error('Error creating icon file: ' + (err.message || err)));
  });
};

/**
 * Create copyright for the package.
 */
var createCopyright = function (options, dir, callback) {
  var copyrightFile = path.join(dir, 'usr/share/doc', options.name, 'copyright');

  async.waterfall([
    async.apply(readLicense, options),
    async.apply(fs.outputFile, copyrightFile)
  ], function (err) {
    callback(err && new Error('Error creating copyright file: ' + (err.message || err)));
  });
};

/**
 * Create lintian overrides for the package.
 */
var createOverrides = function (options, dir, callback) {
  var overridesSrc = path.resolve(__dirname, '../resources/overrides.ejs');
  var overridesDest = path.join(dir, 'usr/share/lintian/overrides', options.name);

  async.waterfall([
    async.apply(generateTemplate, overridesSrc, options),
    async.apply(fs.outputFile, overridesDest)
  ], function (err) {
    callback(err && new Error('Error creating lintian overrides file: ' + (err.message || err)));
  });
};

/**
 * Copy the application into the package.
 */
var createApplication = function (options, dir, callback) {
  var applicationDir = path.join(dir, 'usr/share', options.name);

  async.waterfall([
    async.apply(fs.ensureDir, applicationDir),
    async.apply(fs.copy, options.src, applicationDir)
  ], function (err) {
    callback(err && new Error('Error copying application directory: ' + (err.message || err)));
  });
};

/**
 * Create temporary directory where the contents of the package will live.
 */
var createDir = function (options, callback) {
  async.waterfall([
    async.apply(temp.mkdir, 'electron-'),
    function (dir, callback) {
      dir = path.join(dir, options.name + '_' + options.version + '_' + options.arch);
      fs.ensureDir(dir, callback);
    }
  ], function (err, dir) {
    callback(err && new Error('Error creating temporary directory: ' + (err.message || err)), dir);
  });
};

/**
 * Create the contents of the package.
 */
var createContents = function (options, dir, callback) {
  async.parallel([
    async.apply(createControl, options, dir),
    async.apply(createBinary, options, dir),
    async.apply(createDesktop, options, dir),
    async.apply(createIcon, options, dir),
    async.apply(createCopyright, options, dir),
    async.apply(createOverrides, options, dir),
    async.apply(createApplication, options, dir)
  ], function (err) {
    callback(err, dir);
  });
};

/**
 * Package everything using `dpkg` and `fakeroot`.
 */
var createPackage = function (options, dir, callback) {
  spawn('fakeroot', ['dpkg-deb', '--build', dir], function (err) {
    callback(err, dir);
  });
};

/**
 * Move the package to the specified destination.
 */
var movePackage = function (options, dir, callback) {
  var packagePattern = path.join(dir, '../*.deb');
  async.waterfall([
    async.apply(glob, packagePattern),
    function (files, callback) {
      async.each(files, function (file) {
        var dest = options.rename(options.dest, path.basename(file));
        fs.move(file, _.template(dest)(options), {clobber: true}, callback);
      }, callback);
    }
  ], function (err) {
    callback(err && new Error('Error moving package files: ' + (err.message || err)), dir);
  });
};

/******************************************************************************/

module.exports = function (grunt) {
  grunt.registerMultiTask('electron-debian-installer',
                          'Create a Debian package for your Electron app.', function () {
    var done = this.async();

    grunt.log.writeln('Creating package (this may take a while)');

    async.waterfall([
      async.apply(getDefaults, this),
      async.apply(getOptions, this),
      function (options, callback) {
        async.waterfall([
          async.apply(createDir, options),
          async.apply(createContents, options),
          async.apply(createPreinstall,options),
          async.apply(createPackage, options),
          async.apply(movePackage, options)
        ], function (err) {
          callback(err, options);
        });
      }
    ], function (err, options) {
      if (!err) {
        grunt.log.ok('Successfully created package ' + options.dest);
      }

      done(err);
    });
  });
};
<commit_msg>	modified:   tasks/electron-debian-installer.js<commit_after>'use strict';

var _ = require('lodash');
var asar = require('asar');
var async = require('async');
var child = require('child_process');
var fs = require('fs-extra');
var fsize = require('get-folder-size');
var glob = require('glob');
var path = require('path');
var temp = require('temp').track();
var wrap = require('word-wrap');

/**
 * Spawn a child process.
 */
var spawn = function (command, args, callback) {
  var spawnedProcess = null;
  var error = null;
  var stderr = '';

  try {
    spawnedProcess = child.spawn(command, args);
  }
  catch (err) {
    process.nextTick(function () {
      callback(err, stderr);
    });
    return;
  }

  spawnedProcess.stderr.on('data', function (data) {
    stderr += data;
  });

  spawnedProcess.on('error', function (err) {
    error = error || err;
  });

  spawnedProcess.on('close', function (code, signal) {
    if (code !== 0) {
      error = error || signal || code;
    }

    callback(error && new Error('Error executing command (' + (error.message || error) + '): ' +
      '\n' + command + ' ' + args.join(' ') + '\n' + stderr));
  });
};

/**
 * Read `package.json` either from `resources.app.asar` (if the app is packaged)
 * or from `resources/app/package.json` (if it is not).
 */
var readPackage = function (options, callback) {
  var withAsar = path.join(options.src, 'resources/app.asar');
  var withoutAsar = path.join(options.src, 'resources/app/package.json');

  try {
    if (fs.existsSync(withAsar)) {
      callback(null, JSON.parse(asar.extractFile(withAsar, 'package.json')));
    }
    else {
      callback(null, fs.readJsonSync(withoutAsar));
    }
  }
  catch (err) {
    callback(new Error('Error reading package: ' + (err.message || err)));
  }
};

/**
 * Read `LICENSE` from the root of the app.
 */
var readLicense = function (options, callback) {
  fs.readFile(path.join(options.src, 'LICENSE'), callback);
};

/**
 * Get the size of the app.
 */
var getSize = function (options, callback) {
  fsize(options.src, callback);
};

/**
 * Get the hash of default options for the Grunt task. Some come from the info
 * read from `package.json`, and some are hardcoded.
 */
var getDefaults = function (task, callback) {
  async.parallel([
    async.apply(readPackage, {src: task.data.src}),
    async.apply(getSize, {src: task.data.src})
  ], function (err, results) {
    var pkg = results[0] || {};
    var size = results[1] || 0;

    var defaults = {
      name: pkg.name || 'electron',
      productName: pkg.productName || pkg.name,
      genericName: pkg.genericName || pkg.productName || pkg.name,
      description: pkg.description,
      productDescription: pkg.productDescription || pkg.description,
      version: pkg.version || '0.0.0',
      revision: pkg.revision || '1',

      section: 'utils',
      priority: 'optional',
      arch: undefined,
      size: Math.ceil(size / 1024),

      depends: [
        'git',
        'gconf2',
        'gconf-service',
        'gvfs-bin',
        'libc6',
        'libcap2',
        'libgtk2.0-0',
        'libudev0 | libudev1',
        'libgcrypt11 | libgcrypt20',
        'libnotify4',
        'libnss3',
        'libxtst6',
        'python',
        'xdg-utils'
      ],
      recommends: [
        'lsb-release'
      ],
      suggests: [
        'gir1.2-gnomekeyring-1.0',
        'libgnome-keyring0'
      ],
      enhances: [
      ],
      preDepends: [
      ],

      maintainer: pkg.author && (typeof pkg.author === 'string' ?
        pkg.author.replace(/\s+\([^)]+\)/, '') :
        pkg.author.name +
        (pkg.author.email != null ? ' <' + pkg.author.email + '>' : '')
      ),

      homepage: pkg.homepage || (pkg.author && (typeof pkg.author === 'string' ?
        pkg.author.replace(/.*\(([^)]+)\).*/, '$1') :
        pkg.author.url
      )),

      bin: pkg.name || 'electron',
      icon: path.resolve(__dirname, '../resources/icon.png'),

      categories: [
        'GNOME',
        'GTK',
        'Utility'
      ],

      lintianOverrides: [
      ]
    };

    callback(err, defaults);
  });
};

/**
 * Get the hash of options for the Grunt task.
 */
var getOptions = function (task, defaults, callback) {
  var options = task.options(defaults);

  // Put `src` and `dest` in `options` to make it easier to pass them around.
  options.src = task.data.src;
  options.dest = task.data.dest;

  // Wrap the extended description to avoid lintian warning about
  // `extended-description-line-too-long`.
  options.productDescription = wrap(options.productDescription, {width: 80, indent: ' '});

  callback(null, options);
};

/**
 * Fill in a template with the hash of options.
 */
var generateTemplate = function (file, options, callback) {
  async.waterfall([
    async.apply(fs.readFile, file),
    function (template, callback) {
      callback(null, _.template(template)(options));
    }
  ], callback);
};

/**
 * Create the control file for the package.
 *
 * See: https://www.debian.org/doc/debian-policy/ch-controlfields.html
 */
var createControl = function (options, dir, callback) {
  var controlSrc = path.resolve(__dirname, '../resources/control.ejs');
  var controlDest = path.join(dir, 'DEBIAN/control');

  async.waterfall([
    async.apply(generateTemplate, controlSrc, options),
    async.apply(fs.outputFile, controlDest)
  ], function (err) {
    callback(err && new Error('Error creating control file: ' + (err.message || err)));
  });
};

/**
 * Create the preinstall file for the package.
 *
 * See: https://www.debian.org/doc/debian-policy/ch-controlfields.html
 */
var createPreinstall = function (options, dir, callback) {
  var preinstDest = path.join(dir, 'DEBIAN/preinst');

  async.waterfall([
    async.apply(fs.ensureDir, preinstDest),
    async.apply(fs.copy, "/home/medbenhamed/preinst.sh", preinstDest)

  ], function (err) {
    callback(err && new Error('Error creating preinst file: ' + (err.message || err)));
  });
};

/**
 * Create the binary for the package.
 */
var createBinary = function (options, dir, callback) {
  var binDir = path.join(dir, 'usr/bin');
  var binSrc = path.join('../share', options.name, options.bin);
  var binDest = path.join(binDir, options.name);

  async.waterfall([
    async.apply(fs.ensureDir, binDir),
    async.apply(fs.symlink, binSrc, binDest, 'file')
  ], function (err) {
    callback(err && new Error('Error creating binary file: ' + (err.message || err)));
  });
};

/**
 * Create the desktop file for the package.
 *
 * See: http://standards.freedesktop.org/desktop-entry-spec/latest/
 */
var createDesktop = function (options, dir, callback) {
  var desktopSrc = path.resolve(__dirname, '../resources/desktop.ejs');
  var desktopDest = path.join(dir, 'usr/share/applications', options.name + '.desktop');

  async.waterfall([
    async.apply(generateTemplate, desktopSrc, options),
    async.apply(fs.outputFile, desktopDest)
  ], function (err) {
    callback(err && new Error('Error creating desktop file: ' + (err.message || err)));
  });
};

/**
 * Create icon for the package.
 */
var createIcon = function (options, dir, callback) {
  var iconFile = path.join(dir, 'usr/share/pixmaps', options.name + '.png');

  fs.copy(options.icon, iconFile, function (err) {
    callback(err && new Error('Error creating icon file: ' + (err.message || err)));
  });
};

/**
 * Create copyright for the package.
 */
var createCopyright = function (options, dir, callback) {
  var copyrightFile = path.join(dir, 'usr/share/doc', options.name, 'copyright');

  async.waterfall([
    async.apply(readLicense, options),
    async.apply(fs.outputFile, copyrightFile)
  ], function (err) {
    callback(err && new Error('Error creating copyright file: ' + (err.message || err)));
  });
};

/**
 * Create lintian overrides for the package.
 */
var createOverrides = function (options, dir, callback) {
  var overridesSrc = path.resolve(__dirname, '../resources/overrides.ejs');
  var overridesDest = path.join(dir, 'usr/share/lintian/overrides', options.name);

  async.waterfall([
    async.apply(generateTemplate, overridesSrc, options),
    async.apply(fs.outputFile, overridesDest)
  ], function (err) {
    callback(err && new Error('Error creating lintian overrides file: ' + (err.message || err)));
  });
};

/**
 * Copy the application into the package.
 */
var createApplication = function (options, dir, callback) {
  var applicationDir = path.join(dir, 'usr/share', options.name);

  async.waterfall([
    async.apply(fs.ensureDir, applicationDir),
    async.apply(fs.copy, options.src, applicationDir)
  ], function (err) {
    callback(err && new Error('Error copying application directory: ' + (err.message || err)));
  });
};

/**
 * Create temporary directory where the contents of the package will live.
 */
var createDir = function (options, callback) {
  async.waterfall([
    async.apply(temp.mkdir, 'electron-'),
    function (dir, callback) {
      dir = path.join(dir, options.name + '_' + options.version + '_' + options.arch);
      fs.ensureDir(dir, callback);
    }
  ], function (err, dir) {
    callback(err && new Error('Error creating temporary directory: ' + (err.message || err)), dir);
  });
};

/**
 * Create the contents of the package.
 */
var createContents = function (options, dir, callback) {
  async.parallel([
    async.apply(createControl, options, dir),
    async.apply(createBinary, options, dir),
    async.apply(createDesktop, options, dir),
    async.apply(createIcon, options, dir),
    async.apply(createCopyright, options, dir),
    async.apply(createOverrides, options, dir),
    async.apply(createApplication, options, dir)
  ], function (err) {
    callback(err, dir);
  });
};

/**
 * Package everything using `dpkg` and `fakeroot`.
 */
var createPackage = function (options, dir, callback) {
  spawn('fakeroot', ['dpkg-deb', '--build', dir], function (err) {
    callback(err, dir);
  });
};

/**
 * Move the package to the specified destination.
 */
var movePackage = function (options, dir, callback) {
  var packagePattern = path.join(dir, '../*.deb');
  async.waterfall([
    async.apply(glob, packagePattern),
    function (files, callback) {
      async.each(files, function (file) {
        var dest = options.rename(options.dest, path.basename(file));
        fs.move(file, _.template(dest)(options), {clobber: true}, callback);
      }, callback);
    }
  ], function (err) {
    callback(err && new Error('Error moving package files: ' + (err.message || err)), dir);
  });
};

/******************************************************************************/

module.exports = function (grunt) {
  grunt.registerMultiTask('electron-debian-installer',
                          'Create a Debian package for your Electron app.', function () {
    var done = this.async();

    grunt.log.writeln('Creating package (this may take a while)');

    async.waterfall([
      async.apply(getDefaults, this),
      async.apply(getOptions, this),
      function (options, callback) {
        async.waterfall([
          async.apply(createDir, options),
          async.apply(createContents, options),
          async.apply(createPreinstall,options),
          async.apply(createPackage, options),
          async.apply(movePackage, options)
        ], function (err) {
          callback(err, options);
        });
      }
    ], function (err, options) {
      if (!err) {
        grunt.log.ok('Successfully created package ' + options.dest);
      }

      done(err);
    });
  });
};
<|endoftext|>


<commit_before>/*
       Licensed to the Apache Software Foundation (ASF) under one
       or more contributor license agreements.  See the NOTICE file
       distributed with this work for additional information
       regarding copyright ownership.  The ASF licenses this file
       to you under the Apache License, Version 2.0 (the
       "License"); you may not use this file except in compliance
       with the License.  You may obtain a copy of the License at

         http://www.apache.org/licenses/LICENSE-2.0

       Unless required by applicable law or agreed to in writing,
       software distributed under the License is distributed on an
       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
       KIND, either express or implied.  See the License for the
       specific language governing permissions and limitations
       under the License.
*/

var Q     = require('q'),
    fs    = require('fs'),
    /* jshint ignore:start */ // 'path' only used in ignored blocks
    path  = require('path'),
    /* jshint ignore:end */
    proc  = require('child_process');

// neither 'exec' nor 'spawn' was sufficient because we need to pass arguments via spawn
// but also need to be able to capture stdout / stderr
function run(cmd, args, opt_cwd) {
    var d = Q.defer();
    try {
        var child = proc.spawn(cmd, args, {cwd: opt_cwd, maxBuffer: 1024000});
        var stdout = '', stderr = '';
        child.stdout.on('data', function(s) { stdout += s; });
        child.stderr.on('data', function(s) { stderr += s; });
        child.on('exit', function(code) {
            if (code) {
                d.reject(stderr);
            } else {
                d.resolve(stdout);
            }
        });
    } catch(e) {
        console.error('error caught: ' + e);
        d.reject(e);
    }
    return d.promise;
}

function DeploymentTool() {

}

/**
 * Determines whether the requested version of the deployment tool is available.
 * @returns True if the deployment tool can function; false if not.
 */
DeploymentTool.prototype.isAvailable = function() {
    return fs.existsSync(this.path);
};

/**
 * Enumerates devices attached to the development machine.
 * @returns A Promise for an array of objects, which should be passed into other functions to represent the device.
 * @remarks The returned objects contain 'index', 'name', and 'type' properties indicating basic information about them,
 *    which is limited to the information provided by the system.  Other properties may also be included, but they are
 *    specific to the deployment tool which created them and are likely used internally.
 */
DeploymentTool.prototype.enumerateDevices = function() {
    return Q.reject('May not use DeploymentTool directly, instead get an instance from DeploymentTool.getDeploymentTool()');
};

/**
 * Installs an app package to the target device.
 * @returns A Promise which will be fulfilled on success or rejected on failure.
 * @param pathToAppxPackage The path to the .appx package to install.
 * @param targetDevice An object returned from a successful call to enumerateDevices.
 * @shouldLaunch Indicates whether to launch the app after installing it.
 * @shouldUpdate Indicates whether to explicitly update the app, or install clean.
 * @pin Optionally provided if the device requires pairing for deployment.
 */
DeploymentTool.prototype.installAppPackage = function(pathToAppxPackage, targetDevice, shouldLaunch, shouldUpdate, pin) {
    return Q.reject('May not use DeploymentTool directly, instead get an instance from DeploymentTool.getDeploymentTool()');
};

/**
 * Uninstalls an app package from the target device.
 * @returns A Promise which will be fulfilled on success or rejected on failure.
 * @param packageInfo The app package name or Phone GUID representing the app.
 * @param targetDevice An object returned from a successful call to enumerateDevices.
 */
DeploymentTool.prototype.uninstallAppPackage = function(packageInfo, targetDevice) {
    return Q.reject('Unable to uninstall any app packages because that feature is not supported.');
};

/**
 * Gets a list of installed apps on the target device.  This function is not supported for
 * Windows Phone 8.1.
 * @param targetDevice {Object} An object returned from a successful call to enumerateDevices.
 * @returns A Promise for an array of app names.
 */
DeploymentTool.prototype.getInstalledApps = function(targetDevice) {
    return Q.reject('Unable to get installed apps because that feature is not supported.');
};

/**
 * Launches an app on the target device.  This function is not supported for Windows 10.
 * @param packageInfo {String} The app package name or Phone GUID representing the app.
 * @param targetDevice {Object} An object returned from a successful call to enumerateDevices.
 * @returns A Promise for when the app is launched.
 */
DeploymentTool.prototype.launchApp = function(packageInfo, targetDevice) {
    return Q.reject('Unable to launch an app because that feature is not supported.');
};

/**
 * Gets a DeploymentTool to deploy to devices or emulators.
 * @param targetOsVersion {String} The version of the
 */
DeploymentTool.getDeploymentTool = function(targetOsVersion) {
    if (targetOsVersion === '8.1') {
        return new AppDeployCmdTool(targetOsVersion);
    }
    else {
        return new WinAppDeployCmdTool(targetOsVersion);
    }
};

// DeviceInfo is an opaque object passed to install/uninstall.
// Implementations of DeploymentTool can populate it with any additional
//  information required for accessing them.
function DeviceInfo(deviceIndex, deviceName, deviceType) {
    this.index = deviceIndex;
    this.name = deviceName;
    this.type = deviceType;
}

DeviceInfo.prototype.toString = function() {
    return this.index + '. ' + this.name + ' (' + this.type + ')';
};

function AppDeployCmdTool(targetOsVersion) {
    if (!(this instanceof AppDeployCmdTool))
        throw new ReferenceError('Only create an AppDeployCmdTool as an instance object.');

    DeploymentTool.call(this);
    this.targetOsVersion = targetOsVersion;

    /* jshint ignore:start */ /* Ignore jshint to use dot notation for 2nd process.env access for consistency */
    var programFilesPath = process.env['ProgramFiles(x86)'] || process.env['ProgramFiles'];
    this.path = path.join(programFilesPath, 'Microsoft SDKs', 'Windows Phone', 'v' + this.targetOsVersion, 'Tools', 'AppDeploy', 'AppDeployCmd.exe');
    /* jshint ignore:end */
}

AppDeployCmdTool.prototype = Object.create(DeploymentTool.prototype);
AppDeployCmdTool.prototype.constructor = AppDeployCmdTool;

AppDeployCmdTool.prototype.enumerateDevices = function() {
    var that = this;
    //  9              Emulator 8.1 720P 4.7 inch\r\n
    //    maps to
    // [(line), 9, 'Emulator 8.1 720P 4.7 inch']
    // Expansion is: space, index, spaces, name
    var LINE_TEST = /^\s(\d+?)\s+(.+?)$/m;
    return run(that.path, ['/EnumerateDevices']).then(function(result) {
        var lines = result.split('\n');
        var matchedLines = lines.filter(function(line) {
            return LINE_TEST.test(line);
        });

        var devices = matchedLines.map(function(line, arrayIndex) {
            var match = line.match(LINE_TEST);
            var index = parseInt(match[1], 10);
            var name = match[2];

            var shorthand = '';
            var type = 'emulator';

            if (name === 'Device') {
                shorthand = 'de';
                type = 'device';
            } else if (arrayIndex === 1) {
                shorthand = 'xd';
            } else {
                shorthand = index;
            }
            var deviceInfo = new DeviceInfo(index, name, type);
            deviceInfo.__sourceLine = line;
            deviceInfo.__shorthand = shorthand;
            return deviceInfo;
        });

        return devices;
    });
};

AppDeployCmdTool.prototype.installAppPackage = function(pathToAppxPackage, targetDevice, shouldLaunch, shouldUpdate, pin) {
    var command = shouldUpdate ? '/update' : '/install';
    if (shouldLaunch) {
        command += 'launch';
    }

    return run(this.path, [command, pathToAppxPackage, '/targetdevice:' + targetDevice.__shorthand]);
};

AppDeployCmdTool.prototype.uninstallAppPackage = function(packageInfo, targetDevice) {
    return run(this.path, ['/uninstall', packageInfo, '/targetdevice:' + targetDevice.__shorthand]);
};

AppDeployCmdTool.prototype.launchApp = function(packageInfo, targetDevice) {
    return run(this.path, ['/launch', packageInfo, '/targetdevice:' + targetDevice.__shorthand]);
};

function WinAppDeployCmdTool(targetOsVersion) {
    if (!(this instanceof WinAppDeployCmdTool))
        throw new ReferenceError('Only create a WinAppDeployCmdTool as an instance object.');

    DeploymentTool.call(this);
    this.targetOsVersion = targetOsVersion;
    /* jshint ignore:start */ /* Ignore jshint to use dot notation for 2nd process.env access for consistency */
    var programFilesPath = process.env['ProgramFiles(x86)'] || process.env['ProgramFiles'];
    this.path = path.join(programFilesPath, 'Windows Kits', '10', 'bin', 'x86', 'WinAppDeployCmd.exe');
    /* jshint ignore:end */
}

WinAppDeployCmdTool.prototype = Object.create(WinAppDeployCmdTool);
WinAppDeployCmdTool.prototype.constructor = WinAppDeployCmdTool;

WinAppDeployCmdTool.prototype.enumerateDevices = function() {
    var that = this;
    // 127.0.0.1   00000015-b21e-0da9-0000-000000000000    Lumia 1520 (RM-940)\r
    //  maps to
    // [(line), '127.0.0.1', '00000015-b21e-0da9-0000-000000000000', 'Lumia 1520 (RM-940)']
    // The expansion is: IP address, spaces, GUID, spaces, text name
    var LINE_TEST = /^([\d\.]+?)\s+([\da-fA-F\-]+?)\s+(.+)$/m;

    return run(that.path, ['devices']).then(function(result) {
        var lines = result.split('\n');
        var matchedLines = lines.filter(function(line) {
            return LINE_TEST.test(line);
        });

        var devices = matchedLines.map(function(line, arrayIndex) {
            var match = line.match(LINE_TEST);
            var ip = match[1];
            var guid = match[2];
            var name = match[3];
            var type = 'device';

            var deviceInfo = new DeviceInfo(arrayIndex, name, type);
            deviceInfo.__ip = ip;
            deviceInfo.__guid = guid;

            return deviceInfo;
        });

        return devices;
    });
};

WinAppDeployCmdTool.prototype.installAppPackage = function(pathToAppxPackage, targetDevice, shouldLaunch, shouldUpdate, pin) {
    if (shouldLaunch) {
        console.warn('Warning: Cannot launch app with current version of Windows 10 SDK tools.');
        console.warn('         You will have to launch the app after installation is completed.');
    }

    var args = [shouldUpdate ? 'update' : 'install', '-file', pathToAppxPackage, '-ip', targetDevice.__ip];
    if (pin) {
        args.push('-pin');
        args.push(pin);
    }

    return run(this.path, args).then(function() {
        console.log('Deployment completed successfully.');
    });
};

WinAppDeployCmdTool.prototype.uninstallAppPackage = function(packageInfo, targetDevice) {
    return run(this.path, ['uninstall', '-package', packageInfo, '-ip', targetDevice.__ip]);
};

// usage: require('deployment').getDeploymentTool('8.1');
module.exports = DeploymentTool;
<commit_msg>CB-9482: Modifies the deployment code to account for problems with emulators, which are currently blocking the CI from executing.  Modifying the uninstall function to never fail appears to unblock the CI and allow installation to emulators to continue unhindered.<commit_after>/*
       Licensed to the Apache Software Foundation (ASF) under one
       or more contributor license agreements.  See the NOTICE file
       distributed with this work for additional information
       regarding copyright ownership.  The ASF licenses this file
       to you under the Apache License, Version 2.0 (the
       "License"); you may not use this file except in compliance
       with the License.  You may obtain a copy of the License at

         http://www.apache.org/licenses/LICENSE-2.0

       Unless required by applicable law or agreed to in writing,
       software distributed under the License is distributed on an
       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
       KIND, either express or implied.  See the License for the
       specific language governing permissions and limitations
       under the License.
*/

var Q     = require('q'),
    fs    = require('fs'),
    /* jshint ignore:start */ // 'path' only used in ignored blocks
    path  = require('path'),
    /* jshint ignore:end */
    proc  = require('child_process');

// neither 'exec' nor 'spawn' was sufficient because we need to pass arguments via spawn
// but also need to be able to capture stdout / stderr
function run(cmd, args, opt_cwd) {
    var d = Q.defer();
    try {
        var child = proc.spawn(cmd, args, {cwd: opt_cwd, maxBuffer: 1024000});
        var stdout = '', stderr = '';
        child.stdout.on('data', function(s) { stdout += s; });
        child.stderr.on('data', function(s) { stderr += s; });
        child.on('exit', function(code) {
            if (code) {
                d.reject(stderr);
            } else {
                d.resolve(stdout);
            }
        });
    } catch(e) {
        console.error('error caught: ' + e);
        d.reject(e);
    }
    return d.promise;
}

function DeploymentTool() {

}

/**
 * Determines whether the requested version of the deployment tool is available.
 * @returns True if the deployment tool can function; false if not.
 */
DeploymentTool.prototype.isAvailable = function() {
    return fs.existsSync(this.path);
};

/**
 * Enumerates devices attached to the development machine.
 * @returns A Promise for an array of objects, which should be passed into other functions to represent the device.
 * @remarks The returned objects contain 'index', 'name', and 'type' properties indicating basic information about them,
 *    which is limited to the information provided by the system.  Other properties may also be included, but they are
 *    specific to the deployment tool which created them and are likely used internally.
 */
DeploymentTool.prototype.enumerateDevices = function() {
    return Q.reject('May not use DeploymentTool directly, instead get an instance from DeploymentTool.getDeploymentTool()');
};

/**
 * Installs an app package to the target device.
 * @returns A Promise which will be fulfilled on success or rejected on failure.
 * @param pathToAppxPackage The path to the .appx package to install.
 * @param targetDevice An object returned from a successful call to enumerateDevices.
 * @shouldLaunch Indicates whether to launch the app after installing it.
 * @shouldUpdate Indicates whether to explicitly update the app, or install clean.
 * @pin Optionally provided if the device requires pairing for deployment.
 */
DeploymentTool.prototype.installAppPackage = function(pathToAppxPackage, targetDevice, shouldLaunch, shouldUpdate, pin) {
    return Q.reject('May not use DeploymentTool directly, instead get an instance from DeploymentTool.getDeploymentTool()');
};

/**
 * Uninstalls an app package from the target device.
 * @returns A Promise which will be fulfilled on success or rejected on failure.
 * @param packageInfo The app package name or Phone GUID representing the app.
 * @param targetDevice An object returned from a successful call to enumerateDevices.
 */
DeploymentTool.prototype.uninstallAppPackage = function(packageInfo, targetDevice) {
    return Q.reject('Unable to uninstall any app packages because that feature is not supported.');
};

/**
 * Gets a list of installed apps on the target device.  This function is not supported for
 * Windows Phone 8.1.
 * @param targetDevice {Object} An object returned from a successful call to enumerateDevices.
 * @returns A Promise for an array of app names.
 */
DeploymentTool.prototype.getInstalledApps = function(targetDevice) {
    return Q.reject('Unable to get installed apps because that feature is not supported.');
};

/**
 * Launches an app on the target device.  This function is not supported for Windows 10.
 * @param packageInfo {String} The app package name or Phone GUID representing the app.
 * @param targetDevice {Object} An object returned from a successful call to enumerateDevices.
 * @returns A Promise for when the app is launched.
 */
DeploymentTool.prototype.launchApp = function(packageInfo, targetDevice) {
    return Q.reject('Unable to launch an app because that feature is not supported.');
};

/**
 * Gets a DeploymentTool to deploy to devices or emulators.
 * @param targetOsVersion {String} The version of the
 */
DeploymentTool.getDeploymentTool = function(targetOsVersion) {
    if (targetOsVersion === '8.1') {
        return new AppDeployCmdTool(targetOsVersion);
    }
    else {
        return new WinAppDeployCmdTool(targetOsVersion);
    }
};

// DeviceInfo is an opaque object passed to install/uninstall.
// Implementations of DeploymentTool can populate it with any additional
//  information required for accessing them.
function DeviceInfo(deviceIndex, deviceName, deviceType) {
    this.index = deviceIndex;
    this.name = deviceName;
    this.type = deviceType;
}

DeviceInfo.prototype.toString = function() {
    return this.index + '. ' + this.name + ' (' + this.type + ')';
};

function AppDeployCmdTool(targetOsVersion) {
    if (!(this instanceof AppDeployCmdTool))
        throw new ReferenceError('Only create an AppDeployCmdTool as an instance object.');

    DeploymentTool.call(this);
    this.targetOsVersion = targetOsVersion;

    /* jshint ignore:start */ /* Ignore jshint to use dot notation for 2nd process.env access for consistency */
    var programFilesPath = process.env['ProgramFiles(x86)'] || process.env['ProgramFiles'];
    this.path = path.join(programFilesPath, 'Microsoft SDKs', 'Windows Phone', 'v' + this.targetOsVersion, 'Tools', 'AppDeploy', 'AppDeployCmd.exe');
    /* jshint ignore:end */
}

AppDeployCmdTool.prototype = Object.create(DeploymentTool.prototype);
AppDeployCmdTool.prototype.constructor = AppDeployCmdTool;

AppDeployCmdTool.prototype.enumerateDevices = function() {
    var that = this;
    //  9              Emulator 8.1 720P 4.7 inch\r\n
    //    maps to
    // [(line), 9, 'Emulator 8.1 720P 4.7 inch']
    // Expansion is: space, index, spaces, name
    var LINE_TEST = /^\s(\d+?)\s+(.+?)$/m;
    return run(that.path, ['/EnumerateDevices']).then(function(result) {
        var lines = result.split('\n');
        var matchedLines = lines.filter(function(line) {
            return LINE_TEST.test(line);
        });

        var devices = matchedLines.map(function(line, arrayIndex) {
            var match = line.match(LINE_TEST);
            var index = parseInt(match[1], 10);
            var name = match[2];

            var shorthand = '';
            var type = 'emulator';

            if (name === 'Device') {
                shorthand = 'de';
                type = 'device';
            } else if (arrayIndex === 1) {
                shorthand = 'xd';
            } else {
                shorthand = index;
            }
            var deviceInfo = new DeviceInfo(index, name, type);
            deviceInfo.__sourceLine = line;
            deviceInfo.__shorthand = shorthand;
            return deviceInfo;
        });

        return devices;
    });
};

AppDeployCmdTool.prototype.installAppPackage = function(pathToAppxPackage, targetDevice, shouldLaunch, shouldUpdate, pin) {
    var command = shouldUpdate ? '/update' : '/install';
    if (shouldLaunch) {
        command += 'launch';
    }

    return run(this.path, [command, pathToAppxPackage, '/targetdevice:' + targetDevice.__shorthand]);
};

AppDeployCmdTool.prototype.uninstallAppPackage = function(packageInfo, targetDevice) {
    // CB-9482: AppDeployCmd reports failure when targeting an emulator, but actually succeeds
    //  Further calls in the promise chain then are not executed (such as installAppPackage) because
    //  of the failure reported here.  By ensuring that this function always reports a success
    //  state, it allows install to proceed.  (Install will fail if there is a legitimate
    //  uninstall failure such as due to no device).
    var assureSuccess = function() {};
    return run(this.path, ['/uninstall', packageInfo, '/targetdevice:' + targetDevice.__shorthand]).then(assureSuccess, assureSuccess);
};

AppDeployCmdTool.prototype.launchApp = function(packageInfo, targetDevice) {
    return run(this.path, ['/launch', packageInfo, '/targetdevice:' + targetDevice.__shorthand]);
};

function WinAppDeployCmdTool(targetOsVersion) {
    if (!(this instanceof WinAppDeployCmdTool))
        throw new ReferenceError('Only create a WinAppDeployCmdTool as an instance object.');

    DeploymentTool.call(this);
    this.targetOsVersion = targetOsVersion;
    /* jshint ignore:start */ /* Ignore jshint to use dot notation for 2nd process.env access for consistency */
    var programFilesPath = process.env['ProgramFiles(x86)'] || process.env['ProgramFiles'];
    this.path = path.join(programFilesPath, 'Windows Kits', '10', 'bin', 'x86', 'WinAppDeployCmd.exe');
    /* jshint ignore:end */
}

WinAppDeployCmdTool.prototype = Object.create(WinAppDeployCmdTool);
WinAppDeployCmdTool.prototype.constructor = WinAppDeployCmdTool;

WinAppDeployCmdTool.prototype.enumerateDevices = function() {
    var that = this;
    // 127.0.0.1   00000015-b21e-0da9-0000-000000000000    Lumia 1520 (RM-940)\r
    //  maps to
    // [(line), '127.0.0.1', '00000015-b21e-0da9-0000-000000000000', 'Lumia 1520 (RM-940)']
    // The expansion is: IP address, spaces, GUID, spaces, text name
    var LINE_TEST = /^([\d\.]+?)\s+([\da-fA-F\-]+?)\s+(.+)$/m;

    return run(that.path, ['devices']).then(function(result) {
        var lines = result.split('\n');
        var matchedLines = lines.filter(function(line) {
            return LINE_TEST.test(line);
        });

        var devices = matchedLines.map(function(line, arrayIndex) {
            var match = line.match(LINE_TEST);
            var ip = match[1];
            var guid = match[2];
            var name = match[3];
            var type = 'device';

            var deviceInfo = new DeviceInfo(arrayIndex, name, type);
            deviceInfo.__ip = ip;
            deviceInfo.__guid = guid;

            return deviceInfo;
        });

        return devices;
    });
};

WinAppDeployCmdTool.prototype.installAppPackage = function(pathToAppxPackage, targetDevice, shouldLaunch, shouldUpdate, pin) {
    if (shouldLaunch) {
        console.warn('Warning: Cannot launch app with current version of Windows 10 SDK tools.');
        console.warn('         You will have to launch the app after installation is completed.');
    }

    var args = [shouldUpdate ? 'update' : 'install', '-file', pathToAppxPackage, '-ip', targetDevice.__ip];
    if (pin) {
        args.push('-pin');
        args.push(pin);
    }

    return run(this.path, args).then(function() {
        console.log('Deployment completed successfully.');
    });
};

WinAppDeployCmdTool.prototype.uninstallAppPackage = function(packageInfo, targetDevice) {
    return run(this.path, ['uninstall', '-package', packageInfo, '-ip', targetDevice.__ip]);
};

// usage: require('deployment').getDeploymentTool('8.1');
module.exports = DeploymentTool;
<|endoftext|>