├── test ├── testData │ ├── errorApp.as │ └── testApp.as └── flex_test.js ├── .travis.yml ├── .gitignore ├── .jshintrc ├── .npmignore ├── bin └── mxmlc ├── LICENSE-MIT ├── Gruntfile.js ├── lib └── flex.js ├── install.js ├── package.json ├── FlexSDKs.md ├── README.md └── prepublish.js /test/testData/errorApp.as: -------------------------------------------------------------------------------- 1 | package { 2 | public class errorApp { 3 | public function die():String { 4 | undefinedMethod(); 5 | } 6 | } 7 | } -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "0.10" 4 | before_install: 5 | - npm update -g npm 6 | - npm install -g grunt-cli 7 | 8 | sudo: false 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | lib-cov 2 | *.seed 3 | *.log 4 | *.csv 5 | *.dat 6 | *.out 7 | *.pid 8 | *.gz 9 | 10 | pids 11 | logs 12 | results 13 | 14 | npm-debug.log 15 | node_modules 16 | lib/flex_sdk 17 | -------------------------------------------------------------------------------- /test/testData/testApp.as: -------------------------------------------------------------------------------- 1 | package { 2 | public class testApp { 3 | public function sayHello():String { 4 | var greeting:String = "Hello World!"; 5 | return greeting; 6 | } 7 | } 8 | } -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "curly": true, 3 | "eqeqeq": true, 4 | "immed": true, 5 | "latedef": true, 6 | "newcap": true, 7 | "noarg": true, 8 | "sub": true, 9 | "undef": true, 10 | "boss": true, 11 | "eqnull": true, 12 | "node": true 13 | } 14 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | *.seed 2 | *.log 3 | *.csv 4 | *.dat 5 | *.out 6 | *.pid 7 | *.gz 8 | npm-debug.log 9 | prepublish.log 10 | .gitignore 11 | .gitattributes 12 | .jshintrc 13 | .npmignore 14 | .travis.yml 15 | FlexSDKs.md 16 | Gruntfile.js 17 | prepublish.js 18 | 19 | lib-cov 20 | pids 21 | logs 22 | results 23 | node_modules 24 | test 25 | tests 26 | lib/flex_sdk/runtimes 27 | lib/flex_sdk/frameworks/libs/player/*/ -------------------------------------------------------------------------------- /bin/mxmlc: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | var path = require('path'); 4 | var spawn = require('child_process').spawn; 5 | 6 | var mxmlcPath = require('../lib/flex').bin.mxmlc; 7 | 8 | var args = process.argv.slice(2); 9 | 10 | // For Node 0.6 compatibility, pipe the streams manually, instead of using 11 | // `{ stdio: 'inherit' }`. 12 | var cp = spawn(mxmlcPath, args); 13 | cp.stdout.pipe(process.stdout); 14 | cp.stderr.pipe(process.stderr); 15 | cp.on('exit', process.exit); 16 | 17 | process.on('SIGTERM', function() { 18 | cp.kill('SIGTERM'); 19 | process.exit(1); 20 | }); 21 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013 James M. Greene 2 | 3 | Permission is hereby granted, free of charge, to any person 4 | obtaining a copy of this software and associated documentation 5 | files (the "Software"), to deal in the Software without 6 | restriction, including without limitation the rights to use, 7 | copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the 9 | Software is furnished to do so, subject to the following 10 | conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = function(grunt) { 4 | 5 | // Project configuration. 6 | grunt.initConfig({ 7 | // Metadata. 8 | pkg: grunt.file.readJSON('package.json'), 9 | banner: '/*! <%= pkg.title || pkg.name %> - v<%= pkg.version %> - ' + 10 | '<%= grunt.template.today("yyyy-mm-dd") %>\n' + 11 | '<%= pkg.homepage ? "* " + pkg.homepage + "\\n" : "" %>' + 12 | '* Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author.name %>;' + 13 | ' Licensed <%= _.pluck(pkg.licenses, "type").join(", ") %> */\n', 14 | // Task configuration. 15 | jshint: { 16 | options: { 17 | jshintrc: true 18 | }, 19 | all: ['*.js', 'lib/*.js', 'test/**/*.js'] 20 | }, 21 | nodeunit: { 22 | all: ['test/**/*_test.js'] 23 | } 24 | }); 25 | 26 | // These plugins provide necessary tasks. 27 | grunt.loadNpmTasks('grunt-contrib-jshint'); 28 | grunt.loadNpmTasks('grunt-contrib-nodeunit'); 29 | 30 | // Default task. 31 | grunt.registerTask('default', ['jshint', 'nodeunit']); 32 | 33 | // Travis CI task. 34 | grunt.registerTask('travis', ['jshint', 'nodeunit']); 35 | 36 | }; 37 | -------------------------------------------------------------------------------- /lib/flex.js: -------------------------------------------------------------------------------- 1 | /* 2 | * flex-sdk 3 | * https://github.com/JamesMGreene/node-flex-sdk 4 | * 5 | * Copyright (c) 2013 James M. Greene 6 | * Licensed under the MIT license. 7 | */ 8 | 9 | 'use strict'; 10 | 11 | var fs = require('fs'); 12 | var path = require('path'); 13 | var FLEX_HOME = path.join(__dirname, 'flex_sdk'); 14 | var binDir = path.join(FLEX_HOME, 'bin'); 15 | 16 | var flexSdk = { 17 | FLEX_HOME: FLEX_HOME, 18 | binDir: binDir, 19 | bin: {}, 20 | refresh: function() { 21 | // Clear any existing bin mapping 22 | Object.keys(flexSdk.bin).forEach(function(binKey) { 23 | delete flexSdk.bin[binKey]; 24 | }); 25 | 26 | // Add binary executables to the bin mapping 27 | if (fs.existsSync(flexSdk.binDir)) { 28 | var files = fs.readdirSync(flexSdk.binDir); 29 | var winExecFiles = files.filter(function(filename) { 30 | var ext = filename.slice(-4).toLowerCase(); 31 | return ext === '.bat' || ext === '.exe'; 32 | }); 33 | if (process.platform === 'win32') { 34 | winExecFiles.forEach(function(binFilename) { 35 | var binKey = binFilename.slice(0, -4); 36 | flexSdk.bin[binKey] = path.join(binDir, binFilename); 37 | }); 38 | } 39 | else { 40 | var execFiles = winExecFiles.map(function(binFilename) { 41 | return binFilename.slice(0, -4); 42 | }); 43 | execFiles.forEach(function(binFilename) { 44 | flexSdk.bin[binFilename] = path.join(binDir, binFilename); 45 | }); 46 | } 47 | } 48 | } 49 | }; 50 | 51 | // Load the initial bin mapping 52 | flexSdk.refresh(); 53 | 54 | module.exports = flexSdk; -------------------------------------------------------------------------------- /install.js: -------------------------------------------------------------------------------- 1 | /* 2 | * flex-sdk 3 | * https://github.com/JamesMGreene/node-flex-sdk 4 | * 5 | * Copyright (c) 2013 James M. Greene 6 | * Licensed under the MIT license. 7 | */ 8 | 9 | /* 10 | * This simply corrects the execute permissions on the SDK binaries. 11 | */ 12 | 13 | 'use strict'; 14 | 15 | var playerGlobal = require('playerglobal-latest'); 16 | var flexSdk = require('./lib/flex'); 17 | var fs = require('fs'); 18 | var path = require('path'); 19 | var mkdirp = require('mkdirp'); 20 | 21 | // Ensure that the binaries are user-executable (i.e. Linux shell scripts if published from Windows) 22 | if (process.platform !== 'win32') { 23 | Object.keys(flexSdk.bin).forEach(function(binKey) { 24 | var binaryPath = flexSdk.bin[binKey]; 25 | var stat = fs.statSync(binaryPath); 26 | // 64 === 0100 (no octal literal in strict mode) 27 | if (!(stat.mode & 64)) { 28 | console.log('Fixing file permissions for: ' + binaryPath); 29 | fs.chmodSync(binaryPath, '755'); 30 | } 31 | }); 32 | } 33 | 34 | var flashApiLibDir = path.join(flexSdk.FLEX_HOME, 'frameworks', 'libs', 'player'); 35 | mkdirp(flashApiLibDir, function(err) { 36 | if (err) { 37 | console.error('Failed to install the latest "playerglobal.swc" library collection!\nError: ' + err); 38 | process.exit(1); 39 | } 40 | 41 | // Copy all of the Flash API libraries into the Flex SDK folder 42 | playerGlobal.install(flexSdk.FLEX_HOME, function(err) { 43 | if (err) { 44 | console.error('Failed to install the latest "playerglobal.swc" library collection!\nError: ' + err); 45 | } 46 | else { 47 | console.log('Successfully installed the latest "playerglobal.swc" library collection.'); 48 | } 49 | process.exit(err ? 1 : 0); 50 | }); 51 | }); -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "flex-sdk", 3 | "description": "A Node.js module to download and \"install\" the latest open source Apache/Adobe Flex SDK.", 4 | "version": "4.6.0-0", 5 | "flexSdk": { 6 | "url": "http://fpdownload.adobe.com/pub/flex/sdk/builds/flex4.6/flex_sdk_4.6.0.23201_mpl.zip" 7 | }, 8 | "homepage": "https://github.com/JamesMGreene/node-flex-sdk", 9 | "author": { 10 | "name": "James M. Greene", 11 | "email": "james.m.greene@gmail.com", 12 | "url": "http://jamesgreene.net/" 13 | }, 14 | "repository": { 15 | "type": "git", 16 | "url": "git://github.com/JamesMGreene/node-flex-sdk.git" 17 | }, 18 | "bugs": { 19 | "url": "https://github.com/JamesMGreene/node-flex-sdk/issues" 20 | }, 21 | "licenses": [ 22 | { 23 | "type": "MIT", 24 | "url": "https://github.com/JamesMGreene/node-flex-sdk/blob/master/LICENSE-MIT" 25 | } 26 | ], 27 | "engines": { 28 | "node": ">= 0.8.0" 29 | }, 30 | "main": "lib/flex", 31 | "bin": { 32 | "mxmlc": "./bin/mxmlc" 33 | }, 34 | "scripts": { 35 | "prepublish": "node prepublish.js; if [ \"$npm_package_config_npm_cmd_ran\" == \"install\" ]; then npm run-script postinstall; fi; npm config delete $npm_package_name:npm_cmd_ran", 36 | "preinstall": "npm install playerglobal-latest", 37 | "install": "npm config set $npm_package_name:npm_cmd_ran install", 38 | "postinstall": "node install.js", 39 | "test": "grunt travis --verbose" 40 | }, 41 | "dependencies": { 42 | "playerglobal-latest": "^0.1.6", 43 | "mkdirp": "^0.3.5" 44 | }, 45 | "devDependencies": { 46 | "grunt-contrib-jshint": "^0.10.0", 47 | "grunt-contrib-nodeunit": "^0.3.3", 48 | "grunt": "^0.4.4", 49 | "download": "^0.1.12", 50 | "rimraf": "^2.2.6", 51 | "dos2unix": "^1.1.1", 52 | "async": "^0.6.2" 53 | }, 54 | "keywords": [ 55 | "download", 56 | "install", 57 | "apache", 58 | "adobe", 59 | "flex sdk", 60 | "open source", 61 | "compiler", 62 | "flex", 63 | "mxml", 64 | "actionscript", 65 | "flv", 66 | "flash", 67 | "air" 68 | ] 69 | } 70 | -------------------------------------------------------------------------------- /FlexSDKs.md: -------------------------------------------------------------------------------- 1 | # Apache/Adobe Flex SDK 2 | The following are the URLs used to download the open sourced 3 | Flex SDK for each version number of Apache/Adobe Flex. 4 | 5 | ## Apache Flex SDK v4.8.x+ 6 | - **4.12.0**: http://archive.apache.org/dist/flex/4.12.0/binaries/apache-flex-sdk-4.12.0-bin.zip 7 | - **4.11.0**: http://archive.apache.org/dist/flex/4.11.0/binaries/apache-flex-sdk-4.11.0-bin.zip 8 | - **4.10.0**: http://archive.apache.org/dist/flex/4.10.0/binaries/apache-flex-sdk-4.10.0-bin.zip 9 | - **4.9.1**: http://archive.apache.org/dist/flex/4.9.1/binaries/apache-flex-sdk-4.9.1-bin.zip 10 | - **4.9.0**: http://archive.apache.org/dist/flex/4.9.0/binaries/apache-flex-sdk-4.9.0-bin.zip 11 | - **4.8.0**: http://archive.apache.org/dist/incubator/flex/4.8.0-incubating/binaries/apache-flex-sdk-4.8.0-incubating-bin.zip 12 | 13 | ## Adobe Flex SDK v4.x.x 14 | - **4.6.0**: http://fpdownload.adobe.com/pub/flex/sdk/builds/flex4.6/flex_sdk_4.6.0.23201_mpl.zip 15 | - **4.5.1**: http://fpdownload.adobe.com/pub/flex/sdk/builds/flex4.5/flex_sdk_4.5.1.21328A_mpl.zip 16 | - **4.5.0**: http://fpdownload.adobe.com/pub/flex/sdk/builds/flex4.5/flex_sdk_4.5.0.20967A_mpl.zip 17 | - **4.1.0**: http://fpdownload.adobe.com/pub/flex/sdk/builds/flex4/flex_sdk_4.1.0.16076A_mpl.zip 18 | - **4.0.0**: http://fpdownload.adobe.com/pub/flex/sdk/builds/flex4/flex_sdk_4.0.0.14159A_mpl.zip 19 | 20 | ## Adobe Flex SDK v3.x.x 21 | - **3.6.0:** http://fpdownload.adobe.com/pub/flex/sdk/builds/flex3/flex_sdk_3.6.0.16995A_mpl.zip 22 | - **3.5.0:** http://fpdownload.adobe.com/pub/flex/sdk/builds/flex3/flex_sdk_3.5.0.12683B_mpl.zip 23 | - **3.4.1:** http://fpdownload.adobe.com/pub/flex/sdk/builds/flex3/flex_sdk_3.4.1.10084A_mpl.zip 24 | - **3.4.0:** http://fpdownload.adobe.com/pub/flex/sdk/builds/flex3/flex_sdk_3.4.0.9271A_mpl.zip 25 | - **3.3.0:** http://fpdownload.adobe.com/pub/flex/sdk/builds/flex3/flex_sdk_3.3.0.4852A_mpl.zip 26 | - **3.2.0:** http://fpdownload.adobe.com/pub/flex/sdk/builds/flex3/flex_sdk_3.2.0.3958A_mpl.zip 27 | - **3.1.0:** http://fpdownload.adobe.com/pub/flex/sdk/builds/flex3/flex_sdk_3.1.0.2710A_mpl.zip 28 | - **3.0.1:** http://fpdownload.adobe.com/pub/flex/sdk/builds/flex3/flex_sdk_3.0.1.1092A_mpl.zip 29 | - **3.0.0:** http://fpdownload.adobe.com/pub/flex/sdk/builds/flex3/flex_sdk_3.0.0.477A_mpl.zip 30 | 31 | 32 | ## Source 33 | Data was retrieved from: 34 | 1. the [Apache Flex site][flex/apache/site], and specifically the download page(s) for: 35 | - [Flex 4.9][flex/apache/downloads] 36 | 2. the [Adobe Flex SDK wiki][flex/adobe/wiki]'s ["Downloads" page][flex/adobe/downloads/toc], 37 | and specifically from the individual download page(s) for: 38 | - [Flex 4.6][flex/adobe/downloads/4.6] 39 | - [Flex 4.5][flex/adobe/downloads/4.5] 40 | - [Flex 4][flex/adobe/downloads/4] 41 | - [Flex 3][flex/adobe/downloads/3] 42 | 3. the [Adobe OpenSource SVN for the Flex SDK][flex/adobe/svn], specifically to figure out 43 | which build version of Flex 3.0.1 should be available for download 44 | 45 | 46 | 47 | [flex/apache/site]: http://flex.apache.org/index.html 48 | [flex/apache/downloads]: http://flex.apache.org/download-binaries.html 49 | [flex/adobe/wiki]: http://sourceforge.net/adobe/flexsdk/wiki/ 50 | [flex/adobe/downloads/toc]: http://sourceforge.net/adobe/flexsdk/wiki/Downloads/ 51 | [flex/adobe/downloads/4.6]: http://sourceforge.net/adobe/flexsdk/wiki/Download%20Flex%204.6/ 52 | [flex/adobe/downloads/4.5]: http://sourceforge.net/adobe/flexsdk/wiki/Download%20Flex%204.5/ 53 | [flex/adobe/downloads/4]: http://sourceforge.net/adobe/flexsdk/wiki/Download%20Flex%204/ 54 | [flex/adobe/downloads/3]: http://sourceforge.net/adobe/flexsdk/wiki/Download%20Flex%203/ 55 | [flex/adobe/svn]: http://opensource.adobe.com/svn//opensource/flex/sdk/ 56 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Build Status](https://travis-ci.org/JamesMGreene/node-flex-sdk.png?branch=master)](https://travis-ci.org/JamesMGreene/node-flex-sdk) 2 | 3 | # flex-sdk 4 | 5 | An NPM wrapper for the [Apache Flex SDK][flex/apache/site] / [Adobe Flex SDK][flex/adobe/site]. 6 | 7 | 8 | ## Building and Installing 9 | 10 | ```shell 11 | npm install flex-sdk 12 | ``` 13 | 14 | Or grab the source and 15 | 16 | ```shell 17 | npm install . 18 | ``` 19 | 20 | What this is really doing is just grabbing a particular "blessed" (by this 21 | module) version of the Flex SDK. As new versions of the Apache/Adobe Flex 22 | SDK are released and vetted, this module will be updated accordingly. 23 | 24 | The package has been set up to fetch the Flex SDK and run `mxmlc` for MacOS (darwin), 25 | Linux based platforms (as identified by Node.js), and Windows. If you 26 | spot any platform weirdnesses, let me know or send a patch. 27 | 28 | 29 | ## External Dependencies 30 | 31 | If you intend to _use_ this module after it is installed, almost all of the Flex 32 | SDK binary/executable files have an implicit dependency on Java being installed 33 | on the system _and_ that it is available in the `PATH` such that it can be 34 | invoked just by typing the command `java`. 35 | 36 | 37 | ## Running 38 | 39 | ```shell 40 | bin/mxmlc [mxmlc arguments] 41 | ``` 42 | 43 | Check out the [full list of `mxmlc` command line options][flex/adobe/compiler-options] 44 | for more information. 45 | 46 | And npm will install a link to the binary in `node_modules/.bin` as 47 | it is wont to do. 48 | 49 | 50 | ## Running via node 51 | 52 | The package exports an object contains: 53 | - a `binDir` string which is the path to the "bin" directory of the Flex SDK 54 | - a `bin` object which contains an entry for each executable included in the 55 | "bin" directory of the Flex SDK (e.g. `flexSdk.bin.mxmlc` will provide the 56 | path to the `mxmlc` executable). 57 | - a `refresh` function if you ever need to refresh the `bin` object (e.g. if 58 | you have an existing `flex-sdk` module reference object but then downloaded a 59 | new Flex SDK). 60 | 61 | Below is an example of using this package via node. 62 | 63 | ```js 64 | var childProcess = require('child_process'); 65 | var flexSdk = require('flex-sdk'); 66 | var binPath = flexSdk.bin.mxmlc; 67 | 68 | var childArgs = [ 69 | 'arguments to pass to mxmlc', 70 | path.join(__dirname, 'fileToCompile.as') 71 | ]; 72 | 73 | childProcess.execFile(binPath, childArgs, function(err, stdout, stderr) { 74 | // handle results 75 | }); 76 | ``` 77 | 78 | 79 | # Versioning 80 | The NPM package version tracks the version of the Flex SDK that will be installed, 81 | with an additional build number that is used for revisions to the installer 82 | when necessary. 83 | 84 | As such, `4.6.0-0`, `4.6.0-1`, and `4.6.0-2` will all install Flex SDK v4.6.0 but each 85 | has newer changes to the installer than the previous. 86 | 87 | For the full list of available versions, see [FlexSDKs.md][flex/sdk-versions]. 88 | 89 | 90 | ## Purpose 91 | This is an _NPM wrapper_ and can be used to make the various binary executables 92 | from the Apache/Adobe Flex SDKs (e.g. `mxmlc`) conveniently available. 93 | It is not a Node.js wrapper. 94 | 95 | 96 | ## Contributing 97 | In lieu of a formal styleguide, take care to maintain the existing coding style. 98 | Add unit tests for any new or changed functionality. Lint and test your code 99 | using [Grunt][grunt/site]. 100 | 101 | 102 | ## Release History 103 | - Adobe Flex SDK v4.6.0 → `npm install flex-sdk@~4.6.0` 104 | - Adobe Flex SDK v4.5.1 → `npm install flex-sdk@~4.5.1` 105 | - Adobe Flex SDK v4.5.0 → `npm install flex-sdk@~4.5.0` 106 | - Adobe Flex SDK v4.1.0 → `npm install flex-sdk@~4.1.0` 107 | - Adobe Flex SDK v4.0.0 → `npm install flex-sdk@~4.0.0` 108 | - Adobe Flex SDK v3.6.0 → `npm install flex-sdk@~3.6.0` 109 | - Adobe Flex SDK v3.5.0 → `npm install flex-sdk@~3.5.0` 110 | - Adobe Flex SDK v3.4.1 → `npm install flex-sdk@~3.4.1` 111 | - Adobe Flex SDK v3.4.0 → `npm install flex-sdk@~3.4.0` 112 | - Adobe Flex SDK v3.3.0 → `npm install flex-sdk@~3.3.0` 113 | - Adobe Flex SDK v3.2.0 → `npm install flex-sdk@~3.2.0` 114 | - Adobe Flex SDK v3.1.0 → `npm install flex-sdk@~3.1.0` 115 | - Adobe Flex SDK v3.0.1 → `npm install flex-sdk@~3.0.1` 116 | - Adobe Flex SDK v3.0.0 → `npm install flex-sdk@~3.0.0` 117 | 118 | 119 | ## License 120 | Copyright (c) 2014 James M. Greene 121 | Licensed under the MIT license. 122 | 123 | 124 | 125 | [flex/apache/site]: http://flex.apache.org/index.html "Apache Flex" 126 | [flex/adobe/site]: http://www.adobe.com/devnet/flex.html "Adobe Flex" 127 | [flex/adobe/compiler-options]: http://livedocs.adobe.com/flex/3/html/help.html?content=compilers_14.html "mxmlc command line options" 128 | [flex/sdk-versions]: https://github.com/JamesMGreene/node-flex-sdk/blob/master/FlexSDKs.md "Flex SDK version list" 129 | [grunt/site]: (http://gruntjs.com/) "Grunt" 130 | -------------------------------------------------------------------------------- /prepublish.js: -------------------------------------------------------------------------------- 1 | /* 2 | * flex-sdk 3 | * https://github.com/JamesMGreene/node-flex-sdk 4 | * 5 | * Copyright (c) 2013 James M. Greene 6 | * Licensed under the MIT license. 7 | */ 8 | 9 | /* 10 | * This simply downloads the requested version of the Adobe Flex SDK. 11 | */ 12 | 13 | 'use strict'; 14 | 15 | var DEBUG_TRAVIS = false; 16 | var fs = require('fs'); 17 | var path = require('path'); 18 | fs.existsSync = fs.existsSync || path.existsSync; 19 | var async = require('async'); 20 | var download = require('download'); 21 | var rimraf = require('rimraf'); 22 | var mkdirp = require('mkdirp'); 23 | var D2UConverter = require('dos2unix').dos2unix; 24 | var pkgMeta = require('./package.json'); 25 | 26 | 27 | // IMPORTANT: 28 | // This `require` call MUST be done post-download because the export of this 29 | // module is dynamically created based on the executables present after 30 | // downloading and unzipping the relevant Flex SDK. 31 | // If the `require` call is done prior to the download completing, then the 32 | // module's `refresh` function must be invoked afterward to establish the 33 | // correct list of available binaries. 34 | var flexSdk = require('./lib/flex'); 35 | 36 | 37 | var libPath = path.join(__dirname, 'lib', 'flex_sdk'); 38 | var downloadUrl = pkgMeta.flexSdk.url; 39 | 40 | 41 | process.on('uncaughtException', function(err) { 42 | console.error('FATAL! Uncaught exception: ' + err); 43 | process.exit(1); 44 | }); 45 | 46 | 47 | function logErrorsToFile(errors, phase) { 48 | fs.writeFileSync(path.join(__dirname, 'prepublish.log'), JSON.stringify(errors, null, " ")); 49 | console.error('There were errors during the "' + phase + '"" phase. Check "prepublish.log" for more details!'); 50 | } 51 | 52 | 53 | function cleanDestination(done) { 54 | if (fs.existsSync(libPath)) { 55 | rimraf(libPath, function(err) { 56 | if (err) { 57 | return done(new Error('Error deleting library path: ' + libPath)); 58 | } 59 | mkdirp(libPath, done); 60 | }); 61 | } 62 | else { 63 | mkdirp(libPath, done); 64 | } 65 | } 66 | 67 | 68 | function downloadIt(done) { 69 | var notifiedCount = 0; 70 | var count = 0; 71 | var notificationChunkSize = 1024 * 1024; 72 | 73 | function onData(data) { 74 | count += data.length; 75 | if ((count - notifiedCount) > notificationChunkSize) { 76 | console.log('Received ' + (count / notificationChunkSize).toFixed(1) + ' MB...'); 77 | notifiedCount = count; 78 | } 79 | } 80 | 81 | function onError(err) { 82 | done(new Error('Error with HTTP request:\n' + err)); 83 | } 84 | 85 | function onClose() { 86 | console.log('Received ' + count + ' bytes total!'); 87 | done(); // Next! 88 | } 89 | 90 | function onResponse(response) { 91 | console.log('Receiving...'); 92 | 93 | if (response.statusCode !== 200) { 94 | done(new Error('Error with HTTP request:\n' + JSON.stringify(response.headers))); 95 | } 96 | } 97 | 98 | 99 | console.log('Requesting ' + downloadUrl); 100 | 101 | var downloader = download(downloadUrl, libPath, { extract: true }); 102 | downloader 103 | .on('response', onResponse) 104 | .on('data', onData) 105 | .on('error', onError) 106 | .on('close', onClose); 107 | } 108 | 109 | 110 | function refreshSdk(done) { 111 | // Start utilizing the API by refreshing its binary cache 112 | flexSdk.refresh(); 113 | 114 | done(); 115 | } 116 | 117 | 118 | function fixLineEndings(done) { 119 | console.log('Fixing line endings with the `dos2unix` Node module...'); 120 | 121 | // Convert all DOS line endings (CrLf) to UNIX line endings (Lf) 122 | var d2uOptions = { 123 | glob: { 124 | cwd: libPath 125 | }, 126 | maxConcurrency: 100 /* Only open a max of 100 files at once */ 127 | }; 128 | var conversionEndedAlready = false; 129 | var errors = []; 130 | var dos2unix = new D2UConverter(d2uOptions) 131 | .on('convert.error', function(err) { 132 | err.type = 'convert.error'; 133 | errors.push(err); 134 | }) 135 | .on('processing.error', function(err) { 136 | err.type = 'processing.error'; 137 | errors.push(err); 138 | }) 139 | .on('error', function(err) { 140 | console.error('Critical error while fixing line endings:\n' + (err.stack || err)); 141 | if (!conversionEndedAlready) { 142 | if (errors.length) { 143 | logErrorsToFile(errors, 'dos2unix'); 144 | } 145 | return done(new Error('Exiting prematurely...')); 146 | } 147 | }) 148 | .on('end', function(stats) { 149 | conversionEndedAlready = true; 150 | var err; 151 | if (errors.length || stats.error > 0) { 152 | logErrorsToFile(errors, 'dos2unix'); 153 | err = new Error('"dos2unix" processing completed but had errors'); 154 | } 155 | console.log('dos2unix conversion stats: ' + JSON.stringify(stats)); 156 | 157 | // Next! 158 | done(err); 159 | }); 160 | 161 | // DEBUGGING 162 | if (DEBUG_TRAVIS) { 163 | ['start', 'processing.start', 'processing.skip', 'convert.start', 'convert.end', 'processing.end'].forEach(function(e) { 164 | dos2unix.on(e, function() { 165 | var args = [].slice.call(arguments, 0); 166 | console.log('[DEBUG] dos2unix event: ' + JSON.stringify({ 'type': e, 'args': args }, null, ' ')); 167 | }); 168 | }); 169 | } 170 | 171 | dos2unix.process(['**/*']); 172 | } 173 | 174 | 175 | function fixJavaInvocationsForMac(done) { 176 | // Cleanup: RegExp stuff for finding and replacing 177 | var javaInvocationRegex = /^java .*\$VMARGS/m; 178 | var javaInvocationMatchingRegex = /^(java .*\$VMARGS)/mg; 179 | var javaInvocationReplacement = [ 180 | 'D32=""', 181 | 'D32_OVERRIDE=""', 182 | 'IS_OSX="`uname | grep -i Darwin`"', 183 | 'IS_JAVA64="`java -version 2>&1 | grep -i 64-Bit`"', 184 | 'JAVA_VERSION="`java -version 2>&1 | awk -F \'[ ".]+\' \'NR==1 {print $$3 "." $$4}\'`"', 185 | 'if [ "$$IS_OSX" != "" -a "$$HOSTTYPE" = "x86_64" -a "$$IS_JAVA64" != "" -a "$$JAVA_VERSION" = "1.6" ]; then', 186 | ' D32_OVERRIDE="-d32"', 187 | 'fi', 188 | 'VMARGS="$$VMARGS $$D32_OVERRIDE"', 189 | '', 190 | '$1' 191 | ].join('\n'); 192 | 193 | 194 | // Do the cleanup! 195 | Object.keys(flexSdk.bin).forEach(function(binKey) { 196 | var binaryPath = flexSdk.bin[binKey]; 197 | 198 | // Ensure that the Bash scripts are updated to work with 64-bit JREs on Mac 199 | var ext = binaryPath.slice(-4).toLowerCase(); 200 | if (ext !== '.bat' && ext !== '.exe') { 201 | var contents = fs.readFileSync(binaryPath, { encoding: 'utf8' }); 202 | // Rewrite any Java invocations to ensure they work on Mac 203 | if (contents.match(javaInvocationRegex)) { 204 | console.log('Fixing Java invocation for MacOSX in: ' + binaryPath); 205 | var cleanedContents = contents.replace(javaInvocationMatchingRegex, javaInvocationReplacement); 206 | fs.writeFileSync(binaryPath, cleanedContents, { encoding: 'utf8', mode: '755' }); 207 | } 208 | } 209 | }); 210 | 211 | done(); 212 | } 213 | 214 | 215 | function fixFilePermissions(done) { 216 | Object.keys(flexSdk.bin).forEach(function(binKey) { 217 | var binaryPath = flexSdk.bin[binKey]; 218 | 219 | // Ensure that the binaries are user-executable (problems with unzip library) 220 | var stat = fs.statSync(binaryPath); 221 | // 64 === 0100 (no octal literal in strict mode) 222 | if (!(stat.mode & 64)) { 223 | console.log('Fixing file permissions for: ' + binaryPath); 224 | fs.chmodSync(binaryPath, '755'); 225 | } 226 | }); 227 | 228 | done(); 229 | } 230 | 231 | 232 | // 233 | // Go! 234 | // 235 | async.series([ 236 | cleanDestination, 237 | downloadIt, 238 | refreshSdk, 239 | fixLineEndings, 240 | fixJavaInvocationsForMac, 241 | fixFilePermissions 242 | ], 243 | function (err) { 244 | if (err) { 245 | console.error(err + '\n'); 246 | } 247 | else { 248 | // VICTORY!!! 249 | console.log('SUCCESS! The Flex SDK binaries are available at:\n ' + flexSdk.binDir + '\n'); 250 | } 251 | process.exit(err ? 1 : 0); 252 | } 253 | ); -------------------------------------------------------------------------------- /test/flex_test.js: -------------------------------------------------------------------------------- 1 | // nodeunit-based Functionality Tests 2 | // tests require an active internet connection 3 | 4 | 'use strict'; 5 | 6 | var childProcess = require('child_process'); 7 | var fs = require('fs'); 8 | var path = require('path'); 9 | 10 | fs.existsSync = fs.existsSync || path.existsSync; 11 | 12 | var flexSdk = require('../lib/flex'); 13 | 14 | var safeDelete = function(path) { 15 | if (fs.existsSync(path)) { 16 | try { 17 | fs.unlinkSync(path); 18 | } 19 | catch (err) { 20 | // Swallow it 21 | } 22 | } 23 | }; 24 | 25 | module.exports = { 26 | 27 | testDownloadAndSdkExposure: function(test) { 28 | test.expect(8); 29 | 30 | test.ok(flexSdk.binDir, 'should have binary directory path set'); 31 | test.ok(fs.existsSync(flexSdk.binDir), 'should have binary directory path equal to an existing item'); 32 | test.ok(fs.statSync(flexSdk.binDir).isDirectory(), 'should have binary directory path equal to an existing DIRECTORY'); 33 | test.ok(flexSdk.bin, 'should have bin mapping object'); 34 | test.ok(Object.keys(flexSdk.bin).length > 0, 'should have at least 1 bin mapping entry'); 35 | test.ok(flexSdk.bin.mxmlc, 'should have bin mapping entry for `mxmlc`'); 36 | test.ok(fs.existsSync(flexSdk.bin.mxmlc), 'should have binary for `mxmlc` equal to an existing item'); 37 | test.ok(fs.statSync(flexSdk.bin.mxmlc).isFile(), 'should have binary for `mxmlc` equal to an existing FILE'); 38 | 39 | test.done(); 40 | }, 41 | 42 | testCompileSuccess: { 43 | setUp: function(done) { 44 | // Delete the binary 45 | var targetBinary = path.join(__dirname, 'testData', 'testApp.swf'); 46 | safeDelete(targetBinary); 47 | done(); 48 | }, 49 | tearDown: function(done) { 50 | // Delete the binary 51 | var targetBinary = path.join(__dirname, 'testData', 'testApp.swf'); 52 | safeDelete(targetBinary); 53 | done(); 54 | }, 55 | testIt: function(test) { 56 | test.expect(8); 57 | 58 | var executable = flexSdk.bin.mxmlc; 59 | var targetSource = path.join(__dirname, 'testData', 'testApp.as'); 60 | var targetBinary = path.join(__dirname, 'testData', 'testApp.swf'); 61 | 62 | var childArgs = [ 63 | '+configname=air', 64 | targetSource 65 | ]; 66 | 67 | // Hack for non-Windows boxes 68 | if (process.platform !== 'win32') { 69 | childArgs.unshift(executable); 70 | executable = '/bin/sh'; 71 | } 72 | 73 | test.ok(flexSdk.bin.mxmlc, 'should have a path for `mxmlc`'); 74 | test.strictEqual(fs.existsSync(flexSdk.bin.mxmlc), true, '`mxmlc` should exist at the expected path'); 75 | test.strictEqual(fs.existsSync(targetSource), true, 'the target source file should exist'); 76 | 77 | childProcess.execFile(executable, childArgs, function(err, stdout, stderr) { 78 | test.equal(err, null, 'should not throw an error while executing the child process' + (err || '')); 79 | 80 | var stdoutLower = stdout.toLowerCase(); 81 | var stderrLower = stderr.toLowerCase(); 82 | 83 | var noFailures = stdoutLower.indexOf('fail') === -1 && stderrLower.indexOf('fail') === -1; 84 | var noErrors = stdoutLower.indexOf('error') === -1 && stderrLower.indexOf('error') === -1; 85 | 86 | var containsSwfPath; 87 | // Ignore case (and slashes) for Windows 88 | if (process.platform === 'win32') { 89 | containsSwfPath = stdoutLower.replace(/\\/gi, '/').indexOf(targetBinary.toLowerCase().replace(/\\/gi, '/')) !== -1; 90 | } 91 | else { 92 | containsSwfPath = stdout.indexOf(targetBinary) !== -1; 93 | } 94 | 95 | test.ok(noFailures, 'should compile the target successfully without failures'); 96 | test.ok(noErrors, 'should compile the target successfully without errors'); 97 | test.ok(containsSwfPath, 'should compile the target successfully and show path to output binary'); 98 | test.ok(fs.existsSync(targetBinary), 'compiled output binary should exist'); 99 | 100 | test.done(); 101 | }); 102 | } 103 | }, 104 | 105 | testCompileFailureDueToSynaxError: { 106 | setUp: function(done) { 107 | // Delete the binary 108 | var targetBinary = path.join(__dirname, 'testData', 'errorApp.swf'); 109 | safeDelete(targetBinary); 110 | done(); 111 | }, 112 | tearDown: function(done) { 113 | // Delete the binary 114 | var targetBinary = path.join(__dirname, 'testData', 'errorApp.swf'); 115 | safeDelete(targetBinary); 116 | done(); 117 | }, 118 | testIt: function(test) { 119 | test.expect(7); 120 | 121 | var executable = flexSdk.bin.mxmlc; 122 | var targetSource = path.join(__dirname, 'testData', 'errorApp.as'); 123 | var targetBinary = path.join(__dirname, 'testData', 'errorApp.swf'); 124 | 125 | var childArgs = [ 126 | '+configname=air', 127 | targetSource 128 | ]; 129 | 130 | // Hack for non-Windows boxes 131 | if (process.platform !== 'win32') { 132 | childArgs.unshift(executable); 133 | executable = '/bin/sh'; 134 | } 135 | 136 | test.ok(flexSdk.bin.mxmlc, 'should have a path for `mxmlc`'); 137 | test.strictEqual(fs.existsSync(flexSdk.bin.mxmlc), true, '`mxmlc` should exist at the expected path'); 138 | test.strictEqual(fs.existsSync(targetSource), true, 'the target source file should exist'); 139 | 140 | childProcess.execFile(executable, childArgs, function(err, stdout, stderr) { 141 | test.notEqual(err, null, 'should throw an error while executing the child process'); 142 | 143 | var stdoutLower = stdout.toLowerCase(); 144 | var stderrLower = stderr.toLowerCase(); 145 | 146 | var hadFailures = stdoutLower.indexOf('fail') !== -1 || stderrLower.indexOf('fail') !== -1; 147 | var hadErrors = stdoutLower.indexOf('error') !== -1 || stderrLower.indexOf('error') !== -1; 148 | var containsSwfPath; 149 | // Ignore case for Windows 150 | if (process.platform === 'win32') { 151 | containsSwfPath = stdoutLower.indexOf(targetBinary.toLowerCase()) !== -1; 152 | } 153 | else { 154 | containsSwfPath = stdout.indexOf(targetBinary) !== -1; 155 | } 156 | 157 | test.ok(hadFailures || hadErrors, 'should fail to compile the target with either failures or errors'); 158 | test.ok(!containsSwfPath, 'should not show path to output binary'); 159 | test.ok(!fs.existsSync(targetBinary), 'compiled output binary should not exist'); 160 | 161 | test.done(); 162 | }); 163 | } 164 | }, 165 | 166 | testCompileFailureDueToMissingSource: { 167 | setUp: function(done) { 168 | // Delete the binary 169 | var targetBinary = path.join(__dirname, 'testData', 'nonExistentApp.swf'); 170 | safeDelete(targetBinary); 171 | done(); 172 | }, 173 | tearDown: function(done) { 174 | // Delete the binary 175 | var targetBinary = path.join(__dirname, 'testData', 'nonExistentApp.swf'); 176 | safeDelete(targetBinary); 177 | done(); 178 | }, 179 | testIt: function(test) { 180 | test.expect(7); 181 | 182 | var executable = flexSdk.bin.mxmlc; 183 | var targetSource = path.join(__dirname, 'testData', 'nonExistentApp.as'); 184 | var targetBinary = path.join(__dirname, 'testData', 'nonExistentApp.swf'); 185 | 186 | var childArgs = [ 187 | '+configname=air', 188 | targetSource 189 | ]; 190 | 191 | // Hack for non-Windows boxes 192 | if (process.platform !== 'win32') { 193 | childArgs.unshift(executable); 194 | executable = '/bin/sh'; 195 | } 196 | 197 | test.ok(flexSdk.bin.mxmlc, 'should have a path for `mxmlc`'); 198 | test.strictEqual(fs.existsSync(flexSdk.bin.mxmlc), true, '`mxmlc` should exist at the expected path'); 199 | test.strictEqual(fs.existsSync(targetSource), false, 'the target source file should not exist'); 200 | 201 | childProcess.execFile(executable, childArgs, function(err, stdout, stderr) { 202 | test.notEqual(err, null, 'should throw an error while executing the child process'); 203 | 204 | var stdoutLower = stdout.toLowerCase(); 205 | var stderrLower = stderr.toLowerCase(); 206 | 207 | var hadFailures = stdoutLower.indexOf('fail') !== -1 || stderrLower.indexOf('fail') !== -1; 208 | var hadErrors = stdoutLower.indexOf('error') !== -1 || stderrLower.indexOf('error') !== -1; 209 | var containsSwfPath; 210 | // Ignore case for Windows 211 | if (process.platform === 'win32') { 212 | containsSwfPath = stdoutLower.indexOf(targetBinary.toLowerCase()) !== -1; 213 | } 214 | else { 215 | containsSwfPath = stdout.indexOf(targetBinary) !== -1; 216 | } 217 | 218 | test.ok(hadFailures || hadErrors, 'should fail to compile the target with either failures or errors'); 219 | test.ok(!containsSwfPath, 'should not show path to output binary'); 220 | test.ok(!fs.existsSync(targetBinary), 'compiled output binary should not exist'); 221 | 222 | test.done(); 223 | }); 224 | } 225 | } 226 | }; --------------------------------------------------------------------------------