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
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
|
|
2
|
+
import { default as mimeTypes } from 'mime-types';
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
async run(){
|
|
6
|
+
this.pages = {};
|
|
7
|
+
const urls = this.viewNames.filter(path => !path.match(/(^|\/)_/)).map(path => {
|
|
8
|
+
return new URL(path, 'http://127.0.0.1/');
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
while(urls.length){
|
|
12
|
+
await this.crawlPage({ _url: urls.shift() });
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const pages = Object.values(this.pages).filter(page => page.status == 200 && Object.keys(page.params).length == 1);
|
|
16
|
+
const { inProjectRootDir, generateDir, generateFile, echo } = this.fsBuilder;
|
|
17
|
+
|
|
18
|
+
await inProjectRootDir(async () => {
|
|
19
|
+
await generateDir('build/static', async () => {
|
|
20
|
+
while(pages.length){
|
|
21
|
+
const { params, headers } = pages.shift();
|
|
22
|
+
const contentType = headers['content-type'];
|
|
23
|
+
|
|
24
|
+
const path = params._url.pathname;
|
|
25
|
+
let filePath = path.replace(/^\//, '');
|
|
26
|
+
if(filePath.match(/(^|\/)$/)){
|
|
27
|
+
filePath = `${filePath}index`;
|
|
28
|
+
}
|
|
29
|
+
if(!filePath.match(/[^/]+\.[^/]+$/)){
|
|
30
|
+
filePath = `${filePath}.${mimeTypes.extension(contentType)}`
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const data = (await this.fetch({ _url: new URL(path, 'http://127.0.0.1/') }))[2];
|
|
34
|
+
|
|
35
|
+
await generateFile(filePath, () => {
|
|
36
|
+
echo(data.join(''));
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
},
|
|
42
|
+
|
|
43
|
+
async crawlPage(params){
|
|
44
|
+
const hash = JSON.stringify(params);
|
|
45
|
+
if(this.pages[hash]) return;
|
|
46
|
+
const page = { params };
|
|
47
|
+
this.pages[hash] = page;
|
|
48
|
+
const [ status, headers, data ] = await this.fetch(params);
|
|
49
|
+
page.status = status;
|
|
50
|
+
page.headers = headers;
|
|
51
|
+
if(status != 200 || headers['content-type'] != 'text/html') return;
|
|
52
|
+
const html = data.join('');
|
|
53
|
+
const virtualDom = this.parseHtml(html);
|
|
54
|
+
const urls = this.extractUrls(virtualDom);
|
|
55
|
+
while(urls.length){
|
|
56
|
+
const url = urls.shift();
|
|
57
|
+
await this.crawlPage({ ...url.params, _url: url });
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
|
|
61
|
+
extractUrls(virtualDom){
|
|
62
|
+
const out = [];
|
|
63
|
+
virtualDom.traverse(({ attributes }) => {
|
|
64
|
+
['src', 'href'].forEach(name => {
|
|
65
|
+
const value = attributes[name];
|
|
66
|
+
if(!value) return;
|
|
67
|
+
const url = new URL(value, 'http://127.0.0.1/');
|
|
68
|
+
if(url.host != '127.0.0.1') return;
|
|
69
|
+
out.push(url);
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
return out;
|
|
73
|
+
}
|
|
74
|
+
};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
|
|
2
|
+
export default {
|
|
3
|
+
async run(){
|
|
4
|
+
const [ name = '' ] = this.args;
|
|
5
|
+
let normalizedName = name.replace(/^\//, '');
|
|
6
|
+
if(name == ''){
|
|
7
|
+
console.error('A view name must be given.');
|
|
8
|
+
process.exit();
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
if(!normalizedName.match(/\.[^\/]+$/)){
|
|
12
|
+
normalizedName = `${normalizedName}.js`;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const { inProjectRootDir, generateFile, line, indent } = this.fsBuilder;
|
|
16
|
+
|
|
17
|
+
await inProjectRootDir(async () => {
|
|
18
|
+
|
|
19
|
+
await generateFile(`lib/views/_file_importer.js`, { skipIfExists: true }, () => {
|
|
20
|
+
line();
|
|
21
|
+
line(`export { View as default } from 'pinstripe';`);
|
|
22
|
+
line();
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
await generateFile(`lib/views/${normalizedName}`, () => {
|
|
26
|
+
line();
|
|
27
|
+
line('export default {');
|
|
28
|
+
indent(() => {
|
|
29
|
+
line('render(){')
|
|
30
|
+
indent(() => {
|
|
31
|
+
line('return this.renderHtml`')
|
|
32
|
+
indent(() => {
|
|
33
|
+
line(`<h1>${normalizedName} view<h1></h1>`);
|
|
34
|
+
});
|
|
35
|
+
line('`;')
|
|
36
|
+
});
|
|
37
|
+
line('}')
|
|
38
|
+
});
|
|
39
|
+
line('};');
|
|
40
|
+
line();
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import { App } from 'pinstripe';
|
|
4
|
+
|
|
5
|
+
export default {
|
|
6
|
+
run(){
|
|
7
|
+
console.log('');
|
|
8
|
+
console.log('The following apps are available:');
|
|
9
|
+
console.log('');
|
|
10
|
+
App.names.forEach(appName => {
|
|
11
|
+
console.log(` * ${chalk.green(appName)} (composed of ${JSON.stringify(App.create(appName, this.context).compose())} views)`);
|
|
12
|
+
});
|
|
13
|
+
console.log('');
|
|
14
|
+
}
|
|
15
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import { Command } from 'pinstripe';
|
|
4
|
+
|
|
5
|
+
export default {
|
|
6
|
+
run(){
|
|
7
|
+
console.log('');
|
|
8
|
+
console.log('The following commands are available:');
|
|
9
|
+
console.log('');
|
|
10
|
+
Command.names.forEach(commandName => {
|
|
11
|
+
console.log(` * ${chalk.green(commandName)}`);
|
|
12
|
+
});
|
|
13
|
+
console.log('');
|
|
14
|
+
}
|
|
15
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import { Component } from 'pinstripe';
|
|
4
|
+
|
|
5
|
+
export default {
|
|
6
|
+
run(){
|
|
7
|
+
console.log('');
|
|
8
|
+
console.log('The following components are available:');
|
|
9
|
+
console.log('');
|
|
10
|
+
Component.names.forEach(componentName => {
|
|
11
|
+
console.log(` * ${chalk.green(componentName)}`);
|
|
12
|
+
});
|
|
13
|
+
console.log('');
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import { Migration } from 'pinstripe/database';
|
|
4
|
+
|
|
5
|
+
export default {
|
|
6
|
+
run(){
|
|
7
|
+
console.log('');
|
|
8
|
+
console.log('The following migrations are available:');
|
|
9
|
+
console.log('');
|
|
10
|
+
Migration.names.forEach(migrationName => {
|
|
11
|
+
console.log(` * ${chalk.green(migrationName)}`);
|
|
12
|
+
});
|
|
13
|
+
console.log('');
|
|
14
|
+
}
|
|
15
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import { Row } from 'pinstripe/database';
|
|
4
|
+
|
|
5
|
+
export default {
|
|
6
|
+
run(){
|
|
7
|
+
console.log('');
|
|
8
|
+
console.log('The following models are available:');
|
|
9
|
+
console.log('');
|
|
10
|
+
Row.names.forEach(modelName => {
|
|
11
|
+
console.log(` * ${chalk.green(modelName)}`);
|
|
12
|
+
});
|
|
13
|
+
console.log('');
|
|
14
|
+
}
|
|
15
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import { ServiceFactory } from 'pinstripe';
|
|
4
|
+
|
|
5
|
+
export default {
|
|
6
|
+
run(){
|
|
7
|
+
console.log('');
|
|
8
|
+
console.log('The following views are available:');
|
|
9
|
+
console.log('');
|
|
10
|
+
ServiceFactory.names.forEach(serviceFactoryName => {
|
|
11
|
+
console.log(` * ${chalk.green(serviceFactoryName)}`);
|
|
12
|
+
});
|
|
13
|
+
console.log('');
|
|
14
|
+
}
|
|
15
|
+
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import { App, View } from 'pinstripe';
|
|
4
|
+
|
|
5
|
+
export default {
|
|
6
|
+
run(){
|
|
7
|
+
const { extractOptions } = this.cliUtils;
|
|
8
|
+
|
|
9
|
+
const { app } = extractOptions();
|
|
10
|
+
|
|
11
|
+
if(app){
|
|
12
|
+
this.listComposedViews(typeof app == 'string' ? app : 'main');
|
|
13
|
+
} else {
|
|
14
|
+
this.listAllViews();
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
|
|
18
|
+
listComposedViews(appName){
|
|
19
|
+
const { viewNames, resolveView } = View.mapperFor(App.create(appName, this.context).compose());
|
|
20
|
+
console.log('');
|
|
21
|
+
console.log(`The following views have been composed for app "${appName}":`);
|
|
22
|
+
console.log('');
|
|
23
|
+
viewNames.forEach(viewName => {
|
|
24
|
+
console.log(` * ${chalk.green(viewName)} -> ${chalk.green(resolveView(viewName))}`);
|
|
25
|
+
});
|
|
26
|
+
console.log('');
|
|
27
|
+
},
|
|
28
|
+
|
|
29
|
+
listAllViews(){
|
|
30
|
+
console.log('');
|
|
31
|
+
console.log(`The following views are available:`);
|
|
32
|
+
console.log('');
|
|
33
|
+
View.names.forEach(viewName => {
|
|
34
|
+
console.log(` * ${chalk.green(viewName)}`);
|
|
35
|
+
});
|
|
36
|
+
console.log('');
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
|
|
2
|
+
export default {
|
|
3
|
+
run(){
|
|
4
|
+
const { extractOptions } = this.cliUtils;
|
|
5
|
+
|
|
6
|
+
const { app, withoutBot } = extractOptions({
|
|
7
|
+
app: `main:${process.env.HOST || '127.0.0.1'}:${parseInt(process.env.PORT || '3000')}`,
|
|
8
|
+
withoutBot: false
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
const apps = [];
|
|
13
|
+
let currentPort = 3000;
|
|
14
|
+
|
|
15
|
+
app.trim().split(/\s+/).forEach((app) => {
|
|
16
|
+
const [name, ...serverConfig] = app.split(/:/);
|
|
17
|
+
const [ port, host = '127.0.0.1'] = serverConfig.reverse();
|
|
18
|
+
|
|
19
|
+
if(port){
|
|
20
|
+
apps.push({ name, port: parseInt(port), host });
|
|
21
|
+
} else {
|
|
22
|
+
while(apps.filter(app => app.host == host).map(({ port }) => port).includes(currentPort)) currentPort++;
|
|
23
|
+
apps.push({ name, port: currentPort, host });
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
this.server.start(apps);
|
|
28
|
+
|
|
29
|
+
// if(!withoutBot) this.bot.start();
|
|
30
|
+
}
|
|
31
|
+
};
|
package/lib/component.js
CHANGED
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
|
|
2
|
-
import {
|
|
2
|
+
import { fileURLToPath } from 'url'; // pinstripe-if-client: const fileURLToPath = undefined;
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import { Class } from './class.js';
|
|
5
|
+
import { TEXT_ONLY_TAGS } from './constants.js';
|
|
6
|
+
import { Inflector } from './inflector.js';
|
|
7
|
+
import { VirtualNode } from './virtual_node.js';
|
|
8
|
+
import { Registry } from './registry.js';
|
|
9
|
+
import { ComponentEvent } from './component_event.js';
|
|
10
|
+
import { Client } from './client.js'; // pinstripe-if-client: const Client = undefined;
|
|
5
11
|
|
|
6
12
|
export const Component = Class.extend().include({
|
|
7
13
|
meta(){
|
|
@@ -24,6 +30,30 @@ export const Component = Class.extend().include({
|
|
|
24
30
|
return Inflector.instance.dasherize(name);
|
|
25
31
|
}
|
|
26
32
|
});
|
|
33
|
+
|
|
34
|
+
this.FileImporter.register('js', {
|
|
35
|
+
meta(){
|
|
36
|
+
const { importFile } = this.prototype;
|
|
37
|
+
|
|
38
|
+
this.include({
|
|
39
|
+
async importFile(params){
|
|
40
|
+
const { filePath, relativeFilePathWithoutExtension } = params;
|
|
41
|
+
if((await import(filePath)).default){
|
|
42
|
+
Client.instance.addModule(`
|
|
43
|
+
import { Component } from ${JSON.stringify(fileURLToPath(`${import.meta.url}/../index.js`))};
|
|
44
|
+
import include from ${JSON.stringify(filePath)};
|
|
45
|
+
Component.register(${JSON.stringify(relativeFilePathWithoutExtension)}, include);
|
|
46
|
+
`);
|
|
47
|
+
} else {
|
|
48
|
+
Client.instance.addModule(`
|
|
49
|
+
import ${JSON.stringify(filePath)};
|
|
50
|
+
`);
|
|
51
|
+
}
|
|
52
|
+
return importFile.call(this, params);
|
|
53
|
+
}
|
|
54
|
+
})
|
|
55
|
+
}
|
|
56
|
+
})
|
|
27
57
|
},
|
|
28
58
|
|
|
29
59
|
initialize(node, skipInit = false){
|
|
@@ -46,8 +76,9 @@ export const Component = Class.extend().include({
|
|
|
46
76
|
this.setTimeout(() => this.node.focus());
|
|
47
77
|
}
|
|
48
78
|
|
|
49
|
-
const { autosubmit, trigger } = this.data;
|
|
79
|
+
const { autosubmit, trigger, decorate } = this.data;
|
|
50
80
|
|
|
81
|
+
// replace with pinstripe-autosubmitter?
|
|
51
82
|
if(autosubmit){
|
|
52
83
|
let hash = JSON.stringify(this.values);
|
|
53
84
|
this.setInterval(() => {
|
|
@@ -59,6 +90,7 @@ export const Component = Class.extend().include({
|
|
|
59
90
|
}, 100);
|
|
60
91
|
}
|
|
61
92
|
|
|
93
|
+
// replace with script?
|
|
62
94
|
if(trigger){
|
|
63
95
|
this.setTimeout(() => {
|
|
64
96
|
this.trigger(trigger);
|
|
@@ -103,7 +135,9 @@ export const Component = Class.extend().include({
|
|
|
103
135
|
},
|
|
104
136
|
|
|
105
137
|
get realParent(){
|
|
106
|
-
|
|
138
|
+
if(this.node.parentNode) return this.constructor.instanceFor(this.node.parentNode);
|
|
139
|
+
if(this.node.host instanceof Element) return this.constructor.instanceFor(this.node.host);
|
|
140
|
+
return null;
|
|
107
141
|
},
|
|
108
142
|
|
|
109
143
|
get parent(){
|
|
@@ -122,6 +156,10 @@ export const Component = Class.extend().include({
|
|
|
122
156
|
return out;
|
|
123
157
|
},
|
|
124
158
|
|
|
159
|
+
get parentsIncludingThis(){
|
|
160
|
+
return [this, ...this.parents];
|
|
161
|
+
},
|
|
162
|
+
|
|
125
163
|
get children(){
|
|
126
164
|
return [...this.node.childNodes].map(
|
|
127
165
|
node => this.constructor.instanceFor(node)
|
|
@@ -241,7 +279,7 @@ export const Component = Class.extend().include({
|
|
|
241
279
|
},
|
|
242
280
|
|
|
243
281
|
get document(){
|
|
244
|
-
return this.
|
|
282
|
+
return this.find('parentsIncludingThis', ({ isDocument }) => isDocument);
|
|
245
283
|
},
|
|
246
284
|
|
|
247
285
|
get overlay(){
|
|
@@ -251,6 +289,7 @@ export const Component = Class.extend().include({
|
|
|
251
289
|
get shadow(){
|
|
252
290
|
if(!this.node.shadowRoot){
|
|
253
291
|
this.node.attachShadow({ mode: 'open' });
|
|
292
|
+
this.shadow.observe({ add: true }, component => component.descendants);
|
|
254
293
|
this.shadow.patch(`<slot>`);
|
|
255
294
|
}
|
|
256
295
|
return Component.instanceFor(this.node.shadowRoot);
|
|
@@ -277,7 +316,7 @@ export const Component = Class.extend().include({
|
|
|
277
316
|
const selector = args.pop()
|
|
278
317
|
|
|
279
318
|
const wrapperFn = (event, ...args) => {
|
|
280
|
-
const eventWrapper =
|
|
319
|
+
const eventWrapper = ComponentEvent.instanceFor(event)
|
|
281
320
|
if(selector){
|
|
282
321
|
if(eventWrapper.target.is(selector)){
|
|
283
322
|
return fn.call(eventWrapper.target, eventWrapper, ...args);
|
|
@@ -325,8 +364,8 @@ export const Component = Class.extend().include({
|
|
|
325
364
|
|
|
326
365
|
remove(){
|
|
327
366
|
if(this.realParent){
|
|
328
|
-
|
|
329
|
-
|
|
367
|
+
clean.call(this);
|
|
368
|
+
this.realParent.node.removeChild(this.node);
|
|
330
369
|
}
|
|
331
370
|
return this;
|
|
332
371
|
},
|
|
@@ -414,20 +453,25 @@ export const Component = Class.extend().include({
|
|
|
414
453
|
},
|
|
415
454
|
|
|
416
455
|
async fetch(url, options = {}){
|
|
456
|
+
const { minimumDelay = 0, ...otherOptions } = options;
|
|
417
457
|
const { progressBar } = this.document;
|
|
418
458
|
const frame = this.frame || this;
|
|
419
459
|
const normalizedUrl = new URL(url, frame.url);
|
|
420
460
|
const abortController = new AbortController();
|
|
421
461
|
this._registeredAbortControllers.push(abortController);
|
|
422
462
|
progressBar.start();
|
|
463
|
+
let minimumDelayTimeout;
|
|
423
464
|
const cleanUp = () => {
|
|
465
|
+
clearTimeout(minimumDelayTimeout);
|
|
424
466
|
this._registeredAbortControllers = this._registeredAbortControllers.filter(item => item !== abortController);
|
|
425
467
|
progressBar.stop();
|
|
426
468
|
};
|
|
427
469
|
try {
|
|
428
|
-
const
|
|
429
|
-
signal: abortController.signal
|
|
430
|
-
|
|
470
|
+
const promises = [
|
|
471
|
+
fetch(normalizedUrl, { signal: abortController.signal, ...otherOptions }),
|
|
472
|
+
new Promise(resolve => minimumDelayTimeout = setTimeout(resolve, minimumDelay))
|
|
473
|
+
];
|
|
474
|
+
const [ out ] = await Promise.all(promises);
|
|
431
475
|
cleanUp();
|
|
432
476
|
return out;
|
|
433
477
|
} catch(e){
|
|
@@ -454,7 +498,6 @@ export const Component = Class.extend().include({
|
|
|
454
498
|
const [ collection, selector ] = args;
|
|
455
499
|
return this[collection].filter(item => item.is(selector));
|
|
456
500
|
}
|
|
457
|
-
|
|
458
501
|
});
|
|
459
502
|
|
|
460
503
|
const matchesSelector = (() => {
|
|
@@ -464,10 +507,15 @@ const matchesSelector = (() => {
|
|
|
464
507
|
})();
|
|
465
508
|
|
|
466
509
|
function cleanChildren(){
|
|
510
|
+
if(this.node.shadowRoot){
|
|
511
|
+
this.shadow.children.forEach(child => clean.call(child));
|
|
512
|
+
}
|
|
467
513
|
this.children.forEach(child => clean.call(child));
|
|
468
514
|
}
|
|
469
515
|
|
|
470
516
|
function clean(){
|
|
517
|
+
this.trigger('clean', { bubbles: false });
|
|
518
|
+
|
|
471
519
|
[...this.node.childNodes].forEach(node => node._component && clean.call(node._component));
|
|
472
520
|
|
|
473
521
|
while(this._registeredEventListeners.length){
|
|
@@ -494,6 +542,9 @@ function clearTimers(){
|
|
|
494
542
|
}
|
|
495
543
|
|
|
496
544
|
function initChildren(){
|
|
545
|
+
if(this.node.shadowRoot){
|
|
546
|
+
this.shadow.children.forEach(child => initChildren.call(child));
|
|
547
|
+
}
|
|
497
548
|
this.children.forEach(child => initChildren.call(child));
|
|
498
549
|
}
|
|
499
550
|
|
|
@@ -516,13 +567,19 @@ function createVirtualNode(html){
|
|
|
516
567
|
}
|
|
517
568
|
|
|
518
569
|
function patch(attributes, virtualChildren){
|
|
519
|
-
const
|
|
570
|
+
const isFrame = this.type == 'pinstripe-frame' || this.attributes['data-component'] == 'pinstripe-frame';
|
|
571
|
+
const isEmptyFrame = isFrame && virtualChildren.length == 0;
|
|
520
572
|
if(isEmptyFrame && attributes['data-load-on-init'] === undefined){
|
|
521
573
|
attributes['data-load-on-init'] = 'true';
|
|
522
574
|
}
|
|
523
575
|
patchAttributes.call(this, attributes);
|
|
524
576
|
if(isEmptyFrame) return;
|
|
525
|
-
|
|
577
|
+
if(this.is('pinstripe-silo, [data-component="pinstripe-silo"]')){
|
|
578
|
+
patchChildren.call(this.shadow, virtualChildren);
|
|
579
|
+
patchChildren.call(this, []);
|
|
580
|
+
} else {
|
|
581
|
+
patchChildren.call(this, virtualChildren);
|
|
582
|
+
}
|
|
526
583
|
}
|
|
527
584
|
|
|
528
585
|
function patchAttributes(attributes){
|
|
@@ -534,11 +591,12 @@ function patchAttributes(attributes){
|
|
|
534
591
|
const currentAttributes = this.attributes;
|
|
535
592
|
Object.keys(currentAttributes).forEach((key) => {
|
|
536
593
|
if(attributes[key] === undefined){
|
|
537
|
-
|
|
594
|
+
Element.prototype.removeAttribute.call(this.node, key); // work around for https://github.com/cypress-io/cypress/issues/26206
|
|
595
|
+
// this.node.removeAttribute(key);
|
|
538
596
|
}
|
|
539
597
|
})
|
|
540
598
|
Object.keys(attributes).forEach((key) => {
|
|
541
|
-
if(currentAttributes[key] != attributes[key]){
|
|
599
|
+
if(!currentAttributes.hasOwnProperty(key) || currentAttributes[key] != attributes[key]){
|
|
542
600
|
this.node.setAttribute(key, attributes[key]);
|
|
543
601
|
if(key == 'value'){
|
|
544
602
|
this.node.value = attributes[key];
|
|
@@ -601,10 +659,17 @@ function insert(virtualNode, referenceChild, returnComponent = true){
|
|
|
601
659
|
insert.call(new Component(node, true), child, null, false);
|
|
602
660
|
})
|
|
603
661
|
|
|
604
|
-
this.
|
|
605
|
-
node
|
|
606
|
-
|
|
607
|
-
|
|
662
|
+
if(this.is('pinstripe-silo, [data-component="pinstripe-silo"]')){
|
|
663
|
+
this.shadow.node.insertBefore(
|
|
664
|
+
node,
|
|
665
|
+
referenceChild && referenceChild.node
|
|
666
|
+
);
|
|
667
|
+
} else {
|
|
668
|
+
this.node.insertBefore(
|
|
669
|
+
node,
|
|
670
|
+
referenceChild && referenceChild.node
|
|
671
|
+
);
|
|
672
|
+
}
|
|
608
673
|
|
|
609
674
|
if(returnComponent){
|
|
610
675
|
return Component.instanceFor(node);
|
|
@@ -632,17 +697,4 @@ function normalizeVirtualNode(){
|
|
|
632
697
|
}
|
|
633
698
|
}
|
|
634
699
|
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
[
|
|
638
|
-
['#document', 'pinstripe-document'],
|
|
639
|
-
['a', 'pinstripe-anchor'],
|
|
640
|
-
['body', 'pinstripe-body'],
|
|
641
|
-
['form', 'pinstripe-form']
|
|
642
|
-
].forEach(([name, include]) => {
|
|
643
|
-
Component.register(name, {
|
|
644
|
-
meta(){
|
|
645
|
-
this.include(include);
|
|
646
|
-
}
|
|
647
|
-
})
|
|
648
|
-
});
|
|
700
|
+
ComponentEvent.Component = Component;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
|
|
2
|
+
import { Class } from './class.js';
|
|
3
|
+
import { trapify } from './trapify.js';
|
|
4
|
+
|
|
5
|
+
export const ComponentEvent = Class.extend().include({
|
|
6
|
+
meta(){
|
|
7
|
+
this.assignProps({
|
|
8
|
+
instanceFor(event){
|
|
9
|
+
if(!event._componentEvent){
|
|
10
|
+
event._componentEvent = ComponentEvent.new(event);
|
|
11
|
+
}
|
|
12
|
+
return event._componentEvent;
|
|
13
|
+
}
|
|
14
|
+
});
|
|
15
|
+
},
|
|
16
|
+
|
|
17
|
+
initialize(event){
|
|
18
|
+
this.event = event;
|
|
19
|
+
return trapify(this);
|
|
20
|
+
},
|
|
21
|
+
|
|
22
|
+
__get(target, name){
|
|
23
|
+
const out = target.event[name];
|
|
24
|
+
if(out instanceof Node) return ComponentEvent.Component.instanceFor(out);
|
|
25
|
+
if(typeof out == 'function') return (...args) => out.call(target.event, ...args);
|
|
26
|
+
return out;
|
|
27
|
+
}
|
|
28
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Component as default } from 'pinstripe';
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
|
|
2
|
+
import { loadFrame, getFrame } from "./helpers.js";
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
initialize(...args){
|
|
6
|
+
this.constructor.parent.prototype.initialize.call(this, ...args);
|
|
7
|
+
|
|
8
|
+
const { ignoreEventsFromChildren = false } = this.data;
|
|
9
|
+
this.on('click', (event) => {
|
|
10
|
+
if(ignoreEventsFromChildren && event.target != this) return;
|
|
11
|
+
const { confirm, target = '_self', method = 'GET', href, placeholder } = { ...this.attributes, ...this.data };
|
|
12
|
+
if(new URL(href, window.location.href).host != window.location.host) return;
|
|
13
|
+
event.preventDefault();
|
|
14
|
+
event.stopPropagation();
|
|
15
|
+
loadFrame.call(this, confirm, target, method, href, placeholder);
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
const { target = '_self', method = 'GET', href, preload, placeholder } = { ...this.attributes, ...this.data };
|
|
19
|
+
if(method == 'GET' && target != '_blank'){
|
|
20
|
+
const frame = target == '_overlay' ? this.frame : getFrame.call(this, target);
|
|
21
|
+
if(preload != undefined) this.document.preload(new URL(href, frame.url));
|
|
22
|
+
if(placeholder != undefined) this.document.preload(new URL(placeholder, frame.url));
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if(this.is('input, textarea')) this.on('keyup', (event) => this.trigger('click'));
|
|
26
|
+
}
|
|
27
|
+
};
|