diff --git a/src/configurations/serversettings.d b/src/configurations/serversettings.d index 75ad5e1..bd8e24c 100644 --- a/src/configurations/serversettings.d +++ b/src/configurations/serversettings.d @@ -1,10 +1,19 @@ module diamond.configurations.serversettings; -struct ServerSettings { - /// The addresses to bind - string[] bindAddresses; - /// The port to bind - ushort port; - /// Collection of default headers - string[string] defaultHeaders; +version (WebServer) { + version = WebServer_Or_WebService; +} +else version (WebService) { + version = WebServer_Or_WebService; +} + +version (WebServer_Or_WebService) { + struct ServerSettings { + /// The addresses to bind + string[] bindAddresses; + /// The port to bind + ushort port; + /// Collection of default headers + string[string] defaultHeaders; + } } diff --git a/src/configurations/sitesettings.d b/src/configurations/sitesettings.d index f31c2d4..ac10659 100644 --- a/src/configurations/sitesettings.d +++ b/src/configurations/sitesettings.d @@ -1,14 +1,27 @@ module diamond.configurations.sitesettings; -version (WebServer) { +version (WebService) { + // N/A +} +else { + version = Not_WebService; +} + +version (Not_WebService) { struct SiteSettings { - /// The name of the web site / web server. - string name; + version (WebServer) { + /// The name of the web site / web server. + string name; + } + /// Collection of all views string[string] views; - /// The home route - string homeRoute; - /// The static file route - string staticFileRoute; + + version (WebServer) { + /// The home route + string homeRoute; + /// The static file route + string staticFileRoute; + } } } diff --git a/src/diamondapp.d b/src/diamondapp.d index d412093..b4c36e9 100644 --- a/src/diamondapp.d +++ b/src/diamondapp.d @@ -114,3 +114,36 @@ version (WebServer_Or_WebService) { } } } +else { + import std.json; + import std.string : format; + + import diamond.configurations; + import diamond.views; + + private enum viewBuildJson = import("view-build.json"); + + private string jsonObjectToAA() { + auto viewsJson = parseJSON(viewBuildJson)["views"].object; + + string str = "enum string[string] views = ["; + + foreach (key,value; viewsJson) { + str ~= format("\"%s\" : \"%s\",", key, value.str); + } + + str.length -= 1; + str ~= "];"; + + return str; + } + + mixin(jsonObjectToAA); + + // This applies all views and parses them. + mixin applyViews!(views); + + shared static this() { + // ... + } +} diff --git a/src/exceptions/viewexception.d b/src/exceptions/viewexception.d index 4e0cb4a..617ea4d 100644 --- a/src/exceptions/viewexception.d +++ b/src/exceptions/viewexception.d @@ -1,6 +1,13 @@ module diamond.exceptions.viewexception; -version (WebServer) { +version (WebService) { + // N/A +} +else { + version = Not_WebService; +} + +version (Not_WebService) { /// Exception thrown upon encountering an error thrown by a view. class ViewException : Exception { diff --git a/src/views/getview.d b/src/views/getview.d index ac101d0..74ca1ba 100644 --- a/src/views/getview.d +++ b/src/views/getview.d @@ -35,3 +35,39 @@ version (WebServer) { mixin(generateGetView); } } +else version (WebService) { + // N/A +} +else { + /// Generates the getView function. + mixin template GetView() { + auto generateGetView() { + string getViewMixin = " + View getView(string pageName) { + if (!pageName || !pageName.length) { + return null; + } + + switch (pageName) { + "; + + foreach (pageName,pageContent; viewInitCollection) { + getViewMixin ~= format(q{ + case "%s": { + return new view_%s("%s"); + } + }, pageName, pageName, pageName); + } + + getViewMixin ~= " + default: return null; + } + } + "; + + return getViewMixin; + } + + mixin(generateGetView); + } +} diff --git a/src/views/package.d b/src/views/package.d index 1263fb9..2dc5698 100644 --- a/src/views/package.d +++ b/src/views/package.d @@ -1,18 +1,32 @@ module diamond.views; -version (WebServer) { +version (WebService) { + // N/A +} +else { + version = Not_WebService; +} + +version (Not_WebService) { /// Mixin template for applying views. mixin template applyViews(string[string] views) { import std.string : format; - import vibe.d; + version (WebServer) { + import vibe.d; + } import diamond.templates; import diamond.views.view; - import diamond.controllers : Status; + import diamond.exceptions : ViewException; - import controllers; + version (WebServer) { + import diamond.controllers : Status; + + import controllers; + } + import models; import diamond.views.viewimports; diff --git a/src/views/view.d b/src/views/view.d index 65f21fb..280a9cb 100644 --- a/src/views/view.d +++ b/src/views/view.d @@ -1,95 +1,133 @@ module diamond.views.view; -version (WebServer) { +version (WebService) { + // N/A +} +else { + version = Not_WebService; +} + +version (Not_WebService) { import std.string : format, strip; import std.array : join, replace, split, array; import std.conv : to; import std.algorithm : filter; - import vibe.d : HTTPServerRequest, HTTPServerResponse; + version (WebServer) { + import vibe.d : HTTPServerRequest, HTTPServerResponse; + } /** * Wrapper around a view. */ class View { private: - /// The request. - HTTPServerRequest _request; - /// The response. - HTTPServerResponse _response; + version (WebServer) { + /// The request. + HTTPServerRequest _request; + /// The response. + HTTPServerResponse _response; + } + /// The name. string _name; - /// The route. - immutable(string[]) _route; + + version (WebServer) { + /// The route. + immutable(string[]) _route; + } + /// The place-holders. string[string] _placeHolders; /// The routes string[] _result; protected: - /** - * Creates a new view. - * Params: - * request = The request of the view. - * response = The response of the view. - * name = The name of the view. - * route = The route of the view. - */ - this(HTTPServerRequest request, HTTPServerResponse response, string name, string[] route) { - _request = request; - _response = response; - _name = name; - _route = cast(immutable)route; - - _placeHolders["doctype"] = ""; - _placeHolders["defaultRoute"] = _route[0]; + version (WebServer) { + /** + * Creates a new view. + * Params: + * request = The request of the view. + * response = The response of the view. + * name = The name of the view. + * route = The route of the view. + */ + this(HTTPServerRequest request, HTTPServerResponse response, string name, string[] route) { + _request = request; + _response = response; + _name = name; + _route = cast(immutable)route; + + _placeHolders["doctype"] = ""; + _placeHolders["defaultRoute"] = _route[0]; + } + } + else { + /** + * Creates a new view. + * Params: + * name = The name of the view. + */ + this(string name) { + _name = name; + } } public: final { @property { - /// Gets the request. - auto request() { return _request; } - /// Gets the response. - auto response() { return _response; } - /// Gets the http method. - auto method() { return _request.method; } + version (WebServer) { + /// Gets the request. + auto request() { return _request; } + /// Gets the response. + auto response() { return _response; } + /// Gets the http method. + auto method() { return _request.method; } + } + /// Gets the name. auto name() { return _name; } /// Sets the name. void name(string name) { _name = name; } - /// Gets the route. - auto route() { return _route; } + + version (WebServer) { + /// Gets the route. + auto route() { return _route; } + } + /// Gets the place-holders. ref auto placeHolders() { return _placeHolders; } - /// Gets a boolean determining whether the view is using the default route or not. This is equivalent to route[0]. - auto isDefaultRoute() { return _route.length == 1; } - /// Gets the action of the view. This is equivalent to route[1]. - auto action() { return _route.length >= 2 ? _route[1] : null; } - /// Gets the action parameters of the view. This is equivalent to route[2 .. $]. - auto params() { return _route.length >= 3 ? _route[2 .. $] : null; } - /** - * Gets the root-path. - * Note: Calling this property might be expensive, so caching the value is recommended. - */ - auto rootPath() { - // This makes sure that it's not retrieving the page's route, but the requests. - // It's useful in terms of a view redirecting to another view internally. - // Since the redirected view will have the route of the redirection and not the request. - scope auto path = request.path == "/" ? "default" : request.path[1 .. $]; - scope auto route = path.split("/").filter!(p => p && p.length && p.strip().length).array; - - if (!route || route.length <= 1) { - return ".."; - } - auto rootPathValue = ""; - foreach (i; 0 .. route.length) { - rootPathValue ~= (i == (route.length - 1) ? ".." : "../"); + version (WebServe) { + /// Gets a boolean determining whether the view is using the default route or not. This is equivalent to route[0]. + auto isDefaultRoute() { return _route.length == 1; } + /// Gets the action of the view. This is equivalent to route[1]. + auto action() { return _route.length >= 2 ? _route[1] : null; } + /// Gets the action parameters of the view. This is equivalent to route[2 .. $]. + auto params() { return _route.length >= 3 ? _route[2 .. $] : null; } + /** + * Gets the root-path. + * Note: Calling this property might be expensive, so caching the value is recommended. + */ + auto rootPath() { + // This makes sure that it's not retrieving the page's route, but the requests. + // It's useful in terms of a view redirecting to another view internally. + // Since the redirected view will have the route of the redirection and not the request. + scope auto path = request.path == "/" ? "default" : request.path[1 .. $]; + scope auto route = path.split("/").filter!(p => p && p.length && p.strip().length).array; + + if (!route || route.length <= 1) { + return ".."; + } + + auto rootPathValue = ""; + foreach (i; 0 .. route.length) { + rootPathValue ~= (i == (route.length - 1) ? ".." : "../"); + } + return rootPathValue; } - return rootPathValue; } } @@ -122,8 +160,13 @@ version (WebServer) { result = result.replace(format("@<%s>", key), value); } - auto rootPathValue = rootPath; // Caching the root-path value - return result.replace("@..", rootPathValue); + version (WebServer) { + auto rootPathValue = rootPath; // Caching the root-path value + return result.replace("@..", rootPathValue); + } + else { + return result; + } } /** @@ -199,14 +242,19 @@ version (WebServer) { * This wraps around getView. * Params: * name = The name of the view to retrieve. - * checkRoute = Boolean determining whether the name should be checked upon default routes. + * checkRoute = Boolean determining whether the name should be checked upon default routes. (Value doesn't matter if it isn't a webserver.) * Returns: * The view. */ auto view(string name, bool checkRoute = false) { import diamondapp : getView; // To retrieve views ... - return getView(this.request, this.response, [name], checkRoute); + version (WebServer) { + return getView(this.request, this.response, [name], checkRoute); + } + else { + return getView(name); + } } /** diff --git a/src/views/viewgeneration.d b/src/views/viewgeneration.d index 1da001f..7ae6012 100644 --- a/src/views/viewgeneration.d +++ b/src/views/viewgeneration.d @@ -1,48 +1,91 @@ module diamond.views.viewgeneration; -version (WebServer) { +version (WebService) { + // N/A +} +else { + version = Not_WebService; +} + +version (Not_WebService) { /// Generates all the views into classes. mixin template ViewGeneration() { auto generateViews() { auto routableViewsMixin = "private enum routableViews = ["; bool hasRoutes = false; - enum pageClassFormat = q{ - final class view_%s : View { - public: - %s + version (WebServer) { + enum pageClassFormat = q{ + final class view_%s : View { + public: + %s + + this(HTTPServerRequest request, HTTPServerResponse response, string name, + string[] route = null) { + super(request, response, name, route); - this(HTTPServerRequest request, HTTPServerResponse response, string name, - string[] route = null) { - super(request, response, name, route); + %s + } %s - } - %s + override string generate() { + import std.array; + import std.string; + import std.algorithm; + import std.conv : to; + import vibe.d; - override string generate() { - import std.array; - import std.string; - import std.algorithm; - import std.conv : to; - import vibe.d; + try { + %s + %s - try { - %s - %s + %s + } + catch (HTTPStatusException statusException) { + throw statusException; + } + catch (Throwable t) { + throw new ViewException("%s", t); + } + } + } + }; + } + else { + enum pageClassFormat = q{ + final class view_%s : View { + public: + %s + + this(string name) { + super(name); %s } - catch (HTTPStatusException statusException) { - throw statusException; - } - catch (Throwable t) { - throw new ViewException("%s", t); + + %s + + override string generate() { + import std.array; + import std.string; + import std.algorithm; + import std.conv : to; + + try { + %s + %s + + %s + } + catch (Throwable t) { + throw new ViewException("%s", t); + } } } - } - }; + }; + } + enum placeHolderFormat = q{ foreach (key,value; %s) { @@ -124,11 +167,13 @@ version (WebServer) { break; } - case "route": { - auto stripped = value.strip().replace("\n", ""); - routableViewsMixin ~= format("\"%s\" : \"%s\",", stripped, pageName); - hasRoutes = true; - break; + version (WebServer) { + case "route": { + auto stripped = value.strip().replace("\n", ""); + routableViewsMixin ~= format("\"%s\" : \"%s\",", stripped, pageName); + hasRoutes = true; + break; + } } case "model": { @@ -147,24 +192,26 @@ version (WebServer) { break; } - case "controller": { - if (value && value.length) { - pageController = q{ - auto controllerResult = controller.handle(); - - if (controllerResult == Status.notFound) { - throw new HTTPStatusException(HTTPStatus.NotFound); - } - else if (controllerResult == Status.end) { - return null; - } - }; - - pageMembers ~= format("%s!view_%s controller;\r\n", value, pageName); - pageConstructor ~= format("controller = new %s!view_%s(this);\r\n", value, pageName); + version (WebServer) { + case "controller": { + if (value && value.length) { + pageController = q{ + auto controllerResult = controller.handle(); + + if (controllerResult == Status.notFound) { + throw new HTTPStatusException(HTTPStatus.NotFound); + } + else if (controllerResult == Status.end) { + return null; + } + }; + + pageMembers ~= format("%s!view_%s controller;\r\n", value, pageName); + pageConstructor ~= format("controller = new %s!view_%s(this);\r\n", value, pageName); + } + + break; } - - break; } case "layout": { diff --git a/src/views/viewimports.d b/src/views/viewimports.d index cd1f9a2..c43fea9 100644 --- a/src/views/viewimports.d +++ b/src/views/viewimports.d @@ -1,6 +1,13 @@ module diamond.views.viewimports; -version (WebServer) { +version (WebService) { + // N/A +} +else { + version = Not_WebService; +} + +version (Not_WebService) { /// Generates the collection of views and imports their content mixin template ViewImports() { auto generateViewImports() {