pinstripe 0.9.0 → 0.12.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 +1 -1
- package/cli.js +5 -7
- package/lib/async_path_builder.js +4 -0
- package/lib/async_path_builder.test.js +11 -0
- package/lib/base.js +13 -2
- package/lib/base.test.js +30 -28
- package/lib/client.js +49 -0
- package/lib/command.js +20 -0
- package/lib/commands/_importer.js +2 -0
- package/lib/commands/create_database.js +1 -3
- package/lib/commands/drop_database.js +1 -3
- package/lib/commands/generate_command.js +10 -8
- package/lib/commands/generate_migration.js +10 -8
- package/lib/commands/generate_model.js +11 -9
- package/lib/commands/generate_node_wrapper.js +36 -0
- package/lib/commands/generate_project.js +2 -11
- package/lib/commands/generate_service.js +10 -8
- package/lib/commands/generate_static_site.js +79 -0
- package/lib/commands/generate_view.js +6 -8
- package/lib/commands/init_database.js +2 -4
- package/lib/commands/list_commands.js +2 -3
- package/lib/commands/list_migrations.js +2 -3
- package/lib/commands/list_models.js +2 -3
- package/lib/commands/list_node_wrappers.js +14 -0
- package/lib/commands/list_services.js +2 -3
- package/lib/commands/list_views.js +2 -3
- package/lib/commands/migrate_database.js +1 -3
- package/lib/commands/reset_database.js +2 -4
- package/lib/commands/seed_database.js +2 -4
- package/lib/commands/start_console.js +2 -3
- package/lib/commands/start_server.js +17 -10
- package/lib/constants.js +0 -9
- package/lib/css.js +101 -0
- package/lib/database/adapter.js +23 -0
- package/lib/database/adapters/mysql.js +629 -0
- package/lib/database/adapters/sqlite.js +590 -0
- package/lib/database/column.js +8 -48
- package/lib/database/constants.js +25 -44
- package/lib/database/migration.js +20 -0
- package/lib/database/migrator.js +6 -3
- package/lib/database/row.js +152 -96
- package/lib/database/sql.js +47 -44
- package/lib/database/sql.test.js +58 -0
- package/lib/database/table.js +77 -202
- package/lib/database/union.js +21 -39
- package/lib/database.js +30 -121
- package/lib/environment.js +4 -2
- package/lib/html.js +1 -1
- package/lib/import_all.js +22 -9
- package/lib/index.js +7 -8
- package/lib/initialize.client.js +3 -3
- package/lib/migrations/1627976184_create_user.js +2 -4
- package/lib/migrations/1628057822_create_session.js +2 -4
- package/lib/migrations/_importer.js +2 -0
- package/lib/models/_importer.js +2 -0
- package/lib/models/session.js +2 -4
- package/lib/models/user.js +4 -5
- package/lib/node_wrapper.js +242 -26
- package/lib/node_wrappers/_importer.js +2 -0
- package/lib/node_wrappers/anchor.client.js +18 -0
- package/lib/{widgets → node_wrappers}/document.client.js +12 -19
- package/lib/node_wrappers/form.client.js +16 -0
- package/lib/{widgets → node_wrappers}/frame.client.js +32 -11
- package/lib/node_wrappers/helpers.js +48 -0
- package/lib/node_wrappers/markdown_editor/line_inserter.client.js +14 -0
- package/lib/node_wrappers/markdown_editor.client.js +34 -0
- package/lib/node_wrappers/overlay.client.js +26 -0
- package/lib/{widgets/document → node_wrappers}/progress_bar.client.js +7 -6
- package/lib/overload.js +1 -0
- package/lib/service_factory.js +40 -0
- package/lib/services/_importer.js +2 -0
- package/lib/services/args.js +1 -4
- package/lib/services/cli_utils.js +2 -4
- package/lib/services/config.js +19 -8
- package/lib/services/cookies.js +2 -4
- package/lib/services/database.js +2 -5
- package/lib/services/fetch.js +33 -23
- package/lib/services/fork_environment.js +2 -4
- package/lib/services/fs_builder.js +2 -3
- package/lib/services/params.js +1 -4
- package/lib/services/project.js +1 -3
- package/lib/services/read_file.js +6 -0
- package/lib/services/render_css.js +6 -0
- package/lib/services/render_file.js +4 -7
- package/lib/services/render_form.js +108 -66
- package/lib/services/render_html.js +2 -4
- package/lib/services/render_list.js +58 -0
- package/lib/services/render_markdown.js +44 -0
- package/lib/services/render_table.js +67 -0
- package/lib/services/render_view.js +7 -18
- package/lib/services/reset_environment.js +2 -4
- package/lib/services/run_command.js +2 -4
- package/lib/services/session.js +2 -4
- package/lib/services/theme_config.js +76 -0
- package/lib/services/view.js +4 -0
- package/lib/thatify.js +1 -1
- package/lib/url.js +12 -4
- package/lib/url.test.js +5 -1
- package/lib/validatable.js +1 -5
- package/lib/view.js +109 -2
- package/lib/views/_importer.js +2 -0
- package/lib/views/{layout.js → _layout.js} +13 -17
- package/lib/views/base.css.js +657 -0
- package/lib/views/blocks/default.js +25 -0
- package/lib/views/blocks/help.js +139 -0
- package/lib/views/bundle.js.js +36 -0
- package/lib/{controllers → views}/sign_in.js +5 -4
- package/lib/views/sign_out.js +15 -0
- package/lib/virtual_node.js +41 -46
- package/package.json +10 -14
- package/babel.config.cjs +0 -12
- package/lib/commands/generate_controller.js +0 -33
- package/lib/commands/generate_widget.js +0 -30
- package/lib/commands/list_controllers.js +0 -15
- package/lib/commands/list_widgets.js +0 -15
- package/lib/controller.js +0 -19
- package/lib/controllers/bundle.js +0 -62
- package/lib/controllers/sign_out.js +0 -15
- package/lib/renderable.js +0 -25
- package/lib/scss/index.scss +0 -2
- package/lib/services/render_controller.js +0 -11
- package/lib/services/render_script.js +0 -14
- package/lib/static/bundle.css +0 -10308
- package/lib/static/bundle.css.map +0 -1
- package/lib/widgets/anchor.client.js +0 -54
- package/lib/widgets/document/style.client.js +0 -49
- package/lib/widgets/form.client.js +0 -61
- package/lib/widgets/input.client.js +0 -23
- package/lib/widgets/overlay.client.js +0 -27
- package/lib/widgets/script.client.js +0 -9
- package/pinstripe.scss +0 -2
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
## What is Pinstripe?
|
|
5
5
|
|
|
6
|
-
Pinstripe is a fullstack JavaScript web framework for Node.js
|
|
6
|
+
Pinstripe is a fullstack JavaScript web framework for Node.js.
|
|
7
7
|
|
|
8
8
|
## License
|
|
9
9
|
|
package/cli.js
CHANGED
|
@@ -2,10 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
import { spawn } from 'child_process';
|
|
4
4
|
|
|
5
|
-
import { importAll } from './lib/import_all.js';
|
|
6
5
|
import { project } from './lib/project.js';
|
|
7
6
|
import { Command } from './lib/command.js';
|
|
8
|
-
import {
|
|
7
|
+
import { createEnvironment } from './lib/environment.js';
|
|
9
8
|
|
|
10
9
|
(async () => {
|
|
11
10
|
const { entryPath, localPinstripePath, exists } = await project;
|
|
@@ -18,12 +17,12 @@ import { Environment } from './lib/environment.js';
|
|
|
18
17
|
stdio: 'inherit'
|
|
19
18
|
});
|
|
20
19
|
} else {
|
|
21
|
-
await importAll();
|
|
22
20
|
if(entryPath){
|
|
23
|
-
|
|
24
|
-
await importAll();
|
|
21
|
+
import(entryPath);
|
|
25
22
|
}
|
|
26
23
|
|
|
24
|
+
const { runCommand, resetEnvironment } = await createEnvironment();
|
|
25
|
+
|
|
27
26
|
if(exists){
|
|
28
27
|
Command.unregister('generate-project');
|
|
29
28
|
} else {
|
|
@@ -34,8 +33,7 @@ import { Environment } from './lib/environment.js';
|
|
|
34
33
|
}
|
|
35
34
|
});
|
|
36
35
|
}
|
|
37
|
-
|
|
38
|
-
const { runCommand, resetEnvironment } = Environment.new();
|
|
36
|
+
|
|
39
37
|
try {
|
|
40
38
|
await runCommand(...args);
|
|
41
39
|
} catch(e) {
|
|
@@ -15,6 +15,10 @@ export const AsyncPathBuilder = Base.extend().include({
|
|
|
15
15
|
return new this.constructor(this._startObject, [...this._path, args ]);
|
|
16
16
|
},
|
|
17
17
|
|
|
18
|
+
get toString(){
|
|
19
|
+
return this.__getMissing('toString');
|
|
20
|
+
},
|
|
21
|
+
|
|
18
22
|
then(...args){
|
|
19
23
|
return unwrap(this._startObject, [...this._path]).then(...args);
|
|
20
24
|
}
|
|
@@ -25,3 +25,14 @@ test('AsyncPathBuilder (2)', async () => {
|
|
|
25
25
|
expect(await foo.bar().baz()).toBe("boo");
|
|
26
26
|
expect(await foo.bar().baz().length).toBe(3);
|
|
27
27
|
});
|
|
28
|
+
|
|
29
|
+
test('AsyncPathBuilder (3)', async () => {
|
|
30
|
+
const foo = AsyncPathBuilder.new({
|
|
31
|
+
toString(){
|
|
32
|
+
return "hello world";
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
expect(await foo.toString()).toBe("hello world");
|
|
37
|
+
});
|
|
38
|
+
|
package/lib/base.js
CHANGED
|
@@ -86,6 +86,13 @@ export class Base {
|
|
|
86
86
|
traps.ownKeys = () => {
|
|
87
87
|
return this.__keys();
|
|
88
88
|
};
|
|
89
|
+
|
|
90
|
+
traps.getOwnPropertyDescriptor = (target, prop) => {
|
|
91
|
+
return {
|
|
92
|
+
enumerable: true,
|
|
93
|
+
configurable: true,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
89
96
|
}
|
|
90
97
|
|
|
91
98
|
if(Object.keys(traps).length){
|
|
@@ -110,17 +117,21 @@ const assignProps = (target, ...sources) => {
|
|
|
110
117
|
return;
|
|
111
118
|
}
|
|
112
119
|
const descriptor = { ...Object.getOwnPropertyDescriptor(source, name) };
|
|
113
|
-
const { get } = descriptor;
|
|
120
|
+
const { get, set } = descriptor;
|
|
121
|
+
const { get: targetGet, set: targetSet } = (Object.getOwnPropertyDescriptor(target, name) || {});
|
|
114
122
|
if(get){
|
|
115
123
|
descriptor.get = function(...args){
|
|
116
124
|
return get.call(this.__proxy || this, ...args);
|
|
117
125
|
};
|
|
126
|
+
} else if(targetGet) {
|
|
127
|
+
descriptor.get = targetGet;
|
|
118
128
|
}
|
|
119
|
-
const { set } = descriptor;
|
|
120
129
|
if(set){
|
|
121
130
|
descriptor.set = function(...args){
|
|
122
131
|
set.call(this.__proxy || this, ...args);
|
|
123
132
|
};
|
|
133
|
+
} else if(targetSet){
|
|
134
|
+
descriptor.set = targetSet;
|
|
124
135
|
}
|
|
125
136
|
Object.defineProperty(target, name, descriptor);
|
|
126
137
|
});
|
package/lib/base.test.js
CHANGED
|
@@ -65,32 +65,34 @@ test(`Base - if the __call has been defined getting/setting still works`, async
|
|
|
65
65
|
}).new();
|
|
66
66
|
|
|
67
67
|
expect(fixture.foo).toBe("bar");
|
|
68
|
-
})
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
test(`Base - can produce dynamic keys`, () => {
|
|
71
|
+
const fixture = Base.extend().include({
|
|
72
|
+
baz: 'hello world',
|
|
73
|
+
|
|
74
|
+
__keys(){
|
|
75
|
+
return ['foo', 'bar'];
|
|
76
|
+
}
|
|
77
|
+
}).new();
|
|
78
|
+
|
|
79
|
+
expect(Object.keys(fixture)).toEqual(['foo', 'bar']);
|
|
80
|
+
});
|
|
69
81
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
// return 'apple';
|
|
88
|
-
// }
|
|
89
|
-
// });
|
|
90
|
-
// const Bar = Base.extend().include(Foo);
|
|
91
|
-
// const Baz = Base.extend().include(Bar);
|
|
92
|
-
|
|
93
|
-
// expect(typeof Foo.new().fruit).toBe('undefined');
|
|
94
|
-
// expect(Bar.new().fruit()).toBe('apple');
|
|
95
|
-
// expect(Baz.new().fruit()).toBe('apple');
|
|
96
|
-
// });
|
|
82
|
+
test(`Base - getters and setters with same name can be defined independently`, () => {
|
|
83
|
+
const fixture = Base.extend().include({
|
|
84
|
+
meta(){
|
|
85
|
+
this.prototype.assignProps({
|
|
86
|
+
get foo(){
|
|
87
|
+
return 'bar';
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
},
|
|
91
|
+
|
|
92
|
+
set foo(value){
|
|
93
|
+
|
|
94
|
+
}
|
|
95
|
+
}).new();
|
|
96
|
+
|
|
97
|
+
expect(fixture.foo).toEqual('bar');
|
|
98
|
+
})
|
package/lib/client.js
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
|
|
2
|
+
import { promisify } from 'util';
|
|
3
|
+
import { readFile } from 'fs';
|
|
4
|
+
import { Volume as MemFs } from 'memfs';
|
|
5
|
+
import * as fs from 'fs';
|
|
6
|
+
import { Union as UnionFs } from 'unionfs';
|
|
7
|
+
|
|
8
|
+
import { Base } from './base.js';
|
|
9
|
+
import { overload } from './overload.js';
|
|
10
|
+
|
|
11
|
+
export const client = Base.extend().include({
|
|
12
|
+
initialize(){
|
|
13
|
+
this.files = {};
|
|
14
|
+
},
|
|
15
|
+
|
|
16
|
+
addFile: overload({
|
|
17
|
+
['string, function'](filePath, fn){
|
|
18
|
+
this.files[filePath] = fn;
|
|
19
|
+
},
|
|
20
|
+
|
|
21
|
+
string(filePath){
|
|
22
|
+
this.addFile(filePath, async () => {
|
|
23
|
+
return (await promisify(readFile)(filePath)).toString();
|
|
24
|
+
});
|
|
25
|
+
},
|
|
26
|
+
}),
|
|
27
|
+
|
|
28
|
+
async createFs(entryFilePath){
|
|
29
|
+
const files = {};
|
|
30
|
+
const filePaths = Object.keys(this.files);
|
|
31
|
+
while(filePaths.length){
|
|
32
|
+
const filePath = filePaths.pop();
|
|
33
|
+
const data = await this.files[filePath]();
|
|
34
|
+
files[filePath] = data.replace(/(.*)\/\/\s*pinstripe-if-client:\s*(.*)/g, '$2 // pinstripe-if-server: $1');
|
|
35
|
+
}
|
|
36
|
+
return new UnionFs().use(fs).use(new MemFs.fromJSON({
|
|
37
|
+
...files,
|
|
38
|
+
[entryFilePath]: `
|
|
39
|
+
${
|
|
40
|
+
Object.keys(this.files).filter(filePath => filePath.match(/\/[^\.\/]+(\.client\.js)$/)).map(filePath => `
|
|
41
|
+
import ${JSON.stringify(filePath)};
|
|
42
|
+
`).join('\n')
|
|
43
|
+
}
|
|
44
|
+
`
|
|
45
|
+
}));
|
|
46
|
+
}
|
|
47
|
+
}).new();
|
|
48
|
+
|
|
49
|
+
export const addFileToClient = (...args) => client.addFile(...args);
|
package/lib/command.js
CHANGED
|
@@ -4,6 +4,7 @@ import { Registrable } from './registrable.js';
|
|
|
4
4
|
import { dasherize } from './inflector.js';
|
|
5
5
|
import { overload } from './overload.js';
|
|
6
6
|
import { thatify } from './thatify.js';
|
|
7
|
+
import { addFileToClient } from './client.js';
|
|
7
8
|
|
|
8
9
|
export const Command = Base.extend().include({
|
|
9
10
|
meta(){
|
|
@@ -47,3 +48,22 @@ export const defineCommand = overload({
|
|
|
47
48
|
defineCommand(name, { run: thatify(fn) });
|
|
48
49
|
}
|
|
49
50
|
});
|
|
51
|
+
|
|
52
|
+
export const commandImporter = dirPath => {
|
|
53
|
+
return async filePath => {
|
|
54
|
+
const relativeFilePath = filePath.substr(dirPath.length).replace(/^\//, '');
|
|
55
|
+
|
|
56
|
+
if(filePath.match(/\.js$/)){
|
|
57
|
+
const relativeFilePathWithoutExtension = relativeFilePath.replace(/\.[^/]+$/, '');
|
|
58
|
+
if(relativeFilePathWithoutExtension == '_importer'){
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
addFileToClient(filePath);
|
|
62
|
+
const definition = await ( await import(filePath) ).default;
|
|
63
|
+
if(definition !== undefined){
|
|
64
|
+
defineCommand(relativeFilePathWithoutExtension, definition);
|
|
65
|
+
}
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
};
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
defineCommand('generate-command', async ({
|
|
2
|
+
export default async ({
|
|
5
3
|
cliUtils: { extractArg },
|
|
6
4
|
fsBuilder: { inProjectRootDir, generateFile, line, indent },
|
|
7
5
|
snakeify, dasherize
|
|
@@ -14,17 +12,21 @@ defineCommand('generate-command', async ({
|
|
|
14
12
|
|
|
15
13
|
await inProjectRootDir(async () => {
|
|
16
14
|
|
|
17
|
-
await generateFile(`lib/commands
|
|
15
|
+
await generateFile(`lib/commands/_importer.js`, { skipIfExists: true }, () => {
|
|
16
|
+
line();
|
|
17
|
+
line(`export { commandImporter as default } from 'pinstripe';`);
|
|
18
18
|
line();
|
|
19
|
-
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
await generateFile(`lib/commands/${name}.js`, () => {
|
|
20
22
|
line();
|
|
21
|
-
line(`
|
|
23
|
+
line(`export default () => {`);
|
|
22
24
|
indent(() => {
|
|
23
25
|
line(`console.log('${dasherize(name)} command coming soon!')`);
|
|
24
26
|
});
|
|
25
|
-
line('}
|
|
27
|
+
line('};');
|
|
26
28
|
line();
|
|
27
29
|
});
|
|
28
30
|
|
|
29
31
|
});
|
|
30
|
-
}
|
|
32
|
+
};
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
defineCommand('generate-migration', async ({
|
|
2
|
+
export default async ({
|
|
5
3
|
cliUtils: { extractArg, extractFields, extractOptions },
|
|
6
4
|
fsBuilder: { inProjectRootDir, generateFile, line, indent },
|
|
7
5
|
snakeify
|
|
@@ -22,11 +20,15 @@ defineCommand('generate-migration', async ({
|
|
|
22
20
|
|
|
23
21
|
await inProjectRootDir(async () => {
|
|
24
22
|
|
|
25
|
-
await generateFile(`lib/migrations
|
|
23
|
+
await generateFile(`lib/migrations/_importer.js`, { skipIfExists: true }, () => {
|
|
24
|
+
line();
|
|
25
|
+
line(`export { migrationImporter as default } from 'pinstripe';`);
|
|
26
26
|
line();
|
|
27
|
-
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
await generateFile(`lib/migrations/${name}.js`, () => {
|
|
28
30
|
line();
|
|
29
|
-
line(`
|
|
31
|
+
line(`export default async ({ database }) => {`);
|
|
30
32
|
indent(() => {
|
|
31
33
|
line();
|
|
32
34
|
if(table && fields.length){
|
|
@@ -36,8 +38,8 @@ defineCommand('generate-migration', async ({
|
|
|
36
38
|
line();
|
|
37
39
|
}
|
|
38
40
|
})
|
|
39
|
-
line('}
|
|
41
|
+
line('};');
|
|
40
42
|
line();
|
|
41
43
|
});
|
|
42
44
|
});
|
|
43
|
-
}
|
|
45
|
+
};
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
defineCommand('generate-model', async ({
|
|
2
|
+
export default async ({
|
|
5
3
|
cliUtils: { extractArg, extractFields },
|
|
6
4
|
fsBuilder: { inProjectRootDir, generateFile, line, indent },
|
|
7
5
|
snakeify, pluralize, camelize,
|
|
@@ -17,7 +15,7 @@ defineCommand('generate-model', async ({
|
|
|
17
15
|
const fields = extractFields();
|
|
18
16
|
|
|
19
17
|
const collectionName = camelize(pluralize(name));
|
|
20
|
-
if(!await database[collectionName].exists){
|
|
18
|
+
if(!await database[collectionName].exists()){
|
|
21
19
|
const denormalizedFields = fields.map(({ mandatory, name, type }) => {
|
|
22
20
|
return `${ mandatory ? '^' : '' }${name}:${type}`
|
|
23
21
|
});
|
|
@@ -26,17 +24,21 @@ defineCommand('generate-model', async ({
|
|
|
26
24
|
|
|
27
25
|
await inProjectRootDir(async () => {
|
|
28
26
|
|
|
29
|
-
await generateFile(`lib/models
|
|
27
|
+
await generateFile(`lib/models/_importer.js`, { skipIfExists: true }, () => {
|
|
28
|
+
line();
|
|
29
|
+
line(`export { modelImporter as default } from 'pinstripe';`);
|
|
30
30
|
line();
|
|
31
|
-
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
await generateFile(`lib/models/${name}.js`, () => {
|
|
32
34
|
line();
|
|
33
|
-
line(`
|
|
35
|
+
line(`export default {`);
|
|
34
36
|
indent(() => {
|
|
35
37
|
line();
|
|
36
38
|
});
|
|
37
|
-
line('}
|
|
39
|
+
line('};');
|
|
38
40
|
line();
|
|
39
41
|
});
|
|
40
42
|
|
|
41
43
|
});
|
|
42
|
-
}
|
|
44
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
|
|
2
|
+
export default async ({
|
|
3
|
+
cliUtils: { extractArg },
|
|
4
|
+
fsBuilder: { inProjectRootDir, generateFile, line, indent },
|
|
5
|
+
snakeify
|
|
6
|
+
}) => {
|
|
7
|
+
const name = snakeify(extractArg(''));
|
|
8
|
+
if(name == ''){
|
|
9
|
+
console.error('A node wrapper name must be given.');
|
|
10
|
+
process.exit();
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
await inProjectRootDir(async () => {
|
|
14
|
+
|
|
15
|
+
await generateFile(`lib/node_wrappers/_importer.js`, { skipIfExists: true }, () => {
|
|
16
|
+
line();
|
|
17
|
+
line(`export { nodeWrapperImporter as default } from 'pinstripe';`);
|
|
18
|
+
line();
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
await generateFile(`lib/node_wrappers/${name}.client.js`, () => {
|
|
22
|
+
line();
|
|
23
|
+
line(`export default {`);
|
|
24
|
+
indent(() => {
|
|
25
|
+
line(`initialize(){`);
|
|
26
|
+
indent(() => {
|
|
27
|
+
line(`this.constructor.parent.prototype.initialize.call(this, ...args);`);
|
|
28
|
+
});
|
|
29
|
+
line(`}`);
|
|
30
|
+
});
|
|
31
|
+
line('};');
|
|
32
|
+
line();
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
});
|
|
36
|
+
};
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
|
|
2
2
|
import { spawnSync } from 'child_process';
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
defineCommand('generate-project', async ({
|
|
4
|
+
export default async ({
|
|
7
5
|
cliUtils: { extractArg, extractOptions },
|
|
8
6
|
fsBuilder: { generateDir, generateFile, line, indent, echo }
|
|
9
7
|
}) => {
|
|
@@ -43,16 +41,9 @@ defineCommand('generate-project', async ({
|
|
|
43
41
|
line();
|
|
44
42
|
});
|
|
45
43
|
|
|
46
|
-
await generateFile(`lib/web/_importer.js`, () => {
|
|
47
|
-
line();
|
|
48
|
-
line(`export { webImporter as default } from 'pinstripe';`);
|
|
49
|
-
line();
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
|
|
53
44
|
spawnSync('yarn', [ 'add', ...dependencies ], {
|
|
54
45
|
stdio: 'inherit'
|
|
55
46
|
});
|
|
56
47
|
|
|
57
48
|
});
|
|
58
|
-
}
|
|
49
|
+
};
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
defineCommand('generate-service', async ({
|
|
2
|
+
export default async ({
|
|
5
3
|
cliUtils: { extractArg },
|
|
6
4
|
fsBuilder: { inProjectRootDir, generateFile, line, indent },
|
|
7
5
|
snakeify, camelize
|
|
@@ -14,17 +12,21 @@ defineCommand('generate-service', async ({
|
|
|
14
12
|
|
|
15
13
|
await inProjectRootDir(async () => {
|
|
16
14
|
|
|
17
|
-
await generateFile(`lib/services
|
|
15
|
+
await generateFile(`lib/services/_importer.js`, { skipIfExists: true }, () => {
|
|
16
|
+
line();
|
|
17
|
+
line(`export { serviceImporter as default } from 'pinstripe';`);
|
|
18
18
|
line();
|
|
19
|
-
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
await generateFile(`lib/services/${snakeify(name)}.js`, () => {
|
|
20
22
|
line();
|
|
21
|
-
line(`
|
|
23
|
+
line(`export default () => {`);
|
|
22
24
|
indent(() => {
|
|
23
25
|
line(`return 'Example ${camelize(name)} service'`);
|
|
24
26
|
});
|
|
25
|
-
line('}
|
|
27
|
+
line('};');
|
|
26
28
|
line();
|
|
27
29
|
});
|
|
28
30
|
|
|
29
31
|
});
|
|
30
|
-
}
|
|
32
|
+
};
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
|
|
2
|
+
import { VirtualNode } from '../virtual_node.js';
|
|
3
|
+
import { Url } from '../url.js';
|
|
4
|
+
import { View } from '../view.js';
|
|
5
|
+
import { default as mimeTypes } from 'mime-types';
|
|
6
|
+
|
|
7
|
+
export default {
|
|
8
|
+
|
|
9
|
+
async run(){
|
|
10
|
+
this.pages = {};
|
|
11
|
+
const paths = Object.keys(View.classes).filter(path => !path.match(/(^|\/)_/)).map(path => {
|
|
12
|
+
return `/${path.replace(/(^|\/)index$/, '')}`.replace(/^\/+/, '/');
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
while(paths.length){
|
|
16
|
+
await this.crawlPage({ _path: paths.shift() });
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const pages = Object.values(this.pages).filter(page => page.status == 200 && Object.keys(page.params).length == 1);
|
|
20
|
+
const { inProjectRootDir, generateDir, generateFile, echo } = this.fsBuilder;
|
|
21
|
+
|
|
22
|
+
await inProjectRootDir(async () => {
|
|
23
|
+
await generateDir('build/static', async () => {
|
|
24
|
+
while(pages.length){
|
|
25
|
+
const { params, headers } = pages.shift();
|
|
26
|
+
const contentType = headers['content-type'];
|
|
27
|
+
|
|
28
|
+
const path = params._path;
|
|
29
|
+
let filePath = path.replace(/^\//, '');
|
|
30
|
+
if(filePath.match(/(^|\/)$/)){
|
|
31
|
+
filePath = `${filePath}index`;
|
|
32
|
+
}
|
|
33
|
+
if(!filePath.match(/[^/]+\.[^/]+$/)){
|
|
34
|
+
filePath = `${filePath}.${mimeTypes.extension(contentType)}`
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const data = (await this.fetch({ _path: path }))[2];
|
|
38
|
+
|
|
39
|
+
await generateFile(filePath, () => {
|
|
40
|
+
echo(data.join(''));
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
},
|
|
46
|
+
|
|
47
|
+
async crawlPage(params){
|
|
48
|
+
const hash = JSON.stringify(params);
|
|
49
|
+
if(this.pages[hash]) return;
|
|
50
|
+
const page = { params };
|
|
51
|
+
this.pages[hash] = page;
|
|
52
|
+
const [ status, headers, data ] = await this.fetch(params);
|
|
53
|
+
page.status = status;
|
|
54
|
+
page.headers = headers;
|
|
55
|
+
if(status != 200 || headers['content-type'] != 'text/html') return;
|
|
56
|
+
const html = data.join('');
|
|
57
|
+
const virtualDom = VirtualNode.fromString(html);
|
|
58
|
+
const urls = this.extractUrls(virtualDom);
|
|
59
|
+
while(urls.length){
|
|
60
|
+
const url = urls.shift();
|
|
61
|
+
await this.crawlPage({ ...url.params, _path: url.path });
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
|
|
65
|
+
extractUrls(virtualDom){
|
|
66
|
+
const out = [];
|
|
67
|
+
virtualDom.traverse(({ attributes }) => {
|
|
68
|
+
['src', 'href'].forEach(name => {
|
|
69
|
+
const value = attributes[name];
|
|
70
|
+
if(!value) return;
|
|
71
|
+
const url = Url.fromString(value, 'http://localhost/');
|
|
72
|
+
if(url.host != 'localhost') return;
|
|
73
|
+
out.push(url);
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
return out;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
};
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
defineCommand('generate-view', async ({
|
|
2
|
+
export default async ({
|
|
5
3
|
cliUtils: { extractArg },
|
|
6
4
|
fsBuilder: { inProjectRootDir, generateFile, line, indent }
|
|
7
5
|
}) => {
|
|
@@ -16,14 +14,14 @@ defineCommand('generate-view', async ({
|
|
|
16
14
|
}
|
|
17
15
|
|
|
18
16
|
await inProjectRootDir(async () => {
|
|
19
|
-
|
|
20
|
-
await generateFile(`lib/
|
|
17
|
+
|
|
18
|
+
await generateFile(`lib/views/_importer.js`, { skipIfExists: true }, () => {
|
|
21
19
|
line();
|
|
22
|
-
line(`export {
|
|
20
|
+
line(`export { viewImporter as default } from 'pinstripe';`);
|
|
23
21
|
line();
|
|
24
22
|
});
|
|
25
23
|
|
|
26
|
-
await generateFile(`lib/
|
|
24
|
+
await generateFile(`lib/views/${name}`, () => {
|
|
27
25
|
line();
|
|
28
26
|
line('export default ({ renderHtml, params }) => renderHtml(`');
|
|
29
27
|
indent(() => {
|
|
@@ -33,4 +31,4 @@ defineCommand('generate-view', async ({
|
|
|
33
31
|
line();
|
|
34
32
|
});
|
|
35
33
|
});
|
|
36
|
-
}
|
|
34
|
+
};
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
defineCommand('init-database', async ({ runCommand }) => {
|
|
2
|
+
export default async ({ runCommand }) => {
|
|
5
3
|
await runCommand('create-database');
|
|
6
4
|
await runCommand('migrate-database');
|
|
7
5
|
await runCommand('seed-database');
|
|
8
|
-
}
|
|
6
|
+
};
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
|
|
2
2
|
import chalk from 'chalk';
|
|
3
|
-
import { defineCommand } from 'pinstripe';
|
|
4
3
|
|
|
5
4
|
import { Command } from '../command.js';
|
|
6
5
|
|
|
7
|
-
|
|
6
|
+
export default () => {
|
|
8
7
|
console.log('');
|
|
9
8
|
console.log('The following commands are available:');
|
|
10
9
|
console.log('');
|
|
@@ -12,4 +11,4 @@ defineCommand('list-commands', () => {
|
|
|
12
11
|
console.log(` * ${chalk.green(commandName)}`);
|
|
13
12
|
});
|
|
14
13
|
console.log('');
|
|
15
|
-
}
|
|
14
|
+
};
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
|
|
2
2
|
import chalk from 'chalk';
|
|
3
|
-
import { defineCommand } from 'pinstripe';
|
|
4
3
|
|
|
5
4
|
import { Migration } from '../database/migration.js'
|
|
6
5
|
|
|
7
|
-
|
|
6
|
+
export default () => {
|
|
8
7
|
console.log('');
|
|
9
8
|
console.log('The following migrations are available:');
|
|
10
9
|
console.log('');
|
|
@@ -12,4 +11,4 @@ defineCommand('list-migrations', () => {
|
|
|
12
11
|
console.log(` * ${chalk.green(migrationName)}`);
|
|
13
12
|
});
|
|
14
13
|
console.log('');
|
|
15
|
-
}
|
|
14
|
+
};
|