Skip to content

Commit

Permalink
Ensure object generation is correct
Browse files Browse the repository at this point in the history
  • Loading branch information
Christy Haragan committed Oct 10, 2015
1 parent 814def5 commit f8d1c2c
Show file tree
Hide file tree
Showing 72 changed files with 4,290 additions and 4,206 deletions.
42 changes: 34 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,27 +1,53 @@
# marklogic-typescript-definitions
TypeScript Definition files for MarkLogic built-in functions, available as npm module
TypeScript definition files for MarkLogic server-side-javascript functions and types, available as npm an module.

For the node.js client definitions try the [marklogic-node-typescript-definitions](https://github.com/christyharagan/marklogic-node-typescript-definitions) package

## Usage

Install these files as nodejs dependency using npm:
Install these files as node.js dependency using npm:

```
npm install marklogic-typescript-definitions --save
```

TypeScript enabled editors should pick up the TypeScript definition files automatically
To use the definitions, modify your ```tsconfig.json``` file, adding the following entry to the ```files``` section:

```
node_modules/marklogic-typescript-definitions/ts/index.d.ts
```

So, for example, your ```tsconfig.json``` file might look like:

```json
{
"compilerOptions": {
"module": "commonjs",
"target": "es5",
},
"files": [
"./lib/myCode.ts",
"./node_modules/marklogic-typescript-definitions/ts/index.d.ts"
]
}
```

## Suggested TypeScript Editors

Below are two suggested TypeScript editors:

## Editor
- (Visual Studio Code)[https://code.visualstudio.com/] runs out of the box with TypeScript support.
- (Atom)[https://atom.io/] also provides good support (if not better), but requires installation of the ```atom-typescript``` plugin.

- (Visual Studio Code)[https://code.visualstudio.com/] runs out of the box with this.
- (Atom)[https://atom.io/] also provides good support (if not better), but requires installation of a TypeScript plugin.
## Building the TypeScript definitions

## Building the typescript definitions
The git repository (and npm package) contains the built definitions. If you'd like to re-build them, perform the following:

- 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/
- Delete the files listed below
- Run `npm install`
- Run `gulp` (may take a few minutes)

Expand All @@ -31,7 +57,7 @@ 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
#### XML files to delete
Before trying to build, remove the following xml files (as some of these are xquery only modules):

- admin
Expand Down
48 changes: 27 additions & 21 deletions gulpfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ var fs = require('fs');
var request = require('request');
var through = require('through2');
var typescript = require('gulp-tsc');
var concat = require('gulp-concat');
var File = require('vinyl');

var onError = function(err) {
if (err) {
Expand All @@ -23,21 +25,17 @@ var options = {
mlPass: argv['ml-pass'] || 'passw0rd'
};

var createAddHeader = function(){
return through.obj(function(file){
file.contents = new Buffer('///<reference path="./types.d.ts" />\n' + file.contents.toString())
this.push(file)
})
}

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 createProcessXML = function(){
var query = fs.readFileSync('qconsole/generate-definitions.xqy').toString();

return through.obj(function (file, enc, cb) {
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');

Expand All @@ -54,25 +52,33 @@ gulp.task('generate', function(){
sendImmediately: false
}
}, function(err, httpResponse, body) {
//console.log(body);
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);
console.log(file.path)
cb(new Error(body))
} else {
fs.writeFile(outFile, body, onError);
cb(null, new File({
base: file.base,
path: file.path.replace('/xml/', '/ts/').replace('.xml', '.d.ts'),
contents: new Buffer(body)
}));
}

cb(null, file);
} catch (e) {
console.log(e);
}
});
}));
});
}

gulp.task('generate', function(){
return gulp.src(['xml/**/*.xml'])
.pipe(createProcessXML())
.pipe(concat('functions.d.ts'))
.pipe(createAddHeader())
.pipe(gulp.dest('./ts/'));
});

gulp.task('validate', ['generate'], function(){
Expand Down
7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
{
"name": "marklogic-typescript-definitions",
"version": "0.2.0",
"version": "0.3.0",
"description": "TypeScript Definition files for MarkLogic built-in functions",
"author": "Geert Josten <[email protected]>",
"contributors": [
{ "name" : "Christy Haragan",
{
"name": "Christy Haragan",
"email": "[email protected]",
"url": "https://github.com/christyharagan"
}
],
"typings": "./ts/index.d.ts",
"keywords": [
"typescript",
"marklogic"
Expand All @@ -19,6 +19,7 @@
"gulp-tsc": "^1.1.1",
"request": "^2.62.0",
"through2": "^2.0.0",
"vinyl": "^1.0.0",
"yargs": "^3.25.0"
},
"engine": "node >= 0.4.1",
Expand Down
92 changes: 74 additions & 18 deletions qconsole/generate-definitions.xqy
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,12 @@ let $definition := xdmp:xslt-eval(
<xsl:if test="preceding-sibling::apidoc:param[not(@class) or @class = 'javascript'][@name = current()/@name]">2</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:value-of select="local:fixType(@type, true())"/>
<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:value-of select="local:fixType(string(apidoc:return[not(@class) or @class = 'javascript']), false())"/>
<xsl:text>;&#10;&#10;</xsl:text>
</xsl:template>

Expand Down Expand Up @@ -89,34 +89,82 @@ let $definition := xdmp:xslt-eval(

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

<xsl:variable name="preType" select="replace(replace($pType, '^(.+)[?+*](,\.\.\.)?$', '$1'), ' ', '')"/>
<xsl:variable name="preTypeAndCardinality" select="replace(replace($pType, '^([^,]+)(,\.\.\.)?$', '$1'), ' ', '')"/>
<xsl:variable name="lastCharacter" select="substring($preTypeAndCardinality, string-length($preTypeAndCardinality))"/>
<xsl:variable name="preType" select="if (matches($lastCharacter, '^[?*+]$')) then substring($preTypeAndCardinality, 1, string-length($preTypeAndCardinality) - 1) else $preTypeAndCardinality"/>
<xsl:variable name="isArray" select="matches($lastCharacter, '^[*+]$')"/>
<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:value-of select="local:fixEachType($type, $isArray, $isForParameter)"/>
</xsl:function>

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

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

<xsl:choose>
<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="matches($type, '^function\(.*\)as(.+)$')">
<xsl:value-of select="local:fixFunctionType($type, $isArray)"/>
</xsl:when>
<xsl:when test="$isArray">
<xsl:choose>
<xsl:when test="$type = ('document-node()', 'binary()', 'element()', 'node()')">
<xsl:value-of select="local:fixArrayType('any', $isForParameter)"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="local:fixArrayType(string-join(local:fixSingleType($type, $isForParameter), ''), $isForParameter)"/>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="local:fixSingleType($type, $isForParameter)"/>
</xsl:otherwise>
</xsl:choose>

<xsl:if test="contains($typeUnion, '|')">
<xsl:value-of select="concat('|', string-join(local:fixEachType(substring-after($typeUnion, '|'), $isArray, $isForParameter), ''))"/>
</xsl:if>
</xsl:function>

<xsl:function name="local:fixArrayType">
<xsl:param name="type"/>
<xsl:param name="isForParameter"/>
<xsl:value-of select="concat(concat(if($isForParameter) then 'MLArray&lt;' else 'ValueIterator&lt;', $type), '&gt;')"/>
</xsl:function>

<xsl:function name="local:fixSingleType">
<xsl:param name="type"/>
<xsl:param name="isForParameter"/>
<xsl:choose>
<xsl:when test="$type = 'ValueIterator'">ValueIterator&lt;any&gt;</xsl:when>
<xsl:when test="$type = 'document-node()'">DocumentNode&lt;any&gt;</xsl:when>
<xsl:when test="$type = ('binary()')">MLNode&lt;any&gt;</xsl:when>
<xsl:when test="$type = ('element()', 'node()', 'item()')">
<xsl:choose>
<xsl:when test="$isForParameter">MLNodeOrObject&lt;any&gt;</xsl:when>
<xsl:otherwise>MLNode&lt;any&gt;</xsl:otherwise>
</xsl:choose>
</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 = ('String', 'xs:anyURI', 'xs:NCName', 'xs:string', 'xs:time', '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 test="$type = ('Int', 'double', 'xs:numeric', 'numeric', 'xs:decimal', 'xs:double', 'xs:unsignedLong', '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\([^)]+\)$')">
<xsl:choose>
<!-- TODO: Can we perform generics on this? -->
<xsl:when test="$isForParameter">MLNodeOrObject&lt;any&gt;</xsl:when>
<xsl:otherwise>MLNode&lt;any&gt;</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:otherwise>
<xsl:variable name="local-name" select="replace($type, '^([^:.]+[:.])?([^\(\)]+)\(?\)?$', '$2')"/>
Expand All @@ -133,25 +181,33 @@ let $definition := xdmp:xslt-eval(
</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:param name="isArray"/>
<xsl:text>(</xsl:text>
<xsl:value-of select="local:fixParameters(replace($type, '^function\((.+)\)as(.+)?$', '$1'), 1)"/>
<xsl:if test="matches($type, '^function\((.+)\)as(.+)$')">
<xsl:value-of select="local:fixParameters(replace($type, '^function\((.+)\)as(.+)$', '$1'), 1)"/>
</xsl:if>
<xsl:text>)=&gt;</xsl:text>
<xsl:value-of select="local:fixType(replace($type, '^function\((.+)\)as(.+)?$', '$2'))"/>
<xsl:variable name="returnType" select="local:fixType(replace($type, '^function\(.*\)as(.+)$', '$1'), false())"/>
<xsl:choose>
<xsl:when test="$isArray">
<xsl:value-of select="local:fixArrayType($returnType, false())"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$returnType"/>
</xsl:otherwise>
</xsl:choose>
</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:value-of select="local:fixType($type, true())"/>
<xsl:if test="contains($parameters, ',')">
<xsl:value-of select="concat(',', string-join(local:fixParameters(substring-after($parameters, ','), $number + 1), ''))"/>
</xsl:if>
Expand Down
42 changes: 0 additions & 42 deletions ts/AccessorBuiltins.d.ts

This file was deleted.

Loading

0 comments on commit f8d1c2c

Please sign in to comment.