@swell/cli 1.0.2 → 2.0.1-alpha.2

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.
Files changed (105) hide show
  1. package/LICENSE.md +21 -0
  2. package/README.md +2 -140
  3. package/bin/dev.cmd +3 -0
  4. package/bin/dev.js +7 -0
  5. package/bin/run.cmd +3 -0
  6. package/bin/run.js +7 -0
  7. package/dist/app-command.d.ts +22 -0
  8. package/dist/app-command.js +45 -0
  9. package/dist/commands/app/_pull.d.ts +8 -0
  10. package/dist/commands/app/_pull.js +45 -0
  11. package/dist/commands/app/_uninstall.d.ts +12 -0
  12. package/dist/commands/app/_uninstall.js +45 -0
  13. package/dist/commands/app/info.d.ts +15 -0
  14. package/dist/commands/app/info.js +92 -0
  15. package/dist/commands/app/install.d.ts +17 -0
  16. package/dist/commands/app/install.js +177 -0
  17. package/dist/commands/app/push.d.ts +17 -0
  18. package/dist/commands/app/push.js +158 -0
  19. package/dist/commands/app/version.d.ts +18 -0
  20. package/dist/commands/app/version.js +156 -0
  21. package/dist/commands/app/watch.d.ts +15 -0
  22. package/dist/commands/app/watch.js +110 -0
  23. package/dist/commands/create/app.d.ts +21 -0
  24. package/dist/commands/create/app.js +210 -0
  25. package/dist/commands/create/content.d.ts +19 -0
  26. package/dist/commands/create/content.js +87 -0
  27. package/dist/commands/create/function.d.ts +25 -0
  28. package/dist/commands/create/function.js +191 -0
  29. package/dist/commands/create/index.d.ts +6 -0
  30. package/dist/commands/create/index.js +34 -0
  31. package/dist/commands/create/model.d.ts +19 -0
  32. package/dist/commands/create/model.js +87 -0
  33. package/dist/commands/create/notification.d.ts +25 -0
  34. package/dist/commands/create/notification.js +170 -0
  35. package/dist/commands/login.d.ts +22 -0
  36. package/dist/commands/login.js +77 -0
  37. package/dist/commands/logout.d.ts +8 -0
  38. package/dist/commands/logout.js +45 -0
  39. package/dist/commands/logs.d.ts +23 -0
  40. package/dist/commands/logs.js +207 -0
  41. package/dist/commands/switch.d.ts +10 -0
  42. package/dist/commands/switch.js +41 -0
  43. package/dist/commands/whoami.d.ts +7 -0
  44. package/dist/commands/whoami.js +24 -0
  45. package/dist/create-collection-command.d.ts +26 -0
  46. package/dist/create-collection-command.js +97 -0
  47. package/dist/create-command.d.ts +16 -0
  48. package/dist/create-command.js +59 -0
  49. package/dist/index.d.ts +1 -0
  50. package/dist/index.js +1 -0
  51. package/dist/lib/api.d.ts +13 -0
  52. package/dist/lib/api.js +117 -0
  53. package/dist/lib/app-config.d.ts +29 -0
  54. package/dist/lib/app-config.js +127 -0
  55. package/dist/lib/apps/app-config.d.ts +42 -0
  56. package/dist/lib/apps/app-config.js +167 -0
  57. package/dist/lib/apps/index.d.ts +67 -0
  58. package/dist/lib/apps/index.js +167 -0
  59. package/dist/lib/apps/paths.d.ts +18 -0
  60. package/dist/lib/apps/paths.js +54 -0
  61. package/dist/lib/bundle.d.ts +1 -0
  62. package/dist/lib/bundle.js +40 -0
  63. package/dist/lib/config.d.ts +37 -0
  64. package/dist/lib/config.js +131 -0
  65. package/dist/lib/constants.d.ts +5 -0
  66. package/dist/lib/constants.js +17 -0
  67. package/dist/lib/create/content.d.ts +23 -0
  68. package/dist/lib/create/content.js +40 -0
  69. package/dist/lib/create/function.d.ts +17 -0
  70. package/dist/lib/create/function.js +36 -0
  71. package/dist/lib/create/index.d.ts +13 -0
  72. package/dist/lib/create/index.js +20 -0
  73. package/dist/lib/create/model.d.ts +22 -0
  74. package/dist/lib/create/model.js +30 -0
  75. package/dist/lib/create/notification.d.ts +25 -0
  76. package/dist/lib/create/notification.js +1 -0
  77. package/dist/lib/info.d.ts +38 -0
  78. package/dist/lib/info.js +91 -0
  79. package/dist/lib/logs/index.d.ts +23 -0
  80. package/dist/lib/logs/index.js +88 -0
  81. package/dist/lib/logs/line-output.d.ts +5 -0
  82. package/dist/lib/logs/line-output.js +13 -0
  83. package/dist/lib/logs/output.d.ts +7 -0
  84. package/dist/lib/logs/output.js +8 -0
  85. package/dist/lib/logs/table-output.d.ts +11 -0
  86. package/dist/lib/logs/table-output.js +128 -0
  87. package/dist/lib/sessions.d.ts +9 -0
  88. package/dist/lib/sessions.js +110 -0
  89. package/dist/lib/stores.d.ts +63 -0
  90. package/dist/lib/stores.js +173 -0
  91. package/dist/lib/style.d.ts +24 -0
  92. package/dist/lib/style.js +29 -0
  93. package/dist/lib/swell-function-wrapper.d.ts +88 -0
  94. package/dist/lib/swell-function-wrapper.js +302 -0
  95. package/dist/remote-app-command.d.ts +36 -0
  96. package/dist/remote-app-command.js +367 -0
  97. package/dist/swell-command.d.ts +21 -0
  98. package/dist/swell-command.js +43 -0
  99. package/oclif.manifest.json +1085 -0
  100. package/package.json +81 -43
  101. package/LICENSE +0 -674
  102. package/dist/bin/multipart-parser-85ef9626.js +0 -456
  103. package/dist/bin/swell-0f71f07d.js +0 -30670
  104. package/dist/bin/swell.js +0 -24
  105. package/dist/man/swell.1 +0 -85
@@ -0,0 +1,167 @@
1
+ /* eslint-disable camelcase */
2
+ import isEmpty from 'lodash/isEmpty.js';
3
+ import * as fs from 'node:fs';
4
+ import * as path from 'node:path';
5
+ import { bundleFunction } from '../bundle.js';
6
+ import { ConfigType } from './index.js';
7
+ class IgnoringFileError extends Error {
8
+ constructor(message) {
9
+ super(message);
10
+ this.name = 'IgnoringFileError';
11
+ }
12
+ }
13
+ class FunctionProcessingError extends Error {
14
+ originalError;
15
+ constructor(message, error) {
16
+ super(message);
17
+ this.name = 'FunctionProcessingError';
18
+ this.originalError = error;
19
+ }
20
+ }
21
+ /**
22
+ * An app configuration as defined by the Swell API. This implies that the
23
+ * app & the configuration are saved to the API.
24
+ */
25
+ class AppConfig {
26
+ date_created;
27
+ file;
28
+ fileData;
29
+ id;
30
+ /** The local path of a remote AppConfig */
31
+ localPath;
32
+ name;
33
+ parent_id;
34
+ slug;
35
+ values = {};
36
+ constructor(attrs = {}) {
37
+ Object.assign(this, attrs);
38
+ const { localPath } = attrs;
39
+ if (localPath) {
40
+ this.fileData = fs.readFileSync(localPath, 'utf8');
41
+ }
42
+ }
43
+ static create(attrs = {}) {
44
+ switch (attrs.type) {
45
+ case ConfigType.ASSET: {
46
+ return new AppConfigAsset(attrs);
47
+ }
48
+ case ConfigType.FUNCTION: {
49
+ return new AppConfigFunction(attrs);
50
+ }
51
+ case ConfigType.MODEL: {
52
+ return new AppConfigModel(attrs);
53
+ }
54
+ 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
+ return new AppConfigNotification(attrs);
60
+ }
61
+ default: {
62
+ // the default type is content so we want to make sure
63
+ // that we set the expected type
64
+ const defaultConfig = new AppConfigDefault(attrs);
65
+ defaultConfig.type = attrs.type;
66
+ return defaultConfig;
67
+ }
68
+ }
69
+ }
70
+ async postData() {
71
+ if (!this.localPath || !this.fileData) {
72
+ throw new Error('Missing local config path');
73
+ }
74
+ if (this.localPath.endsWith('.json')) {
75
+ try {
76
+ this.values = JSON.parse(this.fileData);
77
+ }
78
+ catch {
79
+ throw new IgnoringFileError('invalid JSON');
80
+ }
81
+ if (isEmpty(this.values)) {
82
+ throw new IgnoringFileError('empty JSON');
83
+ }
84
+ }
85
+ const postData = {
86
+ name: this.values?.name || this.name,
87
+ type: this.type,
88
+ values: this.values,
89
+ };
90
+ return this.preparePostData(postData);
91
+ }
92
+ }
93
+ class AppConfigDefault extends AppConfig {
94
+ type = ConfigType.CONTENT;
95
+ preparePostData(postData) {
96
+ return postData;
97
+ }
98
+ }
99
+ class AppConfigModel extends AppConfig {
100
+ type = ConfigType.MODEL;
101
+ preparePostData(postData) {
102
+ postData.values.collection = this.name;
103
+ return postData;
104
+ }
105
+ }
106
+ class AppConfigNotification extends AppConfig {
107
+ type = ConfigType.NOTIFICATION;
108
+ /**
109
+ * The actual config path is the path to the JSON file that is used to
110
+ * configure the notification. This function ensures that the path is
111
+ * correct.
112
+ *
113
+ * @param localPath - json or tpl file path
114
+ * @returns - json file path
115
+ */
116
+ static actualConfigPath(localPath) {
117
+ return localPath?.replace('.tpl', '.json');
118
+ }
119
+ preparePostData(postData) {
120
+ if (!this.localPath) {
121
+ throw new Error('Missing local config path');
122
+ }
123
+ const templateFile = this.localPath.replace('.json', '.tpl');
124
+ this.fileData = fs.readFileSync(templateFile, 'utf8');
125
+ if (this.fileData) {
126
+ postData.values.content = {
127
+ html: {
128
+ data: this.fileData.replaceAll('\r\n', '\n'),
129
+ },
130
+ };
131
+ }
132
+ return postData;
133
+ }
134
+ }
135
+ class AppConfigFunction extends AppConfig {
136
+ type = ConfigType.FUNCTION;
137
+ async preparePostData(postData) {
138
+ if (!this.localPath) {
139
+ throw new Error('Missing local config path');
140
+ }
141
+ try {
142
+ const { code, config } = await bundleFunction(this.localPath);
143
+ if (!config) {
144
+ throw new IgnoringFileError('Function must export a `config` object.');
145
+ }
146
+ const fileName = path.basename(this.localPath);
147
+ postData.file = {
148
+ data: code,
149
+ // we keep the file extension so we can easily identify the file path
150
+ // when we need to delete the function
151
+ ext: fileName.replace(this.name, ''),
152
+ };
153
+ postData.values = config;
154
+ }
155
+ catch (error) {
156
+ throw new FunctionProcessingError(`Unable to compile function ${this.name}`, error);
157
+ }
158
+ return postData;
159
+ }
160
+ }
161
+ class AppConfigAsset extends AppConfig {
162
+ type = ConfigType.ASSET;
163
+ preparePostData(_postData) {
164
+ throw new Error('Assets not yet supported');
165
+ }
166
+ }
167
+ export { AppConfig, FunctionProcessingError, IgnoringFileError };
@@ -0,0 +1,67 @@
1
+ import { AppConfig } from './app-config.js';
2
+ /**
3
+ * An app as defined by the Swell API. This is different than an app
4
+ * configuration that developers define.
5
+ */
6
+ type App = {
7
+ client?: any;
8
+ client_id?: string;
9
+ configs?: AppConfig[];
10
+ date_created?: string;
11
+ date_updated?: string;
12
+ description?: string;
13
+ id?: string;
14
+ installed?: boolean;
15
+ name?: string;
16
+ private_id?: string;
17
+ public_id?: string;
18
+ published?: boolean;
19
+ version?: string;
20
+ };
21
+ type AppVersion = {
22
+ date_created: string;
23
+ id: string;
24
+ name: string;
25
+ notes: string;
26
+ version: string;
27
+ };
28
+ declare enum ConfigType {
29
+ ASSET = "asset",
30
+ CONTENT = "content",
31
+ FUNCTION = "function",
32
+ MODEL = "model",
33
+ NOTIFICATION = "notification",
34
+ SETTING = "setting",
35
+ WEBHOOK = "webhook"
36
+ }
37
+ type ConfigPathsType = {
38
+ [key in ConfigType]: string;
39
+ };
40
+ declare const ConfigPaths: ConfigPathsType;
41
+ declare enum ConfigInputFields {
42
+ FILE = "file",
43
+ NAME = "name",
44
+ TYPE = "type",
45
+ VALUES = "values",
46
+ VERSION = "version"
47
+ }
48
+ declare function hasAllowedFileExtension(file: string, configType?: ConfigType): boolean;
49
+ declare function getConfigTypeFromPath(path: string): ConfigType | undefined;
50
+ declare function getConfigTypeKeyFromValue(value: string): string | undefined;
51
+ declare function fileExists(filePath: string): boolean;
52
+ declare function writeFile(file: string, data: string): Promise<void>;
53
+ declare function writeJsonFile(file: string, data?: any): Promise<void>;
54
+ declare function appLogoIcon(appPath: string): string | undefined;
55
+ declare function isAppLogoIcon(file: string): boolean;
56
+ declare function appConfigFromFile(configFile: string, configType: ConfigType): AppConfig;
57
+ declare function findAppConfig(app: App, file: string, configType: ConfigType): AppConfig | undefined;
58
+ /**
59
+ * Get files to push in batches prioritized by dependencies
60
+ *
61
+ * @param appConfigs - List of app configs
62
+ * @returns {Array} Batches of files to push
63
+ */
64
+ declare function batchAppConfigsByType(appConfigs: AppConfig[]): Array<any>;
65
+ export { App, AppVersion, ConfigInputFields, ConfigPaths, ConfigPathsType, ConfigType, appConfigFromFile, appLogoIcon, batchAppConfigsByType, fileExists, findAppConfig, getConfigTypeFromPath, getConfigTypeKeyFromValue, hasAllowedFileExtension, isAppLogoIcon, writeFile, writeJsonFile, };
66
+ export { AppConfig, FunctionProcessingError, IgnoringFileError, } from './app-config.js';
67
+ export { allConfigDirsPaths, allConfigFilesPaths, allConfigFilesPathsByType, getAllConfigPaths, configFilePath, } from './paths.js';
@@ -0,0 +1,167 @@
1
+ import { pluralize, titleize } from 'inflection';
2
+ import * as fs from 'node:fs';
3
+ import * as path from 'node:path';
4
+ import { appConfigFileExists } from '../app-config.js';
5
+ import { AppConfig } from './app-config.js';
6
+ var ConfigType;
7
+ (function (ConfigType) {
8
+ ConfigType["ASSET"] = "asset";
9
+ ConfigType["CONTENT"] = "content";
10
+ ConfigType["FUNCTION"] = "function";
11
+ ConfigType["MODEL"] = "model";
12
+ ConfigType["NOTIFICATION"] = "notification";
13
+ ConfigType["SETTING"] = "setting";
14
+ ConfigType["WEBHOOK"] = "webhook";
15
+ })(ConfigType || (ConfigType = {}));
16
+ // Models and content should come first in order
17
+ const ConfigTypeBatchOrder = [
18
+ ConfigType.MODEL,
19
+ ConfigType.CONTENT,
20
+ ConfigType.ASSET,
21
+ ConfigType.FUNCTION,
22
+ ConfigType.NOTIFICATION,
23
+ ConfigType.SETTING,
24
+ ConfigType.WEBHOOK,
25
+ ];
26
+ const ConfigPaths = {
27
+ ...Object.fromEntries(Object.keys(ConfigType).map((type) => [
28
+ type,
29
+ // a bit of a hack to make the path singular for content configs
30
+ // need to refactor this to a function if we add more exceptions
31
+ type === 'CONTENT' ? 'content' : pluralize(type.toLowerCase()),
32
+ ])),
33
+ };
34
+ var ConfigInputFields;
35
+ (function (ConfigInputFields) {
36
+ ConfigInputFields["FILE"] = "file";
37
+ ConfigInputFields["NAME"] = "name";
38
+ ConfigInputFields["TYPE"] = "type";
39
+ ConfigInputFields["VALUES"] = "values";
40
+ ConfigInputFields["VERSION"] = "version";
41
+ })(ConfigInputFields || (ConfigInputFields = {}));
42
+ function hasAllowedFileExtension(file, configType) {
43
+ let allowedFileExtensions = new Set([
44
+ '.js',
45
+ '.json',
46
+ '.tpl',
47
+ '.ts',
48
+ ]);
49
+ if (configType === ConfigType.NOTIFICATION) {
50
+ allowedFileExtensions = new Set(['.json']);
51
+ }
52
+ return allowedFileExtensions.has(path.parse(file).ext);
53
+ }
54
+ function getConfigTypeFromPath(path) {
55
+ for (const type in ConfigPaths) {
56
+ if (ConfigPaths[type] === path) {
57
+ const configType = ConfigType[type];
58
+ return configType;
59
+ }
60
+ }
61
+ return undefined;
62
+ }
63
+ function getConfigTypeKeyFromValue(value) {
64
+ return Object.keys(ConfigType).find((key) => ConfigType[key] === value);
65
+ }
66
+ function fileExists(filePath) {
67
+ try {
68
+ // eslint-disable-next-line no-bitwise
69
+ fs.accessSync(filePath, fs.constants.R_OK | fs.constants.W_OK);
70
+ return true;
71
+ }
72
+ catch (error) {
73
+ if (error.code !== 'ENOENT') {
74
+ throw error;
75
+ }
76
+ return false;
77
+ }
78
+ }
79
+ function writeFile(file, data) {
80
+ return new Promise((resolve, _reject) => {
81
+ fs.mkdir(path.dirname(file), { recursive: true }, (error) => {
82
+ if (error) {
83
+ throw error;
84
+ }
85
+ fs.writeFile(file, data, (error) => {
86
+ if (error) {
87
+ throw error;
88
+ }
89
+ resolve();
90
+ });
91
+ });
92
+ });
93
+ }
94
+ async function writeJsonFile(file, data = {}) {
95
+ return writeFile(file, `${JSON.stringify(data, null, 2)}\n`);
96
+ }
97
+ function appLogoIcon(appPath) {
98
+ const assetsDirPath = path.join(appPath, ConfigPaths['ASSET']);
99
+ if (!appConfigFileExists(assetsDirPath)) {
100
+ return;
101
+ }
102
+ for (const configFile of fs.readdirSync(assetsDirPath)) {
103
+ if (isAppLogoIcon(configFile)) {
104
+ return path.join(assetsDirPath, configFile);
105
+ }
106
+ }
107
+ }
108
+ function isAppLogoIcon(file) {
109
+ return path.parse(file).name === 'icon';
110
+ }
111
+ function appConfigFromFile(configFile, configType) {
112
+ const { name } = path.parse(configFile);
113
+ const appConfig = AppConfig.create({
114
+ localPath: configFile,
115
+ name,
116
+ type: configType,
117
+ values: {},
118
+ });
119
+ return appConfig;
120
+ }
121
+ function findAppConfig(app, file, configType) {
122
+ const { name } = path.parse(file);
123
+ const config = app?.configs?.find((c) => c && c.type === configType && c.name === name);
124
+ return config;
125
+ }
126
+ /**
127
+ * Get files to push in batches prioritized by dependencies
128
+ *
129
+ * @param appConfigs - List of app configs
130
+ * @returns {Array} Batches of files to push
131
+ */
132
+ function batchAppConfigsByType(appConfigs) {
133
+ const modelsWithExtends = appConfigs.filter((item) => item.type === 'model' && item.values.extends);
134
+ const modelsWithoutExtends = appConfigs.filter((item) => item.type === 'model' && !item.values.extends);
135
+ const contentTypesWithCollection = appConfigs.filter((item) => item.type === 'content' && item.values.collection);
136
+ const contentTypesWithoutCollection = appConfigs.filter((item) => item.type === 'content' && !item.values.collection);
137
+ const prioritized = [
138
+ ...modelsWithExtends,
139
+ ...modelsWithoutExtends,
140
+ ...contentTypesWithCollection,
141
+ ...contentTypesWithoutCollection,
142
+ ];
143
+ const sorted = [
144
+ ...prioritized,
145
+ ...appConfigs.filter((item) => !prioritized.includes(item)),
146
+ ];
147
+ const batches = [];
148
+ // eslint-disable-next-line guard-for-in
149
+ for (const key in ConfigTypeBatchOrder) {
150
+ const configType = ConfigTypeBatchOrder[key];
151
+ const configsByType = sorted.filter((item) => item.type === configType);
152
+ if (configsByType.length === 0) {
153
+ continue;
154
+ }
155
+ batches.push({
156
+ configs: configsByType,
157
+ label: titleize(configType),
158
+ type: configType,
159
+ });
160
+ }
161
+ return batches;
162
+ }
163
+ export { ConfigInputFields, ConfigPaths, ConfigType,
164
+ // functions
165
+ appConfigFromFile, appLogoIcon, batchAppConfigsByType, fileExists, findAppConfig, getConfigTypeFromPath, getConfigTypeKeyFromValue, hasAllowedFileExtension, isAppLogoIcon, writeFile, writeJsonFile, };
166
+ export { AppConfig, FunctionProcessingError, IgnoringFileError, } from './app-config.js';
167
+ export { allConfigDirsPaths, allConfigFilesPaths, allConfigFilesPathsByType, getAllConfigPaths, configFilePath, } from './paths.js';
@@ -0,0 +1,18 @@
1
+ import { AppConfig, ConfigType } from './index.js';
2
+ declare function allConfigDirsPaths(appPath: string): Generator<{
3
+ configDirPath: string;
4
+ configType: ConfigType;
5
+ }>;
6
+ declare function allConfigFilesPaths(appPath: string): Generator<{
7
+ configDirPath: string;
8
+ configFile: string;
9
+ configType: ConfigType;
10
+ }, void, unknown>;
11
+ declare function allConfigFilesPathsByType(appPath: string, configTypeKey: string): Generator<{
12
+ configDirPath: string;
13
+ configFile: string;
14
+ configType: ConfigType;
15
+ }, void, unknown>;
16
+ declare function configFilePath(appPath: string, config: AppConfig): string;
17
+ declare function getAllConfigPaths(): Array<string>;
18
+ export { allConfigDirsPaths, allConfigFilesPaths, allConfigFilesPathsByType, getAllConfigPaths, configFilePath, };
@@ -0,0 +1,54 @@
1
+ import * as fs from 'node:fs';
2
+ import * as path from 'node:path';
3
+ import { appConfigFileExists } from '../app-config.js';
4
+ import { ConfigPaths, ConfigType, hasAllowedFileExtension, } from './index.js';
5
+ function* allConfigDirsPaths(appPath) {
6
+ for (const type in ConfigType) {
7
+ if (Object.prototype.hasOwnProperty.call(ConfigType, type)) {
8
+ const configType = ConfigType[type];
9
+ const configPath = ConfigPaths[type];
10
+ const configDirPath = path.join(appPath, configPath);
11
+ if (appConfigFileExists(configDirPath)) {
12
+ yield { configDirPath, configType };
13
+ }
14
+ }
15
+ }
16
+ }
17
+ function* allConfigFilesPaths(appPath) {
18
+ for (const { configDirPath, configType } of allConfigDirsPaths(appPath)) {
19
+ yield* allConfigFilesInDir(configDirPath, configType);
20
+ }
21
+ }
22
+ function* allConfigFilesPathsByType(appPath, configTypeKey) {
23
+ const configPath = ConfigPaths[configTypeKey];
24
+ const configDirPath = path.join(appPath, configPath);
25
+ yield* allConfigFilesInDir(configDirPath, ConfigType[configTypeKey]);
26
+ }
27
+ function* allConfigFilesInDir(configDirPath, configType) {
28
+ for (const file of fs.readdirSync(configDirPath)) {
29
+ const configFile = path.join(configDirPath, file);
30
+ // ignore sub-directories, e.g. functions/lib
31
+ // ignore files that don't have the allowed extensions
32
+ if (fs.lstatSync(configFile).isDirectory() ||
33
+ !hasAllowedFileExtension(configFile, configType)) {
34
+ continue;
35
+ }
36
+ yield { configDirPath, configFile, configType };
37
+ }
38
+ }
39
+ function configFilePath(appPath, config) {
40
+ const configPath = ConfigPaths[config.type.toLocaleUpperCase()];
41
+ const fileExt = config.file?.ext || '.json';
42
+ return path.join(appPath, configPath, [config.name, fileExt].join(''));
43
+ }
44
+ function getAllConfigPaths() {
45
+ const configPaths = [];
46
+ for (const type in ConfigPaths) {
47
+ if (Object.prototype.hasOwnProperty.call(ConfigPaths, type)) {
48
+ const configPath = ConfigPaths[type];
49
+ configPaths.push(configPath);
50
+ }
51
+ }
52
+ return configPaths;
53
+ }
54
+ export { allConfigDirsPaths, allConfigFilesPaths, allConfigFilesPathsByType, getAllConfigPaths, configFilePath, };
@@ -0,0 +1 @@
1
+ export declare function bundleFunction(filePath: string): Promise<any>;
@@ -0,0 +1,40 @@
1
+ import * as esbuild from 'esbuild';
2
+ import fs from 'node:fs';
3
+ import path from 'node:path';
4
+ import { fileURLToPath } from 'node:url';
5
+ export async function bundleFunction(filePath) {
6
+ try {
7
+ const buildResult = await esbuild.build({
8
+ bundle: true,
9
+ entryPoints: [filePath],
10
+ format: 'cjs',
11
+ metafile: true,
12
+ platform: 'node',
13
+ target: ['chrome58'],
14
+ write: false, // Do not write the output to a file
15
+ });
16
+ const { metafile: { inputs }, outputFiles: [{ text: origCode }], } = buildResult;
17
+ // TODO: make a separate method to get dependencies for watch command
18
+ const dependencies = Object.keys(inputs).filter((input) => !input.startsWith('node_modules/'));
19
+ let code = origCode
20
+ .split('\n')
21
+ .map((line) => line.trim().startsWith('module.exports')
22
+ ? line.replace('module.exports', 'var moduleExports')
23
+ : line)
24
+ .join('\n');
25
+ // eslint-disable-next-line no-new-func
26
+ const evalFn = new Function(`${code}\nreturn { ...moduleExports }`);
27
+ const { config, ...moduleExports } = evalFn();
28
+ code += getSwellFunctionWrapper();
29
+ return { code, config, dependencies, moduleExports };
30
+ }
31
+ catch (error) {
32
+ console.log(error);
33
+ throw new Error(`Unable to compile function ${filePath}: ${error.message}`);
34
+ }
35
+ }
36
+ function getSwellFunctionWrapper() {
37
+ const __filename = fileURLToPath(import.meta.url);
38
+ const __dirname = path.dirname(__filename);
39
+ return fs.readFileSync(path.join(__dirname, './swell-function-wrapper.js'), 'utf8');
40
+ }
@@ -0,0 +1,37 @@
1
+ declare const env: any;
2
+ declare function ensureLoggedIn(storeId: string): Promise<any>;
3
+ declare function get(key: string): any;
4
+ declare function getAll(): any;
5
+ declare function getDefaultStore(): any;
6
+ declare function setDefaultStore(storeId: string): void;
7
+ declare function getSessionId(storeId: string): any;
8
+ /**
9
+ * Set store data for later access.
10
+ *
11
+ * It replaces the previous store value if it exists and only stores the
12
+ * following attributes:
13
+ *
14
+ * - sessionId
15
+ * - storeId
16
+ * - name
17
+ *
18
+ * @param store - The store to set
19
+ * @returns {void}
20
+ */
21
+ declare function setStore(store: Store): void;
22
+ declare function getUser(): any;
23
+ declare function setUser(user: User): void;
24
+ declare function clear(): void;
25
+ declare const config: {
26
+ clear: typeof clear;
27
+ ensureLoggedIn: typeof ensureLoggedIn;
28
+ get: typeof get;
29
+ getAll: typeof getAll;
30
+ getDefaultStore: typeof getDefaultStore;
31
+ getSessionId: typeof getSessionId;
32
+ getUser: typeof getUser;
33
+ setDefaultStore: typeof setDefaultStore;
34
+ setStore: typeof setStore;
35
+ setUser: typeof setUser;
36
+ };
37
+ export { config as default, env };
@@ -0,0 +1,131 @@
1
+ import Conf from 'conf';
2
+ import Configstore from 'configstore';
3
+ import { homedir } from 'node:os';
4
+ import path from 'node:path';
5
+ import style from './style.js';
6
+ const configPath = process.env.NODE_ENV === 'test'
7
+ ? path.resolve(process.cwd(), 'test', '.swell', 'config.json')
8
+ : path.resolve(homedir(), '.swell', 'config.json');
9
+ const configDir = process.env.NODE_ENV === 'test'
10
+ ? path.resolve(process.cwd(), 'test', 'fixtures')
11
+ : homedir();
12
+ const configStore = new Configstore('swell', {
13
+ // user: {...},
14
+ // defaultStore: '<store_id>',
15
+ // stores: [
16
+ // {
17
+ // storeId: '<store_id>',
18
+ // sessionId: '<session_id>',
19
+ // name: '<store_name>',
20
+ // }
21
+ // ]
22
+ }, {
23
+ configPath,
24
+ });
25
+ const env = new Conf({
26
+ configName: 'env',
27
+ cwd: path.join(configDir, '.swell'),
28
+ projectName: 'swell',
29
+ projectSuffix: '',
30
+ });
31
+ /**
32
+ * Get specified attributes for given object.
33
+ *
34
+ * @param object - The object to get attributes from
35
+ * @param attributes - The attributes to get from the
36
+ *
37
+ * @returns An array of the values of the specified attributes
38
+ */
39
+ function selectAttributes(object, attributes) {
40
+ // eslint-disable-next-line unicorn/no-array-reduce
41
+ return attributes.reduce((acc, key) => {
42
+ acc[key] = object[key];
43
+ return acc;
44
+ }, {});
45
+ }
46
+ async function ensureLoggedIn(storeId) {
47
+ const currentStore = storeId || getDefaultStore();
48
+ const sessionId = getSessionId(currentStore);
49
+ // still not logged in
50
+ if (!sessionId) {
51
+ const message = [
52
+ `You are not logged in to store ${style.storeId(currentStore)}.`,
53
+ `Use ${style.command('swell login')} to authenticate.`,
54
+ ].join(' ');
55
+ throw new Error(message);
56
+ }
57
+ return sessionId;
58
+ }
59
+ function get(key) {
60
+ return configStore.get(key);
61
+ }
62
+ function getAll() {
63
+ return configStore.all;
64
+ }
65
+ function getDefaultStore() {
66
+ return configStore.get('defaultStore');
67
+ }
68
+ function setDefaultStore(storeId) {
69
+ return configStore.set('defaultStore', storeId);
70
+ }
71
+ function getSessionId(storeId) {
72
+ if (!configStore.has('stores'))
73
+ return;
74
+ const store = configStore
75
+ .get('stores')
76
+ .find((store) => store.storeId === storeId);
77
+ return store?.sessionId;
78
+ }
79
+ /**
80
+ * Set store data for later access.
81
+ *
82
+ * It replaces the previous store value if it exists and only stores the
83
+ * following attributes:
84
+ *
85
+ * - sessionId
86
+ * - storeId
87
+ * - name
88
+ *
89
+ * @param store - The store to set
90
+ * @returns {void}
91
+ */
92
+ function setStore(store) {
93
+ const stores = configStore.get('stores') || [];
94
+ const storeIndex = stores.findIndex((s) => s.storeId === store.storeId);
95
+ const storeConfig = selectAttributes(store, [
96
+ 'storeId',
97
+ 'sessionId',
98
+ 'name',
99
+ 'email',
100
+ ]);
101
+ if (storeIndex === -1) {
102
+ stores.push(storeConfig);
103
+ }
104
+ else {
105
+ stores[storeIndex] = storeConfig;
106
+ }
107
+ return configStore.set('stores', stores);
108
+ }
109
+ function getUser() {
110
+ return configStore.get('user');
111
+ }
112
+ function setUser(user) {
113
+ const userConfig = selectAttributes(user, ['name', 'email']);
114
+ return configStore.set('user', userConfig);
115
+ }
116
+ function clear() {
117
+ return configStore.clear();
118
+ }
119
+ const config = {
120
+ clear,
121
+ ensureLoggedIn,
122
+ get,
123
+ getAll,
124
+ getDefaultStore,
125
+ getSessionId,
126
+ getUser,
127
+ setDefaultStore,
128
+ setStore,
129
+ setUser,
130
+ };
131
+ export { config as default, env };
@@ -0,0 +1,5 @@
1
+ export declare const API_BASE_URL: any;
2
+ export declare const ADMIN_API_BASE_URL: any;
3
+ export declare const LOGIN_HOST: any;
4
+ export declare function getAdminApiBaseUrl(storeId: string): any;
5
+ export declare function getLoginHost(storeId?: string): any;