pinstripe 0.29.0 → 0.30.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 -3
- package/lib/apps/docs.js +6 -0
- package/lib/database/migrator.js +5 -5
- package/lib/extensions/_file_importer.js +1 -0
- package/lib/extensions/multi-tenant/database/row.js +26 -0
- package/lib/extensions/multi-tenant/database/table.js +30 -0
- package/lib/extensions/multi-tenant/database.js +18 -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/markdown.js +1 -1
- package/lib/services/cookies.js +1 -1
- package/lib/services/docs.js +93 -0
- package/lib/services/fetch.js +6 -5
- package/lib/services/render_view.js +7 -1
- package/lib/view.js +0 -1
- package/lib/views/docs/_404.js +16 -0
- package/lib/views/docs/_footer.js +67 -0
- package/lib/views/docs/_header.js +17 -0
- package/lib/views/docs/_hero.js +59 -0
- package/lib/views/docs/_layout.js +118 -0
- package/lib/views/docs/_navbar.js +99 -0
- package/lib/views/docs/_sidebar.js +31 -0
- package/lib/views/docs/default.js +6 -0
- package/lib/views/docs/docs/default.js +24 -0
- package/lib/views/docs/docs/guides/introduction.md +18 -0
- package/lib/views/docs/images/logo.svg +7 -0
- package/lib/views/docs/index.js +16 -0
- package/lib/views/shared/_content.js +1 -5
- package/lib/views/shared/_form.js +1 -1
- package/lib/views/shared/_navbar.js +0 -28
- package/lib/views/shared/_shell/index.js +25 -0
- package/lib/views/shared/_shell/stylesheets/all.css +4 -0
- package/package.json +4 -4
- package/lib/services/session.js +0 -19
- package/lib/views/shared/assets/stylesheets/all.css +0 -4
- /package/lib/views/shared/{assets → _shell}/javascripts/all.js.js +0 -0
- /package/lib/views/shared/{assets → _shell}/javascripts/all.js.map.js +0 -0
- /package/lib/views/shared/{assets → _shell}/stylesheets/global.css +0 -0
- /package/lib/views/shared/{assets → _shell}/stylesheets/reset.css +0 -0
- /package/lib/views/shared/{assets → _shell}/stylesheets/vars.css +0 -0
- /package/lib/views/shared/{assets → _shell}/stylesheets/view.css.js +0 -0
package/README.md
CHANGED
package/lib/apps/docs.js
ADDED
package/lib/database/migrator.js
CHANGED
|
@@ -8,20 +8,20 @@ export const Migrator = Class.extend().include({
|
|
|
8
8
|
},
|
|
9
9
|
|
|
10
10
|
async migrate(){
|
|
11
|
-
if(!await this.database.table('
|
|
12
|
-
await this.database.table('
|
|
13
|
-
await
|
|
11
|
+
if(!await this.database.table('appliedMigrations').exists){
|
|
12
|
+
await this.database.table('appliedMigrations', async appliedMigrations => {
|
|
13
|
+
await appliedMigrations.addColumn('schemaVersion', 'integer');
|
|
14
14
|
});
|
|
15
15
|
}
|
|
16
16
|
const isDevelopmentEnvironment = (process.env.NODE_ENV || 'development') == 'development';
|
|
17
17
|
const migrations = Migration.names.map(name => Migration.for(name)).sort((a, b) => a.schemaVersion - b.schemaVersion);
|
|
18
18
|
for(let i in migrations){
|
|
19
19
|
const migration = migrations[i];
|
|
20
|
-
const isMigrationApplied = await this.database.table('
|
|
20
|
+
const isMigrationApplied = await this.database.table('appliedMigrations').where({ schemaVersion: migration.schemaVersion }).count() > 0;
|
|
21
21
|
if(!isMigrationApplied){
|
|
22
22
|
if(isDevelopmentEnvironment) console.log(`Applying migration: ${migration.name}`);
|
|
23
23
|
await migration.new(this.database).migrate();
|
|
24
|
-
await this.database.table('
|
|
24
|
+
await this.database.table('appliedMigrations').insert({ schemaVersion: migration.schemaVersion });
|
|
25
25
|
}
|
|
26
26
|
}
|
|
27
27
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default undefined;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
|
|
2
|
+
import { Table, Row } from 'pinstripe/database';
|
|
3
|
+
|
|
4
|
+
Row.include({
|
|
5
|
+
meta(){
|
|
6
|
+
const { initialize, update } = this.prototype;
|
|
7
|
+
|
|
8
|
+
this.include({
|
|
9
|
+
initialize(database, fields, exists){
|
|
10
|
+
const columns = Table.for(this.constructor.collectionName).columns;
|
|
11
|
+
if(columns.tenantId && database.tenant){
|
|
12
|
+
return initialize.call(this, database, { ...fields, tenantId: database.tenant.id }, exists);
|
|
13
|
+
}
|
|
14
|
+
return initialize.call(this, database, fields, exists);
|
|
15
|
+
},
|
|
16
|
+
|
|
17
|
+
update(fields){
|
|
18
|
+
const columns = Table.for(this.constructor.collectionName).columns;
|
|
19
|
+
if(columns.tenantId && this.database.tenant){
|
|
20
|
+
return update.call(this, { ...fields, tenantId: this.database.tenant.id });
|
|
21
|
+
}
|
|
22
|
+
return update.call(this, fields);
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
});
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
|
|
2
|
+
import { Table } from 'pinstripe/database';
|
|
3
|
+
|
|
4
|
+
Table.include({
|
|
5
|
+
meta(){
|
|
6
|
+
const { create, initialize } = this.prototype;
|
|
7
|
+
|
|
8
|
+
this.include({
|
|
9
|
+
async create(...args){
|
|
10
|
+
if(this.exists) return;
|
|
11
|
+
await create.call(this, ...args);
|
|
12
|
+
if(this.constructor.name == 'appliedMigrations') return;
|
|
13
|
+
if(this.constructor.name == 'tenants') return;
|
|
14
|
+
await this.addColumn('tenantId', 'foreign_key');
|
|
15
|
+
},
|
|
16
|
+
|
|
17
|
+
initialize(...args){
|
|
18
|
+
const out = initialize.call(this, ...args);
|
|
19
|
+
if(this.constructor.columns.tenantId && this.database.scopedByTenant){
|
|
20
|
+
if(this.database.tenant){
|
|
21
|
+
this.where({ tenantId: this.database.tenant.id });
|
|
22
|
+
} else {
|
|
23
|
+
this.where('1 = 2')
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return out;
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
});
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
|
|
2
|
+
import { Database } from 'pinstripe';
|
|
3
|
+
|
|
4
|
+
Database.include({
|
|
5
|
+
meta(){
|
|
6
|
+
const { singleton } = this.prototype;
|
|
7
|
+
|
|
8
|
+
this.include({
|
|
9
|
+
singleton(...args){
|
|
10
|
+
if(this.tenant) return singleton.call(this, ...args);
|
|
11
|
+
}
|
|
12
|
+
});
|
|
13
|
+
},
|
|
14
|
+
|
|
15
|
+
get scopedByTenant(){
|
|
16
|
+
return this.hasOwnProperty('tenant');
|
|
17
|
+
}
|
|
18
|
+
});
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
|
|
2
|
+
export default {
|
|
3
|
+
async migrate(){
|
|
4
|
+
await this.database.table('tenants', async tenants => {
|
|
5
|
+
await tenants.addColumn('name', 'string', { index: true });
|
|
6
|
+
await tenants.addColumn('host', 'string', { index: true });
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
const tableNames = Object.keys(this.database.info).filter(name => this.database.info[name] == 'table');
|
|
10
|
+
|
|
11
|
+
while(tableNames.length){
|
|
12
|
+
const tableName = tableNames.shift();
|
|
13
|
+
if(tableName == 'appliedMigrations') continue;
|
|
14
|
+
if(tableName == 'tenants') continue;
|
|
15
|
+
|
|
16
|
+
if(this.database[tableName].constructor.columns.tenantId) continue;
|
|
17
|
+
await this.database[tableName].addColumn('tenantId', 'foreign_key');
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
|
|
2
|
+
import { Database } from 'pinstripe';
|
|
3
|
+
import { Client } from "pinstripe/database";
|
|
4
|
+
|
|
5
|
+
export default {
|
|
6
|
+
create(){
|
|
7
|
+
return this.defer(async () => {
|
|
8
|
+
if(!this.context.root.databaseClient){
|
|
9
|
+
this.context.root.databaseClient = Client.new(await this.config.database);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const out = await Database.new(this.context.root.databaseClient);
|
|
13
|
+
|
|
14
|
+
if(out.info.tenants){
|
|
15
|
+
const headers = this.initialParams._headers;
|
|
16
|
+
const hostname = this.initialParams._url.hostname;
|
|
17
|
+
const host = (headers['host'] || hostname).replace(/\:\d+$/, '').toLowerCase();
|
|
18
|
+
const { primaryDomain = '' } = await this.config;
|
|
19
|
+
const domainSuffix = `\.${primaryDomain}`.toLowerCase();
|
|
20
|
+
|
|
21
|
+
if(host.endsWith(domainSuffix)){
|
|
22
|
+
const name = host.substr(0, host.length - domainSuffix.length);
|
|
23
|
+
out.tenant = await out.tenants.where({ name }).first();
|
|
24
|
+
} else {
|
|
25
|
+
out.tenant = await out.tenants.where({ host }).first();
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return out;
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
};
|
package/lib/markdown.js
CHANGED
|
@@ -39,7 +39,7 @@ export const Markdown = Class.extend().include({
|
|
|
39
39
|
paragraph.attributes = {
|
|
40
40
|
...paragraph.attributes,
|
|
41
41
|
'data-component': 'pinstripe-frame',
|
|
42
|
-
'data-url': `/
|
|
42
|
+
'data-url': `/_markdown_slash_blocks/${name}?args=${encodeURIComponent(args)}`,
|
|
43
43
|
};
|
|
44
44
|
paragraph.children = [];
|
|
45
45
|
});
|
package/lib/services/cookies.js
CHANGED
|
@@ -3,7 +3,7 @@ export default {
|
|
|
3
3
|
create(){
|
|
4
4
|
if(!this.context.root.hasOwnProperty('cookies')){
|
|
5
5
|
const cookies = {};
|
|
6
|
-
const cookieHeader = this.
|
|
6
|
+
const cookieHeader = this.initialParams._headers?.cookie;
|
|
7
7
|
if(cookieHeader){
|
|
8
8
|
cookieHeader.split(/;/).forEach(cookie => {
|
|
9
9
|
const matches = cookie.trim().match(/^([^=]+)=(.*)$/);
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
|
|
2
|
+
import { existsSync } from 'fs';
|
|
3
|
+
import { realpath, readFile } from 'fs/promises';
|
|
4
|
+
import { registries } from 'pinstripe/util';
|
|
5
|
+
|
|
6
|
+
export default {
|
|
7
|
+
async create(){
|
|
8
|
+
if(!this.context.root.docs){
|
|
9
|
+
this.context.root.docs = {
|
|
10
|
+
apps: await this.extractDocs('App', 'apps'),
|
|
11
|
+
commands: await this.extractDocs('Command', 'commands'),
|
|
12
|
+
components: await this.extractDocs('Component', 'components'),
|
|
13
|
+
migrations: await this.extractDocs('Migration', 'migrations'),
|
|
14
|
+
models: await this.extractDocs('Row', 'models'),
|
|
15
|
+
services: await this.extractDocs('ServiceFactory', 'services'),
|
|
16
|
+
views: await this.extractDocs('View', 'views'),
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
return this.context.root.docs;
|
|
20
|
+
},
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
async extractDocs(name, namespace){
|
|
25
|
+
const out = {};
|
|
26
|
+
const registry = registries[name];
|
|
27
|
+
const { names } = registry;
|
|
28
|
+
for(let name of names){
|
|
29
|
+
const slug = `${namespace}/${name}`;
|
|
30
|
+
|
|
31
|
+
const Class = registry.for(name);
|
|
32
|
+
|
|
33
|
+
const filePath = Class.filePaths[Class.filePaths.length - 1];
|
|
34
|
+
|
|
35
|
+
if(!filePath || !filePath.match(/\.(js|css)/)) continue;
|
|
36
|
+
|
|
37
|
+
const packageRootPath = await this.getPackageRootPath(filePath);
|
|
38
|
+
|
|
39
|
+
if(packageRootPath == undefined) continue;
|
|
40
|
+
|
|
41
|
+
const packageJson = await this.getPackageJson(packageRootPath);
|
|
42
|
+
|
|
43
|
+
const packageName = packageJson.name;
|
|
44
|
+
|
|
45
|
+
const packageRelativePath = filePath.substr(packageRootPath.length).replace(/^\//, '');
|
|
46
|
+
const repositoryRelativePath = `${packageJson.repository?.directory ? `${packageJson.repository.directory}/` : ''}${packageRelativePath}`;
|
|
47
|
+
|
|
48
|
+
const code = (await readFile(filePath)).toString('utf8');
|
|
49
|
+
|
|
50
|
+
const markdown = code.split(/\/\*\//).map((segment, i) => {
|
|
51
|
+
if(i % 2 == 0 && segment.trim().length){
|
|
52
|
+
return `\`\`\`\n${segment}\n\`\`\``;
|
|
53
|
+
}
|
|
54
|
+
return segment;
|
|
55
|
+
}).join('');
|
|
56
|
+
|
|
57
|
+
out[name] = {
|
|
58
|
+
name,
|
|
59
|
+
slug,
|
|
60
|
+
packageName,
|
|
61
|
+
packageRelativePath,
|
|
62
|
+
repositoryRelativePath,
|
|
63
|
+
markdown
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
return out;
|
|
67
|
+
},
|
|
68
|
+
|
|
69
|
+
async getPackageRootPath(path){
|
|
70
|
+
const packageJsonPath = (await this.findInPath('package.json', path.replace(/[^/]*$/, ''))).shift();
|
|
71
|
+
if(!packageJsonPath) return;
|
|
72
|
+
return packageJsonPath.replace(/package.json$/, '');
|
|
73
|
+
},
|
|
74
|
+
|
|
75
|
+
async getPackageJson(packageRootPath){
|
|
76
|
+
return JSON.parse((await readFile(`${packageRootPath}package.json`)).toString('utf8'));
|
|
77
|
+
},
|
|
78
|
+
|
|
79
|
+
async findInPath(offset, base){
|
|
80
|
+
const out = [];
|
|
81
|
+
while(base) {
|
|
82
|
+
const candidatePath = `${base}/${offset}`;
|
|
83
|
+
if(existsSync(candidatePath)){
|
|
84
|
+
out.push(await realpath(candidatePath));
|
|
85
|
+
}
|
|
86
|
+
if(base == '/'){
|
|
87
|
+
break;
|
|
88
|
+
}
|
|
89
|
+
base = await realpath(`${base}/..`);
|
|
90
|
+
}
|
|
91
|
+
return out;
|
|
92
|
+
}
|
|
93
|
+
};
|
package/lib/services/fetch.js
CHANGED
|
@@ -22,12 +22,13 @@ export default {
|
|
|
22
22
|
return out;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
if(!viewName.match(/(^|\/)_
|
|
26
|
-
out = this.normalizeResponse(await this.renderView(viewName != '' ? `${viewName}/index`: 'index', normalizedParams));
|
|
25
|
+
if(!viewName.match(/(^|\/)_[^\/]+(|\/index)$/)){
|
|
26
|
+
out = this.normalizeResponse(await this.app.renderView(viewName != '' ? `${viewName}/index`: 'index', normalizedParams));
|
|
27
27
|
if(out){
|
|
28
28
|
return out;
|
|
29
29
|
}
|
|
30
|
-
|
|
30
|
+
|
|
31
|
+
out = this.normalizeResponse(await this.app.renderView(viewName, normalizedParams));
|
|
31
32
|
if(out){
|
|
32
33
|
return out;
|
|
33
34
|
}
|
|
@@ -53,7 +54,7 @@ export default {
|
|
|
53
54
|
|
|
54
55
|
const prefixSegments = [];
|
|
55
56
|
while(true){
|
|
56
|
-
const out = this.normalizeResponse(await this.renderView(prefixSegments.length ? [...prefixSegments, 'guard'].join('/') : 'guard', params));
|
|
57
|
+
const out = this.normalizeResponse(await this.app.renderView(prefixSegments.length ? [...prefixSegments, 'guard'].join('/') : 'guard', params));
|
|
57
58
|
if(out){
|
|
58
59
|
return out;
|
|
59
60
|
}
|
|
@@ -67,7 +68,7 @@ export default {
|
|
|
67
68
|
async renderDefaultViews(viewName, params){
|
|
68
69
|
const prefixSegments = viewName != '' ? viewName.split(/\//) : [];
|
|
69
70
|
while(true){
|
|
70
|
-
const out = this.normalizeResponse(await this.renderView(prefixSegments.length ? [...prefixSegments, 'default'].join('/') : 'default', params));
|
|
71
|
+
const out = this.normalizeResponse(await this.app.renderView(prefixSegments.length ? [...prefixSegments, 'default'].join('/') : 'default', params));
|
|
71
72
|
if(out){
|
|
72
73
|
return out;
|
|
73
74
|
}
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
|
|
2
2
|
export default {
|
|
3
3
|
create(){
|
|
4
|
-
return (
|
|
4
|
+
return async (name, params = {}) => {
|
|
5
|
+
const out = await this.app.renderView(name != '' ? `${name}/index`: 'index', params);
|
|
6
|
+
if(out){
|
|
7
|
+
return out;
|
|
8
|
+
}
|
|
9
|
+
return this.app.renderView(name, params);
|
|
10
|
+
}
|
|
5
11
|
}
|
|
6
12
|
};
|
package/lib/view.js
CHANGED
|
@@ -7,7 +7,6 @@ import * as crypto from 'crypto'; // pinstripe-if-client: const crypto = undefin
|
|
|
7
7
|
import { Class } from './class.js';
|
|
8
8
|
import { Registry } from './registry.js';
|
|
9
9
|
import { ServiceConsumer } from './service_consumer.js';
|
|
10
|
-
import { trapify } from './trapify.js'
|
|
11
10
|
|
|
12
11
|
export const View = Class.extend().include({
|
|
13
12
|
meta(){
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
|
|
2
|
+
export default {
|
|
3
|
+
async render(){
|
|
4
|
+
const [ status, headers, body ] = (await this.renderView('_layout', {
|
|
5
|
+
title: 'Not found',
|
|
6
|
+
body: this.renderView('_section', {
|
|
7
|
+
title: 'Not found',
|
|
8
|
+
body: this.renderHtml`
|
|
9
|
+
<p>The page you are looking for can't be found or no longer exists.</p>
|
|
10
|
+
`
|
|
11
|
+
})
|
|
12
|
+
})).toResponseArray();
|
|
13
|
+
|
|
14
|
+
return [ 404, headers, body ];
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
|
|
2
|
+
export const styles = `
|
|
3
|
+
.root {
|
|
4
|
+
padding-top: 8rem;
|
|
5
|
+
padding-bottom: 8rem;
|
|
6
|
+
padding-right: var(--gap);
|
|
7
|
+
padding-left: var(--gap);
|
|
8
|
+
color: var(--color-secondary-text);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.inner {
|
|
12
|
+
display: grid;
|
|
13
|
+
grid-template-columns: 1fr 1fr;
|
|
14
|
+
font-size: 1.3rem;
|
|
15
|
+
max-width: 1200px;
|
|
16
|
+
margin: 0 auto;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.powered-by {
|
|
20
|
+
text-align: right;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.root a {
|
|
24
|
+
color: var(--color-secondary-text);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.root a:hover {
|
|
28
|
+
color: var(--color-black);
|
|
29
|
+
opacity: 1;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
@media (max-width: 767px) {
|
|
33
|
+
.root {
|
|
34
|
+
padding-top: 6.4rem;
|
|
35
|
+
padding-bottom: 12rem;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.inner {
|
|
39
|
+
grid-template-columns: 1fr;
|
|
40
|
+
text-align: center;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.powered-by {
|
|
44
|
+
margin-top: 3.2rem;
|
|
45
|
+
text-align: center;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
`;
|
|
49
|
+
|
|
50
|
+
export default {
|
|
51
|
+
async render(){
|
|
52
|
+
const site = (await this.database.site) || {};
|
|
53
|
+
|
|
54
|
+
return this.renderHtml`
|
|
55
|
+
<footer class="${this.cssClasses.root}" data-test-id="footer">
|
|
56
|
+
<div class="${this.cssClasses.inner}">
|
|
57
|
+
<div>
|
|
58
|
+
${site.title} © ${new Date().getFullYear()}
|
|
59
|
+
</div>
|
|
60
|
+
<div class="${this.cssClasses.poweredBy} ">
|
|
61
|
+
<a href="https://pinstripejs.org/" target="_blank" rel="noopener">Powered by Pinstripe</a>
|
|
62
|
+
</div>
|
|
63
|
+
</div>
|
|
64
|
+
</footer>
|
|
65
|
+
`;
|
|
66
|
+
}
|
|
67
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
|
|
2
|
+
export default {
|
|
3
|
+
async render(){
|
|
4
|
+
|
|
5
|
+
const path = this.initialParams._url.pathname;
|
|
6
|
+
|
|
7
|
+
return this.renderView('_navbar', {
|
|
8
|
+
logoUrl: '/images/logo.svg',
|
|
9
|
+
title: 'Pinstripe',
|
|
10
|
+
links: [
|
|
11
|
+
{ href: '/', body: 'Home', selected: path == '/' },
|
|
12
|
+
{ href: '/docs/guides/introduction', body: 'Docs', selected: path.startsWith('/docs') },
|
|
13
|
+
{ href: 'https://github.com/pinstripe', target: '_blank', body: 'Github' }
|
|
14
|
+
]
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
};
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
export const styles = `
|
|
4
|
+
.root {
|
|
5
|
+
display: flex;
|
|
6
|
+
flex-direction: column;
|
|
7
|
+
align-items: center;
|
|
8
|
+
justify-content: center;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.title {
|
|
12
|
+
color: #000;
|
|
13
|
+
text-align: center;
|
|
14
|
+
font-family: Inter;
|
|
15
|
+
font-size: 87.547px;
|
|
16
|
+
font-style: normal;
|
|
17
|
+
font-weight: 500;
|
|
18
|
+
line-height: normal;
|
|
19
|
+
margin-bottom: 127px;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.title > em {
|
|
23
|
+
font-style: normal;
|
|
24
|
+
background-image: linear-gradient(135deg, #6fbe53, #53bea7);
|
|
25
|
+
-webkit-background-clip: text;
|
|
26
|
+
background-clip: text;
|
|
27
|
+
color: transparent;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.button {
|
|
31
|
+
display: flex;
|
|
32
|
+
align-items: center;
|
|
33
|
+
justify-content: center;
|
|
34
|
+
width: 281px;
|
|
35
|
+
height: 85px;
|
|
36
|
+
flex-shrink: 0;
|
|
37
|
+
border-radius: 7px;
|
|
38
|
+
background: #70BE54;
|
|
39
|
+
color: #FFF;
|
|
40
|
+
text-align: center;
|
|
41
|
+
font-family: Inter;
|
|
42
|
+
font-size: 28px;
|
|
43
|
+
font-style: normal;
|
|
44
|
+
font-weight: 500;
|
|
45
|
+
line-height: normal;
|
|
46
|
+
}
|
|
47
|
+
`;
|
|
48
|
+
|
|
49
|
+
export default {
|
|
50
|
+
render(){
|
|
51
|
+
const { title, button, href } = this.params;
|
|
52
|
+
return this.renderHtml`
|
|
53
|
+
<div class="${this.cssClasses.root}">
|
|
54
|
+
<h1 class="${this.cssClasses.title}">${title}</h1>
|
|
55
|
+
<a class="${this.cssClasses.button}" href="${href}">${button}</a>
|
|
56
|
+
</div>
|
|
57
|
+
`;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
|
|
2
|
+
export const styles = `
|
|
3
|
+
.site {
|
|
4
|
+
display: flex;
|
|
5
|
+
flex-direction: column;
|
|
6
|
+
min-height: 100vh;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.main {
|
|
10
|
+
flex-grow: 1;
|
|
11
|
+
padding-top: 8rem;
|
|
12
|
+
padding-bottom: 8rem;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.outer {
|
|
16
|
+
padding-right: var(--gap);
|
|
17
|
+
padding-left: var(--gap);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.inner {
|
|
21
|
+
max-width: 1200px;
|
|
22
|
+
margin: 0 auto;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
@media (max-width: 767px) {
|
|
26
|
+
#main {
|
|
27
|
+
padding-top: 4.8rem;
|
|
28
|
+
padding-bottom: 4.8rem;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.wrapper {
|
|
33
|
+
display: grid;
|
|
34
|
+
grid-template-columns: 4fr 2fr;
|
|
35
|
+
column-gap: 2.4rem;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.sidebar {
|
|
39
|
+
top: 4.8rem;
|
|
40
|
+
height: max-content;
|
|
41
|
+
padding-left: 4rem;
|
|
42
|
+
font-size: 1.4rem;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.sidebar .section + .section {
|
|
46
|
+
margin-top: 8rem;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.sidebar > *:not(:first-child) {
|
|
50
|
+
margin-top: 8rem;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
@media (max-width: 767px) {
|
|
55
|
+
.wrapper {
|
|
56
|
+
grid-template-columns: 1fr;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.sidebar {
|
|
60
|
+
padding-left: 0;
|
|
61
|
+
margin-top: 8rem;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
@media (min-width: 768px) and (max-width: 991px) {
|
|
66
|
+
.sidebar {
|
|
67
|
+
padding-left: 1.6rem;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
`;
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
export default {
|
|
74
|
+
async render(){
|
|
75
|
+
const { params } = this;
|
|
76
|
+
const { title, body, sidebar = true } = params;
|
|
77
|
+
const site = (await this.database.site) || {};
|
|
78
|
+
|
|
79
|
+
return this.renderHtml`
|
|
80
|
+
<!DOCTYPE html>
|
|
81
|
+
<html lang="${site.language || 'en'}">
|
|
82
|
+
<head>
|
|
83
|
+
<meta charset="utf-8">
|
|
84
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
85
|
+
<title>${title || site.title}</title>
|
|
86
|
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
87
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
88
|
+
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Lora:ital,wght@0,400;0,500;0,600;0,700;1,400;1,700&family=Inter:wght@400;500;600;700;800&display=swap">
|
|
89
|
+
<link rel="stylesheet" href="/assets/stylesheets/all.css">
|
|
90
|
+
<script src="/assets/javascripts/all.js"></script>
|
|
91
|
+
</head>
|
|
92
|
+
|
|
93
|
+
<body>
|
|
94
|
+
${this.renderView('_header')}
|
|
95
|
+
<div class="${this.cssClasses.site}">
|
|
96
|
+
<main id="main" class="${this.cssClasses.main} ${this.cssClasses.outer}">
|
|
97
|
+
<div class="${this.cssClasses.inner}">
|
|
98
|
+
<div class="${sidebar ? this.cssClasses.wrapper : ''}">
|
|
99
|
+
<div data-test-id="main">
|
|
100
|
+
${body}
|
|
101
|
+
</div>
|
|
102
|
+
${() => {
|
|
103
|
+
if(sidebar) return this.renderHtml`
|
|
104
|
+
<aside class="${this.cssClasses.sidebar}" data-test-id="sidebar">
|
|
105
|
+
${this.renderView('_sidebar')}
|
|
106
|
+
</aside>
|
|
107
|
+
`;
|
|
108
|
+
}}
|
|
109
|
+
</div>
|
|
110
|
+
</div>
|
|
111
|
+
</main>
|
|
112
|
+
${this.renderView('_footer')}
|
|
113
|
+
</div>
|
|
114
|
+
</body>
|
|
115
|
+
</html>
|
|
116
|
+
`;
|
|
117
|
+
}
|
|
118
|
+
};
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
|
|
2
|
+
export const styles = `
|
|
3
|
+
.root {
|
|
4
|
+
border-width: 0 0 0.1rem 0;
|
|
5
|
+
border-style: solid;
|
|
6
|
+
border-color: var(--color-light-gray);
|
|
7
|
+
padding-left: 1em;
|
|
8
|
+
padding-right: 1em;
|
|
9
|
+
}
|
|
10
|
+
.inner {
|
|
11
|
+
margin: 0 auto;
|
|
12
|
+
display: flex;
|
|
13
|
+
min-height: 80px;
|
|
14
|
+
max-width: 1200px;
|
|
15
|
+
}
|
|
16
|
+
.brand {
|
|
17
|
+
flex: 0 0 auto;
|
|
18
|
+
display: flex;
|
|
19
|
+
align-items: center;
|
|
20
|
+
color: #000;
|
|
21
|
+
font-family: Inter;
|
|
22
|
+
font-size: 24px;
|
|
23
|
+
font-style: normal;
|
|
24
|
+
font-weight: 500;
|
|
25
|
+
line-height: normal;
|
|
26
|
+
padding: 7px 0 7px 0;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.brand img {
|
|
30
|
+
margin-right: 13px;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.menu {
|
|
34
|
+
flex: 1 1 100%;
|
|
35
|
+
display: flex;
|
|
36
|
+
align-items: center;
|
|
37
|
+
justify-content: flex-end;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.buttons {
|
|
41
|
+
flex: 1 1 100%;
|
|
42
|
+
display: flex;
|
|
43
|
+
align-items: center;
|
|
44
|
+
justify-content: flex-end;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.button {
|
|
48
|
+
display: flex;
|
|
49
|
+
align-items: center;
|
|
50
|
+
justify-content: center;
|
|
51
|
+
color: #000;
|
|
52
|
+
font-family: Inter;
|
|
53
|
+
font-size: 16px;
|
|
54
|
+
font-style: normal;
|
|
55
|
+
font-weight: 400;
|
|
56
|
+
line-height: normal;
|
|
57
|
+
width: 139px;
|
|
58
|
+
height: 38px;
|
|
59
|
+
flex-shrink: 0;
|
|
60
|
+
border-radius: 3px;
|
|
61
|
+
background: #F5F5F5;
|
|
62
|
+
margin-left: 20px;
|
|
63
|
+
position: relative;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.button.is-selected::after, .button:hover::after {
|
|
67
|
+
content: " ";
|
|
68
|
+
display: block;
|
|
69
|
+
width: 100%;
|
|
70
|
+
height: 5px;
|
|
71
|
+
flex-shrink: 0;
|
|
72
|
+
border-radius: 2.5px;
|
|
73
|
+
background: #70BE54;
|
|
74
|
+
position: absolute;
|
|
75
|
+
bottom: -12px;
|
|
76
|
+
}
|
|
77
|
+
`;
|
|
78
|
+
|
|
79
|
+
export default {
|
|
80
|
+
render(){
|
|
81
|
+
const { title, logoUrl, links = [], testId = 'root' } = this.params;
|
|
82
|
+
|
|
83
|
+
return this.renderHtml`
|
|
84
|
+
<div class="${this.cssClasses.root}" data-test-id="${testId}">
|
|
85
|
+
<div class="${this.cssClasses.inner}">
|
|
86
|
+
<div class="${this.cssClasses.brand}">
|
|
87
|
+
<img src="${logoUrl}" />
|
|
88
|
+
<a href="/" data-test-id="title">${title}</a>
|
|
89
|
+
</div>
|
|
90
|
+
<div class="${this.cssClasses.buttons}">
|
|
91
|
+
${links.map(({ body, href, target = '_top', preload, testId, selected }) => this.renderHtml`
|
|
92
|
+
<a class="${this.cssClasses.button} ${selected ? this.cssClasses.isSelected : ''}" href="${href}" target="${target}" ${preload ? 'data-preload' : ''} data-test-id="${testId}">${body}</a>
|
|
93
|
+
`)}
|
|
94
|
+
</div>
|
|
95
|
+
</div>
|
|
96
|
+
</div>
|
|
97
|
+
`;
|
|
98
|
+
}
|
|
99
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
|
|
2
|
+
export default {
|
|
3
|
+
async render(){
|
|
4
|
+
const docs = await this.docs;
|
|
5
|
+
|
|
6
|
+
return this.renderHtml`
|
|
7
|
+
${this.renderView('_section', {
|
|
8
|
+
title: 'Guides',
|
|
9
|
+
body: this.renderHtml`
|
|
10
|
+
<ul>
|
|
11
|
+
<li><a href="/docs/guides/introduction">Introduction</a></li>
|
|
12
|
+
</ul>
|
|
13
|
+
`
|
|
14
|
+
})}
|
|
15
|
+
${Object.keys(docs).filter(name => Object.keys(docs[name]).length > 0).map(name => {
|
|
16
|
+
const items = docs[name];
|
|
17
|
+
|
|
18
|
+
return this.renderView('_section', {
|
|
19
|
+
title: name,
|
|
20
|
+
body: this.renderHtml`
|
|
21
|
+
<ul>
|
|
22
|
+
${Object.values(items).map(({ name, slug }) => this.renderHtml`
|
|
23
|
+
<li><a href="/docs/${slug}">${name}</a></li>
|
|
24
|
+
`)}
|
|
25
|
+
</ul>
|
|
26
|
+
`
|
|
27
|
+
});
|
|
28
|
+
})}
|
|
29
|
+
`
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
|
|
2
|
+
import { escapeHtml } from 'pinstripe/util'
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
async render(){
|
|
6
|
+
const { _url, ...otherParams } = this.params;
|
|
7
|
+
const docs = await this.docs;
|
|
8
|
+
const matches = _url.pathname.match(/^\/docs\/([^\/]+)\/(.+)$/);
|
|
9
|
+
if(!matches) return this.renderView('_404');
|
|
10
|
+
const items = docs[matches[1]];
|
|
11
|
+
if(!items) return this.renderView('_404');
|
|
12
|
+
const item = items[matches[2]];
|
|
13
|
+
if(!item) return this.renderView('_404');
|
|
14
|
+
const { name, markdown } = item;
|
|
15
|
+
return this.renderView('_layout', {
|
|
16
|
+
body: this.renderView('_content', {
|
|
17
|
+
body: this.renderHtml`
|
|
18
|
+
<h1>${this.renderHtml(escapeHtml(name).replace(/([\/_-])/g, '$1<wbr>'))} ${this.inflector.singularize(matches[1])}</h1>
|
|
19
|
+
${this.renderMarkdown(markdown)}
|
|
20
|
+
`
|
|
21
|
+
})
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
|
|
2
|
+
# Introduction
|
|
3
|
+
|
|
4
|
+
Pinstripe is a Node.js based CMS, that can be stripped back to a general purpose web framework.
|
|
5
|
+
|
|
6
|
+
## Quick Start
|
|
7
|
+
|
|
8
|
+
To see it in action run the following:
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
yarn global add pinstripe
|
|
12
|
+
pinstripe generate-project foo
|
|
13
|
+
cd foo
|
|
14
|
+
pinstripe init-database
|
|
15
|
+
pinstripe start-server
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Now go to [http://localhost:3000](http://localhost:3000) and it should be up and running.
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="71" height="71" viewBox="0 0 71 71" fill="none">
|
|
2
|
+
<path d="M27.6287 71H64.529C68.1043 71 70.9999 68.1025 70.9999 64.5273V41.1592C70.9999 55.7115 52.4679 67.8894 27.6287 71Z" fill="#70BE54"/>
|
|
3
|
+
<path d="M64.5292 -3.21061e-06H48.0303C54.5527 4.19429 58.3987 9.35814 58.3987 14.9361C58.3987 16.9731 57.8886 18.9506 56.918 20.8503C65.6775 26.2494 71.0001 33.3645 71.0001 41.1592V6.47273C71.0001 2.89652 68.1045 -3.21061e-06 64.5292 -3.21061e-06Z" fill="#70BE54"/>
|
|
4
|
+
<path d="M51.957 26.9443C42.7481 34.9733 24.5948 40.429 3.7076 40.429C2.4613 40.429 1.2251 40.4088 0 40.3674V61.5298C0.526195 61.5388 1.05643 61.5449 1.58767 61.5449C5.52656 61.5449 9.36242 61.346 13.0609 60.9622C37.3235 58.4797 55.502 48.2642 55.502 36.0519C55.502 32.8433 54.2516 29.7741 51.957 26.9443Z" fill="#00377C"/>
|
|
5
|
+
<path d="M38.5698 -8.29573e-06H0V11.6972C2.77338 11.2689 5.63866 10.9569 8.57061 10.7731C10.7259 10.6297 12.9226 10.5579 15.1496 10.5579C26.5249 10.5579 37.1134 12.4233 45.9406 15.6258C46.4203 14.42 46.6657 13.1787 46.6657 11.9173C46.6657 7.54931 43.7075 3.4742 38.5698 -8.29573e-06Z" fill="#70BE54"/>
|
|
6
|
+
<path d="M41.2574 18.7869C32.2363 15.8298 21.0084 14.0725 8.84127 14.0725C5.83358 14.0725 2.87539 14.1796 0 14.3886V32.7262C18.7814 31.7758 34.7228 26.7705 43.0854 19.7726C43.1823 19.6908 43.2793 19.609 43.3763 19.5272C42.6875 19.2717 41.9775 19.0273 41.2574 18.7869Z" fill="#00377C"/>
|
|
7
|
+
</svg>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
export default {
|
|
4
|
+
render(){
|
|
5
|
+
return this.renderView('_layout', {
|
|
6
|
+
sidebar: false,
|
|
7
|
+
body: this.renderView('_hero', {
|
|
8
|
+
title: this.renderHtml`
|
|
9
|
+
A <em>slick</em> CMS for Node.js
|
|
10
|
+
`,
|
|
11
|
+
href: '/docs/guides/introduction',
|
|
12
|
+
button: 'Get Started'
|
|
13
|
+
})
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
};
|
|
@@ -172,7 +172,7 @@ export default {
|
|
|
172
172
|
<label class="${this.cssClasses.label}">${label}</label>
|
|
173
173
|
${() => {
|
|
174
174
|
const input = (() => {
|
|
175
|
-
if(type.match(/(^|\/)_
|
|
175
|
+
if(type.match(/(^|\/)_[^\/]+(|\/index)$/)){
|
|
176
176
|
return this.renderView(type, { label, name, type, value, component, placeholder, error, cssClasses: this.cssClasses, ...rest });
|
|
177
177
|
}
|
|
178
178
|
if(type == 'textarea'){
|
|
@@ -108,31 +108,3 @@ export default {
|
|
|
108
108
|
`;
|
|
109
109
|
}
|
|
110
110
|
};
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
// <div class="navbar" data-test-id="navbar">
|
|
114
|
-
// <div class="inner">
|
|
115
|
-
// <div class="brand">
|
|
116
|
-
// <a class="item" href="/" data-test-id="title">${site.title}</a>
|
|
117
|
-
// </div>
|
|
118
|
-
// <div class="menu">
|
|
119
|
-
// ${() => {
|
|
120
|
-
// if(isSignedIn) return this.renderHtml`
|
|
121
|
-
// ${isAdmin && this.renderHtml`
|
|
122
|
-
// <div class="item has-dropdown">
|
|
123
|
-
// Add
|
|
124
|
-
// <div class="dropdown">
|
|
125
|
-
// <a class="item" href="/admin/add_page?userId=${user.id}" target="_overlay">Page</a>
|
|
126
|
-
// <a class="item" href="/admin/add_post?userId=${user.id}" target="_overlay">Post</a>
|
|
127
|
-
// </div>
|
|
128
|
-
// </div>
|
|
129
|
-
// `}
|
|
130
|
-
// <a class="item" href="/sign_out" target="_overlay" data-test-id="sign-out">Sign out</a>
|
|
131
|
-
// `;
|
|
132
|
-
// return this.renderHtml`
|
|
133
|
-
// <a class="item" href="/sign_in" target="_overlay" data-preload data-test-id="sign-in">Sign in</a>
|
|
134
|
-
// `;
|
|
135
|
-
// }}
|
|
136
|
-
// </div>
|
|
137
|
-
// </div>
|
|
138
|
-
// </div>
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
|
|
2
|
+
export default {
|
|
3
|
+
render(){
|
|
4
|
+
const { language = 'en', title = '', body } = this.params;
|
|
5
|
+
|
|
6
|
+
return this.renderHtml`
|
|
7
|
+
<!DOCTYPE html>
|
|
8
|
+
<html lang="${language}">
|
|
9
|
+
<head>
|
|
10
|
+
<meta charset="utf-8">
|
|
11
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
12
|
+
<title>${title}</title>
|
|
13
|
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
14
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
15
|
+
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Lora:ital,wght@0,400;0,500;0,600;0,700;1,400;1,700&family=Inter:wght@400;500;600;700;800&display=swap">
|
|
16
|
+
<link rel="stylesheet" href="/_shell/stylesheets/all.css">
|
|
17
|
+
<script src="/_shell/javascripts/all.js"></script>
|
|
18
|
+
</head>
|
|
19
|
+
<body>
|
|
20
|
+
${body}
|
|
21
|
+
</body>
|
|
22
|
+
</html>
|
|
23
|
+
`;
|
|
24
|
+
}
|
|
25
|
+
};
|
package/package.json
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "pinstripe",
|
|
4
|
-
"description": "
|
|
5
|
-
"version": "0.
|
|
4
|
+
"description": "A slick web framework for Node.js.",
|
|
5
|
+
"version": "0.30.0",
|
|
6
6
|
"author": "Jody Salt",
|
|
7
7
|
"license": "MIT",
|
|
8
8
|
"exports": {
|
|
9
9
|
".": "./lib/index.js",
|
|
10
10
|
"./database": "./lib/database/index.js",
|
|
11
|
+
"./multi-tenant": "./lib/extensions/multi-tenant/index.js",
|
|
11
12
|
"./util": "./lib/util.js"
|
|
12
13
|
},
|
|
13
14
|
"bin": {
|
|
@@ -34,7 +35,6 @@
|
|
|
34
35
|
"cron-parser": "^4.3.0",
|
|
35
36
|
"css": "^3.0.0",
|
|
36
37
|
"esbuild": "^0.15.12",
|
|
37
|
-
"generate-avatar": "^1.4.10",
|
|
38
38
|
"html-entities": "^2.3.2",
|
|
39
39
|
"js-yaml": "^4.1.0",
|
|
40
40
|
"luxon": "^2.3.1",
|
|
@@ -53,5 +53,5 @@
|
|
|
53
53
|
"url": "git://github.com/blognami/pinstripe.git",
|
|
54
54
|
"directory": "packages/pinstripe"
|
|
55
55
|
},
|
|
56
|
-
"gitHead": "
|
|
56
|
+
"gitHead": "07d0e77a033fd16381b2641ad22158dc1857899e"
|
|
57
57
|
}
|
package/lib/services/session.js
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
export default {
|
|
3
|
-
create(){
|
|
4
|
-
return this.defer(async () => {
|
|
5
|
-
const { pinstripeSession } = this.cookies;
|
|
6
|
-
if(!pinstripeSession){
|
|
7
|
-
return;
|
|
8
|
-
}
|
|
9
|
-
const [ id, passString ] = pinstripeSession.split(/:/);
|
|
10
|
-
const session = await this.database.sessions.where({ id, passString }).first();
|
|
11
|
-
if(session && session.lastAccessedAt < (Date.now() - 1000 * 60 * 5)){
|
|
12
|
-
await session.update({
|
|
13
|
-
lastAccessedAt: Date.now()
|
|
14
|
-
});
|
|
15
|
-
}
|
|
16
|
-
return session;
|
|
17
|
-
});
|
|
18
|
-
}
|
|
19
|
-
};
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|