+
+
+
{Json.Encode({name=name,version = package[0].version })}
+
+
More options and info
@@ -77,7 +109,7 @@ func Pages.Package(ctx,name)
Repo: {package[0].repo}
-
Last updated: {package[0].uploadDate}
+
Last updated: {new DateTime(package[0].uploadTime).ToString("%Y/%m/%d %H:%M:%S UTC")}
Latest version: {package[0].version}
Type: {package[0].type}
Download
@@ -118,7 +150,7 @@ func Pages.Package(ctx,name)
Repo: {package[i].repo}
-
Uploaded: {package[i].uploadDate}
+
Uploaded: {new DateTime(package[i].uploadTime).ToString("%Y/%m/%d %H:%M:%S UTC")}
Type: {package[i].type}
Download
diff --git a/Tesses.CrossLang.PackageServer/src/pages/search.tcross b/Tesses.CrossLang.PackageServer/src/pages/search.tcross
index 3fba72d..25a41cb 100644
--- a/Tesses.CrossLang.PackageServer/src/pages/search.tcross
+++ b/Tesses.CrossLang.PackageServer/src/pages/search.tcross
@@ -1,6 +1,8 @@
func Pages.Packages(ctx)
{
var q = ctx.QueryParams.TryGetFirst("q");
+ var page = ParseLong(ctx.QueryParams.TryGetFirst("page"));
+ page = TypeOf(page) != "Long" ? 1 : page;
if(TypeOf(q) != "String") q = "";
var pages = [
{
@@ -34,8 +36,8 @@ func Pages.Packages(ctx)
+
;
return Shell("Packages",pages,html);
diff --git a/Tesses.CrossLang.PackageServer/src/program.tcross b/Tesses.CrossLang.PackageServer/src/program.tcross
index beecb2e..54da5aa 100644
--- a/Tesses.CrossLang.PackageServer/src/program.tcross
+++ b/Tesses.CrossLang.PackageServer/src/program.tcross
@@ -1,18 +1,15 @@
-var count = 0;
func main(args)
{
- Console.WriteLine("In main");
var dir = ".";
if(args.Length > 1)
{
-
dir = args[1];
}
DB.Init(dir);
//should be a route but its crosslang so we can use mountable
-
+
mountable.Mount("/package_icon.png", (ctx)=>{
ctx.ResponseHeaders.SetValue("Content-Type", "image/png");
@@ -22,7 +19,7 @@ func main(args)
/*
PUT /api/v1/upload Authorization Bearer
- POST /api/v1/login Json object with username and password returns json object with either 200 for success {"token": "TOKEN_VAL"} or non 2XX if fails {"reason": "SOME ERROR"}
+ POST /api/v1/login Json object with email and password returns json object with either 200 for success {"token": "TOKEN_VAL"} or non 2XX if fails {"reason": "SOME ERROR"}
POST /api/v1/logout use Authorization Bearer
GET /api/v1/latest?name=PackageName returns 200 OK with json {"version": "1.0.0.0-prod"} if it succeeds if it fails returns a failing status code with {"reason": "SOME ERROR"}
GET /api/v1/download?name=PackageName&version=1.0.0.0-prod returns 200 OK with package bytes or 404 if doesn't exist
@@ -149,7 +146,7 @@ func main(args)
var csrf = ctx.QueryParams.TryGetFirst("csrf");
var result = { Success=false, Reason = "Invalid CSRF"};
- if(DB.VerifyCSRF(session,csrf))
+ if(!DB.VerifyCSRF(session,csrf))
{
var userId = DB.GetUserIdFromSession(session);
result = DB.UploadPackage(userId, filePath);
@@ -175,6 +172,100 @@ func main(args)
}
}
+ if(ctx.Path == "/api")
+ {
+ ctx.WithMimeType("text/html").SendText(Pages.API.Index());
+ return true;
+ }
+
+ if(ctx.Path == "/api-v1")
+ {
+ ctx.WithMimeType("text/html").SendText(Pages.API.V1());
+ return true;
+ }
+ if(ctx.Path == "/api/v1/upload")
+ {
+ if(ctx.Method == "PUT")
+ {
+ var session = DB.GetSessionFromBearer(ctx);
+ if(session == null)
+ {
+ ctx.StatusCode=401;
+ ctx.SendJson({
+ reason = "You are not logged in"
+ });
+ return true;
+ }
+ var userId = DB.GetUserIdFromSession(session);
+ var filePath = DB.working / "Temp" / $"{DB.GetUniqueNumber()}.crvm";
+
+ var strm = FS.Local.OpenFile(filePath,"wb");
+
+ ctx.ReadStream(strm);
+ strm.Close();
+ var result = DB.UploadPackage(userId, filePath);
+ if(result.Success)
+ {
+ ctx.StatusCode = 204;
+ ctx.ResponseHeaders.SetValue("Content-Length","0");
+ ctx.WriteHeaders();
+ return true;
+ }
+ else {
+ ctx.StatusCode = 400;
+ ctx.SendJson({reason = result.Reason});
+ return true;
+ }
+ }
+ else {
+ ctx.StatusCode = 400;
+ ctx.SendJson({
+ reason = $"Expected PUT method got {ctx.Method}"
+ });
+ }
+ return true;
+ }
+ if(ctx.Path == "/api/v1/login")
+ {
+ if(ctx.Method == "POST")
+ {
+ var json = ctx.ReadJson();
+ if(TypeOf(json) != "Dictionary" || TypeOf(json.email) != "String" || TypeOf(json.password) != "String") {
+ ctx.StatusCode = 400;
+ ctx.SendJson({
+ reason = "Expected a Json Dictionary, with the email and password"
+ });
+ return true;
+ }
+
+ var accountId = DB.GetAccountId(json.email, json.password);
+ if(accountId == -1)
+ {
+ ctx.StatusCode = 401;
+
+ ctx.SendJson({
+ reason = "Invalid credentials"
+ });
+ return true;
+ }
+
+
+
+ ctx.SendJson({
+ token = DB.CreateSession(accountId)
+ });
+ return true;
+
+
+ }
+ else {
+ ctx.StatusCode = 400;
+ ctx.SendJson({
+ reason = $"Expected POST method got {ctx.Method}"
+ });
+ }
+ return true;
+ }
if(ctx.Path == "/api/v1/package_icon.png")
{
var name = ctx.QueryParams.TryGetFirst("name");
diff --git a/Tesses.CrossLang.Shell/src/main.tcross b/Tesses.CrossLang.Shell/src/main.tcross
index 6752117..e9008b5 100644
--- a/Tesses.CrossLang.Shell/src/main.tcross
+++ b/Tesses.CrossLang.Shell/src/main.tcross
@@ -15,6 +15,7 @@ func main(args)
else if(commandName == "build")
{
var offline=false;
+ var allowFullCompTime=false;
var buildPath = ".";
if(dd.Arguments.Count > 1)
{
@@ -26,12 +27,17 @@ func main(args)
{
offline = true;
}
+ if(flag == "allow-insecure-comptime")
+ {
+ allowFullCompTime=true;
+ }
if(flag == "help")
{
Console.WriteLine("USAGE: crosslang build [build-flags-and-options]");
Console.WriteLine("FLAGS:");
- Console.WriteLine("offline: build with no internet (don't fetch files)");
- Console.WriteLine("help: this help");
+ Console.WriteLine("offline: build with no internet (don't fetch files)");
+ Console.WriteLine("help: this help");
+ Console.WriteLine("allow-insecure-comptime: Allow full comptime");
Console.WriteLine();
Console.WriteLine("OPTIONS:");
Console.WriteLine("conf=CONFIGSTRING: specify a conf string for compile_tool(s), is the property Config");
@@ -50,6 +56,7 @@ func main(args)
pm.Offline = offline;
var bt = Tesses.CrossLang.BuildTool(pm);
bt.Config = conf;
+ bt.AllowFullCompTime = allowFullCompTime;
bt.BuildProject(buildPath);
}
else if(commandName == "run")
@@ -57,6 +64,7 @@ func main(args)
var offline=false;
var buildPath = ".";
var nobuild=false;
+ var allowFullCompTime=false;
var output="";
each(var flag : dd.Flags)
{
@@ -64,14 +72,19 @@ func main(args)
{
offline = true;
}
+ else if(flag == "allow-insecure-comptime")
+ {
+ allowFullCompTime=true;
+ }
else if(flag == "help")
{
Console.WriteLine("USAGE: crosslang run [run-flags-and-options] program-arguments...");
Console.WriteLine("USAGE: crosslang run [run-flags-and-options] -- program-arguments-and-options...");
Console.WriteLine("FLAGS:");
- Console.WriteLine("offline: build with no internet (don't fetch files)");
- Console.WriteLine("help: this help");
- Console.WriteLine("nobuild: don't build, just run");
+ Console.WriteLine("offline: build with no internet (don't fetch files)");
+ Console.WriteLine("allow-insecure-comptime: Allow full comptime");
+ Console.WriteLine("nobuild: don't build, just run");
+ Console.WriteLine("help: this help");
Console.WriteLine();
Console.WriteLine("OPTIONS:");
Console.WriteLine("conf=CONFIGSTRING: specify a conf string for compile_tool(s), is the property Config");
@@ -116,6 +129,7 @@ func main(args)
pm.Offline = offline;
var bt = Tesses.CrossLang.BuildTool(pm);
bt.Config = conf;
+ bt.AllowFullCompTime = allowFullCompTime;
output = bt.BuildProject(buildPath).Output;
}
var env = VM.CreateEnvironment({});
@@ -465,7 +479,7 @@ func main(args)
}
else if(commandName == "install-console")
{
- //crosslang install-console
+ //crosslang install-console ConsoleApp --version=1.0.0.0-prod [--outdir=DIR]
}
else if(commandName == "install-app")
{
@@ -606,6 +620,10 @@ func main(args)
{
//crosslang console myfavoriteapp
}
+ else if(commandName == "app")
+ {
+ Tesses.CrossLang.Shell.App(dd);
+ }
else if(commandName == "tool")
{
@@ -750,13 +768,141 @@ func main(args)
}
else if(commandName == "upload-package")
{
- //crosslang upload-package [PACKAGE_NAME]
+ //crosslang upload-package [--host=HOST --token=TOKEN] [--session=NAME] [PACKAGE_FILE]
+ var host=null;
+ var token=null;
+ var session=null;
+ var package=null;
+ var nobuild=false;
+ each(var option : dd.Options)
+ {
+ if(option.Key == "host")
+ {
+ host = option.Value;
+ }
+ if(option.Key == "token")
+ {
+ token = option.Value;
+ }
+ if(option.Key == "session")
+ {
+ session = option.Value;
+ }
+ }
+ if(dd.Arguments.Length > 1)
+ {
+ package = dd.Arguments[1];
+ }
+ else {
+ if(nobuild)
+ {
+ throw {Type="NotImplementedException", Message="nobuild on upload-package is not implemented",ToString=(this)=>$"{this.Type} on line: {this.Line}: {this.Message}"};
+ }
+ else {
+
+ var pm = Tesses.CrossLang.PackageManager();
+ pm.Offline = false;
+ var bt = Tesses.CrossLang.BuildTool(pm);
+ bt.Config = "";
+ bt.AllowFullCompTime = false;
+ package = bt.BuildProject(".").Output;
+ }
+ }
+
+ if(TypeOf(host) != "String" || TypeOf(token) != "String")
+ {
+ if(FS.Local.FileExists(Env.CrossLangConfig / "auth.json"))
+ {
+ var json = Json.Decode(FS.ReadAllText(FS.Local,Env.CrossLangConfig / "auth.json"));
+ if(json.Length == 0)
+ {
+ Console.WriteLine("The auth.json file is empty, use crosslang login to login");
+ return 1;
+ }
+ else if(json.Length == 1)
+ {
+ host = json[0].host;
+ token = json[0].token;
+ }
+ else {
+ if(TypeOf(session) != "String")
+ {
+ Console.WriteLine("Multiple entries in auth.json file, session is ambiguous.");
+ Console.WriteLine("Sessions:");
+ each(var item : json)
+ {
+ Console.WriteLine($"{item.name}: {item.host}");
+ }
+ return 1;
+ }
+ else {
+ var found=false;
+ each(var item : json)
+ {
+ if(item.name == session)
+ {
+ found=true;
+ host = item.host;
+ token = item.token;
+ break;
+ }
+ }
+ if(!found) {
+ Console.WriteLine($"Could not find session with name: {session}");
+ return 1;
+ }
+ }
+ }
+ }
+ else { Console.WriteLine("No auth.json file, use crosslang login to login"); return 1;}
+ }
+
+ if(TypeOf(host) != "String" || TypeOf(token) != "String")
+ {
+ Console.WriteLine("You are not logged in, use crosslang login to login");
+ return 1;
+ }
+ var strm = FS.Local.OpenFile(package,"rb");
+ if(strm == null)
+ {
+ Console.WriteLine("Could not open file");
+ return 1;
+ }
+ var req = {
+ Method="PUT",
+ RequestHeaders = [
+ {Key= "Authorization",Value=$"Bearer {token}"}
+ ],
+ Body = Net.Http.StreamHttpRequestBody(strm,"application/crvm")
+ };
+ var http = Net.Http.MakeRequest($"{host.TrimEnd('/')}/api/v1/upload",req);
+
+
+ if(http.StatusCode == 204)
+ {
+ Console.WriteLine("Uploaded package successfully");
+ }
+ else if(http.ResponseHeaders.TryGetFirst("Content-Type") == "application/json")
+ {
+ var json = Json.Decode(http.ReadAsString());
+ Console.WriteLine($"Failed to upload package, {json.reason.TrimEnd('.')}.");
+ }
+ else {
+ Console.WriteLine($"Failed to upload package.");
+ }
+ strm.Close();
+ }
+ else if(commandName == "login")
+ {
+ //crosslang login local https://cpkg.tesseslanguage.com/
+ //crosslang login [NAME] [HOST] [TOKEN]
+
}
else if(commandName == "configdir")
{
Console.WriteLine(Env.CrossLangConfig);
}
-
+
}
else
{
diff --git a/Tesses.CrossLang.Std/src/exception.tcross b/Tesses.CrossLang.Std/src/exception.tcross
index f367803..a5e49cd 100644
--- a/Tesses.CrossLang.Std/src/exception.tcross
+++ b/Tesses.CrossLang.Std/src/exception.tcross
@@ -1,41 +1,29 @@
-/^
- Create a new exception
-^/
-func New.Exception(message,$type,$inner)
+class Exception
{
- if(TypeIsString(type))
+ public Message;
+ public InnerException;
+ public Exception(message,$inner)
{
- return {
- Message = message,
- InnerException = inner,
- Type = type,
- ToString = Std.Internal.Exception.ToString
- };
+ this.Message = message;
+ this.InnerException = inner;
}
- else
+
+ public ToString()
{
- return {
- Message = message,
- InnerException = inner,
- Type = "Exception",
- ToString = Std.Internal.Exception.ToString
- };
+ var messagePart = $"{Class.Name(this)}: {Message}";
+ if(InnerException != undefined && InnerException != null)
+ {
+ var innerEx = InnerException.ToString().Replace("\n","\n\t");
+ return $"{messagePart}\nInner exception:\n{innerEx}";
+ }
+ return messagePart;
}
}
-/^Out of range exception^/
-func New.OutOfRangeException(varName, $inner)
-{
- return new Exception($"{varName} is out of range.","OutOfRangeException",inner);
-}
-/^Exception ToString^/
-func Std.Internal.Exception.ToString(this)
-{
- var messagePart = $"{this.Type}: {this.Message}";
- if(this.InnerException != undefined && this.InnerException != null)
- {
- var innerEx = this.InnerException.ToString().Replace("\n","\n\t");
- return $"{messagePart}\nInner exception:\n{innerEx}";
- }
- return messagePart;
-}
+class OutOfRangeException : Exception
+{
+ public OutOfRangeException(varName,$inner)
+ {
+ Exception($"{varName} is out of range.",inner);
+ }
+}
\ No newline at end of file
diff --git a/build.tcross b/build.tcross
index 36fc00b..e1a0c04 100644
--- a/build.tcross
+++ b/build.tcross
@@ -27,18 +27,21 @@ func main(args)
cmd("crossvm",["./Tesses.CrossLang.Shell/bin/Tesses.CrossLang.Shell-1.0.0.0-prod.crvm","build","Tesses.CrossLang.PackageServer"]);
//cmd("crossvm",["./Tesses.CrossLang.Shell/bin/Tesses.CrossLang.Shell-1.0.0.0-prod.crvm","build","Tesses.CrossLang.WebSite"]);
cmd("crossvm",["./Tesses.CrossLang.Shell/bin/Tesses.CrossLang.Shell-1.0.0.0-prod.crvm","build","Tesses.CrossLang.Std"]);
- cmd("crossvm",["./Tesses.CrossLang.Shell/bin/Tesses.CrossLang.Shell-1.0.0.0-prod.crvm","build","Templates/console"]);
+ cmd("crossvm",["./Tesses.CrossLang.Shell/bin/Tesses.CrossLang.Shell-1.0.0.0-prod.crvm","build","Templates/console"]);
cmd("crossvm",["./Tesses.CrossLang.Shell/bin/Tesses.CrossLang.Shell-1.0.0.0-prod.crvm","build","Templates/emptyweb"]);
cmd("crossvm",["./Tesses.CrossLang.Shell/bin/Tesses.CrossLang.Shell-1.0.0.0-prod.crvm","build","Templates/web"]);
cmd("crossvm",["./Tesses.CrossLang.Shell/bin/Tesses.CrossLang.Shell-1.0.0.0-prod.crvm","build","Templates/template"]);
cmd("crossvm",["./Tesses.CrossLang.Shell/bin/Tesses.CrossLang.Shell-1.0.0.0-prod.crvm","build","Templates/lib"]);
cmd("crossvm",["./Tesses.CrossLang.Shell/bin/Tesses.CrossLang.Shell-1.0.0.0-prod.crvm","build","Templates/compiletool"]);
cmd("crossvm",["./Tesses.CrossLang.Shell/bin/Tesses.CrossLang.Shell-1.0.0.0-prod.crvm","build","Templates/tool"]);
- /*cmd("crossvm",["./Tesses.CrossLang.Shell/bin/Tesses.CrossLang.Shell-1.0.0.0-prod.crvm","build","Tesses.CrossLang.PackageServer"]);
+ cmd("crossvm",["./Tesses.CrossLang.Shell/bin/Tesses.CrossLang.Shell-1.0.0.0-prod.crvm","build","Templates/gui"]);
+ /*
cmd("crossvm",["./Tesses.CrossLang.Shell/bin/Tesses.CrossLang.Shell-1.0.0.0-prod.crvm","build","Tesses.CrossLang.PackageServer"]);
cmd("crossvm",["./Tesses.CrossLang.Shell/bin/Tesses.CrossLang.Shell-1.0.0.0-prod.crvm","build","Tesses.CrossLang.PackageServer"]);
cmd("crossvm",["./Tesses.CrossLang.Shell/bin/Tesses.CrossLang.Shell-1.0.0.0-prod.crvm","build","Tesses.CrossLang.PackageServer"]);
- cmd("crossvm",["./Tesses.CrossLang.Shell/bin/Tesses.CrossLang.Shell-1.0.0.0-prod.crvm","build","Tesses.CrossLang.PackageServer"]);*/
+ cmd("crossvm",["./Tesses.CrossLang.Shell/bin/Tesses.CrossLang.Shell-1.0.0.0-prod.crvm","build","Tesses.CrossLang.PackageServer"]);
+ cmd("crossvm",["./Tesses.CrossLang.Shell/bin/Tesses.CrossLang.Shell-1.0.0.0-prod.crvm","build","Tesses.CrossLang.PackageServer"]);
+ */
cmd("crossvm",["./Tesses.CrossLang.Shell/bin/Tesses.CrossLang.Shell-1.0.0.0-prod.crvm","build","crosslang_shell_archive_maker"]);
if(args.Length > 1)
diff --git a/crosslang_shell_archive_maker/src/main.tcross b/crosslang_shell_archive_maker/src/main.tcross
index 20e9184..75861fd 100644
--- a/crosslang_shell_archive_maker/src/main.tcross
+++ b/crosslang_shell_archive_maker/src/main.tcross
@@ -54,6 +54,8 @@ func create_archive()
copyFile("Templates/web/bin/Tesses.CrossLang.Template.Website-1.0.0.0-prod.crvm", templates / "web.crvm");
copyFile("Templates/emptyweb/bin/Tesses.CrossLang.Template.EmptyWebsite-1.0.0.0-prod.crvm", templates / "emptyweb.crvm");
copyFile("Templates/tool/bin/Tesses.CrossLang.Template.Tool-1.0.0.0-prod.crvm", templates / "tool.crvm");
+ copyFile("Templates/gui/bin/Tesses.CrossLang.Template.GUI-1.0.0.0-prod.crvm", templates / "gui.crvm");
+
var packageCache = r / "PackageCache";
tmpFS.CreateDirectory(packageCache);
diff --git a/newtonsoft_json_config_schema.cs b/newtonsoft_json_config_schema.cs
index 10c859e..7684f0a 100644
--- a/newtonsoft_json_config_schema.cs
+++ b/newtonsoft_json_config_schema.cs
@@ -38,7 +38,7 @@ namespace Tesses.CrossLang
public string license {get;set;}=""; //optional, but recommended to tell people what the license is
- public string readme {get;set;}=""; //optional but tells people about the package
+ public string description {get;set;}=""; //optional but tells people about the package
}
public static void Main(string[] args)
diff --git a/project_types.txt b/project_types.txt
index 0b39801..467367c 100644
--- a/project_types.txt
+++ b/project_types.txt
@@ -3,4 +3,4 @@ lib: a library
app: a gui app (used for eventual gui system)
template: used for project templates
compile_tool: run before source is compiled for project if it is in the dependency tree for the project (and is not linked to said projects)
-tool: a tool invokable via crosslang
\ No newline at end of file
+tool: a tool invokable via crosslang (gets Tesses.CrossLang.Args for free)
\ No newline at end of file