@silexlabs/silex 3.0.0-alpha.48 → 3.0.0-alpha.49
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/dist/client/client/config.d.ts +2 -0
- package/dist/client/css/admin.css +15 -0
- package/dist/client/js/main.js +12 -12
- package/dist/plugins/client/plugins/client/website-info.d.ts +1 -0
- package/dist/plugins/client/plugins/client/website-info.js +55 -0
- package/dist/plugins/client/plugins/client/website-info.js.map +1 -0
- package/dist/plugins/server/plugins/server/GitlabConnector.js +4 -4
- package/dist/plugins/server/plugins/server/GitlabConnector.js.map +1 -1
- package/dist/plugins/server/plugins/server/SslPlugin.js +5 -5
- package/dist/plugins/server/plugins/server/SslPlugin.js.map +1 -1
- package/dist/plugins/server/plugins/server/StaticPlugin.js +4 -0
- package/dist/plugins/server/plugins/server/StaticPlugin.js.map +1 -1
- package/dist/plugins/server/server/config.js +4 -5
- package/dist/plugins/server/server/config.js.map +1 -1
- package/dist/plugins/server/server/connectors/FsStorage.js +1 -1
- package/dist/plugins/server/server/connectors/FsStorage.js.map +1 -1
- package/dist/server/server/config.js +4 -5
- package/dist/server/server/connectors/FsStorage.js +1 -1
- package/dist/server/server/express.js +2 -2
- package/package.json +1 -1
- package/public/silex.js +5 -0
- package/src/css/grapesjs.scss +1 -0
- package/src/css/index.scss +1 -0
- package/src/css/website-info.scss +13 -0
- package/src/ts/client/api.ts +1 -1
- package/src/ts/client/config.ts +3 -0
- package/src/ts/client/grapesjs/LoginDialog.ts +0 -1
- package/src/ts/client/grapesjs/index.ts +0 -2
- package/src/ts/client/grapesjs/settings.ts +1 -1
- package/src/ts/client/grapesjs/storage.ts +0 -1
- package/src/ts/client/index.ts +1 -3
- package/src/ts/plugins/client/website-info.ts +63 -0
- package/src/ts/plugins/server/GitlabConnector.ts +4 -4
- package/src/ts/plugins/server/SslPlugin.ts +5 -5
- package/src/ts/plugins/server/StaticPlugin.ts +4 -0
- package/src/ts/server/config.ts +4 -5
- package/src/ts/server/connectors/FsStorage.ts +1 -1
- package/src/ts/server/express.ts +2 -2
- package/dist/client/client/grapesjs/website-info.d.ts +0 -2
- package/src/ts/client/grapesjs/website-info.ts +0 -39
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Silex website builder, free/libre no-code tool for makers.
|
|
3
|
+
* Copyright (c) 2023 lexoyo and Silex Labs foundation
|
|
4
|
+
*
|
|
5
|
+
* This program is free software: you can redistribute it and/or modify
|
|
6
|
+
* it under the terms of the GNU Affero General Public License as published by
|
|
7
|
+
* the Free Software Foundation, either version 3 of the License, or any later version.
|
|
8
|
+
*
|
|
9
|
+
* This program is distributed in the hope that it will be useful,
|
|
10
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
12
|
+
* GNU Affero General Public License for more details.
|
|
13
|
+
*
|
|
14
|
+
* You should have received a copy of the GNU Affero General Public License
|
|
15
|
+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import { ClientEvent } from '../../client/events.js'
|
|
19
|
+
|
|
20
|
+
interface WebsiteInfoOptions {
|
|
21
|
+
websiteId: string
|
|
22
|
+
connectorId: string
|
|
23
|
+
appendTo: 'commands' | 'options' | 'views' | 'project-bar-container' | 'project-bar-panel' | 'views-container'
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export default async function(config) {
|
|
27
|
+
config.on(ClientEvent.GRAPESJS_START, async () => {
|
|
28
|
+
const grapesPlugin = (editor, opts: Partial<WebsiteInfoOptions>) => {
|
|
29
|
+
const options = {
|
|
30
|
+
appendTo: 'commands',
|
|
31
|
+
...opts,
|
|
32
|
+
} as WebsiteInfoOptions
|
|
33
|
+
editor.on('storage:end:load', async () => {
|
|
34
|
+
// Get website meta data
|
|
35
|
+
const { websiteId, connectorId } = options
|
|
36
|
+
// Get the website meta data
|
|
37
|
+
const websiteMeta = await config.api.websiteMetaRead({ websiteId, connectorId })
|
|
38
|
+
displayWebsiteMeta(websiteMeta)
|
|
39
|
+
})
|
|
40
|
+
return {}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
config.grapesJsConfig.plugins.push(grapesPlugin)
|
|
44
|
+
config.grapesJsConfig.pluginsOpts[grapesPlugin.toString()] = {
|
|
45
|
+
websiteId: config.websiteId,
|
|
46
|
+
connectorId: config.storageId,
|
|
47
|
+
}
|
|
48
|
+
function displayWebsiteMeta(websiteMeta) {
|
|
49
|
+
// Create the container
|
|
50
|
+
const container = document.createElement('div')
|
|
51
|
+
container.classList.add('gjs-website-meta')
|
|
52
|
+
// Add the container to the UI
|
|
53
|
+
// Add the name of the website in the top bar
|
|
54
|
+
const topBar = document.querySelector('.gjs-pn-devices-c')
|
|
55
|
+
topBar?.appendChild(container)
|
|
56
|
+
// Display the website meta data
|
|
57
|
+
container.innerHTML = `
|
|
58
|
+
<div class="gjs-website-meta-image" style="background: url(${websiteMeta.imageUrl});"></div>
|
|
59
|
+
<div class="gjs-website-meta-name">${websiteMeta.name}</div>
|
|
60
|
+
`
|
|
61
|
+
}
|
|
62
|
+
})
|
|
63
|
+
}
|
|
@@ -119,7 +119,7 @@ export default class GitlabConnector implements StorageConnector {
|
|
|
119
119
|
constructor(private config: ServerConfig, opts: Partial<GitlabOptions>) {
|
|
120
120
|
this.options = {
|
|
121
121
|
branch: 'main',
|
|
122
|
-
assetsFolder: '',
|
|
122
|
+
assetsFolder: 'assets',
|
|
123
123
|
metaRepo: 'silex-meta',
|
|
124
124
|
metaRepoFile: 'websites.json',
|
|
125
125
|
...opts,
|
|
@@ -131,7 +131,7 @@ export default class GitlabConnector implements StorageConnector {
|
|
|
131
131
|
// **
|
|
132
132
|
// Convenience methods for the Gitlab API
|
|
133
133
|
private getAssetPath(path: string): string {
|
|
134
|
-
return `${this.options.assetsFolder}${path}`
|
|
134
|
+
return encodeURIComponent(`${this.options.assetsFolder}${path}`)
|
|
135
135
|
}
|
|
136
136
|
|
|
137
137
|
private async createFile(session: GitlabSession, websiteId: WebsiteId, path: string, content: string, isBase64 = false): Promise<void> {
|
|
@@ -375,7 +375,6 @@ export default class GitlabConnector implements StorageConnector {
|
|
|
375
375
|
const { content } = result
|
|
376
376
|
const contentDecoded = Buffer.from(content, 'base64').toString('utf8')
|
|
377
377
|
const websites = (JSON.parse(contentDecoded) as MetaRepoFileContent).websites
|
|
378
|
-
console.log('listWebsites', {websites, contentDecoded, content, result})
|
|
379
378
|
return Object.entries(websites).map(([websiteId, {meta, createdAt, updatedAt}]) => ({
|
|
380
379
|
websiteId,
|
|
381
380
|
createdAt: new Date(createdAt),
|
|
@@ -514,7 +513,7 @@ export default class GitlabConnector implements StorageConnector {
|
|
|
514
513
|
} catch (e) {
|
|
515
514
|
// If the file does not exist, create it
|
|
516
515
|
if (e.statusCode === 404 || e.httpStatusCode === 404 || e.message.endsWith('A file with this name doesn\'t exist')) {
|
|
517
|
-
await this.createFile(session, websiteId, file.path, content, true)
|
|
516
|
+
await this.createFile(session, websiteId, this.getAssetPath(file.path), content, true)
|
|
518
517
|
} else {
|
|
519
518
|
throw e
|
|
520
519
|
}
|
|
@@ -537,6 +536,7 @@ export default class GitlabConnector implements StorageConnector {
|
|
|
537
536
|
if(!response.ok) throw new ApiError(`Gitlab API error: ${json?.message ?? json?.error ?? response.statusText}`, response.status)
|
|
538
537
|
// From base64 string to buffer
|
|
539
538
|
const buf = Buffer.from(json.content, 'base64')
|
|
539
|
+
// Return the image bytes
|
|
540
540
|
return buf
|
|
541
541
|
}
|
|
542
542
|
|
|
@@ -47,18 +47,18 @@ export default async function(config, opts = {}) {
|
|
|
47
47
|
// SSL
|
|
48
48
|
// force ssl if the env var SILEX_FORCE_HTTPS is set
|
|
49
49
|
if (options.forceHttps) {
|
|
50
|
-
console.
|
|
50
|
+
console.info('> [SslPlugin] Force SSL option is enabled')
|
|
51
51
|
app.set('forceSSLOptions', {
|
|
52
52
|
trustXFPHeader: !!options.trustXFPHeader,
|
|
53
53
|
})
|
|
54
54
|
router.use(forceSSL)
|
|
55
55
|
} else {
|
|
56
|
-
console.
|
|
56
|
+
console.info('> [SslPlugin] Force SSL option is disabled, env var SILEX_FORCE_HTTPS not set')
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
// SSL certificate
|
|
60
60
|
if (options.privateKey && options.certificate) {
|
|
61
|
-
console.
|
|
61
|
+
console.info('> [SslPlugin] SSL certificate is enabled, found certificate:', options.certificate)
|
|
62
62
|
try {
|
|
63
63
|
const privateKey = readFileSync(options.privateKey).toString()
|
|
64
64
|
const certificate = readFileSync(options.certificate).toString()
|
|
@@ -71,13 +71,13 @@ export default async function(config, opts = {}) {
|
|
|
71
71
|
}
|
|
72
72
|
|
|
73
73
|
createServer(sslServerOptions, this).listen(options.sslPort, () => {
|
|
74
|
-
console.
|
|
74
|
+
console.info('> [SslPlugin] Listening on port ', options.sslPort)
|
|
75
75
|
})
|
|
76
76
|
} catch (e) {
|
|
77
77
|
console.error('> [SslPlugin] Load certificate failed.', e)
|
|
78
78
|
}
|
|
79
79
|
} else {
|
|
80
|
-
console.
|
|
80
|
+
console.info('> [SslPlugin] Certificate disabled, env vars SILEX_SSL_CERTIFICATE and SILEX_SSL_PRIVATE_KEY not set')
|
|
81
81
|
}
|
|
82
82
|
app.use(router)
|
|
83
83
|
})
|
|
@@ -48,6 +48,9 @@ export default async function(config, opts = {}) {
|
|
|
48
48
|
}, {
|
|
49
49
|
route: '/',
|
|
50
50
|
path: join(__dirname, '../../../../..', 'dist', 'client'),
|
|
51
|
+
}, {
|
|
52
|
+
route: '/',
|
|
53
|
+
path: join(__dirname, '../../../../..', 'dist', 'plugins', 'client'),
|
|
51
54
|
},
|
|
52
55
|
]
|
|
53
56
|
// add project route for source maps
|
|
@@ -57,6 +60,7 @@ export default async function(config, opts = {}) {
|
|
|
57
60
|
}] : []),
|
|
58
61
|
...opts,
|
|
59
62
|
}
|
|
63
|
+
console.info('> [StaticPlugin] Serving static files')
|
|
60
64
|
|
|
61
65
|
config.on(ServerEvent.STARTUP_START, ({app}) => {
|
|
62
66
|
const router = express.Router()
|
package/src/ts/server/config.ts
CHANGED
|
@@ -103,7 +103,7 @@ export class ServerConfig extends Config {
|
|
|
103
103
|
async addRoutes(app: Application) {
|
|
104
104
|
const path = process.env.SILEX_CLIENT_CONFIG
|
|
105
105
|
if (path) {
|
|
106
|
-
console.
|
|
106
|
+
console.info(`> Serving client side config ${path} at ${CLIENT_CONFIG_FILE_NAME}`)
|
|
107
107
|
try {
|
|
108
108
|
// Load the client config file
|
|
109
109
|
let clientConfig = (await readFile(path as string)).toString()
|
|
@@ -111,7 +111,7 @@ export class ServerConfig extends Config {
|
|
|
111
111
|
app.get(`/${CLIENT_CONFIG_FILE_NAME}`, async (req: Request, res: Response) => {
|
|
112
112
|
// Reload each time in debug mode
|
|
113
113
|
if (this.debug) {
|
|
114
|
-
console.
|
|
114
|
+
console.info('[Debug mode] Reloading config file', path)
|
|
115
115
|
clientConfig = (await readFile(path)).toString()
|
|
116
116
|
}
|
|
117
117
|
// Send the config file
|
|
@@ -143,7 +143,7 @@ export class ServerConfig extends Config {
|
|
|
143
143
|
*/
|
|
144
144
|
async loadUserConfig() {
|
|
145
145
|
if (this.userConfigPath) {
|
|
146
|
-
console.
|
|
146
|
+
console.info('> Loading user config', this.userConfigPath)
|
|
147
147
|
try {
|
|
148
148
|
// Initiate the process with the config file which is just another plugin
|
|
149
149
|
await this.addPlugin(this.userConfigPath, {})
|
|
@@ -158,12 +158,11 @@ export class ServerConfig extends Config {
|
|
|
158
158
|
* This is the main config file
|
|
159
159
|
*/
|
|
160
160
|
async loadSilexConfig() {
|
|
161
|
-
console.
|
|
161
|
+
console.info('> Loading config', this.configFilePath)
|
|
162
162
|
try {
|
|
163
163
|
// Initiate the process with the config file which is just another plugin
|
|
164
164
|
await this.addPlugin(this.configFilePath, {})
|
|
165
165
|
} catch(e) {
|
|
166
|
-
console.log(e.requireStack[0])
|
|
167
166
|
// Check if the error is about the config file not found and not another module not found in the config file
|
|
168
167
|
if(e.code === 'MODULE_NOT_FOUND' && (!e.requireStack || !e.requireStack.find(path => path === this.configFilePath))) {
|
|
169
168
|
console.info('> /!\\ Config file not found', this.configFilePath)
|
|
@@ -32,7 +32,7 @@ import { fileURLToPath } from 'url'
|
|
|
32
32
|
if(!globalThis.__dirname) {
|
|
33
33
|
// @ts-ignore
|
|
34
34
|
globalThis.__dirname = dirname(process.cwd() + '/src/ts/server/connectors/FsStorage.ts')
|
|
35
|
-
console.
|
|
35
|
+
console.info('Redefining __dirname', globalThis.__dirname)
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
type FsSession = ConnectorSession
|
package/src/ts/server/express.ts
CHANGED
|
@@ -33,7 +33,7 @@ export function create(config: ServerConfig): Application {
|
|
|
33
33
|
// CORS
|
|
34
34
|
const options = config.expressOptions
|
|
35
35
|
if (options.cors) {
|
|
36
|
-
console.
|
|
36
|
+
console.info('> CORS are ENABLED:', options.cors)
|
|
37
37
|
app.use(cors({
|
|
38
38
|
origin: options.cors,
|
|
39
39
|
}))
|
|
@@ -45,7 +45,7 @@ export function create(config: ServerConfig): Application {
|
|
|
45
45
|
app.use(bodyParser.json({ limit: options.jsonLimit }))
|
|
46
46
|
app.use(bodyParser.text({ limit: options.textLimit }))
|
|
47
47
|
app.use(bodyParser.urlencoded({ limit: options.urlencodedLimit }))
|
|
48
|
-
console.
|
|
48
|
+
console.info('> Session name:', options.sessionName)
|
|
49
49
|
app.use(cookieParser() as any)
|
|
50
50
|
app.use(session({
|
|
51
51
|
name: options.sessionName,
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import { ClientEvent } from '../events'
|
|
2
|
-
import { websiteMetaRead } from '../api'
|
|
3
|
-
import { WebsiteMeta, WebsiteMetaFileContent } from '../../types'
|
|
4
|
-
|
|
5
|
-
export default (config, opts: any = {}) => {
|
|
6
|
-
config.on(ClientEvent.STARTUP_END, async ({ editor }) => {
|
|
7
|
-
console.log('websiteMetaPlugin STARTUP')
|
|
8
|
-
console.log('websiteMetaPlugin storage:end:load')
|
|
9
|
-
// Get website meta data
|
|
10
|
-
const websiteMeta = await websiteMetaRead({websiteId: config.websiteId, connectorId: config.connectorId})
|
|
11
|
-
// Display in the editor
|
|
12
|
-
displayWebsiteMeta(editor, websiteMeta)
|
|
13
|
-
editor.on('storage:end:load', async () => {
|
|
14
|
-
})
|
|
15
|
-
})
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
function displayWebsiteMeta(editor, websiteMeta: WebsiteMeta) {
|
|
19
|
-
// Check if the container exists in the UI
|
|
20
|
-
let container = document.querySelector('.gjs-website-meta')
|
|
21
|
-
if(!container) {
|
|
22
|
-
// Create the container
|
|
23
|
-
container = document.createElement('div')
|
|
24
|
-
container.classList.add('gjs-website-meta')
|
|
25
|
-
// Add the container to the UI
|
|
26
|
-
editor.Panels.add('gjs-website-meta', {
|
|
27
|
-
id: 'gjs-website-meta',
|
|
28
|
-
el: container,
|
|
29
|
-
visible: true,
|
|
30
|
-
})
|
|
31
|
-
}
|
|
32
|
-
// Display the website meta data
|
|
33
|
-
container.innerHTML = `
|
|
34
|
-
<div class="gjs-website-meta-title">Website</div>
|
|
35
|
-
<div class="gjs-website-meta-name">${websiteMeta.name}</div>
|
|
36
|
-
<div class="gjs-website-meta-image" style="background: ${websiteMeta.imageUrl}"></div>
|
|
37
|
-
`
|
|
38
|
-
console.log('displayWebsiteMeta', websiteMeta, container)
|
|
39
|
-
}
|