pinstripe 0.22.0 → 0.24.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -0
- package/cli.js +46 -0
- package/lib/app.js +35 -0
- package/lib/apps/_file_importer.js +1 -0
- package/lib/apps/docs.js +6 -0
- package/lib/apps/main.js +6 -0
- package/lib/class.js +64 -0
- package/lib/client.js +20 -0
- package/lib/command.js +41 -0
- package/lib/commands/_file_importer.js +1 -0
- package/lib/commands/drop_database.js +6 -0
- package/lib/commands/generate_app.js +41 -0
- package/lib/commands/generate_command.js +39 -0
- package/lib/commands/generate_component.js +51 -0
- package/lib/commands/generate_migration.js +55 -0
- package/lib/commands/generate_model.js +43 -0
- package/lib/commands/generate_project.js +133 -0
- package/lib/commands/generate_service.js +32 -0
- package/lib/commands/generate_static_site.js +74 -0
- package/lib/commands/generate_view.js +44 -0
- package/lib/commands/init_database.js +9 -0
- package/lib/commands/list_apps.js +15 -0
- package/lib/commands/list_commands.js +15 -0
- package/lib/commands/list_components.js +16 -0
- package/lib/commands/list_migrations.js +15 -0
- package/lib/commands/list_models.js +15 -0
- package/lib/commands/list_services.js +15 -0
- package/lib/commands/list_views.js +39 -0
- package/lib/commands/migrate_database.js +6 -0
- package/lib/commands/purge_old_sessions.js +12 -0
- package/lib/commands/reset_database.js +9 -0
- package/lib/commands/seed_database.js +6 -0
- package/lib/commands/show_config.js +6 -0
- package/lib/commands/start_repl.js +6 -0
- package/lib/commands/start_server.js +31 -0
- package/lib/component.js +86 -34
- package/lib/component_event.js +28 -0
- package/lib/components/_file_importer.js +1 -0
- package/lib/components/a.js +27 -0
- package/lib/components/body.js +2 -4
- package/lib/components/document.js +18 -11
- package/lib/components/form.js +2 -4
- package/lib/components/helpers.js +11 -14
- package/lib/components/pinstripe_frame.js +60 -0
- package/lib/components/{markdown_editor.js → pinstripe_markdown_editor.js} +7 -8
- package/lib/components/pinstripe_modal.js +77 -0
- package/lib/components/{overlay.js → pinstripe_overlay.js} +11 -18
- package/lib/components/{progress_bar.js → pinstripe_progress_bar.js} +2 -4
- package/lib/components/pinstripe_silo.js +2 -0
- package/lib/components/pinstripe_skeleton.js +55 -0
- package/lib/components/script.js +11 -0
- package/lib/constants.js +26 -0
- package/lib/context.js +40 -0
- package/lib/database/client.js +242 -0
- package/lib/database/column_reference.js +13 -0
- package/lib/database/constants.js +87 -0
- package/lib/database/index.js +7 -0
- package/lib/database/migration.js +30 -0
- package/lib/database/migrator.js +28 -0
- package/lib/database/row.js +390 -0
- package/lib/database/singleton.js +12 -0
- package/lib/database/table.js +516 -0
- package/lib/database/table_reference.js +33 -0
- package/lib/database/union.js +128 -0
- package/lib/database.js +139 -0
- package/lib/defer.js +35 -0
- package/lib/defer.test.js +37 -0
- package/lib/escape_html.js +2 -0
- package/lib/extensions/_file_importer.js +2 -0
- package/lib/extensions/multi-tenant/database/row.js +27 -0
- package/lib/extensions/multi-tenant/database/table.js +30 -0
- package/lib/extensions/multi-tenant/database.js +8 -0
- package/lib/extensions/multi-tenant/index.js +4 -0
- package/lib/extensions/multi-tenant/migrations/1627976174_create_tenant_table_and_add_tenant_id_to_existing_tables.js +20 -0
- package/lib/extensions/multi-tenant/migrations/_file_importer.js +2 -0
- package/lib/extensions/multi-tenant/services/_file_importer.js +2 -0
- package/lib/extensions/multi-tenant/services/database.js +32 -0
- package/lib/html.js +72 -0
- package/lib/import_all.js +94 -0
- package/lib/index.js +11 -2
- package/lib/inflector.js +173 -0
- package/lib/lru_cache.js +53 -0
- package/lib/lru_cache.test.js +45 -0
- package/lib/markdown.js +58 -0
- package/lib/model.js +110 -0
- package/lib/project.js +72 -0
- package/lib/registry.js +130 -0
- package/lib/service_consumer.js +16 -0
- package/lib/service_factory.js +20 -0
- package/lib/services/_file_importer.js +1 -0
- package/lib/services/app.js +11 -0
- package/lib/services/args.js +9 -0
- package/lib/services/bot.js +69 -0
- package/lib/services/cli_utils.js +77 -0
- package/lib/services/client_builder.js +70 -0
- package/lib/services/config.js +66 -0
- package/lib/services/cookies.js +19 -0
- package/lib/services/create_model.js +8 -0
- package/lib/services/database.js +14 -0
- package/lib/services/defer.js +8 -0
- package/lib/services/fetch.js +115 -0
- package/lib/services/format_date.js +8 -0
- package/lib/services/fs_builder.js +132 -0
- package/lib/services/inflector.js +8 -0
- package/lib/services/initial_params.js +13 -0
- package/lib/services/params.js +13 -0
- package/lib/services/parse_html.js +8 -0
- package/lib/services/project.js +8 -0
- package/lib/services/render_form.js +165 -0
- package/lib/services/render_html.js +8 -0
- package/lib/services/render_markdown.js +9 -0
- package/lib/services/render_view.js +6 -0
- package/lib/services/repl.js +54 -0
- package/lib/services/run_command.js +8 -0
- package/lib/services/run_in_new_workspace.js +11 -0
- package/lib/services/send_mail.js +47 -0
- package/lib/services/server.js +105 -0
- package/lib/services/view.js +6 -0
- package/lib/singleton.js +13 -0
- package/lib/string_reader.js +22 -0
- package/lib/trapify.js +32 -0
- package/lib/unescape_html.js +2 -0
- package/lib/unescape_html.test.js +9 -0
- package/lib/util.js +3 -0
- package/lib/validation_error.js +7 -0
- package/lib/view.js +82 -0
- package/lib/view_file_importers/md.js +42 -0
- package/lib/views/_file_importer.js +1 -0
- package/lib/views/main/assets/javascripts/all.js.js +7 -0
- package/lib/views/main/assets/javascripts/all.js.map.js +7 -0
- package/lib/views/main/assets/stylesheets/all.css.js +28 -0
- package/lib/views/main/assets/stylesheets/components/button.css +43 -0
- package/lib/views/main/assets/stylesheets/components/card.css +29 -0
- package/lib/views/main/assets/stylesheets/components/form.css +4 -0
- package/lib/views/main/assets/stylesheets/components/frame.css +3 -0
- package/lib/views/main/assets/stylesheets/components/input.css +40 -0
- package/lib/views/main/assets/stylesheets/components/label.css +9 -0
- package/lib/views/main/assets/stylesheets/components/overlay.css +11 -0
- package/lib/views/main/assets/stylesheets/components/pagination.css +60 -0
- package/lib/views/main/assets/stylesheets/components/progress_bar.css +20 -0
- package/lib/views/main/assets/stylesheets/components/textarea.css +10 -0
- package/lib/views/main/assets/stylesheets/global.css +120 -0
- package/lib/views/main/assets/stylesheets/reset.css +74 -0
- package/lib/views/main/assets/stylesheets/vars.css +25 -0
- package/lib/virtual_node.js +171 -0
- package/lib/virtual_node.test.js +28 -0
- package/lib/workspace.js +21 -0
- package/package.json +28 -6
- package/lib/components/anchor.js +0 -22
- package/lib/components/frame.js +0 -49
- package/lib/components/index.js +0 -9
- package/lib/event_wrapper.js +0 -26
package/README.md
ADDED
package/cli.js
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { spawn } from 'child_process';
|
|
4
|
+
|
|
5
|
+
import { Project } from './lib/project.js';
|
|
6
|
+
import { Command } from './lib/command.js';
|
|
7
|
+
import { importAll } from './lib/import_all.js';
|
|
8
|
+
import { Workspace } from './lib/workspace.js';
|
|
9
|
+
|
|
10
|
+
(async () => {
|
|
11
|
+
const { entryPath, localPinstripePath, exists } = await Project.instance;
|
|
12
|
+
const { argv, env, execPath } = process;
|
|
13
|
+
const args = argv.slice(2);
|
|
14
|
+
|
|
15
|
+
if (env.IS_LOCAL_PINSTRIPE != 'true' && localPinstripePath) {
|
|
16
|
+
spawn(execPath, [localPinstripePath, ...args], {
|
|
17
|
+
env: { ...env, IS_LOCAL_PINSTRIPE: 'true' },
|
|
18
|
+
stdio: 'inherit'
|
|
19
|
+
});
|
|
20
|
+
} else {
|
|
21
|
+
if(entryPath){
|
|
22
|
+
import(entryPath);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
await importAll();
|
|
26
|
+
|
|
27
|
+
if(exists){
|
|
28
|
+
Command.unregister('generate-project');
|
|
29
|
+
} else {
|
|
30
|
+
const allowedCommands = ['generate-project', 'list-commands'];
|
|
31
|
+
Command.names.forEach(commandName => {
|
|
32
|
+
if(!allowedCommands.includes(commandName)){
|
|
33
|
+
Command.unregister(commandName);
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
try {
|
|
39
|
+
await Workspace.run(async function(){
|
|
40
|
+
await this.runCommand(...args);
|
|
41
|
+
});
|
|
42
|
+
} catch(e) {
|
|
43
|
+
console.error(e);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
})();
|
package/lib/app.js
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
|
|
2
|
+
import { Class } from './class.js';
|
|
3
|
+
import { Registry } from './registry.js';
|
|
4
|
+
import { View } from './view.js';
|
|
5
|
+
import { ServiceConsumer } from './service_consumer.js';
|
|
6
|
+
|
|
7
|
+
export const App = Class.extend().include({
|
|
8
|
+
meta(){
|
|
9
|
+
this.include(Registry);
|
|
10
|
+
this.include(ServiceConsumer);
|
|
11
|
+
},
|
|
12
|
+
|
|
13
|
+
compose(){
|
|
14
|
+
return [];
|
|
15
|
+
},
|
|
16
|
+
|
|
17
|
+
get viewMapper(){
|
|
18
|
+
if(!this._viewMapper){
|
|
19
|
+
this._viewMapper = View.mapperFor(this.compose());
|
|
20
|
+
}
|
|
21
|
+
return this._viewMapper;
|
|
22
|
+
},
|
|
23
|
+
|
|
24
|
+
renderView(...args){
|
|
25
|
+
return this.viewMapper.renderView(this.context, ...args);
|
|
26
|
+
},
|
|
27
|
+
|
|
28
|
+
isView(...args){
|
|
29
|
+
return this.viewMapper.isView(...args);
|
|
30
|
+
},
|
|
31
|
+
|
|
32
|
+
get viewNames(){
|
|
33
|
+
return this.viewMapper.viewNames;
|
|
34
|
+
}
|
|
35
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { App as default } from 'pinstripe';
|
package/lib/apps/docs.js
ADDED
package/lib/apps/main.js
ADDED
package/lib/class.js
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
|
|
2
|
+
export class Class {
|
|
3
|
+
|
|
4
|
+
static extend(){
|
|
5
|
+
return class extends this {};
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
static include(...includes){
|
|
9
|
+
includes.forEach(include => {
|
|
10
|
+
if(typeof include.meta == 'function') include.meta.call(this);
|
|
11
|
+
this.prototype.assignProps(include, name => name != 'meta');
|
|
12
|
+
});
|
|
13
|
+
return this;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
static assignProps(...sources){
|
|
17
|
+
return assignProps(this, ...sources);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
static new(...args){
|
|
21
|
+
return new this(...args);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
static get parent(){
|
|
25
|
+
return this.__proto__;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
constructor(...args){
|
|
29
|
+
let out = this.initialize(...args);
|
|
30
|
+
if(typeof out?.then == 'function'){
|
|
31
|
+
return out.then(out => out || this);
|
|
32
|
+
}
|
|
33
|
+
return out || this;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
initialize(){
|
|
37
|
+
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
assignProps(...sources){
|
|
41
|
+
return assignProps(this, ...sources);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const assignProps = (target, ...sources) => {
|
|
46
|
+
const fn = typeof sources[sources.length - 1] == 'function' ? sources.pop() : () => true;
|
|
47
|
+
|
|
48
|
+
sources.forEach(source => {
|
|
49
|
+
Object.getOwnPropertyNames(source).forEach(name => {
|
|
50
|
+
if(!fn(name)){
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
const descriptor = { ...Object.getOwnPropertyDescriptor(source, name) };
|
|
54
|
+
const { get: targetGet, set: targetSet } = (Object.getOwnPropertyDescriptor(target, name) || {});
|
|
55
|
+
const { get = targetGet, set = targetSet } = descriptor;
|
|
56
|
+
|
|
57
|
+
if(get) descriptor.get = get;
|
|
58
|
+
if(set) descriptor.set = set;
|
|
59
|
+
|
|
60
|
+
Object.defineProperty(target, name, descriptor);
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
return target;
|
|
64
|
+
};
|
package/lib/client.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { fileURLToPath } from 'url';
|
|
2
|
+
|
|
3
|
+
import { Class } from './class.js';
|
|
4
|
+
import { Singleton } from './singleton.js';
|
|
5
|
+
|
|
6
|
+
export const Client = Class.extend().include({
|
|
7
|
+
meta(){
|
|
8
|
+
this.include(Singleton);
|
|
9
|
+
},
|
|
10
|
+
|
|
11
|
+
initialize(){
|
|
12
|
+
this.modules = [];
|
|
13
|
+
|
|
14
|
+
this.addModule(`import ${JSON.stringify(fileURLToPath(`${import.meta.url}/../index.js`))};`);
|
|
15
|
+
},
|
|
16
|
+
|
|
17
|
+
addModule(...modules){
|
|
18
|
+
this.modules.push(...modules);
|
|
19
|
+
}
|
|
20
|
+
});
|
package/lib/command.js
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
|
|
2
|
+
import { Class } from './class.js';
|
|
3
|
+
import { inflector } from './inflector.js';
|
|
4
|
+
import { Registry } from './registry.js';
|
|
5
|
+
import { ServiceConsumer } from './service_consumer.js';
|
|
6
|
+
|
|
7
|
+
export const Command = Class.extend().include({
|
|
8
|
+
meta(){
|
|
9
|
+
this.include(Registry);
|
|
10
|
+
this.include(ServiceConsumer);
|
|
11
|
+
|
|
12
|
+
this.assignProps({
|
|
13
|
+
normalizeName(name){
|
|
14
|
+
return inflector.dasherize(name);
|
|
15
|
+
},
|
|
16
|
+
|
|
17
|
+
get schedules(){
|
|
18
|
+
if(!this.hasOwnProperty('_schedules')){
|
|
19
|
+
this._schedules = [];
|
|
20
|
+
}
|
|
21
|
+
return this._schedules;
|
|
22
|
+
},
|
|
23
|
+
|
|
24
|
+
schedule(...args){
|
|
25
|
+
this.schedules.push(args);
|
|
26
|
+
return this;
|
|
27
|
+
},
|
|
28
|
+
|
|
29
|
+
async run(context, name = 'list-commands', ...args){
|
|
30
|
+
return context.fork().run(async context => {
|
|
31
|
+
context.args = [ ...args ];
|
|
32
|
+
await this.create(name, context).run();
|
|
33
|
+
});
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
},
|
|
37
|
+
|
|
38
|
+
run(){
|
|
39
|
+
console.error(`No such command "${this.constructor.name}" exists.`);
|
|
40
|
+
}
|
|
41
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Command as default } from 'pinstripe';
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
export default {
|
|
4
|
+
async run(){
|
|
5
|
+
const [ name = '' ] = this.args;
|
|
6
|
+
const normalizedName = this.inflector.snakeify(name);
|
|
7
|
+
if(normalizedName == ''){
|
|
8
|
+
console.error('An app name must be given.');
|
|
9
|
+
process.exit();
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const { inProjectRootDir, generateFile, line, indent } = this.fsBuilder;
|
|
13
|
+
|
|
14
|
+
await inProjectRootDir(async () => {
|
|
15
|
+
|
|
16
|
+
await generateFile(`lib/apps/_file_importer.js`, { skipIfExists: true }, () => {
|
|
17
|
+
line();
|
|
18
|
+
line(`export { App as default } from 'pinstripe';`);
|
|
19
|
+
line();
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
await generateFile(`lib/apps/${normalizedName}.js`, () => {
|
|
23
|
+
line();
|
|
24
|
+
line(`export default {`);
|
|
25
|
+
indent(() => {
|
|
26
|
+
line('compose(){');
|
|
27
|
+
indent(() => {
|
|
28
|
+
line(`return ['shared', '${this.inflector.dasherize(normalizedName)}'];`);
|
|
29
|
+
});
|
|
30
|
+
line('}');
|
|
31
|
+
});
|
|
32
|
+
line('};');
|
|
33
|
+
line();
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
await this.runCommand('generate-view', `${normalizedName}/index`);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
export default {
|
|
4
|
+
async run(){
|
|
5
|
+
const [ name = '' ] = this.args;
|
|
6
|
+
const normalizedName = this.inflector.snakeify(name);
|
|
7
|
+
if(normalizedName == ''){
|
|
8
|
+
console.error('A command name must be given.');
|
|
9
|
+
process.exit();
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const { inProjectRootDir, generateFile, line, indent } = this.fsBuilder;
|
|
13
|
+
|
|
14
|
+
await inProjectRootDir(async () => {
|
|
15
|
+
|
|
16
|
+
await generateFile(`lib/commands/_file_importer.js`, { skipIfExists: true }, () => {
|
|
17
|
+
line();
|
|
18
|
+
line(`export { Command as default } from 'pinstripe';`);
|
|
19
|
+
line();
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
await generateFile(`lib/commands/${normalizedName}.js`, () => {
|
|
23
|
+
line();
|
|
24
|
+
line(`export default {`);
|
|
25
|
+
indent(() => {
|
|
26
|
+
line('run(){');
|
|
27
|
+
indent(() => {
|
|
28
|
+
line(`console.log('${this.inflector.dasherize(normalizedName)} command coming soon!')`);
|
|
29
|
+
});
|
|
30
|
+
line('}');
|
|
31
|
+
});
|
|
32
|
+
line('};');
|
|
33
|
+
line();
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
|
|
2
|
+
export default {
|
|
3
|
+
async run(){
|
|
4
|
+
const { extractArg } = this.cliUtils;
|
|
5
|
+
const name = this.inflector.snakeify(extractArg(''));
|
|
6
|
+
if(name == ''){
|
|
7
|
+
console.error('A component name must be given.');
|
|
8
|
+
process.exit();
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const { inProjectRootDir, generateFile, line, indent } = this.fsBuilder;
|
|
12
|
+
|
|
13
|
+
await inProjectRootDir(async () => {
|
|
14
|
+
|
|
15
|
+
await generateFile(`lib/components/_file_importer.js`, { skipIfExists: true }, () => {
|
|
16
|
+
line();
|
|
17
|
+
line(`export { Component as default } from 'pinstripe';`);
|
|
18
|
+
line();
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
await generateFile(`lib/components/${name}.js`, () => {
|
|
22
|
+
line();
|
|
23
|
+
line(`export default {`);
|
|
24
|
+
indent(() => {
|
|
25
|
+
line(`initialize(...args){`);
|
|
26
|
+
indent(() => {
|
|
27
|
+
line(`this.constructor.parent.prototype.initialize.call(this, ...args);`);
|
|
28
|
+
line();
|
|
29
|
+
line('this.shadow.patch(`');
|
|
30
|
+
indent(() => {
|
|
31
|
+
line(`<style>`);
|
|
32
|
+
indent(() => {
|
|
33
|
+
line(`.root {`);
|
|
34
|
+
indent(() => {
|
|
35
|
+
line(`background: yellow;`)
|
|
36
|
+
})
|
|
37
|
+
line(`}`);
|
|
38
|
+
});
|
|
39
|
+
line(`</style>`);
|
|
40
|
+
line(`<div class="root"><slot></div>`);
|
|
41
|
+
});
|
|
42
|
+
line('`);');
|
|
43
|
+
});
|
|
44
|
+
line(`}`);
|
|
45
|
+
});
|
|
46
|
+
line('};');
|
|
47
|
+
line();
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
|
|
2
|
+
export default {
|
|
3
|
+
async run(){
|
|
4
|
+
const { extractArg, extractFields, extractOptions } = this.cliUtils;
|
|
5
|
+
|
|
6
|
+
const suffix = this.inflector.snakeify(extractArg('migration'));
|
|
7
|
+
const fields = extractFields();
|
|
8
|
+
const { table } = extractOptions({
|
|
9
|
+
table: (() => {
|
|
10
|
+
const matches = suffix.match(/_to_(.+)$/);
|
|
11
|
+
if(matches){
|
|
12
|
+
return matches[1];
|
|
13
|
+
}
|
|
14
|
+
})()
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
const unixTime = Math.floor(new Date().getTime() / 1000);
|
|
18
|
+
const name = `${unixTime}_${suffix}`;
|
|
19
|
+
|
|
20
|
+
const { inProjectRootDir, generateFile, line, indent } = this.fsBuilder;
|
|
21
|
+
|
|
22
|
+
await inProjectRootDir(async () => {
|
|
23
|
+
|
|
24
|
+
await generateFile(`lib/migrations/_file_importer.js`, { skipIfExists: true }, () => {
|
|
25
|
+
line();
|
|
26
|
+
line(`export { Migration as default } from 'pinstripe/database';`);
|
|
27
|
+
line();
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
await generateFile(`lib/migrations/${name}.js`, () => {
|
|
31
|
+
line();
|
|
32
|
+
line(`export default {`);
|
|
33
|
+
indent(() => {
|
|
34
|
+
line(`async migrate(){`);
|
|
35
|
+
indent(() => {
|
|
36
|
+
if(table && fields.length){
|
|
37
|
+
line(`await this.database.table('${table}', async ${table} => {`);
|
|
38
|
+
indent(() => {
|
|
39
|
+
fields.forEach(({ name, type }) => {
|
|
40
|
+
line(`await ${table}.addColumn('${name}', '${type}');`);
|
|
41
|
+
});
|
|
42
|
+
})
|
|
43
|
+
line(`});`);
|
|
44
|
+
} else {
|
|
45
|
+
line();
|
|
46
|
+
}
|
|
47
|
+
})
|
|
48
|
+
line(`}`);
|
|
49
|
+
})
|
|
50
|
+
line('};');
|
|
51
|
+
line();
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
|
|
2
|
+
export default {
|
|
3
|
+
async run(){
|
|
4
|
+
|
|
5
|
+
const { extractArg, extractFields } = this.cliUtils;
|
|
6
|
+
const name = this.inflector.snakeify(extractArg(''));
|
|
7
|
+
if(name == ''){
|
|
8
|
+
console.error('A model name must be given.');
|
|
9
|
+
process.exit();
|
|
10
|
+
}
|
|
11
|
+
const fields = extractFields();
|
|
12
|
+
|
|
13
|
+
const collectionName = this.inflector.camelize(this.inflector.pluralize(name));
|
|
14
|
+
if(!await this.database[collectionName]){
|
|
15
|
+
const denormalizedFields = fields.map(({ mandatory, name, type }) => {
|
|
16
|
+
return `${ mandatory ? '^' : '' }${name}:${type}`
|
|
17
|
+
});
|
|
18
|
+
await this.runCommand('generate-migration', `create_${name}`, ...denormalizedFields, '--table', collectionName)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const { inProjectRootDir, generateFile, line, indent } = this.fsBuilder;
|
|
22
|
+
|
|
23
|
+
await inProjectRootDir(async () => {
|
|
24
|
+
|
|
25
|
+
await generateFile(`lib/models/_file_importer.js`, { skipIfExists: true }, () => {
|
|
26
|
+
line();
|
|
27
|
+
line(`export { Row as default } from 'pinstripe/database';`);
|
|
28
|
+
line();
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
await generateFile(`lib/models/${name}.js`, () => {
|
|
32
|
+
line();
|
|
33
|
+
line(`export default {`);
|
|
34
|
+
indent(() => {
|
|
35
|
+
line();
|
|
36
|
+
});
|
|
37
|
+
line('};');
|
|
38
|
+
line();
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
|
|
2
|
+
import { spawnSync } from 'child_process';
|
|
3
|
+
import * as crypto from 'crypto';
|
|
4
|
+
|
|
5
|
+
export default {
|
|
6
|
+
async run(){
|
|
7
|
+
|
|
8
|
+
const { extractArg, extractOptions } = this.cliUtils;
|
|
9
|
+
const name = extractArg('');
|
|
10
|
+
if(name == ''){
|
|
11
|
+
console.error('A project name must be given.');
|
|
12
|
+
process.exit();
|
|
13
|
+
}
|
|
14
|
+
const { with: dependencies } = extractOptions({
|
|
15
|
+
with: []
|
|
16
|
+
});
|
|
17
|
+
if(!dependencies.includes('pinstripe')){
|
|
18
|
+
dependencies.unshift('pinstripe')
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const { generateDir, generateFile, line, indent, echo } = this.fsBuilder;
|
|
22
|
+
|
|
23
|
+
await generateDir(name, async () => {
|
|
24
|
+
|
|
25
|
+
await generateFile(`package.json`, () => {
|
|
26
|
+
echo(JSON.stringify({
|
|
27
|
+
type: "module",
|
|
28
|
+
name,
|
|
29
|
+
version: "0.0.0",
|
|
30
|
+
license: "MIT",
|
|
31
|
+
exports: {
|
|
32
|
+
".": "./lib/index.js"
|
|
33
|
+
},
|
|
34
|
+
}, null, 2));
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
await generateFile(`pinstripe.config.js`, () => {
|
|
38
|
+
line();
|
|
39
|
+
line(`const environment = process.env.NODE_ENV || 'development';`);
|
|
40
|
+
line();
|
|
41
|
+
line(`let database;`);
|
|
42
|
+
line(`if(environment == 'production'){`)
|
|
43
|
+
indent(() => {
|
|
44
|
+
line(`database = {`);
|
|
45
|
+
indent(() => {
|
|
46
|
+
line(`adapter: 'mysql',`)
|
|
47
|
+
line(`host: 'localhost',`);
|
|
48
|
+
line(`user: 'root',`);
|
|
49
|
+
line(`password: '',`);
|
|
50
|
+
line(`database: \`${this.inflector.snakeify(name)}_\${environment}\``);
|
|
51
|
+
});
|
|
52
|
+
line(`};`);
|
|
53
|
+
});
|
|
54
|
+
line(`} else {`);
|
|
55
|
+
indent(() => {
|
|
56
|
+
line(`database = {`);
|
|
57
|
+
indent(() => {
|
|
58
|
+
line(`adapter: 'sqlite',`);
|
|
59
|
+
line(`filename: \`\${environment}.db\``)
|
|
60
|
+
});
|
|
61
|
+
line(`};`);
|
|
62
|
+
});
|
|
63
|
+
line(`}`);
|
|
64
|
+
line();
|
|
65
|
+
line(`let mail;`);
|
|
66
|
+
line(`if(environment == 'production'){`)
|
|
67
|
+
indent(() => {
|
|
68
|
+
line(`mail = {`);
|
|
69
|
+
indent(() => {
|
|
70
|
+
line(`adapter: 'smtp',`)
|
|
71
|
+
line(`host: "smtp.example.com",`)
|
|
72
|
+
line(`port: 465,`);
|
|
73
|
+
line(`secure: true, // use TLS`);
|
|
74
|
+
line(`auth: {`);
|
|
75
|
+
indent(() => {
|
|
76
|
+
line(`user: "username",`);
|
|
77
|
+
line(`pass: "password",`);
|
|
78
|
+
});
|
|
79
|
+
line(`}`);
|
|
80
|
+
});
|
|
81
|
+
line(`};`);
|
|
82
|
+
});
|
|
83
|
+
line(`} else {`);
|
|
84
|
+
indent(() => {
|
|
85
|
+
line(`mail = {`);
|
|
86
|
+
indent(() => {
|
|
87
|
+
line(`adapter: 'dummy'`);
|
|
88
|
+
});
|
|
89
|
+
line(`};`);
|
|
90
|
+
});
|
|
91
|
+
line(`}`);
|
|
92
|
+
line();
|
|
93
|
+
line(`export default {`);
|
|
94
|
+
indent(() => {
|
|
95
|
+
line(`database,`);
|
|
96
|
+
line(`mail,`);
|
|
97
|
+
line(`salt: '${crypto.randomUUID()}'`)
|
|
98
|
+
})
|
|
99
|
+
line(`};`);
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
await generateFile(`lib/index.js`, () => {
|
|
103
|
+
line();
|
|
104
|
+
line(`import { importAll } from 'pinstripe';`);
|
|
105
|
+
dependencies.forEach((dependency) => {
|
|
106
|
+
if(dependency != 'pinstripe') line(`import '${dependency}';`);
|
|
107
|
+
});
|
|
108
|
+
line();
|
|
109
|
+
line(`importAll(import.meta.url);`);
|
|
110
|
+
line();
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
await generateFile(`README.md`, () => {
|
|
114
|
+
line();
|
|
115
|
+
line(`# ${name}`);
|
|
116
|
+
line();
|
|
117
|
+
line('## Getting started');
|
|
118
|
+
line();
|
|
119
|
+
line('```bash');
|
|
120
|
+
indent(() => {
|
|
121
|
+
line('pinstripe init-database');
|
|
122
|
+
line('pinstripe start-server');
|
|
123
|
+
});
|
|
124
|
+
line('```');
|
|
125
|
+
line();
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
spawnSync('yarn', [ 'add', ...dependencies ], {
|
|
129
|
+
stdio: 'inherit'
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
|
|
2
|
+
export default {
|
|
3
|
+
async run(){
|
|
4
|
+
const [ name = '' ] = this.args;
|
|
5
|
+
if(name == ''){
|
|
6
|
+
console.error('A service name must be given.');
|
|
7
|
+
process.exit();
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const { inProjectRootDir, generateFile, line, indent } = this.fsBuilder;
|
|
11
|
+
|
|
12
|
+
await inProjectRootDir(async () => {
|
|
13
|
+
|
|
14
|
+
await generateFile(`lib/services/_file_importer.js`, { skipIfExists: true }, () => {
|
|
15
|
+
line();
|
|
16
|
+
line(`export { ServiceFactory as default } from 'pinstripe';`);
|
|
17
|
+
line();
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
await generateFile(`lib/services/${this.inflector.snakeify(name)}.js`, () => {
|
|
21
|
+
line();
|
|
22
|
+
line(`export default () => {`);
|
|
23
|
+
indent(() => {
|
|
24
|
+
line(`return 'Example ${this.inflector.camelize(name)} service'`);
|
|
25
|
+
});
|
|
26
|
+
line('};');
|
|
27
|
+
line();
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
};
|