UNPKG

@ambers/cli

Version:

An implementation of the Smalltalk language that runs on top of the JS runtime.

1,260 lines (1,208 loc) 165 kB
define(["amber/boot", "require", "amber/core/Kernel-Objects"], function($boot,requirejs){"use strict"; var $core=$boot.api,nil=$boot.nilAsValue,$nil=$boot.nilAsReceiver,$recv=$boot.asReceiver,$globals=$boot.globals; var $pkg = $core.addPackage("AmberCli"); $pkg.transport = {"type":"amd","amdNamespace":"amber_cli"}; $core.addClass("AmberCli", $globals.Object, "AmberCli"); //>>excludeStart("ide", pragmas.excludeIdeData); $globals.AmberCli.comment="I am the Amber CLI (CommandLine Interface) tool which runs on Node.js.\x0a\x0aMy responsibility is to start different Amber programs like the FileServer or the Repl.\x0aWhich program to start is determined by the first commandline parameters passed to the AmberCli executable.\x0aUse `help` to get a list of all available options.\x0aAny further commandline parameters are passed to the specific program.\x0a\x0a## Commands\x0a\x0aNew commands can be added by creating a class side method in the `commands` protocol which takes one parameter.\x0aThis parameter is an array of all commandline options + values passed on to the program.\x0aAny `camelCaseCommand` is transformed into a commandline parameter of the form `camel-case-command` and vice versa."; //>>excludeEnd("ide"); $core.addMethod( $core.method({ selector: "commandLineSwitches", protocol: "commandline", //>>excludeStart("ide", pragmas.excludeIdeData); args: [], source: "commandLineSwitches\x0a\x09\x22Collect all methodnames from the 'commands' protocol of the class\x0a\x09 and select the ones with only one parameter.\x0a\x09 Then remove the ':' at the end of the name.\x0a\x09 Additionally all uppercase letters are made lowercase and preceded by a '-'.\x0a\x09 Example: fallbackPage: becomes --fallback-page.\x0a\x09 Return the Array containing the commandline switches.\x22\x0a\x09| switches |\x0a\x09switches := ((self class methodsInProtocol: 'commands') collect: [ :each | each selector]).\x0a\x09switches := switches select: [ :each | each match: '^[^:]*:$'].\x0a\x09switches :=switches collect: [ :each |\x0a\x09\x09(each allButLast replace: '([A-Z])' with: '-$1') asLowercase].\x0a\x09^ switches", referencedClasses: [], //>>excludeEnd("ide"); pragmas: [], messageSends: ["collect:", "methodsInProtocol:", "class", "selector", "select:", "match:", "asLowercase", "replace:with:", "allButLast"] }, function ($methodClass){ return function (){ var self=this,$self=this; var switches; //>>excludeStart("ctx", pragmas.excludeDebugContexts); return $core.withContext(function($ctx1) { //>>excludeEnd("ctx"); switches=[$recv($recv($self._class())._methodsInProtocol_("commands"))._collect_((function(each){ //>>excludeStart("ctx", pragmas.excludeDebugContexts); return $core.withContext(function($ctx2) { //>>excludeEnd("ctx"); return $recv(each)._selector(); //>>excludeStart("ctx", pragmas.excludeDebugContexts); }, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,1)}); //>>excludeEnd("ctx"); })) //>>excludeStart("ctx", pragmas.excludeDebugContexts); ,$ctx1.sendIdx["collect:"]=1 //>>excludeEnd("ctx"); ][0]; switches=$recv(switches)._select_((function(each){ //>>excludeStart("ctx", pragmas.excludeDebugContexts); return $core.withContext(function($ctx2) { //>>excludeEnd("ctx"); return $recv(each)._match_("^[^:]*:$"); //>>excludeStart("ctx", pragmas.excludeDebugContexts); }, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,2)}); //>>excludeEnd("ctx"); })); switches=$recv(switches)._collect_((function(each){ //>>excludeStart("ctx", pragmas.excludeDebugContexts); return $core.withContext(function($ctx2) { //>>excludeEnd("ctx"); return $recv($recv($recv(each)._allButLast())._replace_with_("([A-Z])","-$1"))._asLowercase(); //>>excludeStart("ctx", pragmas.excludeDebugContexts); }, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,3)}); //>>excludeEnd("ctx"); })); return switches; //>>excludeStart("ctx", pragmas.excludeDebugContexts); }, function($ctx1) {$ctx1.fill(self,"commandLineSwitches",{switches:switches})}); //>>excludeEnd("ctx"); }; }), $globals.AmberCli.a$cls); $core.addMethod( $core.method({ selector: "config:", protocol: "commands", //>>excludeStart("ide", pragmas.excludeIdeData); args: ["args"], source: "config: args\x0a\x09Configurator new start", referencedClasses: ["Configurator"], //>>excludeEnd("ide"); pragmas: [], messageSends: ["start", "new"] }, function ($methodClass){ return function (args){ var self=this,$self=this; //>>excludeStart("ctx", pragmas.excludeDebugContexts); return $core.withContext(function($ctx1) { //>>excludeEnd("ctx"); $recv($recv($globals.Configurator)._new())._start(); return self; //>>excludeStart("ctx", pragmas.excludeDebugContexts); }, function($ctx1) {$ctx1.fill(self,"config:",{args:args})}); //>>excludeEnd("ctx"); }; }), $globals.AmberCli.a$cls); $core.addMethod( $core.method({ selector: "handleArguments:", protocol: "commandline", //>>excludeStart("ide", pragmas.excludeIdeData); args: ["args"], source: "handleArguments: args\x0a\x09| selector |\x0a\x0a\x09selector := self selectorForCommandLineSwitch: (args first).\x0a\x09args remove: args first.\x0a\x09self perform: selector withArguments: { args }", referencedClasses: [], //>>excludeEnd("ide"); pragmas: [], messageSends: ["selectorForCommandLineSwitch:", "first", "remove:", "perform:withArguments:"] }, function ($methodClass){ return function (args){ var self=this,$self=this; var selector; //>>excludeStart("ctx", pragmas.excludeDebugContexts); return $core.withContext(function($ctx1) { //>>excludeEnd("ctx"); selector=$self._selectorForCommandLineSwitch_([$recv(args)._first() //>>excludeStart("ctx", pragmas.excludeDebugContexts); ,$ctx1.sendIdx["first"]=1 //>>excludeEnd("ctx"); ][0]); $recv(args)._remove_($recv(args)._first()); $self._perform_withArguments_(selector,[args]); return self; //>>excludeStart("ctx", pragmas.excludeDebugContexts); }, function($ctx1) {$ctx1.fill(self,"handleArguments:",{args:args,selector:selector})}); //>>excludeEnd("ctx"); }; }), $globals.AmberCli.a$cls); $core.addMethod( $core.method({ selector: "help:", protocol: "commands", //>>excludeStart("ide", pragmas.excludeIdeData); args: ["args"], source: "help: args\x0a\x09Transcript show: 'Available commands'.\x0a\x09self commandLineSwitches do: [ :each | console log: each ]", referencedClasses: ["Transcript"], //>>excludeEnd("ide"); pragmas: [], messageSends: ["show:", "do:", "commandLineSwitches", "log:"] }, function ($methodClass){ return function (args){ var self=this,$self=this; //>>excludeStart("ctx", pragmas.excludeDebugContexts); return $core.withContext(function($ctx1) { //>>excludeEnd("ctx"); $recv($globals.Transcript)._show_("Available commands"); $recv($self._commandLineSwitches())._do_((function(each){ //>>excludeStart("ctx", pragmas.excludeDebugContexts); return $core.withContext(function($ctx2) { //>>excludeEnd("ctx"); return $recv(console)._log_(each); //>>excludeStart("ctx", pragmas.excludeDebugContexts); }, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,1)}); //>>excludeEnd("ctx"); })); return self; //>>excludeStart("ctx", pragmas.excludeDebugContexts); }, function($ctx1) {$ctx1.fill(self,"help:",{args:args})}); //>>excludeEnd("ctx"); }; }), $globals.AmberCli.a$cls); $core.addMethod( $core.method({ selector: "init:", protocol: "commands", //>>excludeStart("ide", pragmas.excludeIdeData); args: ["args"], source: "init: args\x0a\x09Initer new start", referencedClasses: ["Initer"], //>>excludeEnd("ide"); pragmas: [], messageSends: ["start", "new"] }, function ($methodClass){ return function (args){ var self=this,$self=this; //>>excludeStart("ctx", pragmas.excludeDebugContexts); return $core.withContext(function($ctx1) { //>>excludeEnd("ctx"); $recv($recv($globals.Initer)._new())._start(); return self; //>>excludeStart("ctx", pragmas.excludeDebugContexts); }, function($ctx1) {$ctx1.fill(self,"init:",{args:args})}); //>>excludeEnd("ctx"); }; }), $globals.AmberCli.a$cls); $core.addMethod( $core.method({ selector: "main", protocol: "startup", //>>excludeStart("ide", pragmas.excludeIdeData); args: [], source: "main\x0a\x09\x22Main entry point for Amber applications.\x0a\x09Parses commandline arguments and starts the according subprogram.\x22\x0a\x09| args packageJSON |\x0a\x09\x0a\x09packageJSON := require value: '../package.json'.\x0a\x09Transcript show: 'Welcome to Amber CLI version ', packageJSON version, ' (Amber ', Smalltalk version, ', NodeJS ', process versions node, ').'.\x0a\x0a\x09args := process argv.\x0a\x09\x22Remove the first args which contain the path to the node executable and the script file.\x22\x0a\x09args removeFrom: 1 to: 2.\x0a\x09\x0a\x09args\x0a\x09\x09ifEmpty: [self help: nil]\x0a\x09\x09ifNotEmpty: [^self handleArguments: args]", referencedClasses: ["Transcript", "Smalltalk"], //>>excludeEnd("ide"); pragmas: [], messageSends: ["value:", "show:", ",", "version", "node", "versions", "argv", "removeFrom:to:", "ifEmpty:ifNotEmpty:", "help:", "handleArguments:"] }, function ($methodClass){ return function (){ var self=this,$self=this; var args,packageJSON; //>>excludeStart("ctx", pragmas.excludeDebugContexts); return $core.withContext(function($ctx1) { //>>excludeEnd("ctx"); var $early={}; try { packageJSON=$recv(require)._value_("../package.json"); $recv($globals.Transcript)._show_([$recv([$recv([$recv([$recv([$recv("Welcome to Amber CLI version ".__comma([$recv(packageJSON)._version() //>>excludeStart("ctx", pragmas.excludeDebugContexts); ,$ctx1.sendIdx["version"]=1 //>>excludeEnd("ctx"); ][0])).__comma(" (Amber ") //>>excludeStart("ctx", pragmas.excludeDebugContexts); ,$ctx1.sendIdx[","]=5 //>>excludeEnd("ctx"); ][0]).__comma($recv($globals.Smalltalk)._version()) //>>excludeStart("ctx", pragmas.excludeDebugContexts); ,$ctx1.sendIdx[","]=4 //>>excludeEnd("ctx"); ][0]).__comma(", NodeJS ") //>>excludeStart("ctx", pragmas.excludeDebugContexts); ,$ctx1.sendIdx[","]=3 //>>excludeEnd("ctx"); ][0]).__comma($recv($recv(process)._versions())._node()) //>>excludeStart("ctx", pragmas.excludeDebugContexts); ,$ctx1.sendIdx[","]=2 //>>excludeEnd("ctx"); ][0]).__comma(").") //>>excludeStart("ctx", pragmas.excludeDebugContexts); ,$ctx1.sendIdx[","]=1 //>>excludeEnd("ctx"); ][0]); args=$recv(process)._argv(); $recv(args)._removeFrom_to_((1),(2)); $recv(args)._ifEmpty_ifNotEmpty_((function(){ //>>excludeStart("ctx", pragmas.excludeDebugContexts); return $core.withContext(function($ctx2) { //>>excludeEnd("ctx"); return $self._help_(nil); //>>excludeStart("ctx", pragmas.excludeDebugContexts); }, function($ctx2) {$ctx2.fillBlock({},$ctx1,1)}); //>>excludeEnd("ctx"); }),(function(){ //>>excludeStart("ctx", pragmas.excludeDebugContexts); return $core.withContext(function($ctx2) { //>>excludeEnd("ctx"); throw $early=[$self._handleArguments_(args)]; //>>excludeStart("ctx", pragmas.excludeDebugContexts); }, function($ctx2) {$ctx2.fillBlock({},$ctx1,2)}); //>>excludeEnd("ctx"); })); return self; } catch(e) {if(e===$early)return e[0]; throw e} //>>excludeStart("ctx", pragmas.excludeDebugContexts); }, function($ctx1) {$ctx1.fill(self,"main",{args:args,packageJSON:packageJSON})}); //>>excludeEnd("ctx"); }; }), $globals.AmberCli.a$cls); $core.addMethod( $core.method({ selector: "repl:", protocol: "commands", //>>excludeStart("ide", pragmas.excludeIdeData); args: ["args"], source: "repl: args\x0a\x09^ Repl new createInterface", referencedClasses: ["Repl"], //>>excludeEnd("ide"); pragmas: [], messageSends: ["createInterface", "new"] }, function ($methodClass){ return function (args){ var self=this,$self=this; //>>excludeStart("ctx", pragmas.excludeDebugContexts); return $core.withContext(function($ctx1) { //>>excludeEnd("ctx"); return $recv($recv($globals.Repl)._new())._createInterface(); //>>excludeStart("ctx", pragmas.excludeDebugContexts); }, function($ctx1) {$ctx1.fill(self,"repl:",{args:args})}); //>>excludeEnd("ctx"); }; }), $globals.AmberCli.a$cls); $core.addMethod( $core.method({ selector: "selectorForCommandLineSwitch:", protocol: "commandline", //>>excludeStart("ide", pragmas.excludeIdeData); args: ["aSwitch"], source: "selectorForCommandLineSwitch: aSwitch\x0a\x09\x22Add ':' at the end and replace all occurences of a lowercase letter preceded by a '-' with the Uppercase letter.\x0a\x09 Example: fallback-page becomes fallbackPage:.\x0a\x09 If no correct selector is found return 'help:'\x22\x0a\x09 | command selector |\x0a\x0a\x09 (self commandLineSwitches includes: aSwitch)\x0a\x09 ifTrue: [ selector := (aSwitch replace: '-[a-z]' with: [ :each | each second asUppercase ]), ':']\x0a\x09 ifFalse: [ selector := 'help:' ].\x0a\x09^ selector", referencedClasses: [], //>>excludeEnd("ide"); pragmas: [], messageSends: ["ifTrue:ifFalse:", "includes:", "commandLineSwitches", ",", "replace:with:", "asUppercase", "second"] }, function ($methodClass){ return function (aSwitch){ var self=this,$self=this; var command,selector; //>>excludeStart("ctx", pragmas.excludeDebugContexts); return $core.withContext(function($ctx1) { //>>excludeEnd("ctx"); if($core.assert($recv($self._commandLineSwitches())._includes_(aSwitch))){ selector=$recv($recv(aSwitch)._replace_with_("-[a-z]",(function(each){ //>>excludeStart("ctx", pragmas.excludeDebugContexts); return $core.withContext(function($ctx2) { //>>excludeEnd("ctx"); return $recv($recv(each)._second())._asUppercase(); //>>excludeStart("ctx", pragmas.excludeDebugContexts); }, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1,2)}); //>>excludeEnd("ctx"); }))).__comma(":"); selector; } else { selector="help:"; selector; } return selector; //>>excludeStart("ctx", pragmas.excludeDebugContexts); }, function($ctx1) {$ctx1.fill(self,"selectorForCommandLineSwitch:",{aSwitch:aSwitch,command:command,selector:selector})}); //>>excludeEnd("ctx"); }; }), $globals.AmberCli.a$cls); $core.addMethod( $core.method({ selector: "serve:", protocol: "commands", //>>excludeStart("ide", pragmas.excludeIdeData); args: ["args"], source: "serve: args\x0a\x09^ (FileServer createServerWithArguments: args) start", referencedClasses: ["FileServer"], //>>excludeEnd("ide"); pragmas: [], messageSends: ["start", "createServerWithArguments:"] }, function ($methodClass){ return function (args){ var self=this,$self=this; //>>excludeStart("ctx", pragmas.excludeDebugContexts); return $core.withContext(function($ctx1) { //>>excludeEnd("ctx"); return $recv($recv($globals.FileServer)._createServerWithArguments_(args))._start(); //>>excludeStart("ctx", pragmas.excludeDebugContexts); }, function($ctx1) {$ctx1.fill(self,"serve:",{args:args})}); //>>excludeEnd("ctx"); }; }), $globals.AmberCli.a$cls); $core.addMethod( $core.method({ selector: "version:", protocol: "commands", //>>excludeStart("ide", pragmas.excludeIdeData); args: ["arguments"], source: "version: arguments", referencedClasses: [], //>>excludeEnd("ide"); pragmas: [], messageSends: [] }, function ($methodClass){ return function (arguments_){ var self=this,$self=this; return self; }; }), $globals.AmberCli.a$cls); $core.addClass("BaseFileManipulator", $globals.Object, "AmberCli"); $core.setSlots($globals.BaseFileManipulator, ["path", "fs"]); $core.addMethod( $core.method({ selector: "dirname", protocol: "private", //>>excludeStart("ide", pragmas.excludeIdeData); args: [], source: "dirname\x0a\x09<inlineJS: 'return __dirname'>", referencedClasses: [], //>>excludeEnd("ide"); pragmas: [["inlineJS:", ["return __dirname"]]], messageSends: [] }, function ($methodClass){ return function (){ var self=this,$self=this; //>>excludeStart("ctx", pragmas.excludeDebugContexts); return $core.withContext(function($ctx1) { //>>excludeEnd("ctx"); return __dirname; return self; //>>excludeStart("ctx", pragmas.excludeDebugContexts); }, function($ctx1) {$ctx1.fill(self,"dirname",{})}); //>>excludeEnd("ctx"); }; }), $globals.BaseFileManipulator); $core.addMethod( $core.method({ selector: "initialize", protocol: "initialization", //>>excludeStart("ide", pragmas.excludeIdeData); args: [], source: "initialize\x0a\x09super initialize.\x0a\x09path := require value: 'path'.\x0a\x09fs := require value: 'fs'", referencedClasses: [], //>>excludeEnd("ide"); pragmas: [], messageSends: ["initialize", "value:"] }, function ($methodClass){ return function (){ var self=this,$self=this; //>>excludeStart("ctx", pragmas.excludeDebugContexts); return $core.withContext(function($ctx1) { //>>excludeEnd("ctx"); [( //>>excludeStart("ctx", pragmas.excludeDebugContexts); $ctx1.supercall = true, //>>excludeEnd("ctx"); ($methodClass.superclass||$boot.nilAsClass).fn.prototype._initialize.call($self)) //>>excludeStart("ctx", pragmas.excludeDebugContexts); ,$ctx1.supercall = false //>>excludeEnd("ctx"); ][0]; $self.path=[$recv(require)._value_("path") //>>excludeStart("ctx", pragmas.excludeDebugContexts); ,$ctx1.sendIdx["value:"]=1 //>>excludeEnd("ctx"); ][0]; $self.fs=$recv(require)._value_("fs"); return self; //>>excludeStart("ctx", pragmas.excludeDebugContexts); }, function($ctx1) {$ctx1.fill(self,"initialize",{})}); //>>excludeEnd("ctx"); }; }), $globals.BaseFileManipulator); $core.addMethod( $core.method({ selector: "rootDirname", protocol: "private", //>>excludeStart("ide", pragmas.excludeIdeData); args: [], source: "rootDirname\x0a\x09^ path join: self dirname with: '..'", referencedClasses: [], //>>excludeEnd("ide"); pragmas: [], messageSends: ["join:with:", "dirname"] }, function ($methodClass){ return function (){ var self=this,$self=this; //>>excludeStart("ctx", pragmas.excludeDebugContexts); return $core.withContext(function($ctx1) { //>>excludeEnd("ctx"); return $recv($self.path)._join_with_($self._dirname(),".."); //>>excludeStart("ctx", pragmas.excludeDebugContexts); }, function($ctx1) {$ctx1.fill(self,"rootDirname",{})}); //>>excludeEnd("ctx"); }; }), $globals.BaseFileManipulator); $core.addClass("Configurator", $globals.BaseFileManipulator, "AmberCli"); $core.addMethod( $core.method({ selector: "initialize", protocol: "initialization", //>>excludeStart("ide", pragmas.excludeIdeData); args: [], source: "initialize\x0a\x09super initialize", referencedClasses: [], //>>excludeEnd("ide"); pragmas: [], messageSends: ["initialize"] }, function ($methodClass){ return function (){ var self=this,$self=this; //>>excludeStart("ctx", pragmas.excludeDebugContexts); return $core.withContext(function($ctx1) { //>>excludeEnd("ctx"); [( //>>excludeStart("ctx", pragmas.excludeDebugContexts); $ctx1.supercall = true, //>>excludeEnd("ctx"); ($methodClass.superclass||$boot.nilAsClass).fn.prototype._initialize.call($self)) //>>excludeStart("ctx", pragmas.excludeDebugContexts); ,$ctx1.supercall = false //>>excludeEnd("ctx"); ][0]; return self; //>>excludeStart("ctx", pragmas.excludeDebugContexts); }, function($ctx1) {$ctx1.fill(self,"initialize",{})}); //>>excludeEnd("ctx"); }; }), $globals.Configurator); $core.addMethod( $core.method({ selector: "start", protocol: "action", //>>excludeStart("ide", pragmas.excludeIdeData); args: [], source: "start\x0a\x09self writeConfigThenDo: [ :err | err\x0a\x09\x09ifNotNil: [ process exit: 111 ]\x0a\x09\x09ifNil: [ process exit ]]", referencedClasses: [], //>>excludeEnd("ide"); pragmas: [], messageSends: ["writeConfigThenDo:", "ifNotNil:ifNil:", "exit:", "exit"] }, function ($methodClass){ return function (){ var self=this,$self=this; //>>excludeStart("ctx", pragmas.excludeDebugContexts); return $core.withContext(function($ctx1) { //>>excludeEnd("ctx"); $self._writeConfigThenDo_((function(err){ //>>excludeStart("ctx", pragmas.excludeDebugContexts); return $core.withContext(function($ctx2) { //>>excludeEnd("ctx"); if(err == null || err.a$nil){ return $recv(process)._exit(); } else { return $recv(process)._exit_((111)); } //>>excludeStart("ctx", pragmas.excludeDebugContexts); }, function($ctx2) {$ctx2.fillBlock({err:err},$ctx1,1)}); //>>excludeEnd("ctx"); })); return self; //>>excludeStart("ctx", pragmas.excludeDebugContexts); }, function($ctx1) {$ctx1.fill(self,"start",{})}); //>>excludeEnd("ctx"); }; }), $globals.Configurator); $core.addMethod( $core.method({ selector: "writeConfigThenDo:", protocol: "action", //>>excludeStart("ide", pragmas.excludeIdeData); args: ["aBlock"], source: "writeConfigThenDo: aBlock\x0a\x09(require value: '@ambers/sdk') configBuilder\x0a\x09\x09writeConfig: process cwd\x0a\x09\x09toFile: 'config.js'\x0a\x09\x09thenDo: aBlock", referencedClasses: [], //>>excludeEnd("ide"); pragmas: [], messageSends: ["writeConfig:toFile:thenDo:", "configBuilder", "value:", "cwd"] }, function ($methodClass){ return function (aBlock){ var self=this,$self=this; //>>excludeStart("ctx", pragmas.excludeDebugContexts); return $core.withContext(function($ctx1) { //>>excludeEnd("ctx"); $recv($recv($recv(require)._value_("@ambers/sdk"))._configBuilder())._writeConfig_toFile_thenDo_($recv(process)._cwd(),"config.js",aBlock); return self; //>>excludeStart("ctx", pragmas.excludeDebugContexts); }, function($ctx1) {$ctx1.fill(self,"writeConfigThenDo:",{aBlock:aBlock})}); //>>excludeEnd("ctx"); }; }), $globals.Configurator); $core.addClass("FileServer", $globals.BaseFileManipulator, "AmberCli"); $core.setSlots($globals.FileServer, ["http", "url", "host", "port", "basePath", "util", "username", "password", "fallbackPage"]); //>>excludeStart("ide", pragmas.excludeIdeData); $globals.FileServer.comment="I am the Amber Smalltalk FileServer.\x0aMy runtime requirement is a functional Node.js executable.\x0a\x0aTo start a FileServer instance on port `4000` use the following code:\x0a\x0a FileServer new start\x0a\x0aA parameterized instance can be created with the following code:\x0a\x0a FileServer createServerWithArguments: options\x0a\x0aHere, `options` is an array of commandline style strings each followed by a value e.g. `#('--port', '6000', '--host', '0.0.0.0')`.\x0aA list of all available parameters can be printed to the commandline by passing `--help` as parameter.\x0aSee the `Options` section for further details on how options are mapped to instance methods.\x0a\x0aAfter startup FileServer checks if the directory layout required by Amber is present and logs a warning on absence.\x0a\x0a\x0a## Options\x0a\x0aEach option is of the form `--some-option-string` which is transformed into a selector of the format `someOptionString:`.\x0aThe trailing `--` gets removed, each `-[a-z]` gets transformed into the according uppercase letter, and a `:` is appended to create a selector which takes a single argument.\x0aAfterwards, the selector gets executed on the `FileServer` instance with the value following in the options array as parameter.\x0a\x0a## Adding new commandline parameters\x0a\x0aAdding new commandline parameters to `FileServer` is as easy as adding a new single parameter method to the `accessing` protocol."; //>>excludeEnd("ide"); $core.addMethod( $core.method({ selector: "base64Decode:", protocol: "private", //>>excludeStart("ide", pragmas.excludeIdeData); args: ["aString"], source: "base64Decode: aString\x0a\x09<inlineJS: 'return (new Buffer(aString, \x22base64\x22).toString())'>", referencedClasses: [], //>>excludeEnd("ide"); pragmas: [["inlineJS:", ["return (new Buffer(aString, \x22base64\x22).toString())"]]], messageSends: [] }, function ($methodClass){ return function (aString){ var self=this,$self=this; //>>excludeStart("ctx", pragmas.excludeDebugContexts); return $core.withContext(function($ctx1) { //>>excludeEnd("ctx"); return (new Buffer(aString, "base64").toString()); return self; //>>excludeStart("ctx", pragmas.excludeDebugContexts); }, function($ctx1) {$ctx1.fill(self,"base64Decode:",{aString:aString})}); //>>excludeEnd("ctx"); }; }), $globals.FileServer); $core.addMethod( $core.method({ selector: "basePath", protocol: "accessing", //>>excludeStart("ide", pragmas.excludeIdeData); args: [], source: "basePath\x0a\x09^ basePath ifNil: [self class defaultBasePath]", referencedClasses: [], //>>excludeEnd("ide"); pragmas: [], messageSends: ["ifNil:", "defaultBasePath", "class"] }, function ($methodClass){ return function (){ var self=this,$self=this; //>>excludeStart("ctx", pragmas.excludeDebugContexts); return $core.withContext(function($ctx1) { //>>excludeEnd("ctx"); var $1; $1=$self.basePath; if($1 == null || $1.a$nil){ return $recv($self._class())._defaultBasePath(); } else { return $1; } //>>excludeStart("ctx", pragmas.excludeDebugContexts); }, function($ctx1) {$ctx1.fill(self,"basePath",{})}); //>>excludeEnd("ctx"); }; }), $globals.FileServer); $core.addMethod( $core.method({ selector: "basePath:", protocol: "accessing", //>>excludeStart("ide", pragmas.excludeIdeData); args: ["aString"], source: "basePath: aString\x0a\x09basePath := aString.\x0a\x09self validateBasePath.", referencedClasses: [], //>>excludeEnd("ide"); pragmas: [], messageSends: ["validateBasePath"] }, function ($methodClass){ return function (aString){ var self=this,$self=this; //>>excludeStart("ctx", pragmas.excludeDebugContexts); return $core.withContext(function($ctx1) { //>>excludeEnd("ctx"); $self.basePath=aString; $self._validateBasePath(); return self; //>>excludeStart("ctx", pragmas.excludeDebugContexts); }, function($ctx1) {$ctx1.fill(self,"basePath:",{aString:aString})}); //>>excludeEnd("ctx"); }; }), $globals.FileServer); $core.addMethod( $core.method({ selector: "checkDirectoryLayout", protocol: "initialization", //>>excludeStart("ide", pragmas.excludeIdeData); args: [], source: "checkDirectoryLayout\x0a\x09(fs existsSync:\x09(self withBasePath: 'index.html')) ifFalse: [\x0a\x09\x09console warn: 'Warning: project directory does not contain index.html.'.\x0a\x09\x09console warn: ' You can specify the directory containing index.html with --base-path.'.\x0a\x09\x09console warn: ' You can also specify a page to be served by default,'.\x0a\x09\x09console warn: ' for all paths that do not map to a file, with --fallback-page.'].", referencedClasses: [], //>>excludeEnd("ide"); pragmas: [], messageSends: ["ifFalse:", "existsSync:", "withBasePath:", "warn:"] }, function ($methodClass){ return function (){ var self=this,$self=this; //>>excludeStart("ctx", pragmas.excludeDebugContexts); return $core.withContext(function($ctx1) { //>>excludeEnd("ctx"); if(!$core.assert($recv($self.fs)._existsSync_($self._withBasePath_("index.html")))){ [$recv(console)._warn_("Warning: project directory does not contain index.html.") //>>excludeStart("ctx", pragmas.excludeDebugContexts); ,$ctx1.sendIdx["warn:"]=1 //>>excludeEnd("ctx"); ][0]; [$recv(console)._warn_(" You can specify the directory containing index.html with --base-path.") //>>excludeStart("ctx", pragmas.excludeDebugContexts); ,$ctx1.sendIdx["warn:"]=2 //>>excludeEnd("ctx"); ][0]; [$recv(console)._warn_(" You can also specify a page to be served by default,") //>>excludeStart("ctx", pragmas.excludeDebugContexts); ,$ctx1.sendIdx["warn:"]=3 //>>excludeEnd("ctx"); ][0]; $recv(console)._warn_(" for all paths that do not map to a file, with --fallback-page."); } return self; //>>excludeStart("ctx", pragmas.excludeDebugContexts); }, function($ctx1) {$ctx1.fill(self,"checkDirectoryLayout",{})}); //>>excludeEnd("ctx"); }; }), $globals.FileServer); $core.addMethod( $core.method({ selector: "fallbackPage", protocol: "accessing", //>>excludeStart("ide", pragmas.excludeIdeData); args: [], source: "fallbackPage\x0a\x09^ fallbackPage", referencedClasses: [], //>>excludeEnd("ide"); pragmas: [], messageSends: [] }, function ($methodClass){ return function (){ var self=this,$self=this; return $self.fallbackPage; }; }), $globals.FileServer); $core.addMethod( $core.method({ selector: "fallbackPage:", protocol: "accessing", //>>excludeStart("ide", pragmas.excludeIdeData); args: ["aString"], source: "fallbackPage: aString\x0a\x09fallbackPage := aString", referencedClasses: [], //>>excludeEnd("ide"); pragmas: [], messageSends: [] }, function ($methodClass){ return function (aString){ var self=this,$self=this; $self.fallbackPage=aString; return self; }; }), $globals.FileServer); $core.addMethod( $core.method({ selector: "handleGETRequest:respondTo:", protocol: "request handling", //>>excludeStart("ide", pragmas.excludeIdeData); args: ["aRequest", "aResponse"], source: "handleGETRequest: aRequest respondTo: aResponse\x0a\x09| uri filename |\x0a\x09uri := url parse: aRequest url.\x0a\x09filename := path join: self basePath with: uri pathname uriDecoded.\x0a\x09fs exists: filename do: [:aBoolean |\x0a\x09\x09aBoolean\x0a\x09\x09\x09ifFalse: [self respondNotFoundTo: aResponse]\x0a\x09\x09\x09ifTrue: [(fs statSync: filename) isDirectory\x0a\x09\x09\x09\x09ifTrue: [self respondDirectoryNamed: filename from: uri to: aResponse]\x0a\x09\x09\x09\x09ifFalse: [self respondFileNamed: filename to: aResponse]]]", referencedClasses: [], //>>excludeEnd("ide"); pragmas: [], messageSends: ["parse:", "url", "join:with:", "basePath", "uriDecoded", "pathname", "exists:do:", "ifFalse:ifTrue:", "respondNotFoundTo:", "ifTrue:ifFalse:", "isDirectory", "statSync:", "respondDirectoryNamed:from:to:", "respondFileNamed:to:"] }, function ($methodClass){ return function (aRequest,aResponse){ var self=this,$self=this; var uri,filename; //>>excludeStart("ctx", pragmas.excludeDebugContexts); return $core.withContext(function($ctx1) { //>>excludeEnd("ctx"); uri=$recv($self.url)._parse_($recv(aRequest)._url()); filename=$recv($self.path)._join_with_($self._basePath(),$recv($recv(uri)._pathname())._uriDecoded()); $recv($self.fs)._exists_do_(filename,(function(aBoolean){ //>>excludeStart("ctx", pragmas.excludeDebugContexts); return $core.withContext(function($ctx2) { //>>excludeEnd("ctx"); if($core.assert(aBoolean)){ if($core.assert($recv($recv($self.fs)._statSync_(filename))._isDirectory())){ return $self._respondDirectoryNamed_from_to_(filename,uri,aResponse); } else { return $self._respondFileNamed_to_(filename,aResponse); } } else { return $self._respondNotFoundTo_(aResponse); } //>>excludeStart("ctx", pragmas.excludeDebugContexts); }, function($ctx2) {$ctx2.fillBlock({aBoolean:aBoolean},$ctx1,1)}); //>>excludeEnd("ctx"); })); return self; //>>excludeStart("ctx", pragmas.excludeDebugContexts); }, function($ctx1) {$ctx1.fill(self,"handleGETRequest:respondTo:",{aRequest:aRequest,aResponse:aResponse,uri:uri,filename:filename})}); //>>excludeEnd("ctx"); }; }), $globals.FileServer); $core.addMethod( $core.method({ selector: "handleOPTIONSRequest:respondTo:", protocol: "request handling", //>>excludeStart("ide", pragmas.excludeIdeData); args: ["aRequest", "aResponse"], source: "handleOPTIONSRequest: aRequest respondTo: aResponse\x0a\x09aResponse writeHead: 200 options: #{'Access-Control-Allow-Origin' -> '*'.\x0a\x09\x09\x09\x09\x09'Access-Control-Allow-Methods' -> 'GET, PUT, POST, DELETE, OPTIONS'.\x0a\x09\x09\x09\x09\x09'Access-Control-Allow-Headers' -> 'Content-Type, Accept'.\x0a\x09\x09\x09\x09\x09'Content-Length' -> 0.\x0a\x09\x09\x09\x09\x09'Access-Control-Max-Age' -> 10}.\x0a\x09aResponse end", referencedClasses: [], //>>excludeEnd("ide"); pragmas: [], messageSends: ["writeHead:options:", "end"] }, function ($methodClass){ return function (aRequest,aResponse){ var self=this,$self=this; //>>excludeStart("ctx", pragmas.excludeDebugContexts); return $core.withContext(function($ctx1) { //>>excludeEnd("ctx"); $recv(aResponse)._writeHead_options_((200),$globals.HashedCollection._newFromPairs_(["Access-Control-Allow-Origin","*","Access-Control-Allow-Methods","GET, PUT, POST, DELETE, OPTIONS","Access-Control-Allow-Headers","Content-Type, Accept","Content-Length",(0),"Access-Control-Max-Age",(10)])); $recv(aResponse)._end(); return self; //>>excludeStart("ctx", pragmas.excludeDebugContexts); }, function($ctx1) {$ctx1.fill(self,"handleOPTIONSRequest:respondTo:",{aRequest:aRequest,aResponse:aResponse})}); //>>excludeEnd("ctx"); }; }), $globals.FileServer); $core.addMethod( $core.method({ selector: "handlePUTRequest:respondTo:", protocol: "request handling", //>>excludeStart("ide", pragmas.excludeIdeData); args: ["aRequest", "aResponse"], source: "handlePUTRequest: aRequest respondTo: aResponse\x0a\x09| file stream |\x0a\x09(self isAuthenticated: aRequest)\x0a\x09\x09ifFalse: [self respondAuthenticationRequiredTo: aResponse. ^ nil].\x0a\x0a\x09file := '.', aRequest url uriDecoded.\x0a\x09stream := fs createWriteStream: file.\x0a\x0a\x09stream on: 'error' do: [:error |\x0a\x09\x09console warn: 'Error creating WriteStream for file ', file.\x0a\x09\x09console warn: ' Did you forget to create the necessary directory in your project (often /src)?'.\x0a\x09\x09console warn: ' The exact error is: ', error asString.\x0a\x09\x09self respondNotCreatedTo: aResponse].\x0a\x0a\x09stream on: 'close' do: [\x0a\x09\x09self respondCreatedTo: aResponse].\x0a\x0a\x09aRequest setEncoding: 'utf8'.\x0a\x09aRequest on: 'data' do: [:data |\x0a\x09\x09stream write: data].\x0a\x0a\x09aRequest on: 'end' do: [\x0a\x09\x09stream writable ifTrue: [stream end]]", referencedClasses: [], //>>excludeEnd("ide"); pragmas: [], messageSends: ["ifFalse:", "isAuthenticated:", "respondAuthenticationRequiredTo:", ",", "uriDecoded", "url", "createWriteStream:", "on:do:", "warn:", "asString", "respondNotCreatedTo:", "respondCreatedTo:", "setEncoding:", "write:", "ifTrue:", "writable", "end"] }, function ($methodClass){ return function (aRequest,aResponse){ var self=this,$self=this; var file,stream; //>>excludeStart("ctx", pragmas.excludeDebugContexts); return $core.withContext(function($ctx1) { //>>excludeEnd("ctx"); if(!$core.assert($self._isAuthenticated_(aRequest))){ $self._respondAuthenticationRequiredTo_(aResponse); return nil; } file=[".".__comma($recv($recv(aRequest)._url())._uriDecoded()) //>>excludeStart("ctx", pragmas.excludeDebugContexts); ,$ctx1.sendIdx[","]=1 //>>excludeEnd("ctx"); ][0]; stream=$recv($self.fs)._createWriteStream_(file); [$recv(stream)._on_do_("error",(function(error){ //>>excludeStart("ctx", pragmas.excludeDebugContexts); return $core.withContext(function($ctx2) { //>>excludeEnd("ctx"); [$recv(console)._warn_(["Error creating WriteStream for file ".__comma(file) //>>excludeStart("ctx", pragmas.excludeDebugContexts); ,$ctx2.sendIdx[","]=2 //>>excludeEnd("ctx"); ][0]) //>>excludeStart("ctx", pragmas.excludeDebugContexts); ,$ctx2.sendIdx["warn:"]=1 //>>excludeEnd("ctx"); ][0]; [$recv(console)._warn_(" Did you forget to create the necessary directory in your project (often /src)?") //>>excludeStart("ctx", pragmas.excludeDebugContexts); ,$ctx2.sendIdx["warn:"]=2 //>>excludeEnd("ctx"); ][0]; $recv(console)._warn_(" The exact error is: ".__comma($recv(error)._asString())); return $self._respondNotCreatedTo_(aResponse); //>>excludeStart("ctx", pragmas.excludeDebugContexts); }, function($ctx2) {$ctx2.fillBlock({error:error},$ctx1,2)}); //>>excludeEnd("ctx"); })) //>>excludeStart("ctx", pragmas.excludeDebugContexts); ,$ctx1.sendIdx["on:do:"]=1 //>>excludeEnd("ctx"); ][0]; [$recv(stream)._on_do_("close",(function(){ //>>excludeStart("ctx", pragmas.excludeDebugContexts); return $core.withContext(function($ctx2) { //>>excludeEnd("ctx"); return $self._respondCreatedTo_(aResponse); //>>excludeStart("ctx", pragmas.excludeDebugContexts); }, function($ctx2) {$ctx2.fillBlock({},$ctx1,3)}); //>>excludeEnd("ctx"); })) //>>excludeStart("ctx", pragmas.excludeDebugContexts); ,$ctx1.sendIdx["on:do:"]=2 //>>excludeEnd("ctx"); ][0]; $recv(aRequest)._setEncoding_("utf8"); [$recv(aRequest)._on_do_("data",(function(data){ //>>excludeStart("ctx", pragmas.excludeDebugContexts); return $core.withContext(function($ctx2) { //>>excludeEnd("ctx"); return $recv(stream)._write_(data); //>>excludeStart("ctx", pragmas.excludeDebugContexts); }, function($ctx2) {$ctx2.fillBlock({data:data},$ctx1,4)}); //>>excludeEnd("ctx"); })) //>>excludeStart("ctx", pragmas.excludeDebugContexts); ,$ctx1.sendIdx["on:do:"]=3 //>>excludeEnd("ctx"); ][0]; $recv(aRequest)._on_do_("end",(function(){ //>>excludeStart("ctx", pragmas.excludeDebugContexts); return $core.withContext(function($ctx2) { //>>excludeEnd("ctx"); if($core.assert($recv(stream)._writable())){ return $recv(stream)._end(); } //>>excludeStart("ctx", pragmas.excludeDebugContexts); }, function($ctx2) {$ctx2.fillBlock({},$ctx1,5)}); //>>excludeEnd("ctx"); })); return self; //>>excludeStart("ctx", pragmas.excludeDebugContexts); }, function($ctx1) {$ctx1.fill(self,"handlePUTRequest:respondTo:",{aRequest:aRequest,aResponse:aResponse,file:file,stream:stream})}); //>>excludeEnd("ctx"); }; }), $globals.FileServer); $core.addMethod( $core.method({ selector: "handleRequest:respondTo:", protocol: "request handling", //>>excludeStart("ide", pragmas.excludeIdeData); args: ["aRequest", "aResponse"], source: "handleRequest: aRequest respondTo: aResponse\x0a\x09aRequest method = 'PUT'\x0a\x09\x09ifTrue: [self handlePUTRequest: aRequest respondTo: aResponse].\x0a\x09aRequest method = 'GET'\x0a\x09\x09ifTrue:[self handleGETRequest: aRequest respondTo: aResponse].\x0a\x09aRequest method = 'OPTIONS'\x0a\x09\x09ifTrue:[self handleOPTIONSRequest: aRequest respondTo: aResponse]", referencedClasses: [], //>>excludeEnd("ide"); pragmas: [], messageSends: ["ifTrue:", "=", "method", "handlePUTRequest:respondTo:", "handleGETRequest:respondTo:", "handleOPTIONSRequest:respondTo:"] }, function ($methodClass){ return function (aRequest,aResponse){ var self=this,$self=this; //>>excludeStart("ctx", pragmas.excludeDebugContexts); return $core.withContext(function($ctx1) { //>>excludeEnd("ctx"); if($core.assert([$recv([$recv(aRequest)._method() //>>excludeStart("ctx", pragmas.excludeDebugContexts); ,$ctx1.sendIdx["method"]=1 //>>excludeEnd("ctx"); ][0]).__eq("PUT") //>>excludeStart("ctx", pragmas.excludeDebugContexts); ,$ctx1.sendIdx["="]=1 //>>excludeEnd("ctx"); ][0])){ $self._handlePUTRequest_respondTo_(aRequest,aResponse); } if($core.assert([$recv([$recv(aRequest)._method() //>>excludeStart("ctx", pragmas.excludeDebugContexts); ,$ctx1.sendIdx["method"]=2 //>>excludeEnd("ctx"); ][0]).__eq("GET") //>>excludeStart("ctx", pragmas.excludeDebugContexts); ,$ctx1.sendIdx["="]=2 //>>excludeEnd("ctx"); ][0])){ $self._handleGETRequest_respondTo_(aRequest,aResponse); } if($core.assert($recv($recv(aRequest)._method()).__eq("OPTIONS"))){ $self._handleOPTIONSRequest_respondTo_(aRequest,aResponse); } return self; //>>excludeStart("ctx", pragmas.excludeDebugContexts); }, function($ctx1) {$ctx1.fill(self,"handleRequest:respondTo:",{aRequest:aRequest,aResponse:aResponse})}); //>>excludeEnd("ctx"); }; }), $globals.FileServer); $core.addMethod( $core.method({ selector: "host", protocol: "accessing", //>>excludeStart("ide", pragmas.excludeIdeData); args: [], source: "host\x0a\x09^ host", referencedClasses: [], //>>excludeEnd("ide"); pragmas: [], messageSends: [] }, function ($methodClass){ return function (){ var self=this,$self=this; return $self.host; }; }), $globals.FileServer); $core.addMethod( $core.method({ selector: "host:", protocol: "accessing", //>>excludeStart("ide", pragmas.excludeIdeData); args: ["hostname"], source: "host: hostname\x0a\x09host := hostname", referencedClasses: [], //>>excludeEnd("ide"); pragmas: [], messageSends: [] }, function ($methodClass){ return function (hostname){ var self=this,$self=this; $self.host=hostname; return self; }; }), $globals.FileServer); $core.addMethod( $core.method({ selector: "initialize", protocol: "initialization", //>>excludeStart("ide", pragmas.excludeIdeData); args: [], source: "initialize\x0a\x09super initialize.\x0a\x09http := self require: 'http'.\x0a\x09util := self require: 'util'.\x0a\x09url := self require: 'url'.\x0a\x09host := self class defaultHost.\x0a\x09port := self class defaultPort.\x0a\x09username := nil.\x0a\x09password := nil.\x0a\x09fallbackPage := nil.", referencedClasses: [], //>>excludeEnd("ide"); pragmas: [], messageSends: ["initialize", "require:", "defaultHost", "class", "defaultPort"] }, function ($methodClass){ return function (){ var self=this,$self=this; //>>excludeStart("ctx", pragmas.excludeDebugContexts); return $core.withContext(function($ctx1) { //>>excludeEnd("ctx"); [( //>>excludeStart("ctx", pragmas.excludeDebugContexts); $ctx1.supercall = true, //>>excludeEnd("ctx"); ($methodClass.superclass||$boot.nilAsClass).fn.prototype._initialize.call($self)) //>>excludeStart("ctx", pragmas.excludeDebugContexts); ,$ctx1.supercall = false //>>excludeEnd("ctx"); ][0]; $self.http=[$self._require_("http") //>>excludeStart("ctx", pragmas.excludeDebugContexts); ,$ctx1.sendIdx["require:"]=1 //>>excludeEnd("ctx"); ][0]; $self.util=[$self._require_("util") //>>excludeStart("ctx", pragmas.excludeDebugContexts); ,$ctx1.sendIdx["require:"]=2 //>>excludeEnd("ctx"); ][0]; $self.url=$self._require_("url"); $self.host=$recv([$self._class() //>>excludeStart("ctx", pragmas.excludeDebugContexts); ,$ctx1.sendIdx["class"]=1 //>>excludeEnd("ctx"); ][0])._defaultHost(); $self.port=$recv($self._class())._defaultPort(); $self.username=nil; $self.password=nil; $self.fallbackPage=nil; return self; //>>excludeStart("ctx", pragmas.excludeDebugContexts); }, function($ctx1) {$ctx1.fill(self,"initialize",{})}); //>>excludeEnd("ctx"); }; }), $globals.FileServer); $core.addMethod( $core.method({ selector: "isAuthenticated:", protocol: "private", //>>excludeStart("ide", pragmas.excludeIdeData); args: ["aRequest"], source: "isAuthenticated: aRequest\x0a\x09\x22Basic HTTP Auth: http://stackoverflow.com/a/5957629/293175\x0a\x09 and https://gist.github.com/1686663\x22\x0a\x09| header token auth parts|\x0a\x0a\x09(username isNil and: [password isNil]) ifTrue: [^ true].\x0a\x0a\x09\x22get authentication header\x22\x0a\x09header := (aRequest headers at: 'authorization') ifNil:[''].\x0a\x09header\x0a\x09ifEmpty: [^ false]\x0a\x09ifNotEmpty: [\x0a\x09\x09\x22get authentication token\x22\x0a\x09\x09token := (header tokenize: ' ') ifNil:[''].\x0a\x09\x09\x22convert back from base64\x22\x0a\x09\x09auth := self base64Decode: (token at: 2).\x0a\x09\x09\x22split token at colon\x22\x0a\x09\x09parts := auth tokenize: ':'.\x0a\x0a\x09\x09((username = (parts at: 1)) and: [password = (parts at: 2)])\x0a\x09\x09\x09ifTrue: [^ true]\x0a\x09\x09\x09ifFalse: [^ false]\x0a\x09].", referencedClasses: [], //>>excludeEnd("ide"); pragmas: [], messageSends: ["ifTrue:", "and:", "isNil", "ifNil:", "at:", "headers", "ifEmpty:ifNotEmpty:", "tokenize:", "base64Decode:", "ifTrue:ifFalse:", "="] }, function ($methodClass){ return function (aRequest){ var self=this,$self=this; var header,token,auth,parts; //>>excludeStart("ctx", pragmas.excludeDebugContexts); return $core.withContext(function($ctx1) { //>>excludeEnd("ctx"); var $1,$2,$3,$4; var $early={}; try { if($core.assert([$recv($self.username)._isNil() //>>excludeStart("ctx", pragmas.excludeDebugContexts); ,$ctx1.sendIdx["isNil"]=1 //>>excludeEnd("ctx"); ][0])){ $1=$recv($self.password)._isNil(); } else { $1=false; } if($core.assert($1)){ return true; } $2=[$recv($recv(aRequest)._headers())._at_("authorization") //>>excludeStart("ctx", pragmas.excludeDebugContexts); ,$ctx1.sendIdx["at:"]=1 //>>excludeEnd("ctx"); ][0]; if($2 == null || $2.a$nil){ header=""; } else { header=$2; } $recv(header)._ifEmpty_ifNotEmpty_((function(){ throw $early=[false]; }),(function(){ //>>excludeStart("ctx", pragmas.excludeDebugContexts); return $core.withContext(function($ctx2) { //>>excludeEnd("ctx"); $3=[$recv(header)._tokenize_(" ") //>>excludeStart("ctx", pragmas.excludeDebugContexts); ,$ctx2.sendIdx["tokenize:"]=1 //>>excludeEnd("ctx"); ][0]; if($3 == null || $3.a$nil){ token=""; } else { token=$3; } auth=$self._base64Decode_([$recv(token)._at_((2)) //>>excludeStart("ctx", pragmas.excludeDebugContexts); ,$ctx2.sendIdx["at:"]=2 //>>excludeEnd("ctx"); ][0]); parts=$recv(auth)._tokenize_(":"); if($core.assert([$recv($self.username).__eq([$recv(parts)._at_((1)) //>>excludeStart("ctx", pragmas.excludeDebugContexts); ,$ctx2.sendIdx["at:"]=3 //>>excludeEnd("ctx"); ][0]) //>>excludeStart("ctx", pragmas.excludeDebugContexts); ,$ctx2.sendIdx["="]=1 //>>excludeEnd("ctx"); ][0])){ $4=$recv($self.password).__eq($recv(parts)._at_((2))); } else { $4=false; } if($core.assert($4)){ throw $early=[true]; } else { throw $early=[false]; } //>>excludeStart("ctx", pragmas.excludeDebugContexts); }, function($ctx2) {$ctx2.fillBlock({},$ctx1,5)}); //>>excludeEnd("ctx"); })); return self; } catch(e) {if(e===$early)return e[0]; throw e} //>>excludeStart("ctx", pragmas.excludeDebugContexts); }, function($ctx1) {$ctx1.fill(self,"isAuthenticated:",{aRequest:aRequest,header:header,token:token,auth:auth,parts:parts})}); //>>excludeEnd("ctx"); }; }), $globals.FileServer); $core.addMethod( $core.method({ selector: "password:", protocol: "accessing", //>>excludeStart("ide", pragmas.excludeIdeData); args: ["aPassword"], source: "password: aPassword\x0a\x09password := aPassword.", referencedClasses: [], //>>excludeEnd("ide"); pragmas: [], messageSends: [] }, function ($methodClass){ return function (aPassword){ var self=this,$self=this; $self.password=aPassword; return self; }; }), $globals.FileServer); $core.addMethod( $core.method({ selector: "port", protocol: "accessing", //>>excludeStart("ide", pragmas.excludeIdeData); args: [], source: "port\x0a\x09^ port", referencedClasses: [], //>>excludeEnd("ide"); pragmas: [], messageSends: [] }, function ($methodClass){ return function (){ var self=this,$self=this; return $self.port; }; }), $globals.FileServer); $core.addMethod( $core.method({ selector: "port:", protocol: "accessing", //>>excludeStart("ide", pragmas.excludeIdeData); args: ["aNumber"], source: "port: aNumber\x0a\x09port := aNumber", referencedClasses: [], //>>excludeEnd("ide"); pragmas: [], messageSends: [] }, function ($methodClass){ return function (aNumber){ var self=this,$self=this; $self.port=aNumber; return self; }; }), $globals.FileServer); $core.addMethod( $core.method({ selector: "require:", protocol: "private", //>>excludeStart("ide", pragmas.excludeIdeData); args: ["aModuleString"], source: "require: aModuleString\x0a\x09\x22call to the require function\x22\x0a\x09^require value: aModuleString", referencedClasses: [], //>>excludeEnd("ide"); pragmas: [], messageSends: ["value:"] }, function ($methodClass){ return function (aModuleString){ var self=this,$self=this; //>>excludeStart("ctx", pragmas.excludeDebugContexts); return $core.withContext(function($ctx1) { //>>excludeEnd("ctx"); return $recv(require)._value_(aModuleString); //>>excludeStart("ctx", pragmas.excludeDebugContexts); }, function($ctx1) {$ctx1.fill(self,"require:",{aModuleString:aModuleString})}); //>>excludeEnd("ctx"); }; }), $globals.FileServer); $core.addMethod( $core.method({ selector: "respondAuthenticationRequiredTo:", protocol: "request handling", //>>excludeStart("ide", pragmas.excludeIdeData); args: ["aResponse"], source: "respondAuthenticationRequiredTo: aResponse\x0a\x09aResponse\x0a\x09\x09writeHead: 401 options: #{'WWW-Authenticate' -> 'Basic realm=\x22Secured Developer Area\x22'};\x0a\x09\x09write: '<html><body>Authentication needed</body></html>';\x0a\x09\x09end.", referencedClasses: [], //>>excludeEnd("ide"); pragmas: [], messageSends: ["writeHead:options:", "write:", "end"] }, function ($methodClass){ return function (aResponse){ var self=this,$self=this; //>>excludeStart("ctx", pragmas.excludeDebugContexts); return $core.withContext(function($ctx1) { //>>excludeEnd("ctx"); $recv(aResponse)._writeHead_options_((401),$globals.HashedCollection._newFromPairs_(["WWW-Authenticate","Basic realm=\x22Secured Developer Area\x22"])); $recv(aResponse)._write_("<html><body>Authentication needed</body></html>"); $recv(aResponse)._end(); return self; //>>excludeStart("ctx", pragmas.excludeDebugContexts); }, function($ctx1) {$ctx1.fill(self,"respondAuthenticationRequiredTo:",{aResponse:aResponse})}); //>>excludeEnd("ctx"); }; }), $globals.FileServer); $core.addMethod( $core.method({ selector: "respondCreatedTo:", protocol: "request handling", //>>excludeStart("ide", pragmas.excludeIdeData); args: ["aResponse"], source: "respondCreatedTo: aResponse\x0a\x09aResponse\x0a\x09\x09writeHead: 201 options: #{'Content-Type' -> 'text/plain'. 'Access-Control-Allow-Origin' -> '*'};\x0a\x09\x09end.", referencedClasses: [], //>>excludeEnd("ide"); pragmas: [], messageSends: ["writeHead:options:", "end"] }, function ($methodClass){ return function (aResponse){ var self=this,$self=this; //>>excludeStart("ctx", pragmas.excludeDebugContexts); return $core.withContext(function($ctx1) { //>>excludeEnd("ctx"); $recv(aResponse)._writeHead_options_((201),$globals.HashedCollection._newFromPairs_(["Content-Type","text/plain","Access-Control-Allow-Origin","*"])); $recv(aResponse)._end(); return self; //>>excludeStart("ctx", pragmas.excludeDebugContexts); }, function($ctx1) {$ctx1.fill(self,"respondCreatedTo:",{aResponse:aResponse})}); //>>excludeEnd("ctx"); }; }), $globals.FileServer); $core.addMethod( $core.method({ selector: "respondDirectoryNamed:from:to:", protocol: "request handling", //>>excludeStart("ide", pragmas.excludeIdeData); args: ["aDirname", "aUrl", "aResponse"], source: "respondDirectoryNamed: aDirname from: aUrl to: aResponse\x0a\x09(aUrl pathname endsWith: '/')\x0a\x09\x09ifTrue: [self respondFileNamed: aDirname, 'index.html' to: aResponse]\x0a\x09\x09ifFalse: [self respondRedirect: aUrl pathname, '/', (aUrl search ifNil: ['']) to: aResponse]", referencedClasses: [], //>>excludeEnd("ide"); pragmas: [], messageSends: ["ifTrue:ifFalse:", "endsWith:", "pathname", "respondFileNamed:to:", ",", "respondRedirect:to:", "ifNil:", "search"] }, function ($methodClass){ return function (aDirname,aUrl,aResponse){ var self=this,$self=this; //>>excludeStart("ctx", pragmas.excludeDebugContexts); return $core.withContext(function($ctx1) { //>>excludeEnd("ctx"); var $1,$2,$3; if($core.assert($recv([$recv(aUrl)._pathname() //>>excludeStart("ctx", pragmas.excludeDebugContexts); ,$ctx1.sendIdx["pathname"]=1 //>>excludeEnd("ctx"); ][0])._endsWith_("/"))){ $self._respondFileNamed_to_([$recv(aDirname).__comma("index.html") //>>excludeStart("ctx", pragmas.excludeDebugContexts); ,$ctx1.sendIdx[","]=1 //>>excludeEnd("ctx"); ][0],aResponse); } else { $1=$recv($recv(aUrl)._pathname()).__comma("/"); $2=$recv(aUrl)._search