@swell/cli 2.0.1-alpha.9 → 2.0.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 (102) hide show
  1. package/dist/app-command.d.ts +1 -1
  2. package/dist/app-command.js +9 -9
  3. package/dist/commands/app/dev.d.ts +16 -0
  4. package/dist/commands/app/dev.js +28 -0
  5. package/dist/commands/app/frontend/deploy.d.ts +15 -0
  6. package/dist/commands/app/frontend/deploy.js +41 -0
  7. package/dist/commands/app/frontend/dev.d.ts +19 -0
  8. package/dist/commands/app/frontend/dev.js +108 -0
  9. package/dist/commands/app/info.js +14 -9
  10. package/dist/commands/app/init.d.ts +12 -0
  11. package/dist/commands/app/init.js +34 -0
  12. package/dist/commands/app/install.d.ts +4 -4
  13. package/dist/commands/app/install.js +36 -42
  14. package/dist/commands/app/pull.d.ts +15 -0
  15. package/dist/commands/app/pull.js +50 -0
  16. package/dist/commands/app/push.d.ts +11 -14
  17. package/dist/commands/app/push.js +64 -138
  18. package/dist/commands/app/release.d.ts +13 -0
  19. package/dist/commands/app/release.js +148 -0
  20. package/dist/commands/app/version.d.ts +5 -4
  21. package/dist/commands/app/version.js +63 -42
  22. package/dist/commands/app/watch.d.ts +2 -4
  23. package/dist/commands/app/watch.js +3 -83
  24. package/dist/commands/create/app.d.ts +35 -11
  25. package/dist/commands/create/app.js +143 -137
  26. package/dist/commands/create/content.d.ts +2 -2
  27. package/dist/commands/create/content.js +10 -10
  28. package/dist/commands/create/frontend.d.ts +12 -0
  29. package/dist/commands/create/frontend.js +38 -0
  30. package/dist/commands/create/function.d.ts +3 -3
  31. package/dist/commands/create/function.js +22 -22
  32. package/dist/commands/create/model.d.ts +2 -2
  33. package/dist/commands/create/model.js +11 -11
  34. package/dist/commands/create/notification.d.ts +4 -4
  35. package/dist/commands/create/notification.js +38 -40
  36. package/dist/commands/env.d.ts +12 -0
  37. package/dist/commands/env.js +31 -0
  38. package/dist/commands/login.d.ts +1 -1
  39. package/dist/commands/login.js +18 -24
  40. package/dist/commands/logs.js +0 -1
  41. package/dist/commands/theme/dev.d.ts +21 -0
  42. package/dist/commands/theme/dev.js +164 -0
  43. package/dist/commands/theme/init.d.ts +9 -0
  44. package/dist/commands/theme/init.js +15 -0
  45. package/dist/commands/theme/pull.d.ts +20 -0
  46. package/dist/commands/theme/pull.js +65 -0
  47. package/dist/commands/theme/push.d.ts +19 -0
  48. package/dist/commands/theme/push.js +89 -0
  49. package/dist/create-app-command.d.ts +20 -0
  50. package/dist/create-app-command.js +253 -0
  51. package/dist/create-collection-command.d.ts +9 -9
  52. package/dist/create-collection-command.js +23 -23
  53. package/dist/{create-command.d.ts → create-config-command.d.ts} +1 -1
  54. package/dist/{create-command.js → create-config-command.js} +7 -7
  55. package/dist/env/local.d.ts +8 -0
  56. package/dist/env/local.js +7 -0
  57. package/dist/env/production.d.ts +8 -0
  58. package/dist/env/production.js +7 -0
  59. package/dist/env/review.d.ts +8 -0
  60. package/dist/env/review.js +7 -0
  61. package/dist/env/staging.d.ts +8 -0
  62. package/dist/env/staging.js +7 -0
  63. package/dist/lib/api.d.ts +4 -2
  64. package/dist/lib/api.js +50 -21
  65. package/dist/lib/app-config.d.ts +13 -5
  66. package/dist/lib/app-config.js +62 -24
  67. package/dist/lib/apps/app-config.d.ts +17 -3
  68. package/dist/lib/apps/app-config.js +194 -66
  69. package/dist/lib/apps/index.d.ts +93 -12
  70. package/dist/lib/apps/index.js +155 -50
  71. package/dist/lib/apps/paths.d.ts +14 -7
  72. package/dist/lib/apps/paths.js +73 -28
  73. package/dist/lib/bundle.js +15 -3
  74. package/dist/lib/config.d.ts +9 -2
  75. package/dist/lib/config.js +49 -1
  76. package/dist/lib/constants.d.ts +5 -0
  77. package/dist/lib/constants.js +24 -6
  78. package/dist/lib/create/content.d.ts +2 -2
  79. package/dist/lib/create/content.js +1 -1
  80. package/dist/lib/create/function.d.ts +2 -2
  81. package/dist/lib/create/function.js +2 -2
  82. package/dist/lib/create/index.d.ts +1 -1
  83. package/dist/lib/create/index.js +11 -7
  84. package/dist/lib/create/model.d.ts +2 -2
  85. package/dist/lib/create/notification.d.ts +2 -2
  86. package/dist/lib/info.js +2 -2
  87. package/dist/lib/logs/index.js +1 -1
  88. package/dist/lib/sessions.js +2 -2
  89. package/dist/lib/stores.d.ts +9 -4
  90. package/dist/lib/stores.js +13 -8
  91. package/dist/lib/style.d.ts +2 -0
  92. package/dist/lib/style.js +2 -0
  93. package/dist/lib/swell-function-wrapper.d.ts +40 -1
  94. package/dist/lib/swell-function-wrapper.js +107 -22
  95. package/dist/push-app-command.d.ts +73 -0
  96. package/dist/push-app-command.js +743 -0
  97. package/dist/remote-app-command.d.ts +37 -11
  98. package/dist/remote-app-command.js +432 -169
  99. package/oclif.manifest.json +872 -123
  100. package/package.json +14 -1
  101. package/dist/commands/app/_pull.d.ts +0 -8
  102. package/dist/commands/app/_pull.js +0 -45
@@ -1,8 +1,8 @@
1
1
  interface CreateContentFileBody {
2
2
  collection: string;
3
- label?: string;
4
3
  description?: string;
5
4
  fields?: ContentFieldProps[];
5
+ label?: string;
6
6
  views?: ContentViewProps[];
7
7
  }
8
8
  interface ContentViewProps {
@@ -12,7 +12,7 @@ interface ContentViewProps {
12
12
  tabs: [];
13
13
  }
14
14
  type ContentView = 'edit' | 'list' | 'new';
15
- type ContentType = 'asset' | 'basic_html' | 'blocks' | 'boolean' | 'category_lookup' | 'checkbox' | 'checkboxes' | 'collection' | 'color' | 'currency' | 'customer_lookup' | 'date' | 'datetime' | 'document' | 'dropdown' | 'email' | 'field_group' | 'generic_lookup' | 'icon' | 'image' | 'long_text' | 'lookup' | 'markdown' | 'number' | 'percent' | 'phone' | 'product_lookup' | 'radio' | 'rich_html' | 'select' | 'short_text' | 'slider' | 'slug' | 'tags' | 'text' | 'textarea' | 'time' | 'toggle' | 'url' | 'variant_lookup' | 'video';
15
+ type ContentType = 'asset' | 'basic_html' | 'boolean' | 'category_lookup' | 'checkbox' | 'checkboxes' | 'collection' | 'color' | 'color_scheme' | 'color_scheme_group' | 'currency' | 'customer_lookup' | 'date' | 'datetime' | 'document' | 'dropdown' | 'email' | 'field_group' | 'font_family' | 'generic_lookup' | 'html' | 'icon' | 'image' | 'long_text' | 'lookup' | 'markdown' | 'number' | 'percent' | 'phone' | 'product_lookup' | 'radio' | 'rich_html' | 'rich_text' | 'select' | 'short_text' | 'slider' | 'slug' | 'tags' | 'text' | 'textarea' | 'time' | 'toggle' | 'url' | 'variant_lookup' | 'video';
16
16
  interface ContentFieldProps {
17
17
  id: string;
18
18
  label: string;
@@ -8,8 +8,8 @@ const parseViews = (views) => {
8
8
  viewResponse.push({
9
9
  id: viewId,
10
10
  ...(viewId === 'list' ? { nav: {} } : {}),
11
- tabs: [],
12
11
  fields: [],
12
+ tabs: [],
13
13
  });
14
14
  }
15
15
  return viewResponse;
@@ -7,11 +7,11 @@ interface CreateFunctionArgs {
7
7
  interface WriteFunctionFileParams {
8
8
  description: string;
9
9
  events: string;
10
- route: string;
11
10
  functionName: string;
12
11
  language: FunctionLanguage;
12
+ route: string;
13
13
  schedule: string;
14
14
  trigger: FunctionType;
15
15
  }
16
- declare const getFunctionTemplate: ({ description, events, route, schedule, language, trigger, }: WriteFunctionFileParams) => string;
16
+ declare const getFunctionTemplate: ({ description, events, language, route, schedule, trigger, }: WriteFunctionFileParams) => string;
17
17
  export { CreateFunctionArgs, FunctionLanguage, FunctionType, WriteFunctionFileParams, getFunctionTemplate, };
@@ -1,9 +1,9 @@
1
- const getFunctionTemplate = ({ description, events, route, schedule, language, trigger, }) => {
1
+ const getFunctionTemplate = ({ description, events, language, route, schedule, trigger, }) => {
2
2
  let typeAppend = ``;
3
3
  if (trigger === 'model') {
4
4
  const eventsList = events
5
5
  .split(/\s*,\s*/g)
6
- .filter((e) => e)
6
+ .filter(Boolean)
7
7
  .map((eventName) => `'${eventName}'`)
8
8
  .join(', ');
9
9
  typeAppend = `,
@@ -10,4 +10,4 @@ declare const toFunctionFileName: (value: string) => string;
10
10
  declare const toCollectionName: (value: string) => string;
11
11
  declare const toCollectionLabel: (value: string) => string;
12
12
  declare const toNotificationLabel: (value: string) => string;
13
- export { CreateFileParams, toFileName, toAppName, toAppId, toFunctionFileName, toCollectionName, toCollectionLabel, toNotificationLabel, };
13
+ export { CreateFileParams, toAppId, toAppName, toCollectionLabel, toCollectionName, toFileName, toFunctionFileName, toNotificationLabel, };
@@ -1,14 +1,18 @@
1
- import { dasherize, pluralize, underscore, titleize } from 'inflection';
1
+ import { dasherize, pluralize, titleize, underscore } from 'inflection';
2
2
  // Example: 'My Thing' => 'my-thing'
3
3
  const toFileName = (value) => dasherize(underscore(value.split('.')[0].replace(' ', '_'))).toLowerCase();
4
4
  // Example: 'my-things' => 'My Things'
5
- const toAppName = (value) => pluralize(titleize(value).replace('-', ' '));
5
+ const toAppName = (value) => titleize(value)
6
+ .replaceAll(/[_\s-:./-]+/g, ' ')
7
+ .replaceAll(/([a-z])([A-Z])/g, '$1 $2')
8
+ .replaceAll(/(\d)([a-z])/gi, '$1 $2')
9
+ .replaceAll(/([a-z])(\d)/gi, '$1 $2');
6
10
  // Example: 'My App' => 'my_app'
7
11
  const toAppId = (value) => String(value || '')
8
- .replace(/[^a-zA-Z0-9\-_\s:\.\/]/g, '')
9
- .replace(/[_\s-:\.\/]+/g, '_')
10
- .replace(/^[_]+|[_]+$/g, '')
11
- .replace(/([a-z])([A-Z])/g, '$1_$2')
12
+ .replaceAll(/[^\s\w./:-]/g, '')
13
+ .replaceAll(/[_\s-:./]+/g, '_')
14
+ .replaceAll(/^_+|_+$/g, '')
15
+ .replaceAll(/([a-z])([A-Z])/g, '$1_$2')
12
16
  .toLowerCase();
13
17
  // Example: 'My Thing' => 'my-thing'
14
18
  // And: 'myThing' => 'myThing'
@@ -19,4 +23,4 @@ const toCollectionName = (value) => pluralize(value.replaceAll(/[^A-Za-z]/g, '-'
19
23
  const toCollectionLabel = (value) => pluralize(titleize(value).replace('-', ' '));
20
24
  // Example: 'order-receipt' => 'Order Receipt'
21
25
  const toNotificationLabel = (value) => titleize(value).replace('-', ' ');
22
- export { toFileName, toAppName, toAppId, toFunctionFileName, toCollectionName, toCollectionLabel, toNotificationLabel, };
26
+ export { toAppId, toAppName, toCollectionLabel, toCollectionName, toFileName, toFunctionFileName, toNotificationLabel, };
@@ -1,9 +1,9 @@
1
1
  interface CreateModelFileBody {
2
- label?: string;
3
2
  collection?: string;
4
3
  description?: string;
5
- fields?: ModelFieldResponse;
6
4
  events?: ModelEventObject;
5
+ fields?: ModelFieldResponse;
6
+ label?: string;
7
7
  }
8
8
  interface ModelEventObject {
9
9
  types?: ModelEvent[];
@@ -1,11 +1,11 @@
1
1
  interface WriteNotificationsFileParams {
2
+ admin?: boolean;
2
3
  description: string;
3
4
  event: string;
4
5
  model: string;
5
6
  name: string;
6
- subject: string;
7
- admin?: boolean;
8
7
  once?: boolean;
8
+ subject: string;
9
9
  }
10
10
  interface CreateNotificationFileBody {
11
11
  admin?: boolean;
package/dist/lib/info.js CHANGED
@@ -20,7 +20,7 @@ export class FieldDefinitions {
20
20
  get client() {
21
21
  return {
22
22
  label: 'Test store',
23
- transform: (client) => `${client.name} (${style.storeId(client.id)})`,
23
+ transform: (client) => client && `${client.name} (${style.storeId(client.id)})`,
24
24
  };
25
25
  }
26
26
  get dateCreated() {
@@ -57,7 +57,7 @@ export class FieldDefinitions {
57
57
  label: 'Version',
58
58
  transform: (_version) => {
59
59
  if (this.versions.length === 0) {
60
- return 'N/A';
60
+ return this.app.version || 'N/A';
61
61
  }
62
62
  return [
63
63
  style.appConfigValue(this.versions[0].version),
@@ -83,6 +83,6 @@ export class LoggedItem {
83
83
  }
84
84
  })
85
85
  .join('\n');
86
- return `Function ${event ? `${event.type} >` : ''} ${style.logMethod(method.toUpperCase())} /${name} ${logLines ? `\n${logLines}` : ''}`;
86
+ return `Function ${event ? `${event.hook ? `${event.hook}:` : ''}${event.type} >` : ''} ${style.logMethod(method.toUpperCase())} /${name} ${logLines ? `\n${logLines}` : ''}`;
87
87
  }
88
88
  }
@@ -20,7 +20,6 @@ function createServer(onSessionId, storeId) {
20
20
  // the spinner is used to show progress while waiting for the browser
21
21
  const spinner = ux.action;
22
22
  serverForLogin({
23
- storeId,
24
23
  onPost(req) {
25
24
  // we received the session id from the browser so we can move on
26
25
  const sessionId = req.headers['x-session'];
@@ -37,6 +36,7 @@ function createServer(onSessionId, storeId) {
37
36
  ].join(' '));
38
37
  await open(loginUrl);
39
38
  },
39
+ storeId,
40
40
  });
41
41
  }
42
42
  /**
@@ -52,7 +52,7 @@ function createServer(onSessionId, storeId) {
52
52
  * from the browser
53
53
  * @returns void
54
54
  */
55
- function serverForLogin({ storeId, onPost, onStart, }) {
55
+ function serverForLogin({ onPost, onStart, storeId, }) {
56
56
  // flag to track if the POST and GET requests have been handled
57
57
  // we only want to handle them once
58
58
  let postHandled = false;
@@ -35,6 +35,7 @@ declare function selectStoreId({ authorizations, currentStoreId, force, }: {
35
35
  * Select the store to switch to from a CLI prompt from the list of
36
36
  * already logged in stores.
37
37
  *
38
+ * @param message Store selection message
38
39
  * @returns The store ID to switch to
39
40
  * @throws CLIError - If there are no stores to switch to
40
41
  */
@@ -42,6 +43,8 @@ declare function selectLoggedInStoreId(message?: string): Promise<string>;
42
43
  /**
43
44
  * Select an environment.
44
45
  *
46
+ * @param message Environment selection message
47
+ * @returns Environment to switch to
45
48
  * @throws CLIError - If there are no stores to switch to
46
49
  */
47
50
  declare function selectEnvironmentId(message?: string): Promise<string>;
@@ -51,13 +54,15 @@ declare function selectEnvironmentId(message?: string): Promise<string>;
51
54
  * If there is no current store id, it will always be set as the default
52
55
  * without asking.
53
56
  *
54
- * @param currentStoreId - The ID of the default store
55
- * @param storeId - The ID of the store to set as the default
57
+ * @param storeParams -
58
+ * currentStoreId - The ID of the default store
59
+ * storeId - The ID of the store to set as the default
60
+ * @param force - True to force
56
61
  *
57
62
  * @returns void
58
63
  */
59
64
  declare function modifyDefaultStore({ currentStoreId, storeId, }: {
60
65
  currentStoreId: string;
61
66
  storeId: string;
62
- }): Promise<void>;
63
- export { modifyDefaultStore, selectLoggedInStoreId, selectStoreId, selectEnvironmentId, showStores, };
67
+ }, force?: boolean): Promise<void>;
68
+ export { modifyDefaultStore, selectEnvironmentId, selectLoggedInStoreId, selectStoreId, showStores, };
@@ -101,6 +101,7 @@ async function selectStoreId({ authorizations, currentStoreId, force = false, })
101
101
  * Select the store to switch to from a CLI prompt from the list of
102
102
  * already logged in stores.
103
103
  *
104
+ * @param message Store selection message
104
105
  * @returns The store ID to switch to
105
106
  * @throws CLIError - If there are no stores to switch to
106
107
  */
@@ -123,14 +124,16 @@ async function selectLoggedInStoreId(message) {
123
124
  new Separator(),
124
125
  { name: 'Login to another account', value: '' },
125
126
  ],
127
+ loop: false,
126
128
  message: message || 'Which store do you want to switch to?',
127
129
  pageSize: 25,
128
- loop: false,
129
130
  });
130
131
  }
131
132
  /**
132
133
  * Select an environment.
133
134
  *
135
+ * @param message Environment selection message
136
+ * @returns Environment to switch to
134
137
  * @throws CLIError - If there are no stores to switch to
135
138
  */
136
139
  async function selectEnvironmentId(message) {
@@ -145,7 +148,7 @@ async function selectEnvironmentId(message) {
145
148
  value: 'test',
146
149
  },
147
150
  ],
148
- message: message || 'Which envoronment?',
151
+ message: message || 'Which environment?',
149
152
  });
150
153
  }
151
154
  /**
@@ -154,20 +157,22 @@ async function selectEnvironmentId(message) {
154
157
  * If there is no current store id, it will always be set as the default
155
158
  * without asking.
156
159
  *
157
- * @param currentStoreId - The ID of the default store
158
- * @param storeId - The ID of the store to set as the default
160
+ * @param storeParams -
161
+ * currentStoreId - The ID of the default store
162
+ * storeId - The ID of the store to set as the default
163
+ * @param force - True to force
159
164
  *
160
165
  * @returns void
161
166
  */
162
- async function modifyDefaultStore({ currentStoreId, storeId, }) {
167
+ async function modifyDefaultStore({ currentStoreId, storeId, }, force = false) {
163
168
  let modifyDefault = false;
164
- if (currentStoreId && currentStoreId !== storeId) {
169
+ if (!force && currentStoreId && currentStoreId !== storeId) {
165
170
  modifyDefault = await confirm({
166
171
  message: `Do you want to make ${style.storeId(storeId)} your default store?`,
167
172
  });
168
173
  }
169
- if (!currentStoreId || modifyDefault) {
174
+ if (force || !currentStoreId || modifyDefault) {
170
175
  config.setDefaultStore(storeId);
171
176
  }
172
177
  }
173
- export { modifyDefaultStore, selectLoggedInStoreId, selectStoreId, selectEnvironmentId, showStores, };
178
+ export { modifyDefaultStore, selectEnvironmentId, selectLoggedInStoreId, selectStoreId, showStores, };
@@ -5,9 +5,11 @@ declare const _default: {
5
5
  link: import("chalk").ChalkInstance;
6
6
  path: import("chalk").ChalkInstance;
7
7
  dim: import("chalk").ChalkInstance;
8
+ strike: import("chalk").ChalkInstance;
8
9
  command: import("chalk").ChalkInstance;
9
10
  storeId: import("chalk").ChalkInstance;
10
11
  currentUser: import("chalk").ChalkInstance;
12
+ appName: import("chalk").ChalkInstance;
11
13
  appEnvLive: import("chalk").ChalkInstance;
12
14
  appEnv: import("chalk").ChalkInstance;
13
15
  appConfigName: import("chalk").ChalkInstance;
package/dist/lib/style.js CHANGED
@@ -7,11 +7,13 @@ export default {
7
7
  link: chalk.blueBright.underline,
8
8
  path: chalk.underline,
9
9
  dim: chalk.dim,
10
+ strike: chalk.strikethrough,
10
11
  // styles for consistent output of some elements
11
12
  command: chalk.magenta.bold,
12
13
  storeId: chalk.yellow,
13
14
  currentUser: chalk.blueBright.underline,
14
15
  // apps
16
+ appName: chalk.yellow,
15
17
  appEnvLive: chalk.magenta,
16
18
  appEnv: chalk.yellow,
17
19
  appConfigName: chalk.yellow,
@@ -1,4 +1,11 @@
1
- declare function handleRequest(originalRequest: any, _env: any, context: any): Promise<Response>;
1
+ /**
2
+ * Handle a function request.
3
+ * @param {Request} originalRequest from cloudflare
4
+ * @param {*} _env cloudflare environment vars
5
+ * @param {*} context cloudflare conttext
6
+ * @returns {Promise<SwellResponse>}
7
+ */
8
+ declare function request(originalRequest: Request, _env: any, context: any): Promise<SwellResponse>;
2
9
  /**
3
10
  * Invokes one of the function types that are available.
4
11
  *
@@ -35,10 +42,19 @@ declare function handleRequest(originalRequest: any, _env: any, context: any): P
35
42
  * @param {Event} context
36
43
  */
37
44
  declare function executeModuleHandler(req: SwellRequest, context: Event): Promise<any>;
45
+ /**
46
+ * Helper to determine if a value is an ordinary object.
47
+ * @param {any} obj
48
+ * @returns {boolean}
49
+ */
50
+ declare function isOrdinaryObject(val: any): boolean;
38
51
  declare const origialConsoleLog: {
39
52
  (...data: any[]): void;
40
53
  (message?: any, ...optionalParams: any[]): void;
41
54
  };
55
+ /**
56
+ * Class representing a Swell request.
57
+ */
42
58
  declare class SwellRequest {
43
59
  constructor(req: any, context: any);
44
60
  originalRequest: any;
@@ -62,8 +78,21 @@ declare class SwellRequest {
62
78
  url: URL | undefined;
63
79
  parseJson(input: any): any;
64
80
  log(level: any, ...line: any[]): void;
81
+ getIngestableLogs(response: any): {
82
+ params: any;
83
+ } | undefined;
65
84
  ingestLogs(response: any): Promise<void>;
85
+ /**
86
+ * Merge values into app data for the current request.
87
+ * @param {object|string} idOrValues string to indicate app ID, or values to merge
88
+ * @param {object|undefined} values values to merge into app data
89
+ * @returns {object|undefined} existing app data merged with values if passed
90
+ */
91
+ appValues(idOrValues: object | string, values?: object | undefined): object | undefined;
66
92
  }
93
+ /**
94
+ * Class representing the Swell backend API.
95
+ */
67
96
  declare class SwellAPI {
68
97
  constructor(req: any, context: any);
69
98
  request: any;
@@ -79,10 +108,20 @@ declare class SwellAPI {
79
108
  delete(url: any, data: any): Promise<any>;
80
109
  settings(id?: any): Promise<any>;
81
110
  }
111
+ /**
112
+ * Class representing a Swell error.
113
+ */
82
114
  declare class SwellError extends Error {
83
115
  constructor(message: any, options?: {});
84
116
  status: any;
85
117
  }
118
+ /**
119
+ * Class representing a Swell response.
120
+ */
86
121
  declare class SwellResponse extends Response {
122
+ static _respond(req: any, response: any, context: any): any;
123
+ static _respondWithLogs(response: any, req: any): SwellResponse;
87
124
  constructor(data: any, options?: {});
125
+ _swellData: any;
126
+ _swellOptions: {};
88
127
  }
@@ -1,9 +1,16 @@
1
1
  "use strict";
2
2
  const origialConsoleLog = console.log;
3
3
  addEventListener('fetch', (event) => {
4
- event.respondWith(handleRequest(event.request, event.env, event));
4
+ event.respondWith(request(event.request, event.env, event));
5
5
  });
6
- async function handleRequest(originalRequest, _env, context) {
6
+ /**
7
+ * Handle a function request.
8
+ * @param {Request} originalRequest from cloudflare
9
+ * @param {*} _env cloudflare environment vars
10
+ * @param {*} context cloudflare conttext
11
+ * @returns {Promise<SwellResponse>}
12
+ */
13
+ async function request(originalRequest, _env, context) {
7
14
  const req = new SwellRequest(originalRequest, context);
8
15
  await req.initialize();
9
16
  let response;
@@ -12,16 +19,10 @@ async function handleRequest(originalRequest, _env, context) {
12
19
  }
13
20
  catch (err) {
14
21
  // Log the error for Swell
15
- console.error(err.stack);
22
+ console.error(err);
16
23
  response = new SwellResponse({ error: err.message }, { status: err.status || 500 });
17
24
  }
18
- // Create a response by default if one is not returned
19
- if (!(response instanceof Response)) {
20
- response = new SwellResponse(response);
21
- }
22
- // Send logs back to Swell
23
- context.waitUntil(req.ingestLogs(response));
24
- return response;
25
+ return SwellResponse._respond(req, response, context);
25
26
  }
26
27
  /**
27
28
  * Invokes one of the function types that are available.
@@ -74,6 +75,9 @@ async function executeModuleHandler(req, context) {
74
75
  }
75
76
  throw new Error(`Function does not export a method to handle ${method.toUpperCase()} requests`);
76
77
  }
78
+ /**
79
+ * Class representing a Swell request.
80
+ */
77
81
  class SwellRequest {
78
82
  constructor(req, context) {
79
83
  this.originalRequest = req;
@@ -141,11 +145,11 @@ class SwellRequest {
141
145
  origialConsoleLog(...line);
142
146
  this._logs.push({
143
147
  date: Date.now(),
144
- line: line.map((l) => JSON.stringify(l)),
148
+ line: line.map((l) => (l instanceof Error ? l.stack : JSON.stringify(l))),
145
149
  ...(level !== 'info' ? { level } : {}),
146
150
  });
147
151
  }
148
- async ingestLogs(response) {
152
+ getIngestableLogs(response) {
149
153
  if (!this.logParams) {
150
154
  return;
151
155
  }
@@ -153,23 +157,51 @@ class SwellRequest {
153
157
  this.logParams.time = Date.now() - this.logParams.$start;
154
158
  delete this.logParams.$start;
155
159
  }
156
- const result = await this.swell.post('/:logs', {
157
- $ingest_function_logs: {
158
- params: {
159
- ...this.logParams,
160
- message: {
161
- ...this.logParams?.message,
162
- logs: this._logs,
163
- status: response.status,
164
- },
160
+ return {
161
+ params: {
162
+ ...this.logParams,
163
+ message: {
164
+ ...this.logParams?.message,
165
+ logs: this._logs,
166
+ status: response.status,
165
167
  },
166
168
  },
169
+ };
170
+ }
171
+ async ingestLogs(response) {
172
+ const ingestableLogs = this.getIngestableLogs(response);
173
+ if (!ingestableLogs) {
174
+ return;
175
+ }
176
+ const result = await this.swell.post('/:logs', {
177
+ $ingest_function_logs: ingestableLogs,
167
178
  });
168
179
  if (!result?.success) {
169
180
  console.error('Error ingesting logs', result);
170
181
  }
171
182
  }
183
+ /**
184
+ * Merge values into app data for the current request.
185
+ * @param {object|string} idOrValues string to indicate app ID, or values to merge
186
+ * @param {object|undefined} values values to merge into app data
187
+ * @returns {object|undefined} existing app data merged with values if passed
188
+ */
189
+ appValues(idOrValues, values = undefined) {
190
+ const appId = typeof idOrValues === 'string' ? appIdOrValues : this.appId;
191
+ const appValues = typeof idOrValues === 'string' ? values : idOrValues;
192
+ if (!appId || !isOrdinaryObject(appValues)) {
193
+ return undefined;
194
+ }
195
+ return {
196
+ $app: {
197
+ [appId]: appValues,
198
+ },
199
+ };
200
+ }
172
201
  }
202
+ /**
203
+ * Class representing the Swell backend API.
204
+ */
173
205
  class SwellAPI {
174
206
  constructor(req, context) {
175
207
  this.request = req;
@@ -261,6 +293,9 @@ class SwellAPI {
261
293
  return this.makeRequest('GET', `/settings/${id}`);
262
294
  }
263
295
  }
296
+ /**
297
+ * Class representing a Swell error.
298
+ */
264
299
  class SwellError extends Error {
265
300
  constructor(message, options = {}) {
266
301
  let formattedMessage;
@@ -278,10 +313,13 @@ class SwellError extends Error {
278
313
  this.status = options.status || 500;
279
314
  }
280
315
  }
316
+ /**
317
+ * Class representing a Swell response.
318
+ */
281
319
  class SwellResponse extends Response {
282
320
  constructor(data, options = {}) {
283
321
  const resultHeaders = {};
284
- let result;
322
+ let result = '';
285
323
  if (typeof data === 'string') {
286
324
  result = data;
287
325
  resultHeaders['Content-Type'] = 'text/plain;charset=UTF-8';
@@ -298,5 +336,52 @@ class SwellResponse extends Response {
298
336
  ...(options.headers || {}),
299
337
  },
300
338
  });
339
+ // Saved for future access
340
+ this._swellData = data;
341
+ this._swellOptions = options || {};
301
342
  }
343
+ static _respond(req, response, context) {
344
+ let finalResponse = response;
345
+ // Convert a plain Response instance to SwellResponse
346
+ if (finalResponse instanceof Response &&
347
+ !(finalResponse instanceof SwellResponse)) {
348
+ finalResponse = new SwellResponse(response.body, {
349
+ status: response.status,
350
+ headers: response.headers,
351
+ });
352
+ }
353
+ else if (!(finalResponse instanceof SwellResponse)) {
354
+ finalResponse = new SwellResponse(response);
355
+ }
356
+ // Send logs back with the response for event hooks
357
+ if (req.data?.$event?.hook) {
358
+ return SwellResponse._respondWithLogs(finalResponse, req);
359
+ }
360
+ // Ingest logs in the background
361
+ context.waitUntil(req.ingestLogs(finalResponse));
362
+ return finalResponse;
363
+ }
364
+ static _respondWithLogs(response, req) {
365
+ const ingestableLogs = req.getIngestableLogs(response);
366
+ // Rebuild response with logs
367
+ const responseData = response instanceof SwellResponse ? response?._swellData : response;
368
+ const resultData = ingestableLogs
369
+ ? {
370
+ $logs: ingestableLogs,
371
+ $data: responseData,
372
+ }
373
+ : responseData;
374
+ return new SwellResponse(resultData, response?._swellOptions);
375
+ }
376
+ }
377
+ /**
378
+ * Helper to determine if a value is an ordinary object.
379
+ * @param {any} obj
380
+ * @returns {boolean}
381
+ */
382
+ function isOrdinaryObject(val) {
383
+ return (typeof val === 'object' &&
384
+ val !== null &&
385
+ Object.getPrototypeOf(val) === Object.prototype);
302
386
  }
387
+ ;
@@ -0,0 +1,73 @@
1
+ /// <reference types="node" />
2
+ import { App, AppConfig, ConfigType, FrontendProjectType } from './lib/apps/index.js';
3
+ import { RemoteAppCommand } from './remote-app-command.js';
4
+ type WatchFileEvent = 'change' | 'deleted' | 'new';
5
+ export declare abstract class PushAppCommand extends RemoteAppCommand {
6
+ frontendPath: string;
7
+ logWatchChanges: boolean;
8
+ onWatchChange?: ((appConfig?: AppConfig, result?: any) => void) | undefined;
9
+ watchingChangeQueue: Array<any>;
10
+ watchingChangeQueueRunning: boolean;
11
+ watchingFiles: Array<string>;
12
+ watchListener: (eventType: string, filename: Buffer | null | string) => Promise<void>;
13
+ buildFrontend(projectType: FrontendProjectType): Promise<void>;
14
+ chooseAppToPull(query?: any): Promise<App>;
15
+ createAppStorefront(hasOtherStorefronts?: boolean): Promise<any>;
16
+ deployAppFrontend(force?: boolean, log?: boolean): Promise<void>;
17
+ deployFrontend(projectType: FrontendProjectType): Promise<string>;
18
+ ensureAppExists(file?: string, shouldCreate?: boolean): Promise<boolean>;
19
+ ensureLoggedIn(): Promise<true | undefined>;
20
+ exec(command: string, onOutput?: (string: string) => any | false): Promise<void>;
21
+ getAllAppStorefronts(params?: {
22
+ type?: string;
23
+ }): Promise<any>;
24
+ getAllStorefronts(params?: {
25
+ app_id?: string;
26
+ theme_app_id?: string;
27
+ type?: string;
28
+ }): Promise<any>;
29
+ getAppStorefront(params?: {
30
+ storefront_id?: string;
31
+ type?: string;
32
+ }): Promise<any>;
33
+ getAppToPull(args: {
34
+ appId?: string;
35
+ targetPath?: string;
36
+ }, shouldChoose?: boolean): Promise<App | undefined>;
37
+ getExistingApp(appId: string): Promise<App>;
38
+ getFrontendDeploymentHash(): string | undefined;
39
+ getFrontendProjectType(required?: boolean): FrontendProjectType | null;
40
+ getStorefrontToPull(args?: {
41
+ appId?: string;
42
+ targetPath?: string;
43
+ }, flags?: {
44
+ 'storefront-id'?: string;
45
+ 'storefront-select'?: boolean;
46
+ }): Promise<any>;
47
+ getStorefrontToPush(flags?: {
48
+ 'storefront-id'?: string;
49
+ 'storefront-select'?: boolean;
50
+ }): Promise<any>;
51
+ handleWatchFileChange(configFile: string, configType: ConfigType, event: WatchFileEvent): Promise<void>;
52
+ logAppFrontendUrl(): void;
53
+ logDashboardUrl(flags: {
54
+ [flag: string]: any;
55
+ }): void;
56
+ logStorefrontConnected(): void;
57
+ logStorefrontFrontendUrl(storefront?: any, branchId?: string): void;
58
+ pushFile(relativePath: string): Promise<void>;
59
+ pushFilePath(relativePath: string, force?: boolean): Promise<void>;
60
+ resolveAppPath(appId?: string, targetPath?: string): string;
61
+ runWatchChangeQueue(): Promise<void>;
62
+ saveCurrentStorefront(): void;
63
+ setWatchingFiles(): void;
64
+ updateFrontendDeployment(currentStore: string, projectType: FrontendProjectType, deploymentUrl: string, deploymentHash: string): Promise<void>;
65
+ watchForChanges({ logChanges, onChange, syncAll, }?: {
66
+ logChanges?: boolean | undefined;
67
+ onChange?: (() => void) | undefined;
68
+ syncAll?: boolean | undefined;
69
+ }): Promise<void>;
70
+ wranglerDeployFrontend(projectType: FrontendProjectType): Promise<string>;
71
+ private confirmRemoveInstalledApp;
72
+ }
73
+ export {};