Skip to content

Commit

Permalink
Output correct types. Ensure this works with TypeScript 1.6
Browse files Browse the repository at this point in the history
  • Loading branch information
Christy Haragan committed Oct 6, 2015
1 parent 0e81c91 commit 814def5
Show file tree
Hide file tree
Showing 142 changed files with 1,329 additions and 7,326 deletions.
53 changes: 52 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ TypeScript enabled editors should pick up the TypeScript definition files automa
- Clone this project
- Create a folder xml/
- Download a copy of the documentation from here: http://docs.marklogic.com/MarkLogic_8_pubs.zip
- Extract the zip, and copy the contents of the folder pubs/raw/apidoc/ into xml/
- Extract the zip, and copy the contents of the folder pubs/raw/apidoc/ into xml/
- Run `npm install`
- Run `gulp` (may take a few minutes)

Expand All @@ -30,3 +30,54 @@ Note: you likely want to override ml-host, ml-user, and such. It runs by default
```
gulp --ml-host=ml8-ml1 --ml-port=8000 --ml-user=admin --ml-pass=admin
```

#### XML Files to ignore
Before trying to build, remove the following xml files (as some of these are xquery only modules):

- admin
- convert
- css
- cpf
- custom-dictionary
- debug
- dls
- docbook
- domains
- ec2-2009-11-30
- excel
- flexrep
- geojson
- georss
- geospatial
- gml
- hadoop
- info
- infodev
- json
- kml
- links
- manage* (all files beginning with 'manage')
- mgcm
- msword
- package* (all files beginning with 'package')
- pdf
- powerpoint
- pipelines
- pki
- plugin
- Profile
- rest
- RESTClient
- searchapi
- security
- semantics-stub
- spell
- thesaurus
- tieredstorage
- temporal-stub
- triggers
- views
- work-processing-ml
- xhtml
- xinc
- xpointer
23 changes: 11 additions & 12 deletions gulpfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,30 +17,30 @@ var onError = function(err) {
};

var options = {
mlHost: argv['ml-host'] || 'ml8-ml1',
mlHost: argv['ml-host'] || 'localhost',
mlPort: argv['ml-port'] || '8000',
mlUser: argv['ml-user'] || 'admin',
mlPass: argv['ml-pass'] || 'admin'
mlPass: argv['ml-pass'] || 'passw0rd'
};


gulp.task('generate', function(){
var query;

fs.readFile('qconsole/generate-definitions.xqy', null, function(err, data) {
query = data.toString();
});

return gulp.src(['xml/**/*.xml'])
.pipe(through.obj(function (file, enc, cb) {

console.log(file.path);

var outFile = file.path.replace('/xml/', '/ts/').replace('.xml', '.d.ts');

var xml = file.contents.toString();
var escapedXml = xml.replace(/\\/gm, '\\\\').replace(/"/gm, '\\"').replace(/(\n\r|\r\n|\n|\r)/gm, '\\n').replace(/\t/gm, '\\t');

request({
method: 'POST',
url: 'http://' + options.mlHost + ':' + options.mlPort + '/v1/eval',
Expand All @@ -58,15 +58,15 @@ gulp.task('generate', function(){
try {
// get rid of multipart response wrapping
body = body.replace(/^([^\r]*\r\n){5}/, '').replace(/\r\n[^\r]*\r\n$/, '');

if (err || httpResponse.statusCode !== 200) {
console.log('FAILED!');
console.log(body);
//console.log(escapedXml);
} else {
fs.writeFile(outFile, body, onError);
}

cb(null, file);
} catch (e) {
console.log(e);
Expand All @@ -77,8 +77,7 @@ gulp.task('generate', function(){

gulp.task('validate', ['generate'], function(){
gulp.src(['ts/**/*.ts'])
.pipe(typescript({emitError: false}))
;
.pipe(typescript({emitError: false}));
});

// Default Task
Expand Down
10 changes: 8 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
{
"name": "marklogic-typescript-definitions",
"version": "0.0.1",
"version": "0.2.0",
"description": "TypeScript Definition files for MarkLogic built-in functions",
"main": "",
"author": "Geert Josten <[email protected]>",
"contributors": [
{ "name" : "Christy Haragan",
"email": "[email protected]",
"url": "https://github.com/christyharagan"
}
],
"typings": "./ts/index.d.ts",
"keywords": [
"typescript",
"marklogic"
Expand Down
131 changes: 84 additions & 47 deletions qconsole/generate-definitions.xqy
Original file line number Diff line number Diff line change
@@ -1,87 +1,82 @@
xquery version "1.0-ml";

(:
let $docs-dir := "/Users/gjosten/Projects/github-grtjn/marklogic-typescript-definitions/xml/"
let $docs-files := xdmp:filesystem-directory($docs-dir)/*[ends-with(*:filename, ".xml")]/*:filename
for $file in $docs-files
let $xml := xdmp:document-get(concat($docs-dir, $file))
:)

declare variable $xml external;
let $xml := xdmp:unquote($xml)

let $definition := xdmp:xslt-eval(
<xsl:stylesheet version="2.0" exclude-result-prefixes="#all" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:apidoc="http://marklogic.com/xdmp/apidoc" xmlns:local="local">

<xsl:output method="text" indent="yes" omit-xml-declaration="yes"/>

<xsl:template match="@*|node()" mode="#all">
<xsl:copy>
<xsl:apply-templates select="@*|node()" mode="#current"/>
</xsl:copy>
</xsl:template>

<xsl:template match="apidoc:function" mode="#all">
<xsl:param name="use-function-keyword" select="false()"/>
<xsl:text> /** </xsl:text>
<xsl:value-of select="normalize-space(apidoc:summary[not(@class) or @class = 'javascript'])"/>
<xsl:text> **/&#10;</xsl:text>

<xsl:text>&#32;&#32;</xsl:text>
<xsl:if test="$use-function-keyword">
<xsl:text>function </xsl:text>
</xsl:if>
<xsl:value-of select="local:fixName(@name)"/>
<xsl:text>(</xsl:text>
<xsl:for-each select="apidoc:params/apidoc:param[not(@class) or @class = 'javascript']">
<xsl:variable name="is-multi" select ="substring(@type, string-length(@type) - 3) = ',...'"/>
<xsl:if test="$is-multi">...</xsl:if>
<xsl:value-of select="local:fixName(@name)"/>
<xsl:if test="preceding-sibling::apidoc:param[not(@class) or @class = 'javascript'][@name = current()/@name]">2</xsl:if>
<xsl:if test="string(@optional) = 'true'">?</xsl:if>
<xsl:if test="not($is-multi) and string(@optional) = 'true'">?</xsl:if>
<xsl:text>: </xsl:text>
<xsl:value-of select="local:fixType(@type)"/>
<xsl:if test="$is-multi">[]</xsl:if>
<xsl:if test="not(position() = last())">, </xsl:if>
</xsl:for-each>
<xsl:text>): </xsl:text>
<xsl:value-of select="local:fixType(string(apidoc:return[not(@class) or @class = 'javascript']))"/>
<xsl:text>;&#10;&#10;</xsl:text>
</xsl:template>

<xsl:template match="/">
<xsl:variable name="root" select="."/>

<xsl:text>// Type definitions for </xsl:text><xsl:value-of select="apidoc:module/@name"/><xsl:text>&#10;</xsl:text>
<xsl:text>// Definitions: </xsl:text><xsl:value-of select="base-uri(.)"/><xsl:text>&#10;&#10;</xsl:text>

<xsl:text>/**</xsl:text>
<xsl:value-of select="apidoc:module/apidoc:summary[not(@class) or @class = 'javascript']"/>
<xsl:text>**/&#10;&#10;</xsl:text>

<xsl:for-each select="distinct-values(((apidoc:module/@lib, 'xdmp')[1], //apidoc:function[empty(@http-verb)]/@lib))">
<xsl:variable name="lib" select="."/>
<xsl:variable name="name" select="local:fixName($lib)"/>
<xsl:variable name="name" select="local:fixName($lib)"/>

<xsl:choose>
<xsl:when test="$name = 'alert'">
<xsl:text>declare module </xsl:text>
<xsl:value-of select="$name"/>
<xsl:text> {{&#10;&#10;</xsl:text>

<xsl:apply-templates select="$root//apidoc:function[@lib = $lib][empty(@http-verb)][not(@class) or @class = 'javascript']">
<xsl:with-param name="use-function-keyword" select="true()"/>
</xsl:apply-templates>

<xsl:text>}}&#10;</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:text>interface </xsl:text>
<xsl:value-of select="$name"/>
<xsl:text>Functions {{&#10;&#10;</xsl:text>

<xsl:apply-templates select="$root//apidoc:function[@lib = $lib][empty(@http-verb)][not(@class) or @class = 'javascript']"/>

<xsl:text>}}&#10;</xsl:text>

<xsl:text>declare var </xsl:text>
<xsl:value-of select="$name"/>
<xsl:text>:</xsl:text>
Expand All @@ -91,32 +86,77 @@ let $definition := xdmp:xslt-eval(
</xsl:choose>
</xsl:for-each>
</xsl:template>

<xsl:function name="local:fixType">
<xsl:param name="type"/>
<xsl:param name="pType"/>

<xsl:variable name="quantifier" select="replace($type, '^.+([?+*])?$', '$1')"/>
<xsl:variable name="type" select="replace($type, '^(.+)[?+*]$', '$1')"/>
<xsl:variable name="preType" select="replace(replace($pType, '^(.+)[?+*](,\.\.\.)?$', '$1'), ' ', '')"/>
<xsl:variable name="type" select="if (substring($preType, 1, 1) = '(') then substring($preType, 2, string-length($preType) - 2) else $preType"/>

<xsl:value-of select="local:fixEachType($type)"/>
</xsl:function>

<xsl:function name="local:fixEachType">
<xsl:param name="typeUnion"/>

<xsl:variable name="type" select="substring-before(concat($typeUnion,'|'),'|')"/>

<xsl:choose>
<xsl:when test="$type = ('binary()', 'document-node()', 'element()', 'node()')">Node</xsl:when>
<xsl:when test="$type = 'empty-sequence()'">void</xsl:when>
<xsl:when test="$type = ('String', 'item()', 'xs:anyURI', 'xs:string', 'xs:time', 'xs:unsignedLong', '(cts:order|xs:string)')">string</xsl:when>
<xsl:when test="$type = 'json:array'">Array&lt;any&gt;</xsl:when>
<xsl:when test="$type = ('json:object', 'map:map', '(element()|map:map)', 'xdmp:function')">Object</xsl:when>
<xsl:when test="$type = ('function()', 'function(*)')">() => any</xsl:when>
<xsl:when test="$type = 'xs:dateTime'">Date</xsl:when>
<xsl:when test="$type = ('Int', 'xs:decimal', 'xs:double', 'xs:float', 'xs:integer', 'xs:long', 'xs:positiveInteger', 'xs:unsignedInt')">number</xsl:when>
<xsl:when test="matches($type, '^(schema-)?[Ee]lement\([^)]+\)$')">Node</xsl:when>
<!-- generic fallback -->
<xsl:when test="$type = ('document-node()')">DocumentNode&lt;any&gt;</xsl:when>
<xsl:when test="$type = ('binary()', 'element()', 'node()')">MLNode&lt;any&gt;</xsl:when>
<xsl:when test="$type = ('empty-sequence()', 'Null')">void</xsl:when>
<xsl:when test="$type = ('String', 'item()', 'xs:anyURI', 'xs:NCName', 'xs:string', 'xs:time', 'xs:unsignedLong', 'xs:duration', 'xs:dayTimeDuration')">string</xsl:when>
<xsl:when test="$type = ('json:array', 'Array')">Array&lt;any&gt;</xsl:when>
<xsl:when test="$type = 'ValueIterator'">ValueIterator&lt;any&gt;</xsl:when>
<xsl:when test="$type = ('json:object', 'map:map')">&#123;&#91;key:string&#93;:any&#125;</xsl:when>
<xsl:when test="$type = ('function()', 'xdmp:function', 'function(*', 'function(*)')">() => any</xsl:when>
<xsl:when test="$type = 'xs:boolean'">boolean</xsl:when>
<xsl:when test="$type = 'xs:anyAtomicType'">any</xsl:when>
<xsl:when test="$type = ('xs:dateTime', 'xs:date')">Date</xsl:when>
<xsl:when test="$type = ('Int', 'double', 'xs:numeric', 'numeric', 'xs:decimal', 'xs:double', 'xs:int', 'xs:float', 'xs:integer', 'xs:long', 'xs:nonNegativeInteger', 'xs:positiveInteger', 'xs:unsignedInt')">number</xsl:when>
<xsl:when test="matches($type, '^(schema-)?[Ee]lement\([^)]+\)$')">MLNode&lt;any&gt;</xsl:when>
<xsl:when test="matches($type, '^function\(')">
<xsl:value-of select="local:fixFunctionType($type)"/>
</xsl:when>
<xsl:otherwise>
<!--xsl:variable name="local-name" select="replace($type, '^([^:]+:)?(.+)$', '$2')"/>
<xsl:value-of select="concat(upper-case(substring($local-name, 1, 1)), substring($local-name, 2))"/-->
<xsl:text>Object</xsl:text>
<xsl:variable name="local-name" select="replace($type, '^([^:.]+[:.])?([^\(\)]+)\(?\)?$', '$2')"/>
<xsl:variable name="fixed-local-name" select="string-join(local:fixName($local-name), '')"/>
<xsl:variable name="type-name" select="concat(upper-case(substring($fixed-local-name, 1, 1)), substring($fixed-local-name, 2))"/>
<xsl:choose>
<xsl:when test="contains($type, ':') or contains($type, '.')">
<xsl:variable name="prefix-name" select="replace($type, '^([^:.]+[:.])?(.+)$', '$1')"/>
<xsl:value-of select="concat(substring($prefix-name, 1, string-length($prefix-name) - 1), concat('.', $type-name))"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$type-name"/>
</xsl:otherwise>
</xsl:choose>
</xsl:otherwise>
</xsl:choose>
<xsl:if test="contains($typeUnion, '|')">
<xsl:value-of select="concat('|', string-join(local:fixEachType(substring-after($typeUnion, '|')), ''))"/>
</xsl:if>
</xsl:function>


<xsl:function name="local:fixFunctionType">
<xsl:param name="type"/>
<xsl:text>(</xsl:text>
<xsl:value-of select="local:fixParameters(replace($type, '^function\((.+)\)as(.+)?$', '$1'), 1)"/>
<xsl:text>)=&gt;</xsl:text>
<xsl:value-of select="local:fixType(replace($type, '^function\((.+)\)as(.+)?$', '$2'))"/>
</xsl:function>

<xsl:function name="local:fixParameters">
<xsl:param name="parameters"/>
<xsl:param name="number"/>
<xsl:value-of select="concat(concat('p', $number), ':')"/>
<xsl:variable name="type" select="substring-before(concat($parameters,','),',')"/>
<xsl:value-of select="local:fixType($type)"/>
<xsl:if test="contains($parameters, ',')">
<xsl:value-of select="concat(',', string-join(local:fixParameters(substring-after($parameters, ','), $number + 1), ''))"/>
</xsl:if>
</xsl:function>

<xsl:function name="local:fixName">
<xsl:param name="name"/>

Expand All @@ -143,10 +183,7 @@ let $definition := xdmp:xslt-eval(
</xsl:otherwise>
</xsl:choose>
</xsl:function>

</xsl:stylesheet>, $xml)

(:
return xdmp:save(concat(replace($docs-dir, 'xml/$', 'ts/'), replace($file, '\.xml$', ''), '.d.ts'), $definition)
:)
return $definition

return $definition
Loading

0 comments on commit 814def5

Please sign in to comment.