@swell/cli 2.9.4 → 2.9.5
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 +2 -3
- package/dist/app-command.js +3 -6
- package/dist/commands/app/dev.d.ts +2 -2
- package/dist/commands/app/dev.js +49 -33
- package/dist/commands/app/frontend/dev.js +12 -6
- package/dist/commands/app/push.d.ts +1 -0
- package/dist/commands/app/push.js +3 -3
- package/dist/commands/app/release.js +2 -2
- package/dist/commands/create/app.d.ts +1 -1
- package/dist/commands/create/app.js +1 -1
- package/dist/commands/create/frontend.js +3 -3
- package/dist/commands/create/tests.js +10 -8
- package/dist/commands/inspect/extensions.js +4 -4
- package/dist/commands/schema.js +21 -18
- package/dist/commands/theme/dev.js +5 -5
- package/dist/commands/theme/push.d.ts +1 -0
- package/dist/commands/theme/push.js +3 -3
- package/dist/create-app-command.js +2 -2
- package/dist/create-config-command.d.ts +1 -1
- package/dist/create-config-command.js +3 -3
- package/dist/help/custom-help.d.ts +1 -1
- package/dist/help/types.d.ts +1 -1
- package/dist/lib/api.d.ts +1 -0
- package/dist/lib/api.js +1 -1
- package/dist/lib/app-config.d.ts +13 -8
- package/dist/lib/app-config.js +25 -23
- package/dist/lib/apps/app-config.d.ts +5 -5
- package/dist/lib/apps/app-config.js +53 -37
- package/dist/lib/apps/index.d.ts +15 -14
- package/dist/lib/apps/index.js +40 -23
- package/dist/lib/apps/paths.d.ts +1 -1
- package/dist/lib/apps/paths.js +3 -3
- package/dist/lib/bundle.js +26 -17
- package/dist/lib/config.d.ts +8 -8
- package/dist/lib/config.js +8 -10
- package/dist/lib/constants.d.ts +9 -9
- package/dist/lib/create/content.d.ts +6 -6
- package/dist/lib/create/content.js +7 -8
- package/dist/lib/create/function.d.ts +5 -6
- package/dist/lib/create/function.js +7 -8
- package/dist/lib/create/index.d.ts +8 -9
- package/dist/lib/create/index.js +7 -8
- package/dist/lib/create/model.d.ts +4 -4
- package/dist/lib/create/model.js +4 -5
- package/dist/lib/create/notification.d.ts +2 -3
- package/dist/lib/create/setting.d.ts +4 -4
- package/dist/lib/create/setting.js +3 -4
- package/dist/lib/create/tests/types.d.ts +3 -4
- package/dist/lib/create/tests.d.ts +1 -2
- package/dist/lib/create/tests.js +12 -13
- package/dist/lib/create/webhook.d.ts +6 -6
- package/dist/lib/create/webhook.js +15 -10
- package/dist/lib/function-source-analysis.js +3 -3
- package/dist/lib/info.d.ts +1 -1
- package/dist/lib/logs/index.d.ts +1 -0
- package/dist/lib/logs/line-output.d.ts +1 -0
- package/dist/lib/logs/line-output.js +12 -4
- package/dist/lib/logs/output.d.ts +1 -0
- package/dist/lib/logs/table-output.d.ts +1 -0
- package/dist/lib/logs/table-output.js +8 -5
- package/dist/lib/package-manager.d.ts +5 -5
- package/dist/lib/package-manager.js +9 -7
- package/dist/lib/proxy.js +4 -3
- package/dist/lib/sessions.d.ts +1 -2
- package/dist/lib/sessions.js +1 -2
- package/dist/lib/stores.d.ts +6 -6
- package/dist/lib/stores.js +5 -6
- package/dist/lib/swell-function-wrapper.d.ts +1 -193
- package/dist/lib/swell-function-wrapper.js +1 -1
- package/dist/lib/theme-sync.js +0 -5
- package/dist/push-app-command.d.ts +7 -6
- package/dist/push-app-command.js +35 -37
- package/dist/remote-app-command.d.ts +6 -4
- package/dist/remote-app-command.js +39 -25
- package/dist/swell-api-command.d.ts +1 -0
- package/dist/swell-api-command.js +3 -3
- package/dist/types/index.d.ts +94 -0
- package/dist/types/index.js +4 -0
- package/oclif.manifest.json +1 -1
- package/package.json +3 -3
package/dist/lib/app-config.d.ts
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* App configuration for local development of Swell Apps.
|
|
3
|
+
*/
|
|
4
|
+
import Conf from 'conf';
|
|
5
|
+
import type { LocalApp } from '../types/index.js';
|
|
6
|
+
import type { App } from './apps/index.js';
|
|
2
7
|
/**
|
|
3
8
|
* Checks if the swell config file exists at the given path, default to cwd.
|
|
4
9
|
*
|
|
@@ -6,9 +11,9 @@ import { App } from './apps';
|
|
|
6
11
|
* @returns boolean
|
|
7
12
|
* @throws Error
|
|
8
13
|
*/
|
|
9
|
-
declare function swellConfigFileExists(configFilePath?: string): boolean
|
|
10
|
-
declare function writeRcFile(path: string, data: any): Promise<void>;
|
|
11
|
-
declare function readRcFile(path: string): App
|
|
14
|
+
export declare function swellConfigFileExists(configFilePath?: string): Promise<boolean>;
|
|
15
|
+
export declare function writeRcFile(path: string, data: any): Promise<void>;
|
|
16
|
+
export declare function readRcFile(path: string): Promise<App>;
|
|
12
17
|
/**
|
|
13
18
|
* Returns a new configuration instance in the current working directory or
|
|
14
19
|
* a parent directory.
|
|
@@ -19,19 +24,19 @@ declare function readRcFile(path: string): App;
|
|
|
19
24
|
*
|
|
20
25
|
* @returns Conf
|
|
21
26
|
*/
|
|
22
|
-
declare function config(configDir?: string): LocalApp
|
|
27
|
+
declare function config(configDir?: string): Promise<LocalApp>;
|
|
23
28
|
/**
|
|
24
29
|
* Returns a new configuration instance in the current working directory only.
|
|
25
30
|
*
|
|
26
31
|
* @param path Path of the current working directory
|
|
27
32
|
* @returns Conf
|
|
28
33
|
*/
|
|
29
|
-
declare function newConfig(path?: string):
|
|
34
|
+
export declare function newConfig(path?: string): Conf;
|
|
30
35
|
/**
|
|
31
36
|
* Returns a new configuration instance at the specified path.
|
|
32
37
|
*
|
|
33
38
|
* @param appPath Path of the current working directory
|
|
34
39
|
* @returns Conf
|
|
35
40
|
*/
|
|
36
|
-
declare function newConfigAtPath(appPath?: string):
|
|
37
|
-
export
|
|
41
|
+
export declare function newConfigAtPath(appPath?: string): Promise<Conf>;
|
|
42
|
+
export default config;
|
package/dist/lib/app-config.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* App configuration for local development of Swell Apps.
|
|
3
3
|
*/
|
|
4
4
|
import Conf from 'conf';
|
|
5
|
-
import * as fs from 'node:fs';
|
|
5
|
+
import * as fs from 'node:fs/promises';
|
|
6
6
|
import * as path from 'node:path';
|
|
7
7
|
const schema = {
|
|
8
8
|
compatibilities: { type: 'object' },
|
|
@@ -30,7 +30,7 @@ function swellConfigFile(dir = '') {
|
|
|
30
30
|
if (!dir) {
|
|
31
31
|
dir = process.cwd();
|
|
32
32
|
}
|
|
33
|
-
return path.join(dir,
|
|
33
|
+
return path.join(dir, `${APP_FILE_NAME}.${APP_FILE_EXT}`);
|
|
34
34
|
}
|
|
35
35
|
/**
|
|
36
36
|
* Checks if the swell config file exists at the given path, default to cwd.
|
|
@@ -39,14 +39,14 @@ function swellConfigFile(dir = '') {
|
|
|
39
39
|
* @returns boolean
|
|
40
40
|
* @throws Error
|
|
41
41
|
*/
|
|
42
|
-
function swellConfigFileExists(configFilePath = '') {
|
|
42
|
+
export async function swellConfigFileExists(configFilePath = '') {
|
|
43
43
|
// if the config file path is not provided, try to find it as the default
|
|
44
44
|
if (!configFilePath) {
|
|
45
45
|
configFilePath = swellConfigFile();
|
|
46
46
|
}
|
|
47
47
|
try {
|
|
48
48
|
// eslint-disable-next-line no-bitwise
|
|
49
|
-
fs.
|
|
49
|
+
await fs.access(configFilePath, fs.constants.R_OK | fs.constants.W_OK);
|
|
50
50
|
return true;
|
|
51
51
|
}
|
|
52
52
|
catch (error) {
|
|
@@ -64,9 +64,9 @@ function swellConfigFileExists(configFilePath = '') {
|
|
|
64
64
|
* @returns string
|
|
65
65
|
* @throws Error
|
|
66
66
|
*/
|
|
67
|
-
function swellConfigFilePath(dir = '') {
|
|
67
|
+
async function swellConfigFilePath(dir = '') {
|
|
68
68
|
const configFilePath = swellConfigFile(dir);
|
|
69
|
-
if (swellConfigFileExists(configFilePath)) {
|
|
69
|
+
if (await swellConfigFileExists(configFilePath)) {
|
|
70
70
|
return configFilePath;
|
|
71
71
|
}
|
|
72
72
|
// if the file doesn't exist, try to find it in the parent directory
|
|
@@ -76,16 +76,16 @@ function swellConfigFilePath(dir = '') {
|
|
|
76
76
|
}
|
|
77
77
|
return swellConfigFilePath(path.resolve(dir, '..'));
|
|
78
78
|
}
|
|
79
|
-
async function writeRcFile(path, data) {
|
|
79
|
+
export async function writeRcFile(path, data) {
|
|
80
80
|
let dataToWrite = '# This file is automatically generated by the Swell CLI\n';
|
|
81
81
|
for (const [key, value] of Object.entries(data)) {
|
|
82
82
|
dataToWrite += `${key}=${value}\n`;
|
|
83
83
|
}
|
|
84
|
-
fs.
|
|
84
|
+
return fs.writeFile(path, dataToWrite, { encoding: 'utf8' });
|
|
85
85
|
}
|
|
86
|
-
function readRcFile(path) {
|
|
86
|
+
export async function readRcFile(path) {
|
|
87
87
|
const data = {};
|
|
88
|
-
const dataFromFile = fs.
|
|
88
|
+
const dataFromFile = await fs.readFile(path, 'utf8');
|
|
89
89
|
const lines = dataFromFile.split('\n');
|
|
90
90
|
for (const line of lines) {
|
|
91
91
|
const cleanLine = line.trim();
|
|
@@ -111,24 +111,26 @@ function readRcFile(path) {
|
|
|
111
111
|
*
|
|
112
112
|
* @returns Conf
|
|
113
113
|
*/
|
|
114
|
-
function config(configDir = '') {
|
|
115
|
-
const dirPath = configDir || path.dirname(swellConfigFilePath());
|
|
116
|
-
let config;
|
|
114
|
+
async function config(configDir = '') {
|
|
115
|
+
const dirPath = configDir || path.dirname(await swellConfigFilePath());
|
|
117
116
|
try {
|
|
118
|
-
config = new Conf({
|
|
117
|
+
const config = new Conf({
|
|
119
118
|
clearInvalidConfig: true,
|
|
120
119
|
configName: APP_FILE_NAME,
|
|
121
120
|
cwd: dirPath,
|
|
122
121
|
schema,
|
|
123
122
|
});
|
|
123
|
+
return Object.assign(config, {
|
|
124
|
+
// for convenience, we add custom properties to the Conf object
|
|
125
|
+
// we prefix them with "sw" to avoid conflicts with Conf's properties
|
|
126
|
+
swDirPath: dirPath,
|
|
127
|
+
});
|
|
124
128
|
}
|
|
125
129
|
catch (error) {
|
|
126
|
-
throw new Error(`Error parsing swell.json: ${error.
|
|
130
|
+
throw new Error(`Error parsing swell.json: ${error.message}`, {
|
|
131
|
+
cause: error,
|
|
132
|
+
});
|
|
127
133
|
}
|
|
128
|
-
// for convenience, we add custom properties to the Conf object
|
|
129
|
-
// we prefix them with "sw" to avoid conflicts with Conf's properties
|
|
130
|
-
config.swDirPath = dirPath;
|
|
131
|
-
return config;
|
|
132
134
|
}
|
|
133
135
|
/**
|
|
134
136
|
* Returns a new configuration instance in the current working directory only.
|
|
@@ -136,7 +138,7 @@ function config(configDir = '') {
|
|
|
136
138
|
* @param path Path of the current working directory
|
|
137
139
|
* @returns Conf
|
|
138
140
|
*/
|
|
139
|
-
function newConfig(path) {
|
|
141
|
+
export function newConfig(path) {
|
|
140
142
|
return new Conf({
|
|
141
143
|
clearInvalidConfig: true,
|
|
142
144
|
configName: APP_FILE_NAME,
|
|
@@ -151,8 +153,8 @@ function newConfig(path) {
|
|
|
151
153
|
* @param appPath Path of the current working directory
|
|
152
154
|
* @returns Conf
|
|
153
155
|
*/
|
|
154
|
-
function newConfigAtPath(appPath) {
|
|
155
|
-
const dirPath = appPath || path.dirname(swellConfigFilePath());
|
|
156
|
+
export async function newConfigAtPath(appPath) {
|
|
157
|
+
const dirPath = appPath || path.dirname(await swellConfigFilePath());
|
|
156
158
|
return new Conf({
|
|
157
159
|
configName: APP_FILE_NAME,
|
|
158
160
|
cwd: dirPath,
|
|
@@ -163,4 +165,4 @@ function newConfigAtPath(appPath) {
|
|
|
163
165
|
function serialize(value) {
|
|
164
166
|
return JSON.stringify(value, null, 2);
|
|
165
167
|
}
|
|
166
|
-
export
|
|
168
|
+
export default config;
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
/// <reference types="node" />
|
|
2
|
-
/// <reference types="node" />
|
|
1
|
+
/// <reference types="node" resolution-mode="require"/>
|
|
2
|
+
/// <reference types="node" resolution-mode="require"/>
|
|
3
3
|
import { ConfigType } from './index.js';
|
|
4
4
|
export declare class IgnoringFileError extends Error {
|
|
5
5
|
constructor(message: string);
|
|
6
6
|
}
|
|
7
7
|
export declare class FunctionProcessingError extends Error {
|
|
8
|
-
|
|
8
|
+
cause: Error;
|
|
9
9
|
constructor(message: string, error: Error);
|
|
10
10
|
}
|
|
11
11
|
interface AppConfigFile {
|
|
@@ -30,7 +30,6 @@ export declare abstract class AppConfig {
|
|
|
30
30
|
date_updated?: string;
|
|
31
31
|
file?: AppConfigFile;
|
|
32
32
|
file_path?: string;
|
|
33
|
-
fileContent?: string;
|
|
34
33
|
fileData?: Buffer;
|
|
35
34
|
fileHash?: string;
|
|
36
35
|
filePath: string;
|
|
@@ -45,7 +44,8 @@ export declare abstract class AppConfig {
|
|
|
45
44
|
};
|
|
46
45
|
version?: string;
|
|
47
46
|
constructor(attrs?: Partial<AppConfig>);
|
|
48
|
-
|
|
47
|
+
load(): Promise<void>;
|
|
48
|
+
static create(attrs?: Partial<AppConfig>): Promise<AppConfig>;
|
|
49
49
|
isRootConfig(configDir: string): boolean;
|
|
50
50
|
postData(): Promise<any>;
|
|
51
51
|
prepareFileData(): any;
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { getEncoding } from 'istextorbinary';
|
|
2
2
|
import isEmpty from 'lodash/isEmpty.js';
|
|
3
3
|
import { detectFilenameMime } from 'mime-detect';
|
|
4
|
-
import * as fs from 'node:fs';
|
|
4
|
+
import * as fs from 'node:fs/promises';
|
|
5
5
|
import * as path from 'node:path';
|
|
6
6
|
import { bundleFunction, bundleComponent, bundleWorkflow } from '../bundle.js';
|
|
7
7
|
import { analyzeFunctionSource, hasKindDiagnostic, workflowStaticConfigError, } from '../function-source-analysis.js';
|
|
8
|
-
import { AllConfigPaths, ConfigType,
|
|
8
|
+
import { AllConfigPaths, ConfigType, filePathExistsAsync, hashFile, } from './index.js';
|
|
9
9
|
export class IgnoringFileError extends Error {
|
|
10
10
|
constructor(message) {
|
|
11
11
|
super(message);
|
|
@@ -13,11 +13,11 @@ export class IgnoringFileError extends Error {
|
|
|
13
13
|
}
|
|
14
14
|
}
|
|
15
15
|
export class FunctionProcessingError extends Error {
|
|
16
|
-
|
|
16
|
+
cause;
|
|
17
17
|
constructor(message, error) {
|
|
18
18
|
super(message);
|
|
19
|
+
this.cause = error;
|
|
19
20
|
this.name = 'FunctionProcessingError';
|
|
20
|
-
this.originalError = error;
|
|
21
21
|
}
|
|
22
22
|
}
|
|
23
23
|
/**
|
|
@@ -35,8 +35,6 @@ export class AppConfig {
|
|
|
35
35
|
date_updated;
|
|
36
36
|
file;
|
|
37
37
|
file_path;
|
|
38
|
-
// UTF8 content of local file
|
|
39
|
-
fileContent;
|
|
40
38
|
// Buffer of local file data
|
|
41
39
|
fileData;
|
|
42
40
|
fileHash;
|
|
@@ -80,67 +78,83 @@ export class AppConfig {
|
|
|
80
78
|
if (!appPath.endsWith(filePath)) {
|
|
81
79
|
this.appPath = path.join(appPath, filePath);
|
|
82
80
|
}
|
|
83
|
-
|
|
84
|
-
|
|
81
|
+
}
|
|
82
|
+
async load() {
|
|
83
|
+
if (await filePathExistsAsync(this.appPath)) {
|
|
84
|
+
this.fileData = await fs.readFile(this.appPath);
|
|
85
|
+
this.fileHash = hashFile(this.appPath, this.fileData, this.filePath);
|
|
85
86
|
this.hash = this.hash || this.fileHash;
|
|
86
|
-
this.
|
|
87
|
-
this.fileContent = this.fileData.toString('utf8');
|
|
88
|
-
this.byteSize = Buffer.byteLength(this.fileContent);
|
|
87
|
+
this.byteSize = this.fileData.length;
|
|
89
88
|
this.mbSize = this.byteSize / 1024 / 1024;
|
|
90
89
|
}
|
|
91
90
|
}
|
|
92
|
-
static create(attrs = {}) {
|
|
91
|
+
static async create(attrs = {}) {
|
|
92
|
+
let instance;
|
|
93
93
|
switch (attrs.type) {
|
|
94
94
|
case ConfigType.ASSET: {
|
|
95
|
-
|
|
95
|
+
instance = new AppConfigAsset(attrs);
|
|
96
|
+
break;
|
|
96
97
|
}
|
|
97
98
|
case ConfigType.FUNCTION: {
|
|
98
|
-
|
|
99
|
+
instance = new AppConfigFunction(attrs);
|
|
100
|
+
break;
|
|
99
101
|
}
|
|
100
102
|
case ConfigType.MODEL: {
|
|
101
|
-
|
|
103
|
+
instance = new AppConfigModel(attrs);
|
|
104
|
+
break;
|
|
102
105
|
}
|
|
103
106
|
case ConfigType.CONTENT: {
|
|
104
|
-
|
|
107
|
+
instance = new AppConfigContent(attrs);
|
|
108
|
+
break;
|
|
105
109
|
}
|
|
106
110
|
case ConfigType.NOTIFICATION: {
|
|
107
|
-
|
|
111
|
+
instance = new AppConfigNotification(attrs);
|
|
112
|
+
break;
|
|
108
113
|
}
|
|
109
114
|
case ConfigType.SETTING: {
|
|
110
|
-
|
|
115
|
+
instance = new AppConfigSetting(attrs);
|
|
116
|
+
break;
|
|
111
117
|
}
|
|
112
118
|
case ConfigType.WEBHOOK: {
|
|
113
|
-
|
|
119
|
+
instance = new AppConfigWebhook(attrs);
|
|
120
|
+
break;
|
|
114
121
|
}
|
|
115
122
|
case ConfigType.FRONTEND: {
|
|
116
|
-
|
|
123
|
+
instance = new AppConfigFrontend(attrs);
|
|
124
|
+
break;
|
|
117
125
|
}
|
|
118
126
|
case ConfigType.THEME: {
|
|
119
|
-
|
|
127
|
+
instance = new AppConfigTheme(attrs);
|
|
128
|
+
break;
|
|
120
129
|
}
|
|
121
130
|
case ConfigType.COMPONENT: {
|
|
122
|
-
|
|
131
|
+
instance = new AppConfigComponent(attrs);
|
|
132
|
+
break;
|
|
123
133
|
}
|
|
124
134
|
default: {
|
|
125
135
|
// the default type is file
|
|
126
136
|
const defaultConfig = new AppConfigDefault(attrs);
|
|
127
137
|
defaultConfig.type = attrs.type;
|
|
128
|
-
|
|
138
|
+
instance = defaultConfig;
|
|
139
|
+
break;
|
|
129
140
|
}
|
|
130
141
|
}
|
|
142
|
+
await instance.load();
|
|
143
|
+
return instance;
|
|
131
144
|
}
|
|
132
145
|
isRootConfig(configDir) {
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
146
|
+
const pos = this.filePath.startsWith(configDir + '/')
|
|
147
|
+
? configDir.length + 1
|
|
148
|
+
: 0;
|
|
149
|
+
return !this.filePath.includes('/', pos);
|
|
136
150
|
}
|
|
137
151
|
async postData() {
|
|
138
|
-
if (this.
|
|
152
|
+
if (this.fileData === undefined) {
|
|
139
153
|
return;
|
|
140
154
|
}
|
|
141
155
|
if (this.hasValues && this.filePath.endsWith('.json')) {
|
|
142
156
|
try {
|
|
143
|
-
this.values = JSON.parse(this.
|
|
157
|
+
this.values = JSON.parse(this.fileData.toString('utf8'));
|
|
144
158
|
}
|
|
145
159
|
catch {
|
|
146
160
|
throw new IgnoringFileError('Invalid JSON');
|
|
@@ -205,17 +219,16 @@ export class AppConfigContent extends AppConfig {
|
|
|
205
219
|
export class AppConfigNotification extends AppConfig {
|
|
206
220
|
hasValues = true;
|
|
207
221
|
type = ConfigType.NOTIFICATION;
|
|
208
|
-
preparePostData(postData) {
|
|
222
|
+
async preparePostData(postData) {
|
|
209
223
|
const isTemplate = this.isRootConfig('notifications') &&
|
|
210
224
|
(this.filePath.endsWith('.tpl') || this.filePath.endsWith('.liquid'));
|
|
211
225
|
if (isTemplate) {
|
|
212
226
|
// Get json config to match collection/model name
|
|
213
|
-
let jsonData;
|
|
214
227
|
try {
|
|
215
228
|
const jsonPath = this.filePath
|
|
216
229
|
.replace('.tpl', '.json')
|
|
217
230
|
.replace('.liquid', '.json');
|
|
218
|
-
jsonData = JSON.parse(fs.
|
|
231
|
+
const jsonData = JSON.parse(await fs.readFile(jsonPath, 'utf8'));
|
|
219
232
|
postData.values.collection = jsonData?.collection || jsonData?.model;
|
|
220
233
|
}
|
|
221
234
|
catch {
|
|
@@ -223,7 +236,7 @@ export class AppConfigNotification extends AppConfig {
|
|
|
223
236
|
}
|
|
224
237
|
postData.file = {
|
|
225
238
|
content_type: 'text/plain',
|
|
226
|
-
data: this.
|
|
239
|
+
data: this.fileData?.toString('utf8')?.replaceAll('\r\n', '\n'),
|
|
227
240
|
};
|
|
228
241
|
}
|
|
229
242
|
return postData;
|
|
@@ -350,16 +363,19 @@ export class AppConfigFrontend extends AppConfigDefault {
|
|
|
350
363
|
export class AppConfigTheme extends AppConfigDefault {
|
|
351
364
|
hasValues = false;
|
|
352
365
|
type = ConfigType.THEME;
|
|
353
|
-
preparePostData(postData) {
|
|
354
|
-
const isConfigJson = this.filePath
|
|
366
|
+
async preparePostData(postData) {
|
|
367
|
+
const isConfigJson = this.filePath && /^theme\/config\/[^./]+\.json$/.test(this.filePath);
|
|
355
368
|
// Files in theme/config/*.json are treated as settings with values
|
|
356
369
|
if (isConfigJson) {
|
|
357
370
|
try {
|
|
358
|
-
const jsonData = JSON.parse(fs.
|
|
371
|
+
const jsonData = JSON.parse(await fs.readFile(this.filePath, 'utf8'));
|
|
359
372
|
postData.values = jsonData;
|
|
360
373
|
}
|
|
361
|
-
catch {
|
|
362
|
-
//
|
|
374
|
+
catch (error) {
|
|
375
|
+
// If the file is not valid JSON, ignore it silently.
|
|
376
|
+
if (!(error instanceof SyntaxError)) {
|
|
377
|
+
throw error;
|
|
378
|
+
}
|
|
363
379
|
}
|
|
364
380
|
}
|
|
365
381
|
return postData;
|
package/dist/lib/apps/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
/// <reference types="node" />
|
|
2
|
-
/// <reference types="node" />
|
|
1
|
+
/// <reference types="node" resolution-mode="require"/>
|
|
2
|
+
/// <reference types="node" resolution-mode="require"/>
|
|
3
3
|
import { AppConfig } from './app-config.js';
|
|
4
4
|
export { AppConfig, FunctionProcessingError, IgnoringFileError, } from './app-config.js';
|
|
5
5
|
export { allBaseFilesInDir, allConfigDirsPaths, allConfigFilesInDir, allConfigFilesPaths, allConfigFilesPathsByType, getAllConfigPaths, globAllFilesByPath, isPathDirectory, } from './paths.js';
|
|
@@ -9,7 +9,7 @@ export declare const PUSH_CONCURRENCY = 3;
|
|
|
9
9
|
* configuration that developers define.
|
|
10
10
|
*/
|
|
11
11
|
export interface App {
|
|
12
|
-
categories?:
|
|
12
|
+
categories?: string[];
|
|
13
13
|
client?: any;
|
|
14
14
|
client_id?: string;
|
|
15
15
|
compatibilities?: {
|
|
@@ -19,8 +19,8 @@ export interface App {
|
|
|
19
19
|
date_created?: string;
|
|
20
20
|
date_updated?: string;
|
|
21
21
|
description?: string;
|
|
22
|
-
extensions?:
|
|
23
|
-
features?:
|
|
22
|
+
extensions?: any[];
|
|
23
|
+
features?: string[];
|
|
24
24
|
frontend?: {
|
|
25
25
|
deployment?: null | object;
|
|
26
26
|
deployment_hash?: string;
|
|
@@ -42,12 +42,13 @@ export interface App {
|
|
|
42
42
|
kind?: string;
|
|
43
43
|
logo_icon?: unknown;
|
|
44
44
|
name?: string;
|
|
45
|
+
owned?: boolean;
|
|
45
46
|
preview_image?: unknown;
|
|
46
47
|
preview_mobile_image?: unknown;
|
|
47
48
|
private_id?: string;
|
|
48
49
|
public_id?: string;
|
|
49
50
|
published?: boolean;
|
|
50
|
-
purchase_options?:
|
|
51
|
+
purchase_options?: string[];
|
|
51
52
|
storefront?: {
|
|
52
53
|
[key: string]: any;
|
|
53
54
|
};
|
|
@@ -63,7 +64,7 @@ export interface App {
|
|
|
63
64
|
[key: string]: any;
|
|
64
65
|
};
|
|
65
66
|
type?: string;
|
|
66
|
-
use_cases?:
|
|
67
|
+
use_cases?: string[];
|
|
67
68
|
version?: string;
|
|
68
69
|
}
|
|
69
70
|
export declare enum SwellJsonFields {
|
|
@@ -133,21 +134,21 @@ export declare const CUSTOM_FRAMEWORK_SLUG = "custom";
|
|
|
133
134
|
export declare const FrontendProjectTypes: FrontendProjectType[];
|
|
134
135
|
export declare function getFrontendProjectSlugs(withNone?: boolean, withLegacy?: boolean): string[];
|
|
135
136
|
export declare function getFrontendProjectValidValues(withNone?: boolean, withLegacy?: boolean): string;
|
|
136
|
-
export declare function getFrontendProjectType(appPath: string): FrontendProjectType | undefined
|
|
137
|
+
export declare function getFrontendProjectType(appPath: string): Promise<FrontendProjectType | undefined>;
|
|
137
138
|
/**
|
|
138
139
|
* Get project commands transformed for the detected package manager.
|
|
139
140
|
* Detects the package manager from lock files in appPath and transforms
|
|
140
141
|
* npm-style commands to the equivalent for that package manager.
|
|
141
142
|
*/
|
|
142
|
-
export declare function getProjectCommands(appPath: string, projectType: FrontendProjectType): {
|
|
143
|
+
export declare function getProjectCommands(appPath: string, projectType: FrontendProjectType): Promise<{
|
|
143
144
|
buildCommand?: string;
|
|
144
145
|
devCommand: string;
|
|
145
|
-
}
|
|
146
|
+
}>;
|
|
146
147
|
/**
|
|
147
148
|
* Get a suggested dev command for an unrecognized frontend project,
|
|
148
149
|
* translated for the detected package manager.
|
|
149
150
|
*/
|
|
150
|
-
export declare function getManualDevHint(appPath: string, port: number): string
|
|
151
|
+
export declare function getManualDevHint(appPath: string, port: number): Promise<string>;
|
|
151
152
|
export declare function getConfigTypeFromPath(path: string): ConfigType | undefined;
|
|
152
153
|
export declare function getConfigTypeKeyFromValue(value: string): string | undefined;
|
|
153
154
|
export declare function filePathExists(filePath: string): boolean;
|
|
@@ -157,8 +158,8 @@ export declare function deleteFile(file: string): Promise<void>;
|
|
|
157
158
|
export declare function writeJsonFile(file: string, data?: any): Promise<void>;
|
|
158
159
|
export declare function hashFile(filePath: string, fileContents?: Buffer, relativePath?: string): string;
|
|
159
160
|
export declare function hashString(...contents: (Buffer | string)[]): string;
|
|
160
|
-
export declare function appAssetImage(appPath: string, fileName: string): string | undefined
|
|
161
|
-
export declare function appConfigFromFile(filePath: string, configType: ConfigType, appPath: string): AppConfig
|
|
161
|
+
export declare function appAssetImage(appPath: string, fileName: string): Promise<string | undefined>;
|
|
162
|
+
export declare function appConfigFromFile(filePath: string, configType: ConfigType, appPath: string): Promise<AppConfig>;
|
|
162
163
|
export declare function findAppConfig(app: App, filePath: string, configType: ConfigType): AppConfig | undefined;
|
|
163
164
|
interface BatchAppFiles {
|
|
164
165
|
configs: AppConfig[];
|
|
@@ -173,5 +174,5 @@ interface BatchAppFiles {
|
|
|
173
174
|
* @returns {BatchAppFiles[]} Batches of files to push
|
|
174
175
|
*/
|
|
175
176
|
export declare function batchAppFilesByType(configs: AppConfig[]): BatchAppFiles[];
|
|
176
|
-
export declare function hasAppContext(): boolean
|
|
177
|
+
export declare function hasAppContext(): Promise<boolean>;
|
|
177
178
|
export declare function getCurrentAppSlugId(): Promise<string | undefined>;
|
package/dist/lib/apps/index.js
CHANGED
|
@@ -205,18 +205,20 @@ export function getFrontendProjectSlugs(withNone = true, withLegacy = true) {
|
|
|
205
205
|
export function getFrontendProjectValidValues(withNone = true, withLegacy = true) {
|
|
206
206
|
return getFrontendProjectSlugs(withNone, withLegacy).join(', ');
|
|
207
207
|
}
|
|
208
|
-
export function getFrontendProjectType(appPath) {
|
|
208
|
+
export async function getFrontendProjectType(appPath) {
|
|
209
209
|
// Try frontend/package.json first (workspace structure), then root package.json (legacy)
|
|
210
210
|
const pkgPaths = [
|
|
211
211
|
path.join(appPath, 'frontend', 'package.json'),
|
|
212
212
|
path.join(appPath, 'package.json'),
|
|
213
213
|
];
|
|
214
214
|
for (const pkgPath of pkgPaths) {
|
|
215
|
-
|
|
215
|
+
// eslint-disable-next-line no-await-in-loop
|
|
216
|
+
if (!(await filePathExistsAsync(pkgPath))) {
|
|
216
217
|
continue;
|
|
217
218
|
}
|
|
218
219
|
try {
|
|
219
|
-
|
|
220
|
+
// eslint-disable-next-line no-await-in-loop
|
|
221
|
+
const content = await fs.promises.readFile(pkgPath, 'utf8');
|
|
220
222
|
const pkg = JSON.parse(content);
|
|
221
223
|
for (const projectType of FrontendProjectTypes) {
|
|
222
224
|
if (pkg.dependencies?.[projectType.mainPackage] ||
|
|
@@ -242,9 +244,16 @@ export function getFrontendProjectType(appPath) {
|
|
|
242
244
|
};
|
|
243
245
|
}
|
|
244
246
|
}
|
|
245
|
-
catch {
|
|
247
|
+
catch (error) {
|
|
246
248
|
// Ignore JSON parse errors, try next path
|
|
247
|
-
|
|
249
|
+
if (error instanceof SyntaxError) {
|
|
250
|
+
continue;
|
|
251
|
+
}
|
|
252
|
+
// Ignore file not found errors, try next path
|
|
253
|
+
if (error.code === 'ENOENT') {
|
|
254
|
+
continue;
|
|
255
|
+
}
|
|
256
|
+
throw error;
|
|
248
257
|
}
|
|
249
258
|
}
|
|
250
259
|
return undefined;
|
|
@@ -254,8 +263,8 @@ export function getFrontendProjectType(appPath) {
|
|
|
254
263
|
* Detects the package manager from lock files in appPath and transforms
|
|
255
264
|
* npm-style commands to the equivalent for that package manager.
|
|
256
265
|
*/
|
|
257
|
-
export function getProjectCommands(appPath, projectType) {
|
|
258
|
-
const pm = detectPackageManager(appPath);
|
|
266
|
+
export async function getProjectCommands(appPath, projectType) {
|
|
267
|
+
const pm = await detectPackageManager(appPath);
|
|
259
268
|
return {
|
|
260
269
|
buildCommand: projectType.buildCommand
|
|
261
270
|
? transformCommand(projectType.buildCommand, pm)
|
|
@@ -267,12 +276,12 @@ export function getProjectCommands(appPath, projectType) {
|
|
|
267
276
|
* Get a suggested dev command for an unrecognized frontend project,
|
|
268
277
|
* translated for the detected package manager.
|
|
269
278
|
*/
|
|
270
|
-
export function getManualDevHint(appPath, port) {
|
|
271
|
-
const pm = detectPackageManager(appPath);
|
|
279
|
+
export async function getManualDevHint(appPath, port) {
|
|
280
|
+
const pm = await detectPackageManager(appPath);
|
|
272
281
|
return transformCommand(`npm run dev -- --port ${port}`, pm);
|
|
273
282
|
}
|
|
274
283
|
export function getConfigTypeFromPath(path) {
|
|
275
|
-
for (const type
|
|
284
|
+
for (const type of Object.keys(AllConfigPaths)) {
|
|
276
285
|
if (AllConfigPaths[type] === path) {
|
|
277
286
|
const configType = ConfigType[type];
|
|
278
287
|
return configType;
|
|
@@ -343,12 +352,12 @@ export function hashString(...contents) {
|
|
|
343
352
|
}
|
|
344
353
|
return hash.digest('hex', { length: 16 });
|
|
345
354
|
}
|
|
346
|
-
export function appAssetImage(appPath, fileName) {
|
|
355
|
+
export async function appAssetImage(appPath, fileName) {
|
|
347
356
|
const assetsDirPath = path.join(appPath, AllConfigPaths['ASSET']);
|
|
348
|
-
if (!
|
|
357
|
+
if (!(await filePathExistsAsync(assetsDirPath))) {
|
|
349
358
|
return;
|
|
350
359
|
}
|
|
351
|
-
for (const configFile of fs.
|
|
360
|
+
for (const configFile of await fs.promises.readdir(assetsDirPath)) {
|
|
352
361
|
if (path.parse(configFile).name === fileName) {
|
|
353
362
|
return path.join(assetsDirPath, configFile);
|
|
354
363
|
}
|
|
@@ -357,7 +366,7 @@ export function appAssetImage(appPath, fileName) {
|
|
|
357
366
|
function getNameFromFilePath(filePath) {
|
|
358
367
|
return path.parse(filePath).name.replaceAll('_', '-');
|
|
359
368
|
}
|
|
360
|
-
export function appConfigFromFile(filePath, configType, appPath) {
|
|
369
|
+
export async function appConfigFromFile(filePath, configType, appPath) {
|
|
361
370
|
const name = getNameFromFilePath(filePath);
|
|
362
371
|
// Notification basenames must not contain dots: the inspect identifier
|
|
363
372
|
// grammar (app.<slug>.<model>.<name>) splits on '.', so a dotted name
|
|
@@ -365,7 +374,7 @@ export function appConfigFromFile(filePath, configType, appPath) {
|
|
|
365
374
|
if (configType === ConfigType.NOTIFICATION && name.includes('.')) {
|
|
366
375
|
throw new Error(`Notification file '${filePath}': basename cannot contain '.'. Rename the file.`);
|
|
367
376
|
}
|
|
368
|
-
const config = AppConfig.create({
|
|
377
|
+
const config = await AppConfig.create({
|
|
369
378
|
name,
|
|
370
379
|
filePath,
|
|
371
380
|
appPath,
|
|
@@ -390,10 +399,10 @@ export function findAppConfig(app, filePath, configType) {
|
|
|
390
399
|
* @returns {BatchAppFiles[]} Batches of files to push
|
|
391
400
|
*/
|
|
392
401
|
export function batchAppFilesByType(configs) {
|
|
393
|
-
const modelsWithExtends = configs.filter((config) => config.type ===
|
|
394
|
-
const modelsWithoutExtends = configs.filter((config) => config.type ===
|
|
395
|
-
const contentTypesWithCollection = configs.filter((config) => config.type ===
|
|
396
|
-
const contentTypesWithoutCollection = configs.filter((config) => config.type ===
|
|
402
|
+
const modelsWithExtends = configs.filter((config) => config.type === ConfigType.MODEL && config.values.extends);
|
|
403
|
+
const modelsWithoutExtends = configs.filter((config) => config.type === ConfigType.MODEL && !config.values.extends);
|
|
404
|
+
const contentTypesWithCollection = configs.filter((config) => config.type === ConfigType.CONTENT && config.values.collection);
|
|
405
|
+
const contentTypesWithoutCollection = configs.filter((config) => config.type === ConfigType.CONTENT && !config.values.collection);
|
|
397
406
|
const prioritized = new Set([
|
|
398
407
|
...modelsWithExtends,
|
|
399
408
|
...modelsWithoutExtends,
|
|
@@ -424,17 +433,25 @@ export function batchAppFilesByType(configs) {
|
|
|
424
433
|
return batches;
|
|
425
434
|
}
|
|
426
435
|
export function hasAppContext() {
|
|
427
|
-
return
|
|
436
|
+
return filePathExistsAsync('swell.json');
|
|
428
437
|
}
|
|
429
438
|
export async function getCurrentAppSlugId() {
|
|
430
|
-
if (!hasAppContext()) {
|
|
439
|
+
if (!(await hasAppContext())) {
|
|
431
440
|
return;
|
|
432
441
|
}
|
|
433
442
|
try {
|
|
434
443
|
const appConfig = JSON.parse(await fs.promises.readFile('swell.json', 'utf8'));
|
|
435
444
|
return appConfig.id;
|
|
436
445
|
}
|
|
437
|
-
catch {
|
|
438
|
-
//
|
|
446
|
+
catch (error) {
|
|
447
|
+
// Ignore JSON parse error
|
|
448
|
+
if (error instanceof SyntaxError) {
|
|
449
|
+
return;
|
|
450
|
+
}
|
|
451
|
+
// Ignore error when swell.json does not exists
|
|
452
|
+
if (error.code === 'ENOENT') {
|
|
453
|
+
return;
|
|
454
|
+
}
|
|
455
|
+
throw error;
|
|
439
456
|
}
|
|
440
457
|
}
|
package/dist/lib/apps/paths.d.ts
CHANGED
|
@@ -23,4 +23,4 @@ export declare function allConfigFilesInDir(appPath: string, dirPath: string, co
|
|
|
23
23
|
}, void, unknown>;
|
|
24
24
|
export declare function allBaseFilesInDir(appPath: string): Generator<string, void, unknown>;
|
|
25
25
|
export declare function getAllConfigPaths(appType: string): string[];
|
|
26
|
-
export declare function isPathDirectory(path: string): boolean
|
|
26
|
+
export declare function isPathDirectory(path: string): Promise<boolean>;
|
package/dist/lib/apps/paths.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { globby, globbySync, isGitIgnored, } from 'globby';
|
|
2
|
-
import * as fs from 'node:fs';
|
|
2
|
+
import * as fs from 'node:fs/promises';
|
|
3
3
|
import * as path from 'node:path';
|
|
4
4
|
import { AllConfigPaths, ConfigType, StandardConfigPaths, StorefrontConfigPaths, ThemeConfigPaths, filePathExists, } from './index.js';
|
|
5
5
|
function globOptions(appPath, options) {
|
|
@@ -99,9 +99,9 @@ export function getAllConfigPaths(appType) {
|
|
|
99
99
|
}
|
|
100
100
|
return configPaths;
|
|
101
101
|
}
|
|
102
|
-
export function isPathDirectory(path) {
|
|
102
|
+
export async function isPathDirectory(path) {
|
|
103
103
|
try {
|
|
104
|
-
const stat = fs.
|
|
104
|
+
const stat = await fs.stat(path);
|
|
105
105
|
return stat.isDirectory();
|
|
106
106
|
}
|
|
107
107
|
catch {
|