DocsBrowser is looking nice and I'm actually doing the docs for one file to work on the design more.

main
Zed A. Shaw 1 year ago
parent ba8c6064fe
commit 2ac767b858
  1. 17
      admin/pages/DocsBrowser.svelte
  2. 23
      commands/codedoc.js
  3. 2
      lib/docgen.js
  4. 117
      lib/ormish.js
  5. 3
      package.json

@ -77,6 +77,7 @@
}
export > heading h4 {
font-family: var(--font-family);
margin: 0px !important;
}
@ -117,13 +118,17 @@
{#if docs_data}
{#each docs_data.exports as exp}
{#if exp.isa === "class"}
<h2>Class: { exp.name }</h2>
<export>
<heading>
<h2>Class: { exp.name }</h2>
<Code content={ exp.code } language="javascript" />
</heading>
<comment>
{#if exp.comment}
{@html exp.comment}
{/if}
</comment>
<Code content={ exp.code } language="javascript" />
</export>
{#each exp.methods as member}
<export>
@ -131,19 +136,18 @@
<h4>{ member.name }</h4>
<meta-data>
{docs_data.source}:{ member.line_start }
<em>{ member.isa }</em>
<em>{ member.isa } of { exp.name }</em>
{#if member.static}<b>static</b>{/if}
{#if member.async}<b>async</b>{/if}
{#if member.generator}<b>generator</b>{/if}
</meta-data>
</heading>
<info>
{#if exp.comment}
{#if member.comment}
<comment>
{ @html exp.comment }
{ @html member.comment }
</comment>
{/if}
<h4>Signature</h4>
<Code content={ member.code } language="javascript" />
</info>
</export>
@ -166,7 +170,6 @@
{@html exp.comment}
</comment>
{/if}
<h4>Signature</h4>
<Code content={ exp.code } language="javascript" />
</info>
</export>

@ -27,14 +27,21 @@ export const required = [
const RENDERER = create_renderer();
/*
Strips 1 leading space from the comments, or the \s\* combinations
in traditional documentation comments.
If we strip more it'll mess up formatting in markdown for indentation
formats. Weirdly Remarkable seems to be able to handle leading spaces pretty
well so only need to remove one space or \s\* combinations like with
traditional comment docs.
*/
const render_comment = (comment) => {
// strip 1 leading space from the comments, if we strip more it'll
// mess up formatting in markdown for indentation formats
const lines = comment.split(/\n/).map(l => l.replace(/^\s/, ''));
const lines = comment.split(/\n/).map(l => l.replace(/^(\s*\*\s?|\s)/, ''));
return RENDERER.render(lines.join("\n"));
}
// handy function for checking things are good and aborting
/* Handy function for checking things are good and aborting. */
const check = (test, fail_message) => {
if(!test) {
log.error(fail_message);
@ -61,8 +68,6 @@ class ParseWalker {
methods: [],
}
new_class.comment = this.find_comment(new_class.line_start);
acorn_walk.simple(root, {
ClassDeclaration: (cls_node) => {
assert(cls_node.id.name === new_class.name, "Name of class changed!");
@ -159,13 +164,13 @@ class ParseWalker {
}
/**
* Find the nearest comment to this line, giving
* about 2 lines of slack.
Find the nearest comment to this line, giving
about 2 lines of slack.
*/
find_comment(line) {
for(let c of this.comments) {
const distance = c.end - line;
if(!c.found && distance < 0 && distance > -3) {
if(!c.found && distance == -1) {
c.found = true;
return render_comment(c.value);
}

@ -97,7 +97,7 @@ export const create_renderer = (toc) => {
let level = tokens[idx].hLevel;
let content = tokens[idx + 1].content;
let slug = slugify(content, {lower: true, strict: true});
toc.push({level, content, slug});
if(toc) toc.push({level, content, slug});
return `<h${level} id="${slug}">`;
}

@ -3,10 +3,18 @@ import knexConfig from 'knex';
import assert from 'assert';
import { attachPaginate } from 'knex-paginate';
/*
A preconfigured knex.js driver using the config.development configuration
by default.
_TODO_: Need to make this configurable, even though I just use one config right now since I run sqlite3 all the time.
*/
export const knex = knexConfig(config.development);
// run the PERF_TRICKS to configure sqlite3 when thing start, really need to make this
// a configuration and only do it with sqlite3, but for now just get this done
/*
run the PERF_TRICKS to configure sqlite3 when thing start, really need to make this
a configuration and only do it with sqlite3, but for now just get this done
*/
if(config.development.client === "sqlite3") {
const PERF_TRICKS = [
"pragma journal_mode = WAL", // use a WAL journal to not block writers/readers
@ -25,6 +33,10 @@ if(config.development.client === "sqlite3") {
attachPaginate();
/*
Filled in by `load_schema` to give access to the database scheme in the admin
tool and generally through the API.
*/
export const SCHEMA = {};
const load_schema = async () => {
@ -43,11 +55,11 @@ await load_schema();
is called by Model.validation and you can call it directly to get rules
for a database table.
+ `name string` - the table name.
+ `rules Object` - default rules with empty "" for the rules you want filled in
+ `all boolean` - set this to true if you want everything
+ `no_id boolean` - defaults to true, set false if you also want the id
+ `return Object` - the resulting rules to use with Validator
1. `name string` - the table name.
2. `rules Object` - default rules with empty "" for the rules you want filled in
3. `all boolean` - set this to true if you want everything
4. `no_id boolean` - defaults to true, set false if you also want the id
5. `return Object` - the resulting rules to use with Validator
*/
export const validation = (name, rules, all=false, no_id=true) => {
assert(rules, "rules parameter is required and will be modified");
@ -99,20 +111,73 @@ export const validation = (name, rules, all=false, no_id=true) => {
return rules;
}
/*
The base class for all models found in `lib/models.js`. You use this by extending it with:
```javascript
class User extends Model.from_table('user') {
}
```
This will create a `User` class that is automatically configured using the SCHEMA create from the `user` table in your database. You won't need to define the attributes on this class as it will be correctly populated from the database.
The database is therefore the "source of truth" for all of the models. You can then add functions to extend what this class does.
*/
export class Model {
/*
Allows you to build a new object of this Model with the given `attr`
already set, but really you should use the `Model.from(attr)` method instead.
This does _no_ object sanitization with `Model.clean(attr)` method, and if
it doesn't match the underlying database it will throw an exception.
- `attr Object` - the attributes for this model
*/
constructor(attr) {
assert(attr, "Must give attributes.");
Object.assign(this, attr);
}
/*
How to actually create a new instance of this model. This
will do two things:
1. Correctly use the schema for the subclass model.
2. Sanitize the input to remove anything that shouldn't be in the database.
The `also_remove` parameter is a list of additional keys to also scrub from the object.
- `attr Object` -- The attributes this should start with.
- `also_remove Array` -- list of additional attributes to remove.
*/
static from(attr, also_remove=undefined) {
return new this(this.clean(attr, also_remove));
}
/*
Returns an object representing the schema for this Model. Remember that this
will reflect what's in the database schema, which is formatted however
`knex.js` formats your database Schema. Might not be portable between
databases and only tested with SQlite3.
_This is an attribute accessor, so just do `obj.schema` rather than call it like a function._
- `return Object` - The schema for this model.
*/
get schema() {
return this.constructor.schema;
}
/*
Uses the `this.schema` scrub out any attributes that are not valid for the
schema. This is effectively a whitelist for the allowed attributes based on
the database schema. You can use the `also_remove` parameter to list
additional attributes to remove, which you should do to sanitize incoming
objects for things like password fields.
- `attr Object` - The attributes to clean.
- `also_remove Array` - Additional attributes to remove.
*/
static clean(attr, also_remove=undefined) {
assert(attr, "Must give attributes to clean.");
@ -128,18 +193,18 @@ export class Model {
return this.constructor.table_name;
}
/**
* Returns an object of basic rules meant for lib/api.js:validate
* based on what's in the database. It's meant to be an easy to
* pass in starter which you can augment. It expects a set of rules
* with keys you want configured. Any key that's set to an empty string ""
* will be filled in with a minimum rule to match the database schema.
*
* It's designed to be called once at the top of an api/ handler to get
* a basic set of rules. You could also run it to print out the rules then
* simply write the rules directly where you need them.
*
* @param rules {Object} - rules specifier
/*
Returns an object of basic rules meant for lib/api.js:validate
based on what's in the database. It's meant to be an easy to
pass in starter which you can augment. It expects a set of rules
with keys you want configured. Any key that's set to an empty string ""
will be filled in with a minimum rule to match the database schema.
It's designed to be called once at the top of an api/ handler to get
a basic set of rules. You could also run it to print out the rules then
simply write the rules directly where you need them.
- `param rules {Object}` - rules specifier
*/
static validation(rules) {
return validation(this.table_name, rules);
@ -204,13 +269,13 @@ export class Model {
return new this(attr);
}
/**
* Implements an upsert (insert but update on conflict) for Postgres, MySQL, and SQLite3 only.
*
* @param { Object } attr - The attributes to insert or update.
* @param { string } conflict_key - The key that can cause a conflict then update.
* @param { boolean } merge - Defaults to true and will change the record. false will ignore and not update on conflict.
* @return { number } - id or undefined
/*
Implements an upsert (insert but update on conflict) for Postgres, MySQL, and SQLite3 only.
+ attr { Object } - The attributes to insert or update.
+ conflict_key { string } - The key that can cause a conflict then update.
+ merge { boolean } - Defaults to true and will change the record. false will ignore and not update on conflict.
+ return { number } - id or undefined
*/
static async upsert(attr, conflict_key, merge=true) {
assert(conflict_key !== undefined, `You forgot to set the conflict_key on upsert to table ${this.table_name}`);

@ -8,7 +8,7 @@
},
"scripts": {
"dev": "run-p -l -n api queue watch tracker rendered-watch",
"DANGER_ADMIN": "cross-env DANGER_ADMIN=1 run-p -l -n api queue tracker watch rendered-watch",
"DANGER_ADMIN": "cross-env DANGER_ADMIN=1 run-p -l -n api queue tracker watch rendered-watch docs",
"prod": "run-p api queue",
"tracker": "node ./bando.js tracker",
"build": "node ./bando.js build --config build.prod.json",
@ -17,6 +17,7 @@
"api": "nodemon ./bando.js api",
"queue": "nodemon ./bando.js queue",
"test": "npx ava tests/**/*.js",
"docs": "nodemon bando.js codedoc --output public/docs/api lib/*.js client/*.js",
"modules": "./bando.js load",
"modules-watch": "nodemon --watch ../ljsthw-private/db/modules/ --ext .md,.js,.sh ./bando.js load",
"rendered-watch": "nodemon --ignore \"rendered/build/**/*\" --watch ./rendered --watch static -e md,svelte,js,css ./bando.js rendered",

Loading…
Cancel
Save