]> git.proxmox.com Git - sencha-touch.git/blobdiff - src/examples/forms/.sencha/app/app-build.js
import Sencha Touch 2.4.2 source
[sencha-touch.git] / src / examples / forms / .sencha / app / app-build.js
diff --git a/src/examples/forms/.sencha/app/app-build.js b/src/examples/forms/.sencha/app/app-build.js
new file mode 100644 (file)
index 0000000..8aa5c24
--- /dev/null
@@ -0,0 +1,609 @@
+importPackage(com.sencha.tools.compressors.yui);
+importPackage(com.sencha.tools.compressors.closure);
+importPackage(com.sencha.tools.external);
+importPackage(com.sencha.tools.compiler.jsb.statements);
+
+var _logger = SenchaLogManager.getLogger("app-build");
+
+function runAppBuild(proj) {
+    var basedir = proj.getProperty("framework.config.dir"),
+        appPath = proj.getProperty("args.path"),
+        envArg = proj.getProperty("args.environment"),
+        ignores = proj.getProperty("framework.ignores"),
+        options = proj.getProperty("build.options"),
+        cssCompression = proj.getProperty("build.compress.css"),
+        config = readConfig(resolvePath(appPath, "app.json")),
+        environment = (envArg == "native") ? 'package' : envArg,
+        destination = 
+            (proj.getProperty("args.destination") + '') ||
+            (proj.getProperty("build.dir") + '') ||
+            (proj.getProperty("app.build.dir") + ''),
+        operations = toJS(proj.getProperty("build.operations")),
+        v2deps = !!(proj.getProperty("v2deps") == "true"),
+        src = appPath,
+        sdk = proj.getProperty("framework.dir"),
+        archive = 
+            (proj.getProperty("args.archive") + '') || 
+            (config.archivePath) || 
+            "archive",
+        nativePackaging = !!(envArg == 'native'),
+        indexHtmlPath = config.indexHtmlPath || 'index.html',
+        appUrl = config.url || resolvePath(src, indexHtmlPath),
+        jsAssets = config.js || [],
+        cssAssets = config.css || [],
+        appCache = config.appCache,
+        ignore = config.ignore,
+        remoteAssets = [],
+        extras = config.extras || config.resources,
+        appJs, sdkJs, sdkIsAll, assets, processIndex;
+
+    destination = joinPath(destination, environment);
+    
+    if(!PathUtil.isAbsolute(archive)) {
+        archive = resolvePath(appPath, archive);
+    }
+    
+    if (operations) {
+        operations = operations.split('\n');
+    } else {
+        operations = [];
+    }
+    
+    if (appUrl.indexOf("file:") != 0 && appUrl.indexOf("http:") != 0) {
+        appUrl = 'file:///' + StringUtil.replace(resolvePath(appUrl), '\\', '/');
+    }
+
+    // check for build dir being immediate child of application dir
+    // native packager can get in to infinite looping when scanning files
+    // under this scenario
+    var canonicalAppPath = new File(appPath).getCanonicalPath(),
+        canonicalDestPath = new File(destination).getCanonicalPath(),
+        parent = new File(canonicalDestPath).getParentFile();
+
+    if(parent && parent.getCanonicalPath() == canonicalAppPath) {
+        _logger.error("Application : {}", canonicalAppPath);
+        _logger.error("Destination : {}", canonicalDestPath);
+        _logger.error("Destination path cannot reside one level under the Application directory")
+        throw "Destination path cannot reside one level under the Application directory";
+    }
+
+
+    _logger.info("Deploying your application to " + destination);
+
+    PathUtil.ensurePathExists(resolvePath(destination));
+
+    jsAssets = each(
+        map(jsAssets, function (asset) {
+            if (typeof asset == 'string') {
+                asset = { path:asset };
+            }
+            asset.type = 'js';
+            return asset;
+        }),
+        function (jsAsset) {
+            if (jsAsset.bundle) {
+                appJs = jsAsset.path;
+            }
+        });
+
+    if (!appJs) {
+        appJs = 'app.js';
+    }
+
+    appJs = resolvePath(destination, appJs);
+
+    cssAssets = map(cssAssets, function (asset) {
+        if (typeof asset == 'string') {
+            asset = { path:asset };
+        }
+        asset.type = 'css';
+        return asset;
+    });
+
+    assets = filter(concat(jsAssets, cssAssets), function (asset) {
+        return !asset.shared || (environment != 'production');
+    });
+
+    _logger.debug("copying all assets");
+    each(assets, function (asset) {
+        if (asset.remote) {
+            asset.bundle = false;
+            asset.update = false;
+            remoteAssets.push(asset);
+        } else {
+            file = asset.path;
+
+            // if not in testing mode, and using the new compiler, and this is
+            // one of the sencha-touch files, don't copy to output directory
+            if( asset.type === 'js' &&
+                !v2deps &&
+                file.indexOf("sencha-touch") != -1) {
+                asset['x-bootstrap'] = true;
+                
+                // only skip the sdk code in the bundle if the bundle flag
+                // on the sdk asset is explicitly set to false
+                if(('bundle' in asset) && asset.bundle === false) {
+                    sdkJs = asset.path;
+                    sdkIsAll = sdkJs.indexOf("-all.js") >= 0;
+                    asset.isSdk = true;
+                }
+            }
+
+            if (asset['x-bootstrap'] && !asset.isSdk) {
+                return;
+            }
+
+            _logger.debug("copying file {}", resolvePath(src, file));
+
+            var srcPath = resolvePath(src, file),
+                dstPath = resolvePath(destination, stripSpecialDirNames(file));
+
+            if(srcPath != dstPath) {
+                PathUtil.ensurePathExists(dstPath);
+                copy(srcPath, dstPath);
+                _logger.info("Copied {} to {}", srcPath, dstPath);
+            }
+        }
+    });
+
+    var ignoreFilter = Filter.getFileNameFilter(
+        new RegexFilter(ignore).setInclusive(false));
+
+    _logger.debug("copying all extras");
+    each(extras, function (extra) {
+        var from = resolvePath(src, extra),
+            to = resolvePath(destination, extra);
+        _logger.debug("Copying from {} to {}", from, to);
+        if (new File(from).exists()) {
+            PathUtil.ensurePathExists(to);
+            copy(from, to, ignoreFilter);
+            _logger.info("Copied {}", from);
+        } else {
+            _logger.warn("File or folder {} not found", from);
+        }
+    });
+
+    // build the app
+
+    processIndex = function () {
+        _logger.debug("processing page : index.html");
+        jsAssets = filter(jsAssets, function(asset){
+            return !(asset['x-bootstrap'] && !asset.isSdk);
+        });
+
+        var appJson = jsonEncode({
+                id:config.id,
+                js:jsAssets,
+                css:cssAssets
+            }),
+            indexHtml, content, compressor, remotes, microloader;
+
+        writeFileContent(new File(destination, 'app.json'), appJson);
+        _logger.info("Generated app.json");
+
+        indexHtml = readFileContent(new File(src, indexHtmlPath));
+
+        if (environment == 'production' && appCache) {
+            indexHtml = StringUtil.replace(
+                indexHtml,
+                '<html manifest=""',
+                '<html manifest="cache.appcache"');
+        }
+
+        compressor = new ClosureCompressor();
+        microloader = (environment == 'production'
+            ? 'production'
+            : 'testing') +
+            '.js';
+        _logger.debug("using microloader : {}", microloader);
+        content = readFileContent(joinPath(sdk, "microloader", microloader));
+        content = compressor.compress(content);
+        remotes = [
+            '<script type="text/javascript">' +
+                content + ';Ext.blink(' +
+                (environment == 'production' ? jsonEncode({
+                    id:config.id
+                }) : appJson) + ')' +
+                '</script>'
+        ];
+
+        each(remoteAssets, function (asset) {
+            var uri = asset.path;
+
+            if (asset.type === 'js') {
+                remotes.push(
+                    '<script type="text/javascript" src="' +
+                        uri +
+                        '"></script>');
+            } else if (asset.type === 'css') {
+                remotes.push(
+                    '<link rel="stylesheet" type="text/css" href="' +
+                        uri +
+                        '" />');
+            }
+        });
+
+        indexHtml = ('' + indexHtml).replace(
+            /<script id="microloader"([^<]+)<\/script>/,
+            remotes.join(''));
+
+        _logger.debug("generating new built index.html");
+        writeFileContent(resolvePath(destination, indexHtmlPath), indexHtml);
+        _logger.info("Embedded microloader into " + indexHtmlPath);
+    };
+
+    _logger.info("Resolving your application dependencies (" + appUrl + ")");
+
+    var preprocessor = new Parser(),
+        jsCompressor = new YuiJavascriptCompressor(),
+        cssCompressor = new YuiCssCompressor(),
+        phantomRunner = new PhantomJsRunner(),
+        processedAssetCount = 0,
+        assetsCount, dependencies, files, file,
+        destinationFile, compressor,
+               cleanFile, cleanDestinationFile;
+
+    if(v2deps) {
+        // if v2deps, use the sencha command 2 sytle dependency resolution mechanism
+        // by running the phantomjs dependencies.js script
+        var phantomOut = phantomRunner.run([
+                resolvePath(basedir, "dependencies.js"),
+                appUrl
+            ]),
+            exitCode = phantomOut.getExitCode(),
+            stdout = phantomOut.getOutput(),
+            buffer = new StringBuilder();
+
+
+        if (exitCode > 0) {
+            _logger.error("dependencies.js exited with non-zero code : " + exitCode);
+            _logger.error(stdout);
+            throw new ExBuild("failed gathering dependencies").raise();
+        }
+        dependencies = jsonDecode(stdout);
+
+        _logger.info("Found " + dependencies.length + " dependencies. Concatenating all into '" + appJs + "'");
+
+        files = map(dependencies, function (dependency) {
+            return resolvePath(src, dependency.path);
+        });
+
+        files.push(appJs);
+
+        each(files, function (file) {
+            buffer.append(FileUtil.readUnicodeFile(resolvePath(file))).append('\n');
+        });
+
+        writeFileContent(appJs, buffer.toString());
+
+        // clear the buffer to free memory
+        buffer.setLength(0);
+    } else {
+        var sdkTag = sdkIsAll ? 'framework' : 'core',
+            sdkFile = sdkJs,
+            sdkJsArgs = [
+                '--options=' + options,
+                'union',
+                '-tag',
+                sdkTag,
+                'and',
+                'concat',
+                '-out=' + resolvePath(destination, sdkFile)
+            ],
+            appJsArgs = [
+                '-options=' + options,
+                'restore',
+                'app-all',
+                'and',
+                'exclude',
+                '-tag',
+                sdkTag,
+                'and',
+                'concatenate',
+                '-out=' + appJs,
+                ''],
+            compilerId = proj.getProperty("compiler.ref.id"),
+            compiler = proj.getReference(compilerId);
+
+        if(sdkJs) {
+            _logger.info("Compiling " + sdkFile + " and dependencies");
+            _logger.debug("running compiler with options : '{}'", sdkJsArgs.join(' '));
+            compiler.dispatchArgs(sdkJsArgs);
+            _logger.info("Compiling app.js and dependencies");
+            _logger.debug("running compiler with options : '{}'", appJsArgs.join(' '));
+            compiler.dispatchArgs(appJsArgs);
+            _logger.info("Completed compilation.");
+        } else {
+            appJsArgs = [
+                '-options=' + options,
+                'restore',
+                'app-all',
+                'and',
+                'concatenate',
+                '-out=' + appJs,
+                ''];
+
+            _logger.debug("running compiler with options : '{}'", appJsArgs.join(' '));
+            compiler.dispatchArgs(appJsArgs);
+            _logger.info("Completed compilation.");        
+        }
+    }
+
+
+    for (var name in config.buildOptions) {
+        if (config.buildOptions.hasOwnProperty(name)) {
+            preprocessor.setParam(name, config.buildOptions[name]);
+        }
+    }
+
+    assetsCount = assets.length;
+
+    each(assets, function (asset) {
+        if(!asset.remote) {
+            file = asset.path;
+            destinationFile = resolvePath(destination, file),
+            cleanFile = stripSpecialDirNames(file),
+            cleanDestinationFile = resolvePath(destination, cleanFile);
+
+            // adjust the asset path to use the cleaned filename
+            asset.path = cleanFile;
+        }
+
+
+        _logger.debug("Assets => Processed : {} Total : {}",
+            processedAssetCount, assetsCount);
+
+        if (asset.type == 'js') {
+            if (!asset.remote && !(asset['x-bootstrap'] && !asset.isSdk)) {
+                _logger.debug("running preprocessor for file {}", cleanDestinationFile);
+                writeFileContent(
+                    cleanDestinationFile,
+                    preprocessor.parse(readFileContent(cleanDestinationFile)));
+                _logger.info('Processed local file ' + asset.path);
+            } else {
+                _logger.info('Processed remote file ' + asset.path);
+            }
+        }
+
+        if (environment == 'testing') {
+            return;
+        }
+
+        if (asset.remote || (asset['x-bootstrap'] && !asset.isSdk)) {
+            ++processedAssetCount;
+        } else {
+            _logger.debug("Minifying " + file);
+
+            if(asset.type == 'js') {
+                writeFileContent(
+                    cleanDestinationFile,
+                    jsCompressor.compress(readFileContent(cleanDestinationFile)));
+
+                _logger.info("Minified " + file);
+            } else if (cssCompression == "true") {
+                writeFileContent(
+                    cleanDestinationFile,
+                    cssCompressor.compress(readFileContent(cleanDestinationFile)));
+
+                _logger.info("Minified " + file);
+            }
+
+            if (environment == 'production') {
+                var content = readFileContent(cleanDestinationFile),
+                    version = '' + FileUtil.createChecksum(content);
+                asset.version = version;
+
+                _logger.debug("prepending checksum on {}", cleanDestinationFile);
+                writeFileContent(
+                    cleanDestinationFile,
+                    "/*" + version  + "*/" + content);
+                content = "";
+
+                _logger.debug("copying destination to archive");
+
+                PathUtil.ensurePathExists(resolvePath(archive, cleanFile, version));
+                copy(cleanDestinationFile, resolvePath(archive, cleanFile, version));
+
+                if (asset.update == 'delta') {
+                    // generate all the deltas to the other archived versions
+                    _logger.debug("generating file deltas");
+                    var archivedVersions = new File(joinPath(archive, cleanFile))
+                        .listFiles();
+
+                    each(archivedVersions, function (archivedVersion) {
+                        if(archivedVersion.isDirectory()) {
+                            return;
+                        }
+                        
+                        archivedVersion = archivedVersion.name;
+
+                        if (archivedVersion == version) {
+                            return;
+                        }
+
+                        var deltaFile = joinPath(
+                            destination,
+                            'deltas',
+                            cleanFile,
+                            archivedVersion + '.json');
+
+                        writeFileContent(deltaFile, '');
+
+                        _logger.debug("Generating delta from {} to {}",
+                            archivedVersion,
+                            version);
+
+                        var runner = new VcDiffRunner(),
+                            args = [
+                                'encode',
+                                '-json',
+                                '-dictionary',
+                                joinPath(archive, cleanFile, archivedVersion),
+                                '-target',
+                                cleanDestinationFile,
+                                '-delta',
+                                resolvePath(deltaFile),
+                                '--stats'
+                            ],
+                            runnerOut = runner.run(args),
+                            exitCode = runnerOut.getExitCode(),
+                            stdout = runnerOut.getOutput();
+                            
+                        if (exitCode > 0) {
+                            _logger.error("failed generating diff from {} to {}",
+                                archivedVersion,
+                                version);
+                            _logger.error(stdout);
+                            throw new ExBuild("failed generating diff from {0} to {1}",
+                                archivedVersion,
+                                version).raise();
+                        }
+                        
+                        // fixup malformed vcdiff content
+                        var deltaFilePath = resolvePath(deltaFile),
+                            content = FileUtil.readFile(deltaFilePath);
+                        if(content.endsWith(",]")) {
+                            _logger.debug("Correcting trailing comma issue in vcdiff output");
+                            FileUtil.writeFile(deltaFilePath, content.substring(0, content.length() - 2) + "]");
+                        }
+                        
+                        content = null;
+                        
+                        _logger.info(
+                            "Generated delta for: {} from hash: '{}' to hash: '{}'",
+                            [cleanFile, archivedVersion, version]);
+                    });
+
+                }
+            }
+
+            if (++processedAssetCount == assetsCount) {
+                _logger.debug("processed all assets, finalizing build...");
+                processIndex();
+
+                if (environment == 'production' && appCache) {
+                    _logger.info("Generating appcache");
+                    appCache.cache = map(appCache.cache, function (cache) {
+                        var checksum = '';
+
+                        if (!/^(\/|(.*):\/\/)/.test(cache)) {
+                            _logger.info(
+                                "Generating checksum for appCache item: {}",
+                                cache);
+
+                            checksum = FileUtil.createChecksum(
+                                readFileData(joinPath(destination, cache)));
+                        }
+
+                        return {
+                            uri:cache,
+                            checksum:checksum
+                        }
+                    });
+
+                    writeAppCache(appCache, joinPath(destination, 'cache.appcache'));
+                }
+
+                if (nativePackaging) {
+                    _logger.info("Generating native package");
+                    var packagerConfig = readConfig(
+                            joinPath(src, 'packager.json'));
+
+                    if (packagerConfig.platform.match(/iOS/)) {
+                        copy(
+                            resolvePath(joinPath(src, 'resources', 'icons')),
+                            resolvePath(destination),
+                            ignoreFilter);
+                        copy(
+                            resolvePath(joinPath(src, 'resources', 'loading')),
+                            resolvePath(destination),
+                            ignoreFilter);
+                    }
+
+                    // add '' here to coerce to javascript string instead of java string
+                    // for json encoding later...
+                    packagerConfig.inputPath = destination + '';
+                    
+                    var origDestination = proj.getProperty("args.destination"), 
+                        nativePackagePath = proj.getProperty("native.build.dir") ||
+                            joinPath(origDestination, "native");
+                    
+                    packagerConfig.outputPath = resolvePath(nativePackagePath) + '';
+                    
+                    PathUtil.ensurePathExists(packagerConfig.outputPath);
+
+                    writeFileContent(
+                        joinPath(src, 'packager.temp.json'),
+                        jsonEncode(packagerConfig, true));
+
+                    _logger.info(
+                        "Packaging your application as a native app to {} ...",  
+                        packagerConfig.outputPath);
+
+                    var stbuildRunner = new StBuildRunner(),
+                        args = ['package', resolvePath(src, 'packager.temp.json')],
+                        stbuildOut = stbuildRunner.run(args),
+                        exitCode = stbuildOut.getExitCode(),
+                        stdout = stbuildOut.getOutput();
+
+                    if (exitCode > 0) {
+                        _logger.error("failed running native packager");
+                        _logger.error(stdout);
+                        throw new ExBuild("failed running native packager")
+                            .raise();
+                    } else {
+                        _logger.info("Successfully packaged native application");
+                        _logger.info(
+                            "Package may be run with 'sencha package run -p {}", 
+                            joinPath(src, 'packager.temp.json'))
+                    }
+                } else {
+                    _logger.debug("skipping native packaging");
+                }
+            }
+        }
+    });
+
+    if (environment == 'testing') {
+        processIndex();
+    }
+    
+    _logger.info("Successfully deployed your application to " + destination);
+
+};
+
+function writeAppCache(appCache, outfile) {
+    _logger.debug("generating appcache manifest...");
+    // build the appCache file
+    var builder = new StringBuilder();
+
+    builder.append("CACHE MANIFEST\n");
+    each(appCache.cache, function (cache) {
+        builder.append("# " + cache.checksum + "\n");
+        builder.append(cache.uri + "\n");
+    });
+
+    builder.append("\n\nFALLBACK:\n");
+
+    each(appCache.fallback, function (fallback) {
+        builder.append(fallback + '\n');
+    });
+
+    builder.append("\n\nNETWORK:\n");
+
+    each(appCache.network, function (network) {
+        builder.append(network + '\n');
+    });
+
+    writeFileContent(
+        outfile,
+        builder.toString());
+
+    builder.setLength(0);
+};
+
+
+(function (proj) {
+       _logger.info("building application");
+       runAppBuild(proj);
+})(project);
\ No newline at end of file