@swell/cli 2.0.1-alpha.16 → 2.0.1-alpha.18
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/app-command.d.ts +1 -1
- package/dist/app-command.js +9 -9
- package/dist/commands/app/dev.d.ts +16 -0
- package/dist/commands/app/dev.js +28 -0
- package/dist/commands/app/frontend/deploy.d.ts +15 -0
- package/dist/commands/app/frontend/deploy.js +41 -0
- package/dist/commands/app/frontend/dev.d.ts +19 -0
- package/dist/commands/app/frontend/dev.js +108 -0
- package/dist/commands/app/info.js +14 -9
- package/dist/commands/app/init.d.ts +12 -0
- package/dist/commands/app/init.js +34 -0
- package/dist/commands/app/install.d.ts +0 -3
- package/dist/commands/app/install.js +12 -21
- package/dist/commands/app/pull.d.ts +15 -0
- package/dist/commands/app/pull.js +50 -0
- package/dist/commands/app/push.d.ts +9 -12
- package/dist/commands/app/push.js +57 -131
- package/dist/commands/app/release.d.ts +13 -0
- package/dist/commands/app/release.js +148 -0
- package/dist/commands/app/version.d.ts +5 -4
- package/dist/commands/app/version.js +60 -39
- package/dist/commands/app/watch.d.ts +2 -4
- package/dist/commands/app/watch.js +3 -83
- package/dist/commands/create/app.d.ts +35 -11
- package/dist/commands/create/app.js +131 -128
- package/dist/commands/create/frontend.d.ts +12 -0
- package/dist/commands/create/frontend.js +38 -0
- package/dist/commands/create/function.d.ts +2 -2
- package/dist/commands/create/function.js +2 -2
- package/dist/commands/create/notification.d.ts +2 -2
- package/dist/commands/create/notification.js +2 -2
- package/dist/commands/env.d.ts +12 -0
- package/dist/commands/env.js +31 -0
- package/dist/commands/login.js +7 -7
- package/dist/commands/logs.js +0 -3
- package/dist/commands/theme/dev.d.ts +21 -0
- package/dist/commands/theme/dev.js +164 -0
- package/dist/commands/theme/init.d.ts +9 -0
- package/dist/commands/theme/init.js +15 -0
- package/dist/commands/theme/pull.d.ts +20 -0
- package/dist/commands/theme/pull.js +65 -0
- package/dist/commands/theme/push.d.ts +19 -0
- package/dist/commands/theme/push.js +89 -0
- package/dist/create-app-command.d.ts +20 -0
- package/dist/create-app-command.js +253 -0
- package/dist/create-collection-command.d.ts +3 -3
- package/dist/create-collection-command.js +4 -4
- package/dist/{create-command.d.ts → create-config-command.d.ts} +1 -1
- package/dist/{create-command.js → create-config-command.js} +3 -5
- package/dist/env/local.d.ts +8 -0
- package/dist/env/local.js +7 -0
- package/dist/env/production.d.ts +8 -0
- package/dist/env/production.js +7 -0
- package/dist/env/review.d.ts +8 -0
- package/dist/env/review.js +7 -0
- package/dist/env/staging.d.ts +8 -0
- package/dist/env/staging.js +7 -0
- package/dist/lib/api.d.ts +1 -0
- package/dist/lib/api.js +39 -13
- package/dist/lib/app-config.d.ts +12 -5
- package/dist/lib/app-config.js +57 -21
- package/dist/lib/apps/app-config.d.ts +17 -3
- package/dist/lib/apps/app-config.js +194 -66
- package/dist/lib/apps/index.d.ts +92 -12
- package/dist/lib/apps/index.js +145 -47
- package/dist/lib/apps/paths.d.ts +14 -7
- package/dist/lib/apps/paths.js +73 -28
- package/dist/lib/config.d.ts +9 -2
- package/dist/lib/config.js +49 -1
- package/dist/lib/constants.d.ts +5 -0
- package/dist/lib/constants.js +23 -4
- package/dist/lib/create/content.d.ts +1 -1
- package/dist/lib/create/index.js +5 -1
- package/dist/lib/info.js +2 -2
- package/dist/lib/stores.d.ts +5 -3
- package/dist/lib/stores.js +7 -5
- package/dist/lib/style.d.ts +2 -0
- package/dist/lib/style.js +2 -0
- package/dist/push-app-command.d.ts +73 -0
- package/dist/push-app-command.js +754 -0
- package/dist/remote-app-command.d.ts +35 -9
- package/dist/remote-app-command.js +417 -159
- package/oclif.manifest.json +817 -71
- package/package.json +13 -1
- package/dist/commands/app/_pull.d.ts +0 -8
- package/dist/commands/app/_pull.js +0 -45
package/dist/lib/app-config.js
CHANGED
|
@@ -5,11 +5,14 @@ import Conf from 'conf';
|
|
|
5
5
|
import * as fs from 'node:fs';
|
|
6
6
|
import * as path from 'node:path';
|
|
7
7
|
const schema = {
|
|
8
|
+
compatibilities: { type: 'object' },
|
|
8
9
|
description: { type: 'string' },
|
|
9
10
|
id: { type: 'string' },
|
|
10
11
|
integrations: { type: 'array' },
|
|
11
12
|
name: { type: 'string' },
|
|
12
13
|
permissions: { type: 'array' },
|
|
14
|
+
storefront: { type: 'object' },
|
|
15
|
+
theme: { type: 'object' },
|
|
13
16
|
type: { type: 'string' },
|
|
14
17
|
version: { type: 'string' },
|
|
15
18
|
};
|
|
@@ -22,23 +25,23 @@ const APP_FILE_EXT = 'json';
|
|
|
22
25
|
* @param dir - the directory to use for the config file path
|
|
23
26
|
* @returns string
|
|
24
27
|
*/
|
|
25
|
-
function
|
|
28
|
+
function swellConfigFile(dir = '') {
|
|
26
29
|
if (!dir) {
|
|
27
30
|
dir = process.cwd();
|
|
28
31
|
}
|
|
29
32
|
return path.join(dir, [APP_FILE_NAME, '.', APP_FILE_EXT].join(''));
|
|
30
33
|
}
|
|
31
34
|
/**
|
|
32
|
-
* Checks if the
|
|
35
|
+
* Checks if the swell config file exists at the given path, default to cwd.
|
|
33
36
|
*
|
|
34
37
|
* @param configFilePath - the path to the app config file
|
|
35
38
|
* @returns boolean
|
|
36
39
|
* @throws Error
|
|
37
40
|
*/
|
|
38
|
-
function
|
|
41
|
+
function swellConfigFileExists(configFilePath = '') {
|
|
39
42
|
// if the config file path is not provided, try to find it as the default
|
|
40
43
|
if (!configFilePath) {
|
|
41
|
-
configFilePath =
|
|
44
|
+
configFilePath = swellConfigFile();
|
|
42
45
|
}
|
|
43
46
|
try {
|
|
44
47
|
// eslint-disable-next-line no-bitwise
|
|
@@ -60,9 +63,9 @@ function appConfigFileExists(configFilePath = '') {
|
|
|
60
63
|
* @returns string
|
|
61
64
|
* @throws Error
|
|
62
65
|
*/
|
|
63
|
-
function
|
|
64
|
-
const configFilePath =
|
|
65
|
-
if (
|
|
66
|
+
function swellConfigFilePath(dir = '') {
|
|
67
|
+
const configFilePath = swellConfigFile(dir);
|
|
68
|
+
if (swellConfigFileExists(configFilePath)) {
|
|
66
69
|
return configFilePath;
|
|
67
70
|
}
|
|
68
71
|
// if the file doesn't exist, try to find it in the parent directory
|
|
@@ -70,10 +73,10 @@ function appConfigFilePath(dir = '') {
|
|
|
70
73
|
if (dir && dir === path.parse(dir).root) {
|
|
71
74
|
return '';
|
|
72
75
|
}
|
|
73
|
-
return
|
|
76
|
+
return swellConfigFilePath(path.resolve(dir, '..'));
|
|
74
77
|
}
|
|
75
78
|
async function writeRcFile(path, data) {
|
|
76
|
-
let dataToWrite = '';
|
|
79
|
+
let dataToWrite = '# This file is automatically generated by the Swell CLI\n';
|
|
77
80
|
for (const [key, value] of Object.entries(data)) {
|
|
78
81
|
dataToWrite += `${key}=${value}\n`;
|
|
79
82
|
}
|
|
@@ -84,9 +87,15 @@ function readRcFile(path) {
|
|
|
84
87
|
const dataFromFile = fs.readFileSync(path, 'utf8');
|
|
85
88
|
const lines = dataFromFile.split('\n');
|
|
86
89
|
for (const line of lines) {
|
|
87
|
-
const
|
|
88
|
-
if (
|
|
89
|
-
|
|
90
|
+
const cleanLine = line.trim();
|
|
91
|
+
if (cleanLine.startsWith('#')) {
|
|
92
|
+
// Ignore comments
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
const [key, value] = cleanLine.trim().split('=');
|
|
96
|
+
const cleanValue = value && value.trim();
|
|
97
|
+
if (key && cleanValue) {
|
|
98
|
+
data[key] = cleanValue;
|
|
90
99
|
}
|
|
91
100
|
}
|
|
92
101
|
return data;
|
|
@@ -95,19 +104,26 @@ function readRcFile(path) {
|
|
|
95
104
|
* Returns a new configuration instance in the current working directory or
|
|
96
105
|
* a parent directory.
|
|
97
106
|
*
|
|
98
|
-
* @param
|
|
107
|
+
* @param configDir - the path to the app config directory. If not provided,
|
|
99
108
|
* the config file will be searched for in the current working directory or
|
|
100
109
|
* a parent directory.
|
|
101
110
|
*
|
|
102
111
|
* @returns Conf
|
|
103
112
|
*/
|
|
104
|
-
function config(
|
|
105
|
-
const dirPath =
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
113
|
+
function config(configDir = '') {
|
|
114
|
+
const dirPath = configDir || path.dirname(swellConfigFilePath());
|
|
115
|
+
let config;
|
|
116
|
+
try {
|
|
117
|
+
config = new Conf({
|
|
118
|
+
clearInvalidConfig: true,
|
|
119
|
+
configName: APP_FILE_NAME,
|
|
120
|
+
cwd: dirPath,
|
|
121
|
+
schema,
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
catch (error) {
|
|
125
|
+
throw new Error(`Error parsing swell.json: ${error.toString()}`);
|
|
126
|
+
}
|
|
111
127
|
// for convenience, we add custom properties to the Conf object
|
|
112
128
|
// we prefix them with "sw" to avoid conflicts with Conf's properties
|
|
113
129
|
config.swDirPath = dirPath;
|
|
@@ -121,9 +137,29 @@ function config(configDirPath = '') {
|
|
|
121
137
|
*/
|
|
122
138
|
function newConfig(path) {
|
|
123
139
|
return new Conf({
|
|
140
|
+
clearInvalidConfig: true,
|
|
124
141
|
configName: APP_FILE_NAME,
|
|
125
142
|
cwd: `${process.cwd()}${path ? `/${path}` : ''}`,
|
|
126
143
|
schema,
|
|
144
|
+
serialize,
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Returns a new configuration instance at the specified path.
|
|
149
|
+
*
|
|
150
|
+
* @param appPath Path of the current working directory
|
|
151
|
+
* @returns Conf
|
|
152
|
+
*/
|
|
153
|
+
function newConfigAtPath(appPath) {
|
|
154
|
+
const dirPath = appPath || path.dirname(swellConfigFilePath());
|
|
155
|
+
return new Conf({
|
|
156
|
+
configName: APP_FILE_NAME,
|
|
157
|
+
cwd: dirPath,
|
|
158
|
+
schema,
|
|
159
|
+
serialize,
|
|
127
160
|
});
|
|
128
161
|
}
|
|
129
|
-
|
|
162
|
+
function serialize(value) {
|
|
163
|
+
return JSON.stringify(value, null, 2);
|
|
164
|
+
}
|
|
165
|
+
export { config as default, newConfig, newConfigAtPath, readRcFile, swellConfigFileExists, writeRcFile, };
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
1
2
|
import { ConfigType } from './index.js';
|
|
2
3
|
declare class IgnoringFileError extends Error {
|
|
3
4
|
constructor(message: string);
|
|
@@ -7,6 +8,7 @@ declare class FunctionProcessingError extends Error {
|
|
|
7
8
|
constructor(message: string, error: Error);
|
|
8
9
|
}
|
|
9
10
|
type AppConfigFile = {
|
|
11
|
+
content_type?: string;
|
|
10
12
|
data?: string;
|
|
11
13
|
date_uploaded?: string;
|
|
12
14
|
ext?: string;
|
|
@@ -20,21 +22,33 @@ type AppConfigFile = {
|
|
|
20
22
|
* app & the configuration are saved to the API.
|
|
21
23
|
*/
|
|
22
24
|
declare abstract class AppConfig {
|
|
25
|
+
appConfigId?: string;
|
|
26
|
+
appPath: string;
|
|
27
|
+
byteSize?: number;
|
|
23
28
|
date_created?: string;
|
|
29
|
+
date_updated?: string;
|
|
24
30
|
file?: AppConfigFile;
|
|
25
|
-
|
|
31
|
+
file_path?: string;
|
|
32
|
+
fileContent?: string;
|
|
33
|
+
fileData?: Buffer;
|
|
34
|
+
fileHash?: string;
|
|
35
|
+
filePath: string;
|
|
36
|
+
hash?: string;
|
|
26
37
|
id?: string;
|
|
27
|
-
|
|
28
|
-
localPath?: string;
|
|
38
|
+
mbSize?: number;
|
|
29
39
|
name?: string;
|
|
30
40
|
parent_id?: string;
|
|
31
41
|
slug?: string;
|
|
32
42
|
values: {
|
|
33
43
|
[key: string]: any;
|
|
34
44
|
};
|
|
45
|
+
version?: string;
|
|
35
46
|
constructor(attrs?: Partial<AppConfig>);
|
|
36
47
|
static create(attrs?: Partial<AppConfig>): AppConfig;
|
|
48
|
+
isRootConfig(configDir: string): boolean;
|
|
37
49
|
postData(): Promise<any>;
|
|
50
|
+
prepareFileData(): any;
|
|
51
|
+
abstract hasValues: boolean;
|
|
38
52
|
/** build the JSON used when making requests (usually push) to the API */
|
|
39
53
|
protected abstract preparePostData(postData: any): Promise<any>;
|
|
40
54
|
abstract type: ConfigType;
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
|
|
1
|
+
import { getEncoding } from 'istextorbinary';
|
|
2
2
|
import isEmpty from 'lodash/isEmpty.js';
|
|
3
|
+
import { detectFilenameMime } from 'mime-detect';
|
|
3
4
|
import * as fs from 'node:fs';
|
|
4
5
|
import * as path from 'node:path';
|
|
5
6
|
import { bundleFunction } from '../bundle.js';
|
|
6
|
-
import { ConfigType } from './index.js';
|
|
7
|
+
import { ConfigPaths, ConfigType, filePathExists, hashFile } from './index.js';
|
|
7
8
|
class IgnoringFileError extends Error {
|
|
8
9
|
constructor(message) {
|
|
9
10
|
super(message);
|
|
@@ -23,21 +24,68 @@ class FunctionProcessingError extends Error {
|
|
|
23
24
|
* app & the configuration are saved to the API.
|
|
24
25
|
*/
|
|
25
26
|
class AppConfig {
|
|
27
|
+
// Used when pushing a theme and the app config is considered
|
|
28
|
+
appConfigId;
|
|
29
|
+
// Full local path of remote AppConfig
|
|
30
|
+
appPath;
|
|
31
|
+
// Size of local file in bytes and mb
|
|
32
|
+
byteSize;
|
|
26
33
|
date_created;
|
|
34
|
+
date_updated;
|
|
27
35
|
file;
|
|
36
|
+
file_path;
|
|
37
|
+
// UTF8 content of local file
|
|
38
|
+
fileContent;
|
|
39
|
+
// Buffer of local file data
|
|
28
40
|
fileData;
|
|
41
|
+
fileHash;
|
|
42
|
+
// Relative path of remote AppConfig, same as file_path if defined
|
|
43
|
+
filePath;
|
|
44
|
+
hash;
|
|
45
|
+
// Server-side props
|
|
29
46
|
id;
|
|
30
|
-
|
|
31
|
-
localPath;
|
|
47
|
+
mbSize;
|
|
32
48
|
name;
|
|
33
49
|
parent_id;
|
|
34
50
|
slug;
|
|
35
51
|
values = {};
|
|
52
|
+
version;
|
|
36
53
|
constructor(attrs = {}) {
|
|
37
54
|
Object.assign(this, attrs);
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
55
|
+
let { appPath, file_path, filePath, name, type } = attrs;
|
|
56
|
+
this.appPath = appPath || '';
|
|
57
|
+
this.filePath = filePath || '';
|
|
58
|
+
if (!type || !name) {
|
|
59
|
+
throw new Error('Missing app config type or name.');
|
|
60
|
+
}
|
|
61
|
+
if (!appPath) {
|
|
62
|
+
throw new Error('Missing app path to initialize config.');
|
|
63
|
+
}
|
|
64
|
+
// Make sure file path is set from server prop or type/name
|
|
65
|
+
if (!filePath) {
|
|
66
|
+
if (file_path) {
|
|
67
|
+
filePath = file_path;
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
// Note this shouldn't be necessary unless the config was created before file_path was added
|
|
71
|
+
const typePath = ConfigPaths[String(type).toUpperCase()];
|
|
72
|
+
filePath = `${typePath}/${name}`;
|
|
73
|
+
if (!typePath) {
|
|
74
|
+
throw new Error(`Missing path for app config type: ${type}`);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
this.filePath = filePath;
|
|
78
|
+
}
|
|
79
|
+
if (!appPath.endsWith(filePath)) {
|
|
80
|
+
this.appPath = path.join(appPath, filePath);
|
|
81
|
+
}
|
|
82
|
+
if (filePathExists(this.appPath)) {
|
|
83
|
+
this.fileHash = hashFile(this.appPath);
|
|
84
|
+
this.hash = this.hash || this.fileHash;
|
|
85
|
+
this.fileData = fs.readFileSync(this.appPath);
|
|
86
|
+
this.fileContent = this.fileData.toString('utf8');
|
|
87
|
+
this.byteSize = Buffer.byteLength(this.fileContent);
|
|
88
|
+
this.mbSize = this.byteSize / 1024 / 1024;
|
|
41
89
|
}
|
|
42
90
|
}
|
|
43
91
|
static create(attrs = {}) {
|
|
@@ -51,120 +99,200 @@ class AppConfig {
|
|
|
51
99
|
case ConfigType.MODEL: {
|
|
52
100
|
return new AppConfigModel(attrs);
|
|
53
101
|
}
|
|
102
|
+
case ConfigType.CONTENT: {
|
|
103
|
+
return new AppConfigContent(attrs);
|
|
104
|
+
}
|
|
54
105
|
case ConfigType.NOTIFICATION: {
|
|
55
|
-
// the path can be a tpl file or a json file as we can use the `create`
|
|
56
|
-
// function when watching for changes. We need to make sure that we
|
|
57
|
-
// always use the json file for AppConfig.
|
|
58
|
-
attrs.localPath = AppConfigNotification.actualConfigPath(attrs.localPath);
|
|
59
106
|
return new AppConfigNotification(attrs);
|
|
60
107
|
}
|
|
108
|
+
case ConfigType.SETTING: {
|
|
109
|
+
return new AppConfigSetting(attrs);
|
|
110
|
+
}
|
|
111
|
+
case ConfigType.WEBHOOK: {
|
|
112
|
+
return new AppConfigWebhook(attrs);
|
|
113
|
+
}
|
|
114
|
+
case ConfigType.FRONTEND: {
|
|
115
|
+
return new AppConfigFrontend(attrs);
|
|
116
|
+
}
|
|
117
|
+
case ConfigType.THEME: {
|
|
118
|
+
return new AppConfigTheme(attrs);
|
|
119
|
+
}
|
|
61
120
|
default: {
|
|
62
|
-
// the default type is
|
|
63
|
-
// that we set the expected type
|
|
121
|
+
// the default type is file
|
|
64
122
|
const defaultConfig = new AppConfigDefault(attrs);
|
|
65
123
|
defaultConfig.type = attrs.type;
|
|
66
124
|
return defaultConfig;
|
|
67
125
|
}
|
|
68
126
|
}
|
|
69
127
|
}
|
|
128
|
+
isRootConfig(configDir) {
|
|
129
|
+
return !this.filePath
|
|
130
|
+
?.replace(new RegExp(`^${configDir}/`), '')
|
|
131
|
+
.includes('/');
|
|
132
|
+
}
|
|
70
133
|
async postData() {
|
|
71
|
-
if (
|
|
72
|
-
throw new Error('Missing local config path');
|
|
73
|
-
}
|
|
74
|
-
if (!this.fileData) {
|
|
134
|
+
if (this.fileContent === undefined) {
|
|
75
135
|
return;
|
|
76
136
|
}
|
|
77
|
-
if (this.
|
|
137
|
+
if (this.hasValues && this.filePath.endsWith('.json')) {
|
|
78
138
|
try {
|
|
79
|
-
this.values = JSON.parse(this.
|
|
139
|
+
this.values = JSON.parse(this.fileContent);
|
|
80
140
|
}
|
|
81
141
|
catch {
|
|
82
|
-
throw new IgnoringFileError('
|
|
142
|
+
throw new IgnoringFileError('Invalid JSON');
|
|
83
143
|
}
|
|
84
144
|
if (isEmpty(this.values)) {
|
|
85
|
-
throw new IgnoringFileError('
|
|
145
|
+
throw new IgnoringFileError('Empty JSON');
|
|
86
146
|
}
|
|
87
147
|
}
|
|
148
|
+
// Detect file content type
|
|
149
|
+
const contentType = this.filePath.endsWith('.liquid') || this.filePath.endsWith('.liquidx')
|
|
150
|
+
? 'application/liquid'
|
|
151
|
+
: detectFilenameMime(this.filePath);
|
|
88
152
|
const postData = {
|
|
153
|
+
file: {
|
|
154
|
+
content_type: contentType,
|
|
155
|
+
data: this.prepareFileData(),
|
|
156
|
+
},
|
|
157
|
+
file_path: this.filePath,
|
|
158
|
+
hash: this.hash,
|
|
159
|
+
// Name is either configured or the last part of the path without extension
|
|
89
160
|
name: this.values?.name || this.name,
|
|
90
161
|
type: this.type,
|
|
91
|
-
values: this.values,
|
|
92
162
|
};
|
|
163
|
+
if (this.hasValues) {
|
|
164
|
+
postData.values = this.values || {};
|
|
165
|
+
}
|
|
93
166
|
return this.preparePostData(postData);
|
|
94
167
|
}
|
|
168
|
+
prepareFileData() {
|
|
169
|
+
if (!this.fileData) {
|
|
170
|
+
return null;
|
|
171
|
+
}
|
|
172
|
+
return getEncoding(this.fileData) === 'binary'
|
|
173
|
+
? { $base64: this.fileData.toString('base64') }
|
|
174
|
+
: this.fileData?.toString('utf8');
|
|
175
|
+
}
|
|
95
176
|
}
|
|
96
177
|
class AppConfigDefault extends AppConfig {
|
|
97
|
-
|
|
178
|
+
hasValues = false;
|
|
179
|
+
type = ConfigType.FILE;
|
|
98
180
|
preparePostData(postData) {
|
|
99
181
|
return postData;
|
|
100
182
|
}
|
|
101
183
|
}
|
|
102
184
|
class AppConfigModel extends AppConfig {
|
|
185
|
+
hasValues = true;
|
|
103
186
|
type = ConfigType.MODEL;
|
|
104
187
|
preparePostData(postData) {
|
|
105
|
-
postData.values.collection =
|
|
188
|
+
postData.values.collection =
|
|
189
|
+
postData.values.collection || postData.values.model || this.name;
|
|
190
|
+
return postData;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
class AppConfigContent extends AppConfig {
|
|
194
|
+
hasValues = true;
|
|
195
|
+
type = ConfigType.CONTENT;
|
|
196
|
+
preparePostData(postData) {
|
|
197
|
+
postData.values.collection = postData.values.collection || this.name;
|
|
106
198
|
return postData;
|
|
107
199
|
}
|
|
108
200
|
}
|
|
109
201
|
class AppConfigNotification extends AppConfig {
|
|
202
|
+
hasValues = true;
|
|
110
203
|
type = ConfigType.NOTIFICATION;
|
|
111
|
-
/**
|
|
112
|
-
* The actual config path is the path to the JSON file that is used to
|
|
113
|
-
* configure the notification. This function ensures that the path is
|
|
114
|
-
* correct.
|
|
115
|
-
*
|
|
116
|
-
* @param localPath - json or tpl file path
|
|
117
|
-
* @returns - json file path
|
|
118
|
-
*/
|
|
119
|
-
static actualConfigPath(localPath) {
|
|
120
|
-
return localPath?.replace('.tpl', '.json');
|
|
121
|
-
}
|
|
122
204
|
preparePostData(postData) {
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
205
|
+
const isTemplate = this.isRootConfig('notifications') &&
|
|
206
|
+
(this.filePath.endsWith('.tpl') || this.filePath.endsWith('.liquid'));
|
|
207
|
+
if (isTemplate) {
|
|
208
|
+
// Get json config to match collection/model name
|
|
209
|
+
let jsonData;
|
|
210
|
+
try {
|
|
211
|
+
const jsonPath = this.filePath
|
|
212
|
+
.replace('.tpl', '.json')
|
|
213
|
+
.replace('.liquid', '.json');
|
|
214
|
+
jsonData = JSON.parse(fs.readFileSync(jsonPath, 'utf8'));
|
|
215
|
+
postData.values.collection = jsonData?.collection || jsonData?.model;
|
|
216
|
+
}
|
|
217
|
+
catch {
|
|
218
|
+
// noop
|
|
219
|
+
}
|
|
220
|
+
postData.file = {
|
|
221
|
+
content_type: 'text/plain',
|
|
222
|
+
data: this.fileContent?.replaceAll('\r\n', '\n'),
|
|
133
223
|
};
|
|
134
224
|
}
|
|
135
225
|
return postData;
|
|
136
226
|
}
|
|
137
227
|
}
|
|
228
|
+
class AppConfigSetting extends AppConfig {
|
|
229
|
+
hasValues = true;
|
|
230
|
+
type = ConfigType.SETTING;
|
|
231
|
+
preparePostData(postData) {
|
|
232
|
+
return postData;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
class AppConfigWebhook extends AppConfig {
|
|
236
|
+
hasValues = true;
|
|
237
|
+
type = ConfigType.WEBHOOK;
|
|
238
|
+
preparePostData(postData) {
|
|
239
|
+
return postData;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
138
242
|
class AppConfigFunction extends AppConfig {
|
|
243
|
+
hasValues = true;
|
|
139
244
|
type = ConfigType.FUNCTION;
|
|
140
245
|
async preparePostData(postData) {
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
246
|
+
const isFunction = this.isRootConfig('functions') &&
|
|
247
|
+
(this.filePath.endsWith('.js') || this.filePath.endsWith('.ts'));
|
|
248
|
+
if (isFunction) {
|
|
249
|
+
try {
|
|
250
|
+
const { code, config } = await bundleFunction(this.filePath);
|
|
251
|
+
if (!config) {
|
|
252
|
+
throw new IgnoringFileError('Function must export a `config` object.');
|
|
253
|
+
}
|
|
254
|
+
// Save the original file and the bundled version
|
|
255
|
+
postData.file = {
|
|
256
|
+
data: this.prepareFileData(),
|
|
257
|
+
};
|
|
258
|
+
postData.build_file = {
|
|
259
|
+
content_type: 'text/javascript',
|
|
260
|
+
data: code,
|
|
261
|
+
};
|
|
262
|
+
postData.values = config;
|
|
263
|
+
}
|
|
264
|
+
catch (error) {
|
|
265
|
+
throw new FunctionProcessingError(`Unable to compile function ${this.name}`, error);
|
|
148
266
|
}
|
|
149
|
-
const fileName = path.basename(this.localPath);
|
|
150
|
-
postData.file = {
|
|
151
|
-
data: code,
|
|
152
|
-
// we keep the file extension so we can easily identify the file path
|
|
153
|
-
// when we need to delete the function
|
|
154
|
-
ext: fileName.replace(this.name, ''),
|
|
155
|
-
};
|
|
156
|
-
postData.values = config;
|
|
157
|
-
}
|
|
158
|
-
catch (error) {
|
|
159
|
-
throw new FunctionProcessingError(`Unable to compile function ${this.name}`, error);
|
|
160
267
|
}
|
|
161
268
|
return postData;
|
|
162
269
|
}
|
|
163
270
|
}
|
|
164
|
-
|
|
271
|
+
// Assets do not get installed but saved as plain files
|
|
272
|
+
class AppConfigAsset extends AppConfigDefault {
|
|
273
|
+
hasValues = false;
|
|
165
274
|
type = ConfigType.ASSET;
|
|
166
|
-
|
|
167
|
-
|
|
275
|
+
}
|
|
276
|
+
class AppConfigFrontend extends AppConfigDefault {
|
|
277
|
+
hasValues = false;
|
|
278
|
+
type = ConfigType.FRONTEND;
|
|
279
|
+
}
|
|
280
|
+
class AppConfigTheme extends AppConfigDefault {
|
|
281
|
+
hasValues = false;
|
|
282
|
+
type = ConfigType.THEME;
|
|
283
|
+
preparePostData(postData) {
|
|
284
|
+
const isConfigJson = this.filePath?.match(/^theme\/config\/[^./]+\.json$/);
|
|
285
|
+
// Files in theme/config/*.json are treated as settings with values
|
|
286
|
+
if (isConfigJson) {
|
|
287
|
+
try {
|
|
288
|
+
const jsonData = JSON.parse(fs.readFileSync(this.filePath, 'utf8'));
|
|
289
|
+
postData.values = jsonData;
|
|
290
|
+
}
|
|
291
|
+
catch {
|
|
292
|
+
// noop
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
return postData;
|
|
168
296
|
}
|
|
169
297
|
}
|
|
170
298
|
export { AppConfig, FunctionProcessingError, IgnoringFileError };
|