This commit is contained in:
Christian Fraß 2023-07-23 14:55:32 +02:00
parent ed4c81def0
commit cf1d5b65c3
10 changed files with 632 additions and 99 deletions

View file

@ -0,0 +1,142 @@
{
"domains": [
{
"name": "calendar",
"key_field": {
"name": "id"
},
"data_fields": [
{
"name": "name",
"nullable": false,
"type": "string_short"
},
{
"name": "description",
"nullable": true,
"type": "string_long"
},
{
"name": "color",
"nullable": true,
"type": "string_short"
}
]
},
{
"name": "calendar_appointment",
"key_field": {
"name": "id"
},
"data_fields": [
{
"name": "calendar_id",
"nullable": false,
"type": "integer"
},
{
"name": "title",
"nullable": false,
"type": "string_short"
},
{
"name": "description",
"nullable": true,
"type": "string_long"
},
{
"name": "location",
"nullable": true,
"type": "string_short"
},
{
"name": "begin",
"description": "UNIX timestamp",
"nullable": false,
"type": "integer"
},
{
"name": "end",
"description": "UNIX timestamp",
"nullable": true,
"type": "integer"
},
{
"name": "contact",
"nullable": true,
"type": "string_short"
}
],
"constraints": [
{
"kind": "foreign_key",
"parameters": {
"fields": [
"calendar_id"
],
"reference": {
"name": "calendar",
"fields": [
"id"
]
}
}
}
]
},
{
"name": "organization",
"key_field": {
"name": "id"
},
"data_fields": [
]
},
{
"name": "organization_calendars",
"data_fields": [
{
"name": "organization_id",
"nullable": false,
"type": "integer"
},
{
"name": "calendar_id",
"nullable": false,
"type": "integer"
}
],
"constraints": [
{
"kind": "foreign_key",
"parameters": {
"fields": [
"organization_id"
],
"reference": {
"name": "organization",
"fields": [
"id"
]
}
}
},
{
"kind": "foreign_key",
"parameters": {
"fields": [
"calendar_id"
],
"reference": {
"name": "calendar",
"fields": [
"id"
]
}
}
}
]
}
]
}

View file

@ -979,6 +979,12 @@ declare namespace lib_plankton.prog {
constructor(value: struct_expression);
}
}
declare namespace lib_plankton.prog {
/**
*/
class struct_type_void extends struct_type {
}
}
declare namespace lib_plankton.prog {
/**
*/
@ -1099,6 +1105,31 @@ declare namespace lib_plankton.prog {
value: (null | struct_expression);
}
}
declare namespace lib_plankton.prog {
/**
*/
class struct_statement_function_definition extends struct_statement {
name: string;
arguments: Array<{
name: string;
type: (null | struct_type);
}>;
output_type: (null | struct_type);
body: struct_statement;
constructor(name: string, arguments_: Array<{
name: string;
type: (null | struct_type);
}>, output_type: (null | struct_type), body: struct_statement);
}
}
declare namespace lib_plankton.prog {
/**
*/
class struct_statement_return extends struct_statement {
expression: struct_expression;
constructor(expression: struct_expression);
}
}
declare namespace lib_plankton.prog {
/**
*/
@ -1126,7 +1157,9 @@ declare namespace lib_plankton.prog {
function render_type(type: struct_type): string;
/**
*/
function render_statement(statement: struct_statement): string;
function render_statement(statement: struct_statement, options?: {
indentation?: int;
}): string;
/**
*/
function render_program(program: struct_program): string;

View file

@ -3110,6 +3110,41 @@ but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with »bacterio-plankton:prog«. If not, see <http://www.gnu.org/licenses/>.
*/
var lib_plankton;
(function (lib_plankton) {
var prog;
(function (prog) {
/**
*/
var struct_type_void = /** @class */ (function (_super) {
__extends(struct_type_void, _super);
function struct_type_void() {
return _super !== null && _super.apply(this, arguments) || this;
}
return struct_type_void;
}(prog.struct_type));
prog.struct_type_void = struct_type_void;
})(prog = lib_plankton.prog || (lib_plankton.prog = {}));
})(lib_plankton || (lib_plankton = {}));
/*
This file is part of »bacterio-plankton:prog«.
Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR'
<info@greenscale.de>
»bacterio-plankton:prog« is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
»bacterio-plankton:prog« is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with »bacterio-plankton:prog«. If not, see <http://www.gnu.org/licenses/>.
*/
@ -3619,6 +3654,83 @@ but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with »bacterio-plankton:prog«. If not, see <http://www.gnu.org/licenses/>.
*/
var lib_plankton;
(function (lib_plankton) {
var prog;
(function (prog) {
/**
*/
var struct_statement_function_definition = /** @class */ (function (_super) {
__extends(struct_statement_function_definition, _super);
function struct_statement_function_definition(name, arguments_, output_type, body) {
var _this = _super.call(this) || this;
_this.name = name;
_this.arguments = arguments_;
_this.output_type = output_type;
_this.body = body;
return _this;
}
return struct_statement_function_definition;
}(prog.struct_statement));
prog.struct_statement_function_definition = struct_statement_function_definition;
})(prog = lib_plankton.prog || (lib_plankton.prog = {}));
})(lib_plankton || (lib_plankton = {}));
/*
This file is part of »bacterio-plankton:prog«.
Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR'
<info@greenscale.de>
»bacterio-plankton:prog« is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
»bacterio-plankton:prog« is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with »bacterio-plankton:prog«. If not, see <http://www.gnu.org/licenses/>.
*/
var lib_plankton;
(function (lib_plankton) {
var prog;
(function (prog) {
/**
*/
var struct_statement_return = /** @class */ (function (_super) {
__extends(struct_statement_return, _super);
function struct_statement_return(expression) {
var _this = _super.call(this) || this;
_this.expression = expression;
return _this;
}
return struct_statement_return;
}(prog.struct_statement));
prog.struct_statement_return = struct_statement_return;
})(prog = lib_plankton.prog || (lib_plankton.prog = {}));
})(lib_plankton || (lib_plankton = {}));
/*
This file is part of »bacterio-plankton:prog«.
Copyright 2016-2023 'Christian Fraß, Christian Neubauer, Martin Springwald GbR'
<info@greenscale.de>
»bacterio-plankton:prog« is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
»bacterio-plankton:prog« is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with »bacterio-plankton:prog«. If not, see <http://www.gnu.org/licenses/>.
*/
@ -3718,6 +3830,10 @@ var lib_plankton;
var type_literal = type;
return render_expression(type_literal.value);
}
else if (type instanceof prog.struct_type_void) {
var type_void = type;
return "void";
}
else if (type instanceof prog.struct_type_boolean) {
var type_boolean = type;
return "boolean";
@ -3798,17 +3914,23 @@ var lib_plankton;
prog.render_type = render_type;
/**
*/
function render_statement(statement) {
function render_statement(statement, options) {
if (options === void 0) { options = {}; }
options = Object.assign({
"indentation": 0
}, options);
if (statement instanceof prog.struct_statement_type_definition) {
var statement_type_definition = statement;
return lib_plankton.string.coin("type {{name}} = {{type}};\n", {
return lib_plankton.string.coin("{{indentation}}type {{name}} = {{type}};\n", {
"indentation": "\t".repeat(options.indentation),
"name": statement_type_definition.name,
"type": render_type(statement_type_definition.type)
});
}
if (statement instanceof prog.struct_statement_declaration) {
else if (statement instanceof prog.struct_statement_declaration) {
var statement_declaration = statement;
return lib_plankton.string.coin("{{kind}} {{name}}{{macro_type}}{{macro_value}};\n", {
return lib_plankton.string.coin("{{indentation}}{{kind}} {{name}}{{macro_type}}{{macro_value}};\n", {
"indentation": "\t".repeat(options.indentation),
"kind": (statement_declaration.constant
? "const"
: "let"),
@ -3825,13 +3947,46 @@ var lib_plankton;
}))
});
}
if (statement instanceof prog.struct_statement_assignment) {
else if (statement instanceof prog.struct_statement_assignment) {
var statement_assignment = statement;
return lib_plankton.string.coin("{{name}} = {{value}};\n", {
return lib_plankton.string.coin("{{indentation}}{{name}} = {{value}};\n", {
"indentation": "\t".repeat(options.indentation),
"name": statement_assignment.name,
"value": render_expression(statement_assignment.value)
});
}
else if (statement instanceof prog.struct_statement_function_definition) {
var statement_function_definition = statement;
return lib_plankton.string.coin("{{indentation}}function {{name}}({{arguments}}){{macro_output_type}} {\n{{body}}}\n", {
"indentation": "\t".repeat(options.indentation),
"name": statement_function_definition.name,
"arguments": (statement_function_definition.arguments
.map(function (argument) { return lib_plankton.string.coin("{{name}}{{macro_type}}", {
"name": argument.name,
"macro_type": ((argument.type === null)
? ""
: lib_plankton.string.coin(" : {{type}}", {
"type": render_type(argument.type)
}))
}); })
.join(", ")),
"macro_output_type": ((statement_function_definition.output_type === null)
? ""
: lib_plankton.string.coin(" : {{type}}", {
"type": render_type(statement_function_definition.output_type)
})),
"body": render_statement(statement_function_definition.body, {
"indentation": (options.indentation + 1)
})
});
}
else if (statement instanceof prog.struct_statement_return) {
var statement_return = statement;
return lib_plankton.string.coin("{{indentation}}return {{expression}};\n", {
"indentation": "\t".repeat(options.indentation),
"expression": render_expression(statement_return.expression)
});
}
else {
throw (new Error("unhandled statement: " + String(statement)));
}
@ -3842,7 +3997,7 @@ var lib_plankton;
function render_program(program) {
return (program.statements
.map(function (statement) { return render_statement(statement); })
.join(""));
.join("\n"));
}
prog.render_program = render_program;
/**

View file

@ -5,10 +5,10 @@ async function main(
) : Promise<void>
{
const outputs : Record<string, type_output> = {
"sqlite": output_sqlite,
"mysql": output_mysql,
"typescript": output_typescript,
"jsonschema": output_jsonschema,
"database-sqlite": output_database_sqlite,
"database-mysql": output_database_mysql,
"backend-typescript": output_backend_typescript,
};
const arg_handler = new lib_plankton.args.class_handler(
@ -18,7 +18,7 @@ async function main(
"type": lib_plankton.args.enum_type.string,
"kind": lib_plankton.args.enum_kind.volatile,
"mode": lib_plankton.args.enum_mode.replace,
"default": "sqlite",
"default": "database-sqlite",
"parameters": {
"indicators_long": ["format"],
"indicators_short": ["f"],

View file

@ -0,0 +1,280 @@
const output_backend_typescript : type_output = {
"render": function (input_data) {
const map_primitive_type = function (typename : string) : lib_plankton.prog.struct_type {
const mymap : Record<string, lib_plankton.prog.struct_type> = {
"boolean": new lib_plankton.prog.struct_type_boolean(),
"integer": new lib_plankton.prog.struct_type_integer(),
// "float": new lib_plankton.prog.struct_type_integer(),
"string_short": new lib_plankton.prog.struct_type_string(),
"string_medium": new lib_plankton.prog.struct_type_string(),
"string_long": new lib_plankton.prog.struct_type_string(),
};
return mymap[typename];
};
const prog_output : lib_plankton.prog.type_output = lib_plankton.prog.output_typescript();
const name_type = function (domain) : string {return ("type_" + domain.name);};
const name_collection = function (domain) : string {return ("collection_" + domain.name);};
const name_repository_function_list = function (domain) : string {
return lib_plankton.string.coin(
"repository_{{name}}_list",
{
"name": domain.name
}
);
};
const name_repository_function_read = function (domain) : string {
return lib_plankton.string.coin(
"repository_{{name}}_read",
{
"name": domain.name
}
);
};
const name_repository_function_create = function (domain) : string {
return lib_plankton.string.coin(
"repository_{{name}}_create",
{
"name": domain.name
}
);
};
const name_repository_function_update = function (domain) : string {
return lib_plankton.string.coin(
"repository_{{name}}_update",
{
"name": domain.name
}
);
};
const name_repository_function_delete = function (domain) : string {
return lib_plankton.string.coin(
"repository_{{name}}_delete",
{
"name": domain.name
}
);
};
return prog_output.render_program(
new lib_plankton.prog.struct_program(
[]
// base
.concat(
[]
)
// lib (database)
.concat(
[]
)
// entities
.concat(
input_data["domains"]
.map(
(domain) => new lib_plankton.prog.struct_statement_type_definition(
name_type(domain),
new lib_plankton.prog.struct_type_record(
domain.data_fields
.map(
(data_field) => ({
"name": data_field.name,
"type": (
data_field.nullable
? new lib_plankton.prog.struct_type_union(
new lib_plankton.prog.struct_type_literal(
new lib_plankton.prog.struct_expression_literal(
null
)
),
map_primitive_type(data_field["type"])
)
: map_primitive_type(data_field["type"])
),
"mandatory": true,
})
)
)
)
)
)
// repositories
.concat(
input_data["domains"]
.map(
(domain) => (
(domain.key_field === null)
? [
// TODO
]
: [
/*
// data
new lib_plankton.prog.struct_statement_declaration(
false,
name_collection(domain),
(
(domain.key_field === null)
? new lib_plankton.prog.struct_type_list(
new lib_plankton.prog.struct_type_construction(
name_type(domain),
null
)
)
: new lib_plankton.prog.struct_type_map(
new lib_plankton.prog.struct_type_integer(),
new lib_plankton.prog.struct_type_construction(
name_type(domain),
null
)
)
),
(
(domain.key_field === null)
? new lib_plankton.prog.struct_expression_literal([])
: new lib_plankton.prog.struct_expression_literal({})
)
),
*/
// list
new lib_plankton.prog.struct_statement_function_definition(
name_repository_function_list(domain),
[],
new lib_plankton.prog.struct_type_construction(
"Promise",
[
new lib_plankton.prog.struct_type_construction(
"Array",
[
new lib_plankton.prog.struct_type_construction(
name_type(domain),
null
),
]
)
]
),
new lib_plankton.prog.struct_statement_return(
// TODO
new lib_plankton.prog.struct_expression_literal(null)
),
),
// read
new lib_plankton.prog.struct_statement_function_definition(
name_repository_function_read(domain),
[
{
"name": "key",
"type": new lib_plankton.prog.struct_type_integer(
),
},
],
new lib_plankton.prog.struct_type_construction(
"Promise",
[
new lib_plankton.prog.struct_type_construction(
name_type(domain),
null
),
]
),
new lib_plankton.prog.struct_statement_return(
// TODO
new lib_plankton.prog.struct_expression_literal(null)
),
),
// create
new lib_plankton.prog.struct_statement_function_definition(
name_repository_function_create(domain),
[
{
"name": "value",
"type": new lib_plankton.prog.struct_type_construction(
name_type(domain),
null
),
},
],
new lib_plankton.prog.struct_type_construction(
"Promise",
[
new lib_plankton.prog.struct_type_integer(
),
]
),
new lib_plankton.prog.struct_statement_return(
// TODO
new lib_plankton.prog.struct_expression_literal(null)
),
),
// update
new lib_plankton.prog.struct_statement_function_definition(
name_repository_function_update(domain),
[
{
"name": "key",
"type": new lib_plankton.prog.struct_type_integer(
),
},
{
"name": "value",
"type": new lib_plankton.prog.struct_type_construction(
name_type(domain),
null
),
},
],
new lib_plankton.prog.struct_type_construction(
"Promise",
[
new lib_plankton.prog.struct_type_void(
),
]
),
new lib_plankton.prog.struct_statement_return(
// TODO
new lib_plankton.prog.struct_expression_literal(null)
),
),
// delete
new lib_plankton.prog.struct_statement_function_definition(
name_repository_function_delete(domain),
[
{
"name": "key",
"type": new lib_plankton.prog.struct_type_integer(
),
},
],
new lib_plankton.prog.struct_type_construction(
"Promise",
[
new lib_plankton.prog.struct_type_void(),
]
),
new lib_plankton.prog.struct_statement_return(
// TODO
new lib_plankton.prog.struct_expression_literal(null)
),
),
]
)
)
.reduce(
(x, y) => x.concat(y),
[]
)
)
// services
.concat(
[]
)
// api
.concat(
[]
)
// server
.concat(
[]
)
)
);
},
};

View file

@ -1,4 +1,4 @@
function mysql_value_encode(
function database_mysql_value_encode(
value : any
) : string
{
@ -27,7 +27,7 @@ function mysql_value_encode(
}
}
const output_mysql : type_output = {
const output_database_mysql : type_output = {
"render": function (input_data) {
return (
input_data.domains
@ -114,7 +114,7 @@ const output_mysql : type_output = {
lib_plankton.string.coin(
"DEFAULT {{value}}",
{
"value": mysql_value_encode(data_field.default),
"value": database_mysql_value_encode(data_field.default),
}
),
]

View file

@ -1,4 +1,4 @@
function sqlite_value_encode(
function database_sqlite_value_encode(
value : any
) : string
{
@ -27,7 +27,7 @@ function sqlite_value_encode(
}
}
const output_sqlite : type_output = {
const output_database_sqlite : type_output = {
"render": function (input_data) {
return (
input_data["domains"]
@ -92,7 +92,7 @@ const output_sqlite : type_output = {
lib_plankton.string.coin(
"DEFAULT {{value}}",
{
"value": sqlite_value_encode(data_field.default),
"value": database_sqlite_value_encode(data_field.default),
}
),
]

View file

@ -1,77 +0,0 @@
const output_typescript : type_output = {
"render": function (input_data) {
const map_primitive_type = function (typename : string) : lib_plankton.prog.struct_type {
const mymap : Record<string, lib_plankton.prog.struct_type> = {
"boolean": new lib_plankton.prog.struct_type_boolean(),
"integer": new lib_plankton.prog.struct_type_integer(),
// "float": new lib_plankton.prog.struct_type_integer(),
"string_short": new lib_plankton.prog.struct_type_string(),
"string_medium": new lib_plankton.prog.struct_type_string(),
"string_long": new lib_plankton.prog.struct_type_string(),
};
return mymap[typename];
};
const name_type : string = ("type_" + domain.name);
const name_collection : string = ("collection_" + domain.name);
const prog_output : lib_plankton.prog.type_output = lib_plankton.prog.output_typescript();
return prog_output.render_program(
new lib_plankton.prog.struct_program(
input_data["domains"]
.map(
(domain) => ([
new lib_plankton.prog.struct_statement_type_definition(
name_type,
new lib_plankton.prog.struct_type_record(
domain.data_fields
.map(
(data_field) => ({
"name": data_field.name,
"type": (
data_field.nullable
? new lib_plankton.prog.struct_type_union(
new lib_plankton.prog.struct_type_literal(
new lib_plankton.prog.struct_expression_literal(
null
)
),
map_primitive_type(data_field["type"])
)
: map_primitive_type(data_field["type"])
),
"mandatory": true,
})
)
)
),
new lib_plankton.prog.struct_statement_declaration(
false,
name_collection,
(
(domain.key_field === null)
? new lib_plankton.prog.struct_type_list(
new lib_plankton.prog.struct_type_construction(
name_type,
null
)
)
: new lib_plankton.prog.struct_type_map(
new lib_plankton.prog.struct_type_integer(),
new lib_plankton.prog.struct_type_construction(
name_type,
null
)
)
),
(
(domain.key_field === null)
? new lib_plankton.prog.struct_expression_literal([])
: new lib_plankton.prog.struct_expression_literal({})
)
)
])
)
.reduce((x, y) => x.concat(y), [])
)
);
},
};

View file

@ -17,10 +17,10 @@ all: build/sindri
temp/sindri-unlinked.js: \
lib/plankton/plankton.d.ts \
source/types.ts \
source/outputs/sqlite.ts \
source/outputs/mysql.ts \
source/outputs/typescript.ts \
source/outputs/jsonschema.ts \
source/outputs/database_sqlite.ts \
source/outputs/database_mysql.ts \
source/outputs/backend_typescript.ts \
source/conf.ts \
source/main.ts
@ ${cmd_log} "compiling …"