@swell/cli 2.9.0 → 2.9.3

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.
@@ -0,0 +1,162 @@
1
+ import { getCurrentAppSlugId } from '../apps/index.js';
2
+ import { classifyIdentifier, resolveInspectScope, } from '../apps/inspect-scope.js';
3
+ import { HEX24 } from '../apps/object-id.js';
4
+ import { resolveAppId } from '../apps/resolve.js';
5
+ export const WORKFLOW_STATUSES = [
6
+ 'active',
7
+ 'failed',
8
+ 'completed',
9
+ 'terminated',
10
+ ];
11
+ export const WORKFLOW_INSTANCE_ID_PATTERN = /^wf_inst_[\dA-Za-z]+$/;
12
+ const REDACTED_WORKFLOW_FIELDS = new Set([
13
+ 'access_token',
14
+ 'api_key',
15
+ 'authorization',
16
+ 'bearer_token',
17
+ 'cf_api_token',
18
+ 'cloudflare_token',
19
+ 'installed_app_id',
20
+ 'params',
21
+ 'private_key',
22
+ 'public_key',
23
+ 'runtime_token',
24
+ 'secret_key',
25
+ 'token',
26
+ 'token_hash',
27
+ ]);
28
+ const RELATIVE_TIME_FORMAT = new Intl.RelativeTimeFormat('en', {
29
+ numeric: 'auto',
30
+ });
31
+ export async function resolveWorkflowOperationRef(api, workflow, flags) {
32
+ const kind = classifyIdentifier(workflow);
33
+ if (kind.kind === 'slug') {
34
+ const appId = HEX24.test(kind.appPart)
35
+ ? kind.appPart
36
+ : await resolveAppId(api, kind.appPart);
37
+ return {
38
+ appId,
39
+ appSlug: kind.appPart,
40
+ query: { workflow_name: kind.name },
41
+ };
42
+ }
43
+ if (kind.kind === 'id') {
44
+ const manifest = await api.get({
45
+ adminPath: `/data/:functions/${kind.id}`,
46
+ });
47
+ if (!manifest?.app_id) {
48
+ throw new Error(`Workflow manifest '${workflow}' does not have an app_id. Pass app.<app>.<workflow> or --app=<slug>.`);
49
+ }
50
+ const workflowName = workflowDisplayName(manifest);
51
+ if (workflowName === kind.id || workflowName === '-') {
52
+ throw new Error(`Workflow manifest '${workflow}' does not have a workflow name. Pass app.<app>.<workflow> or --app=<slug>.`);
53
+ }
54
+ return {
55
+ appId: manifest.app_id,
56
+ query: { workflow_id: kind.id, workflow_name: workflowName },
57
+ };
58
+ }
59
+ if (kind.kind === 'name') {
60
+ const scope = await resolveWorkflowScope(api, flags);
61
+ if (!scope.appId) {
62
+ throw new Error(`Bare workflow name '${workflow}' requires --app=<slug> or --app=. to scope. Alternatively, pass app.<app>.<workflow> or a 24-char manifest id.`);
63
+ }
64
+ return {
65
+ appId: scope.appId,
66
+ appSlug: scope.appSlug,
67
+ query: { workflow_name: workflow },
68
+ };
69
+ }
70
+ throw new Error(`Invalid workflow identifier '${workflow}'. Expected bare name, app.<app>.<workflow>, or 24-char manifest id.`);
71
+ }
72
+ export async function resolveWorkflowScope(api, flags) {
73
+ return resolveInspectScope({
74
+ resolveAppId: (slug) => resolveAppId(api, slug),
75
+ readCurrentAppSlug: () => getCurrentAppSlugId(),
76
+ }, flags);
77
+ }
78
+ export function isWorkflowInstanceIdentifier(value) {
79
+ return WORKFLOW_INSTANCE_ID_PATTERN.test(value);
80
+ }
81
+ export function workflowDisplayName(record) {
82
+ return record.workflow_name || record.name || record.id || '-';
83
+ }
84
+ export function workflowListMeta(record) {
85
+ const parts = [];
86
+ const summary = record.summary || {};
87
+ if (!record.enabled) {
88
+ parts.push('disabled');
89
+ }
90
+ if (summary.active_instances) {
91
+ parts.push(`active ${summary.active_instances}`);
92
+ }
93
+ if (summary.failed_instances) {
94
+ parts.push(`failed ${summary.failed_instances}`);
95
+ }
96
+ if (summary.completed_recent) {
97
+ parts.push(`completed ${summary.completed_recent}`);
98
+ }
99
+ if (summary.terminated_recent) {
100
+ parts.push(`terminated ${summary.terminated_recent}`);
101
+ }
102
+ return parts.join(' · ');
103
+ }
104
+ export function workflowRunDate(run) {
105
+ return (run.date_failed ||
106
+ run.date_terminated ||
107
+ run.date_completed ||
108
+ run.date_started ||
109
+ run.date_created);
110
+ }
111
+ export function workflowRunMeta(run) {
112
+ const parts = [];
113
+ if (run.status) {
114
+ parts.push(run.status);
115
+ }
116
+ const date = workflowRunDate(run);
117
+ if (date) {
118
+ parts.push(formatWorkflowRelativeTime(date));
119
+ }
120
+ return parts.join(' · ');
121
+ }
122
+ export function formatWorkflowRelativeTime(value, now = Date.now()) {
123
+ const timestamp = Date.parse(value);
124
+ if (!Number.isFinite(timestamp)) {
125
+ return value;
126
+ }
127
+ const diffSeconds = Math.round((timestamp - now) / 1000);
128
+ const absSeconds = Math.abs(diffSeconds);
129
+ if (absSeconds < 60) {
130
+ return RELATIVE_TIME_FORMAT.format(diffSeconds, 'second');
131
+ }
132
+ if (absSeconds < 60 * 60) {
133
+ return RELATIVE_TIME_FORMAT.format(Math.round(diffSeconds / 60), 'minute');
134
+ }
135
+ if (absSeconds < 24 * 60 * 60) {
136
+ return RELATIVE_TIME_FORMAT.format(Math.round(diffSeconds / (60 * 60)), 'hour');
137
+ }
138
+ if (absSeconds < 30 * 24 * 60 * 60) {
139
+ return RELATIVE_TIME_FORMAT.format(Math.round(diffSeconds / (24 * 60 * 60)), 'day');
140
+ }
141
+ return value;
142
+ }
143
+ export function redactWorkflowPayload(value) {
144
+ if (Array.isArray(value)) {
145
+ return value.map((item) => redactWorkflowPayload(item));
146
+ }
147
+ if (!value || typeof value !== 'object') {
148
+ if (typeof value === 'string' && value.startsWith('wf_rt_')) {
149
+ return '[redacted]';
150
+ }
151
+ return value;
152
+ }
153
+ const result = {};
154
+ for (const [key, child] of Object.entries(value)) {
155
+ if (REDACTED_WORKFLOW_FIELDS.has(key.toLowerCase())) {
156
+ result[key] = '[redacted]';
157
+ continue;
158
+ }
159
+ result[key] = redactWorkflowPayload(child);
160
+ }
161
+ return result;
162
+ }
@@ -110,6 +110,7 @@
110
110
  "swell logs",
111
111
  "swell logs -f -p -n 10 -c date,req,data",
112
112
  "swell logs -s accounts",
113
+ "swell logs --type workflow --app my-app -s run-import",
113
114
  "swell logs --after 2023-08-25T16:01:02.697Z -c date",
114
115
  "swell logs --after 2023-08-27"
115
116
  ],
@@ -123,7 +124,7 @@
123
124
  "type": "option"
124
125
  },
125
126
  "app": {
126
- "description": "filter logs by app id",
127
+ "description": "filter logs by app id, slug, or \".\" for current swell.json",
127
128
  "name": "app",
128
129
  "hasDynamicHelp": false,
129
130
  "multiple": false,
@@ -218,7 +219,8 @@
218
219
  "api",
219
220
  "function",
220
221
  "webhook",
221
- "transaction"
222
+ "transaction",
223
+ "workflow"
222
224
  ],
223
225
  "type": "option"
224
226
  }
@@ -281,6 +283,10 @@
281
283
  {
282
284
  "description": "Validate a function file",
283
285
  "command": "<%= config.bin %> <%= command.id %> function myfunction.ts"
286
+ },
287
+ {
288
+ "description": "Validate a workflow file",
289
+ "command": "<%= config.bin %> <%= command.id %> function run-import.ts"
284
290
  }
285
291
  ],
286
292
  "flags": {
@@ -809,7 +815,7 @@
809
815
  "name": "versions"
810
816
  }
811
817
  },
812
- "description": "The command shows the latest information about your app including the name,\ndescription, version, public ID, test store, and more. If the \u001b[35m\u001b[1mversions\u001b[22m\u001b[39m argument is passed,\nit will output all versions of the app instead.",
818
+ "description": "The command shows the latest information about your app including the name,\ndescription, version, public ID, test store, and more. If the versions argument is passed,\nit will output all versions of the app instead.",
813
819
  "examples": [
814
820
  {
815
821
  "command": "swell app info",
@@ -1108,7 +1114,7 @@
1108
1114
  "name": "targetPath"
1109
1115
  }
1110
1116
  },
1111
- "description": "Pull all app files, a specific file, or a specific configuration\ntype from an app in your store's test environment to your local machine.\n\nIf APPID is not specified, you will be prompted with a list of apps to choose from.\n\nApp file directories:\n\u001b[4massets/\u001b[24m\n\u001b[4mcontent/\u001b[24m\n\u001b[4mfrontend/\u001b[24m\n\u001b[4mcomponents/\u001b[24m\n\u001b[4mfunctions/\u001b[24m\n\u001b[4mmodels/\u001b[24m\n\u001b[4mnotifications/\u001b[24m\n\u001b[4msettings/\u001b[24m\n\u001b[4mtheme/\u001b[24m\n\u001b[4mwebhooks/\u001b[24m\n\u001b[4mfrontend/\u001b[24m",
1117
+ "description": "Pull all app files, a specific file, or a specific configuration\ntype from an app in your store's test environment to your local machine.\n\nIf APPID is not specified, you will be prompted with a list of apps to choose from.\n\nApp file directories:\nassets/\ncontent/\nfrontend/\ncomponents/\nfunctions/\nmodels/\nnotifications/\nsettings/\ntheme/\nwebhooks/\nfrontend/",
1112
1118
  "examples": [
1113
1119
  "swell app pull",
1114
1120
  "swell app pull example_app",
@@ -1157,7 +1163,7 @@
1157
1163
  "name": "file"
1158
1164
  }
1159
1165
  },
1160
- "description": "Push all app files, a specific file, or a specific configuration\ntype to an app in your store's test environment.\n\nIf the app does not exist, it will be created and its global ID saved to a .swellrc file.\n\n- If no file is specified, all configuration files will be pushed to the store.\n This includes the app icon (assets/icon.png) and swell.json.\n- If a file is specified, only that file will be pushed to the store.\n- If a directory is specified, only files in that directory will be pushed.\n\nApp file directories:\n\u001b[4massets/\u001b[24m\n\u001b[4mcontent/\u001b[24m\n\u001b[4mfrontend/\u001b[24m\n\u001b[4mcomponents/\u001b[24m\n\u001b[4mfunctions/\u001b[24m\n\u001b[4mmodels/\u001b[24m\n\u001b[4mnotifications/\u001b[24m\n\u001b[4msettings/\u001b[24m\n\u001b[4mtheme/\u001b[24m\n\u001b[4mwebhooks/\u001b[24m",
1166
+ "description": "Push all app files, a specific file, or a specific configuration\ntype to an app in your store's test environment.\n\nIf the app does not exist, it will be created and its global ID saved to a .swellrc file.\n\n- If no file is specified, all configuration files will be pushed to the store.\n This includes the app icon (assets/icon.png) and swell.json.\n- If a file is specified, only that file will be pushed to the store.\n- If a directory is specified, only files in that directory will be pushed.\n\nApp file directories:\nassets/\ncontent/\nfrontend/\ncomponents/\nfunctions/\nmodels/\nnotifications/\nsettings/\ntheme/\nwebhooks/",
1161
1167
  "examples": [
1162
1168
  "swell app push",
1163
1169
  "swell app push content",
@@ -1791,12 +1797,13 @@
1791
1797
  },
1792
1798
  "trigger": {
1793
1799
  "default": "",
1794
- "description": "cron | model | route",
1800
+ "description": "cron | model | route | workflow",
1795
1801
  "name": "trigger",
1796
1802
  "options": [
1797
1803
  "cron",
1798
1804
  "model",
1799
- "route"
1805
+ "route",
1806
+ "workflow"
1800
1807
  ]
1801
1808
  }
1802
1809
  },
@@ -1804,7 +1811,9 @@
1804
1811
  "$ swell create function",
1805
1812
  "$ swell create function order-handler.ts model -e order.created,order.updated -y",
1806
1813
  "$ swell create function cleanup.ts cron -s \"0 0 * * *\" -y",
1807
- "$ swell create function api-endpoint.ts route -r public -y"
1814
+ "$ swell create function api-endpoint.ts route -r public -y",
1815
+ "$ swell create function run-import.ts --type workflow -y",
1816
+ "$ swell create function run-import.ts workflow -y"
1808
1817
  ],
1809
1818
  "flags": {
1810
1819
  "app-path": {
@@ -1860,6 +1869,16 @@
1860
1869
  "multiple": false,
1861
1870
  "type": "option"
1862
1871
  },
1872
+ "type": {
1873
+ "description": "Create a workflow function",
1874
+ "name": "type",
1875
+ "hasDynamicHelp": false,
1876
+ "multiple": false,
1877
+ "options": [
1878
+ "workflow"
1879
+ ],
1880
+ "type": "option"
1881
+ },
1863
1882
  "yes": {
1864
1883
  "char": "y",
1865
1884
  "description": "Skip prompts, require all arguments",
@@ -1877,9 +1896,9 @@
1877
1896
  "strict": true,
1878
1897
  "summary": "Create a serverless function in JavaScript or TypeScript.",
1879
1898
  "helpMeta": {
1880
- "usageDirect": "<name> <trigger> [...] -y",
1899
+ "usageDirect": "<name> [<trigger>|workflow] [...] -y",
1881
1900
  "variantSection": {
1882
- "title": "TRIGGER OPTIONS",
1901
+ "title": "FUNCTION MODES",
1883
1902
  "variants": [
1884
1903
  {
1885
1904
  "name": "model",
@@ -1895,6 +1914,11 @@
1895
1914
  "name": "route",
1896
1915
  "flag": "-r, --route=<option>",
1897
1916
  "description": "Access: public (default) | private"
1917
+ },
1918
+ {
1919
+ "name": "workflow",
1920
+ "flag": "--type=workflow",
1921
+ "description": "Durable explicit-create workflow"
1898
1922
  }
1899
1923
  ]
1900
1924
  },
@@ -2553,6 +2577,7 @@
2553
2577
  "swell inspect content app.honest_reviews.reviews",
2554
2578
  "swell inspect webhooks --app=my-app",
2555
2579
  "swell inspect functions app.my-app.payment-sync",
2580
+ "swell inspect workflow-runs --workflow app.my-app.run-import --status active",
2556
2581
  "swell inspect notifications com.orders.receipt.v2",
2557
2582
  "swell inspect settings app.my-app"
2558
2583
  ],
@@ -2828,6 +2853,159 @@
2828
2853
  "webhooks.js"
2829
2854
  ]
2830
2855
  },
2856
+ "inspect:workflow-runs": {
2857
+ "aliases": [],
2858
+ "args": {
2859
+ "identifier": {
2860
+ "description": "wf_inst_* workflow run instance id.",
2861
+ "name": "identifier",
2862
+ "required": false
2863
+ }
2864
+ },
2865
+ "description": "Lists recent workflow runtime instances, or shows one workflow run by instance id.\n\nIdentifier forms:\n (none) - recent runs across installed apps, or --app scope\n wf_inst_<id> - single run detail\n\nUse --workflow=<workflow> to filter list mode by workflow name, app.<app>.<workflow>, or manifest id.\n",
2866
+ "examples": [
2867
+ "swell inspect workflow-runs",
2868
+ "swell inspect workflow-runs --app=my-app --status active",
2869
+ "swell inspect workflow-runs --workflow run-import --app=my-app",
2870
+ "swell inspect workflow-runs --workflow app.my-app.run-import --status active",
2871
+ "swell inspect workflow-runs wf_inst_abc123 --app=my-app",
2872
+ "swell inspect workflow-runs wf_inst_abc123"
2873
+ ],
2874
+ "flags": {
2875
+ "app": {
2876
+ "description": "Filter by app slug, or \".\" for current swell.json.",
2877
+ "name": "app",
2878
+ "hasDynamicHelp": false,
2879
+ "multiple": false,
2880
+ "type": "option"
2881
+ },
2882
+ "live": {
2883
+ "description": "Use live environment (default: test).",
2884
+ "name": "live",
2885
+ "allowNo": false,
2886
+ "type": "boolean"
2887
+ },
2888
+ "json": {
2889
+ "description": "Emit pure JSON without the \"Next steps\" footer. Detail mode only.",
2890
+ "name": "json",
2891
+ "allowNo": false,
2892
+ "type": "boolean"
2893
+ },
2894
+ "yes": {
2895
+ "char": "y",
2896
+ "description": "No-op; accepted for agent compatibility.",
2897
+ "hidden": true,
2898
+ "name": "yes",
2899
+ "allowNo": false,
2900
+ "type": "boolean"
2901
+ },
2902
+ "limit": {
2903
+ "description": "Maximum runs to show.",
2904
+ "name": "limit",
2905
+ "default": 10,
2906
+ "hasDynamicHelp": false,
2907
+ "multiple": false,
2908
+ "type": "option"
2909
+ },
2910
+ "status": {
2911
+ "description": "Workflow run status.",
2912
+ "name": "status",
2913
+ "hasDynamicHelp": false,
2914
+ "multiple": false,
2915
+ "options": [
2916
+ "active",
2917
+ "failed",
2918
+ "completed",
2919
+ "terminated"
2920
+ ],
2921
+ "type": "option"
2922
+ },
2923
+ "workflow": {
2924
+ "description": "Filter by workflow name, app.<app>.<workflow>, or manifest id.",
2925
+ "name": "workflow",
2926
+ "hasDynamicHelp": false,
2927
+ "multiple": false,
2928
+ "type": "option"
2929
+ }
2930
+ },
2931
+ "hasDynamicHelp": false,
2932
+ "hiddenAliases": [],
2933
+ "id": "inspect:workflow-runs",
2934
+ "pluginAlias": "@swell/cli",
2935
+ "pluginName": "@swell/cli",
2936
+ "pluginType": "core",
2937
+ "strict": true,
2938
+ "summary": "Workflow runtime instances.",
2939
+ "isESM": true,
2940
+ "relativePath": [
2941
+ "dist",
2942
+ "commands",
2943
+ "inspect",
2944
+ "workflow-runs.js"
2945
+ ]
2946
+ },
2947
+ "inspect:workflows": {
2948
+ "aliases": [],
2949
+ "args": {
2950
+ "identifier": {
2951
+ "description": "Resource identifier — see \"Identifier forms\" below.",
2952
+ "name": "identifier",
2953
+ "required": false
2954
+ }
2955
+ },
2956
+ "description": "Lists workflow manifests across deployed apps with runtime state. Pass --app=<slug> or --app=. (current swell.json) to scope.\n\nPass an identifier to view a workflow manifest, summary counts, and failed instance sample as JSON.\n\nIdentifier forms:\n app.<app>.<name> - full paste-back key (list column 1)\n <name> - requires --app= scope\n <24-char id> - any scope\n",
2957
+ "examples": [
2958
+ "swell inspect workflows",
2959
+ "swell inspect workflows --app=my-app",
2960
+ "swell inspect workflows app.my-app.run-import",
2961
+ "swell inspect workflows run-import --app=my-app",
2962
+ "swell inspect workflows --live"
2963
+ ],
2964
+ "flags": {
2965
+ "app": {
2966
+ "description": "Filter by app slug, or \".\" for current swell.json.",
2967
+ "name": "app",
2968
+ "hasDynamicHelp": false,
2969
+ "multiple": false,
2970
+ "type": "option"
2971
+ },
2972
+ "live": {
2973
+ "description": "Use live environment (default: test).",
2974
+ "name": "live",
2975
+ "allowNo": false,
2976
+ "type": "boolean"
2977
+ },
2978
+ "json": {
2979
+ "description": "Emit pure JSON without the \"Next steps\" footer. Detail mode only.",
2980
+ "name": "json",
2981
+ "allowNo": false,
2982
+ "type": "boolean"
2983
+ },
2984
+ "yes": {
2985
+ "char": "y",
2986
+ "description": "No-op; accepted for agent compatibility.",
2987
+ "hidden": true,
2988
+ "name": "yes",
2989
+ "allowNo": false,
2990
+ "type": "boolean"
2991
+ }
2992
+ },
2993
+ "hasDynamicHelp": false,
2994
+ "hiddenAliases": [],
2995
+ "id": "inspect:workflows",
2996
+ "pluginAlias": "@swell/cli",
2997
+ "pluginName": "@swell/cli",
2998
+ "pluginType": "core",
2999
+ "strict": true,
3000
+ "summary": "Durable app workflows and runtime state.",
3001
+ "isESM": true,
3002
+ "relativePath": [
3003
+ "dist",
3004
+ "commands",
3005
+ "inspect",
3006
+ "workflows.js"
3007
+ ]
3008
+ },
2831
3009
  "theme:dev": {
2832
3010
  "aliases": [],
2833
3011
  "args": {},
@@ -3072,7 +3250,7 @@
3072
3250
  "name": "targetPath"
3073
3251
  }
3074
3252
  },
3075
- "description": "Pull all theme files, a specific file, or a specific configuration\ntype from a theme in your store's test environment to your local machine.\n\nIf APPID is not specified, you will be prompted with a list of themes to choose from.\n\nTheme file directories:\n\u001b[4massets/\u001b[24m\n\u001b[4mtheme/\u001b[24m",
3253
+ "description": "Pull all theme files, a specific file, or a specific configuration\ntype from a theme in your store's test environment to your local machine.\n\nIf APPID is not specified, you will be prompted with a list of themes to choose from.\n\nTheme file directories:\nassets/\ntheme/",
3076
3254
  "examples": [
3077
3255
  "swell theme pull",
3078
3256
  "swell theme pull mytheme",
@@ -3143,7 +3321,7 @@
3143
3321
  "name": "file"
3144
3322
  }
3145
3323
  },
3146
- "description": "Push all theme files, a specific file, or a specific configuration\ntype to an theme in your store's test environment.\n\nIf the theme does not exist, it will be created and its global ID saved to a .swellrc file.\n\n- If no file is specified, all configuration files will be pushed to the store.\n This includes the theme icon (assets/icon.png) and swell.json.\n- If a file is specified, only that file will be pushed to the store.\n- If a directory is specified, only files in that directory will be pushed.\n\nTheme file directories:\n\u001b[4massets/\u001b[24m\n\u001b[4mtheme/\u001b[24m",
3324
+ "description": "Push all theme files, a specific file, or a specific configuration\ntype to an theme in your store's test environment.\n\nIf the theme does not exist, it will be created and its global ID saved to a .swellrc file.\n\n- If no file is specified, all configuration files will be pushed to the store.\n This includes the theme icon (assets/icon.png) and swell.json.\n- If a file is specified, only that file will be pushed to the store.\n- If a directory is specified, only files in that directory will be pushed.\n\nTheme file directories:\nassets/\ntheme/",
3147
3325
  "examples": [
3148
3326
  "swell theme push",
3149
3327
  "swell theme push assets",
@@ -3378,5 +3556,5 @@
3378
3556
  ]
3379
3557
  }
3380
3558
  },
3381
- "version": "2.9.0"
3559
+ "version": "2.9.3"
3382
3560
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@swell/cli",
3
- "version": "2.9.0",
3
+ "version": "2.9.3",
4
4
  "type": "module",
5
5
  "description": "Swell's command line interface/utility",
6
6
  "keywords": [
@@ -59,6 +59,7 @@
59
59
  "qs": "6.12.3",
60
60
  "semver": "7.5.4",
61
61
  "table": "6.8.1",
62
+ "typescript": "5.2.2",
62
63
  "ws": "8.18.1"
63
64
  },
64
65
  "devDependencies": {
@@ -87,8 +88,7 @@
87
88
  "oclif": "4.0.3",
88
89
  "shx": "0.3.4",
89
90
  "testdouble": "3.20.0",
90
- "ts-node": "10.9.1",
91
- "typescript": "5.2.2"
91
+ "ts-node": "10.9.1"
92
92
  },
93
93
  "oclif": {
94
94
  "bin": "swell",
@@ -116,7 +116,7 @@
116
116
  "lint": "eslint . --ext .ts --config .eslintrc",
117
117
  "postpack": "shx rm -f oclif.manifest.json",
118
118
  "posttest": "npm run lint",
119
- "prepack": "npm run build && oclif manifest && oclif readme",
119
+ "prepack": "npm run build && oclif manifest && NODE_ENV=production oclif readme",
120
120
  "test": "mocha --forbid-only \"test/**/*.test.ts\"",
121
121
  "publish-alpha": "npm version prerelease --preid=alpha && npm publish --tag alpha"
122
122
  },