@fstacksoftware/shopify-dev 1.0.0
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/index.d.ts +2 -0
- package/dist/index.js +33 -0
- package/dist/utils/cf-tunnel.d.ts +7 -0
- package/dist/utils/cf-tunnel.js +94 -0
- package/dist/utils/constants.d.ts +7 -0
- package/dist/utils/constants.js +16 -0
- package/dist/utils/env.d.ts +11 -0
- package/dist/utils/env.js +52 -0
- package/dist/utils/shopify-app.d.ts +14 -0
- package/dist/utils/shopify-app.js +79 -0
- package/package.json +31 -0
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
#! /usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
|
+
};
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
var commander_1 = require("commander");
|
|
8
|
+
var env_1 = __importDefault(require("./utils/env"));
|
|
9
|
+
var cf_tunnel_1 = __importDefault(require("./utils/cf-tunnel"));
|
|
10
|
+
var shopify_app_1 = __importDefault(require("./utils/shopify-app"));
|
|
11
|
+
var constants_1 = require("./utils/constants");
|
|
12
|
+
var env = new env_1.default(constants_1.CLOUDFLARED_FOLDER_PATH, constants_1.ENV_PATH);
|
|
13
|
+
var tunnel = new cf_tunnel_1.default(env);
|
|
14
|
+
var start = function (runMode, isQuickMode, isReset) {
|
|
15
|
+
if (isReset === void 0) { isReset = false; }
|
|
16
|
+
return new shopify_app_1.default(env, tunnel, isQuickMode, isReset).start(runMode);
|
|
17
|
+
};
|
|
18
|
+
commander_1.program
|
|
19
|
+
.command('dev')
|
|
20
|
+
.description('Run a shopify app in dev mode')
|
|
21
|
+
.option('-q,--quick', 'Use Cloudflare quick tunnel')
|
|
22
|
+
.option('-r,--reset', 'Reset your default shopify dev config')
|
|
23
|
+
.action(function (options) {
|
|
24
|
+
start(constants_1.ERunMode['DEV'], options.quick, options.reset);
|
|
25
|
+
});
|
|
26
|
+
commander_1.program
|
|
27
|
+
.command('start')
|
|
28
|
+
.description('Run a shopify app in production mode')
|
|
29
|
+
.option('-q,--quick', 'Use Cloudflare quick tunnel')
|
|
30
|
+
.action(function (options) {
|
|
31
|
+
start(constants_1.ERunMode['PROD'], options.quick);
|
|
32
|
+
});
|
|
33
|
+
commander_1.program.parse(process.argv);
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
12
|
+
var _ = { label: 0, sent: function () { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
13
|
+
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function () { return this; }), g;
|
|
14
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
15
|
+
function step(op) {
|
|
16
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
17
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
18
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
19
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
20
|
+
switch (op[0]) {
|
|
21
|
+
case 0: case 1: t = op; break;
|
|
22
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
23
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
24
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
25
|
+
default:
|
|
26
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
27
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
28
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
29
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
30
|
+
if (t[2]) _.ops.pop();
|
|
31
|
+
_.trys.pop(); continue;
|
|
32
|
+
}
|
|
33
|
+
op = body.call(thisArg, _);
|
|
34
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
35
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
39
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
40
|
+
};
|
|
41
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
+
var tunnel_1 = require("@fstacksoftware/tunnel");
|
|
43
|
+
var path_1 = __importDefault(require("path"));
|
|
44
|
+
var constants_1 = require("./constants");
|
|
45
|
+
var CloudflaredTunnel = /** @class */ (function () {
|
|
46
|
+
function CloudflaredTunnel(env) {
|
|
47
|
+
this.env = env;
|
|
48
|
+
}
|
|
49
|
+
CloudflaredTunnel.prototype.quick = function () {
|
|
50
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
51
|
+
var url;
|
|
52
|
+
return __generator(this, function (_a) {
|
|
53
|
+
switch (_a.label) {
|
|
54
|
+
case 0: return [4 /*yield*/, (0, tunnel_1.useCloudflareTunnel)(parseInt(this.env.get('VITE_PORT')))];
|
|
55
|
+
case 1:
|
|
56
|
+
url = _a.sent();
|
|
57
|
+
return [2 /*return*/, url];
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
};
|
|
62
|
+
CloudflaredTunnel.prototype.tunnel = function () {
|
|
63
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
64
|
+
var tunnel;
|
|
65
|
+
return __generator(this, function (_a) {
|
|
66
|
+
switch (_a.label) {
|
|
67
|
+
case 0:
|
|
68
|
+
if (this.env.get('CF_HOST_PATTERN') && !new RegExp(this.env.get('CF_HOST_PATTERN')).test(this.env.get('VITE_HOST'))) {
|
|
69
|
+
throw new Error("VITE_HOST(".concat(this.env.get('VITE_HOST'), ") does not satisfy the regex condition: ").concat(this.env.get('CF_HOST_PATTERN')));
|
|
70
|
+
}
|
|
71
|
+
tunnel = new tunnel_1.CloudflareTunnel({
|
|
72
|
+
certPath: path_1.default.join(constants_1.CLOUDFLARED_FOLDER_PATH, './cert.pem'),
|
|
73
|
+
cfSecretKey: this.env.get('CF_SECRET_KEY'),
|
|
74
|
+
cfAccountTag: this.env.get('CF_ACCOUNT_TAG'),
|
|
75
|
+
tunnelName: this.env.get('VITE_HOST').split('.')[0],
|
|
76
|
+
tunnels: [
|
|
77
|
+
{
|
|
78
|
+
hostname: this.env.get('VITE_HOST'),
|
|
79
|
+
service: "http://localhost:".concat(this.env.get('VITE_PORT')),
|
|
80
|
+
},
|
|
81
|
+
],
|
|
82
|
+
debug: false,
|
|
83
|
+
});
|
|
84
|
+
return [4 /*yield*/, tunnel.start.bind(tunnel)()];
|
|
85
|
+
case 1:
|
|
86
|
+
_a.sent();
|
|
87
|
+
return [2 /*return*/, this.env.get('VITE_HOST')];
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
};
|
|
92
|
+
return CloudflaredTunnel;
|
|
93
|
+
}());
|
|
94
|
+
exports.default = CloudflaredTunnel;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.ERunMode = exports.ENV_PATH = exports.WEB_FOLDER_PATH = exports.CLOUDFLARED_FOLDER_PATH = void 0;
|
|
7
|
+
var fs_1 = require("fs");
|
|
8
|
+
var path_1 = __importDefault(require("path"));
|
|
9
|
+
exports.CLOUDFLARED_FOLDER_PATH = path_1.default.resolve('./.cloudflared');
|
|
10
|
+
exports.WEB_FOLDER_PATH = path_1.default.resolve('./web');
|
|
11
|
+
exports.ENV_PATH = (0, fs_1.existsSync)(path_1.default.resolve('./web/.env')) ? path_1.default.resolve('./web/.env') : path_1.default.resolve('./.env');
|
|
12
|
+
var ERunMode;
|
|
13
|
+
(function (ERunMode) {
|
|
14
|
+
ERunMode[ERunMode["DEV"] = 0] = "DEV";
|
|
15
|
+
ERunMode[ERunMode["PROD"] = 1] = "PROD";
|
|
16
|
+
})(ERunMode || (exports.ERunMode = ERunMode = {}));
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export default class EnvironmentVariable {
|
|
2
|
+
private cloudflaredFolderPath;
|
|
3
|
+
private envPath;
|
|
4
|
+
data: {
|
|
5
|
+
[key: string]: string;
|
|
6
|
+
};
|
|
7
|
+
constructor(cloudflaredFolderPath: string, envPath: string);
|
|
8
|
+
private getCurrentEnv;
|
|
9
|
+
get(key: string): string;
|
|
10
|
+
set(key: string, value: string): void;
|
|
11
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __assign = (this && this.__assign) || function () {
|
|
3
|
+
__assign = Object.assign || function(t) {
|
|
4
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
5
|
+
s = arguments[i];
|
|
6
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
7
|
+
t[p] = s[p];
|
|
8
|
+
}
|
|
9
|
+
return t;
|
|
10
|
+
};
|
|
11
|
+
return __assign.apply(this, arguments);
|
|
12
|
+
};
|
|
13
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
14
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
var fs_1 = require("fs");
|
|
18
|
+
var path_1 = __importDefault(require("path"));
|
|
19
|
+
var EnvironmentVariable = /** @class */ (function () {
|
|
20
|
+
function EnvironmentVariable(cloudflaredFolderPath, envPath) {
|
|
21
|
+
this.cloudflaredFolderPath = cloudflaredFolderPath;
|
|
22
|
+
this.envPath = envPath;
|
|
23
|
+
this.data = __assign(__assign({}, this.getCurrentEnv()), JSON.parse((0, fs_1.readFileSync)(path_1.default.join(this.cloudflaredFolderPath, './account.json'), { encoding: 'utf-8' })));
|
|
24
|
+
}
|
|
25
|
+
EnvironmentVariable.prototype.getCurrentEnv = function () {
|
|
26
|
+
var content = (0, fs_1.readFileSync)(this.envPath, { encoding: 'utf-8' }).split('\n');
|
|
27
|
+
return content.reduce(function (previousValue, currentValue) {
|
|
28
|
+
var _a;
|
|
29
|
+
if (!currentValue)
|
|
30
|
+
return previousValue;
|
|
31
|
+
var splittedData = currentValue.trim().split('=');
|
|
32
|
+
var key = splittedData[0];
|
|
33
|
+
var value = splittedData[1].trim().replace(/['"]/g, '');
|
|
34
|
+
return __assign(__assign({}, previousValue), (_a = {}, _a[key] = value, _a));
|
|
35
|
+
}, {});
|
|
36
|
+
};
|
|
37
|
+
EnvironmentVariable.prototype.get = function (key) {
|
|
38
|
+
return this.data[key];
|
|
39
|
+
};
|
|
40
|
+
EnvironmentVariable.prototype.set = function (key, value) {
|
|
41
|
+
this.data[key] = value;
|
|
42
|
+
var currentEnv = this.getCurrentEnv();
|
|
43
|
+
currentEnv[key] = value;
|
|
44
|
+
var newEnvData = Object.keys(currentEnv).reduce(function (previousValue, key) {
|
|
45
|
+
previousValue += "".concat(key, "=").concat(currentEnv[key], "\n");
|
|
46
|
+
return previousValue;
|
|
47
|
+
}, '');
|
|
48
|
+
(0, fs_1.writeFileSync)(this.envPath, newEnvData);
|
|
49
|
+
};
|
|
50
|
+
return EnvironmentVariable;
|
|
51
|
+
}());
|
|
52
|
+
exports.default = EnvironmentVariable;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import EnvironmentVariable from './env';
|
|
2
|
+
import CloudflaredTunnel from './cf-tunnel';
|
|
3
|
+
import { ERunMode } from './constants';
|
|
4
|
+
export default class ShopifyApp {
|
|
5
|
+
private env;
|
|
6
|
+
private isQuickTunnel;
|
|
7
|
+
private tunnel;
|
|
8
|
+
private isReset;
|
|
9
|
+
constructor(env: EnvironmentVariable, tunnel: CloudflaredTunnel, isQuickTunnel: boolean, isReset: boolean);
|
|
10
|
+
private updateAppURL;
|
|
11
|
+
private startProd;
|
|
12
|
+
private startDev;
|
|
13
|
+
start(mode: ERunMode): void;
|
|
14
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __assign = (this && this.__assign) || function () {
|
|
3
|
+
__assign = Object.assign || function(t) {
|
|
4
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
5
|
+
s = arguments[i];
|
|
6
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
7
|
+
t[p] = s[p];
|
|
8
|
+
}
|
|
9
|
+
return t;
|
|
10
|
+
};
|
|
11
|
+
return __assign.apply(this, arguments);
|
|
12
|
+
};
|
|
13
|
+
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
14
|
+
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
15
|
+
if (ar || !(i in from)) {
|
|
16
|
+
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
17
|
+
ar[i] = from[i];
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return to.concat(ar || Array.prototype.slice.call(from));
|
|
21
|
+
};
|
|
22
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
23
|
+
var child_process_1 = require("child_process");
|
|
24
|
+
var constants_1 = require("./constants");
|
|
25
|
+
var ShopifyApp = /** @class */ (function () {
|
|
26
|
+
function ShopifyApp(env, tunnel, isQuickTunnel, isReset) {
|
|
27
|
+
this.env = env;
|
|
28
|
+
this.tunnel = tunnel;
|
|
29
|
+
this.isQuickTunnel = isQuickTunnel;
|
|
30
|
+
this.isReset = isReset;
|
|
31
|
+
}
|
|
32
|
+
ShopifyApp.prototype.updateAppURL = function (url) {
|
|
33
|
+
(0, child_process_1.spawn)("npx shopify app update-url --api-key=".concat(this.env.get('VITE_SHOPIFY_API_KEY'), " --app-url=").concat(url, " --redirect-urls=").concat(url, "/auth/callback,").concat(url, "/api/auth/callback,").concat(url, "/auth/shopify/callback"), { shell: true, stdio: 'inherit' });
|
|
34
|
+
};
|
|
35
|
+
ShopifyApp.prototype.startProd = function (host) {
|
|
36
|
+
if (this.isQuickTunnel)
|
|
37
|
+
this.env.set('VITE_HOST', host);
|
|
38
|
+
this.updateAppURL("https://".concat(host));
|
|
39
|
+
(0, child_process_1.spawn)('npm', ['run', 'serve'], {
|
|
40
|
+
shell: true,
|
|
41
|
+
stdio: 'inherit',
|
|
42
|
+
cwd: constants_1.WEB_FOLDER_PATH,
|
|
43
|
+
env: __assign(__assign({}, process.env), { DEBUG: 'true' }),
|
|
44
|
+
});
|
|
45
|
+
};
|
|
46
|
+
ShopifyApp.prototype.startDev = function (host) {
|
|
47
|
+
(0, child_process_1.spawn)('npx', __spreadArray([
|
|
48
|
+
'shopify',
|
|
49
|
+
'app',
|
|
50
|
+
'dev',
|
|
51
|
+
'--tunnel-url',
|
|
52
|
+
"https://".concat(host, ":").concat(this.env.get('VITE_PORT'))
|
|
53
|
+
], (this.isReset ? ['--reset'] : []), true), {
|
|
54
|
+
shell: true,
|
|
55
|
+
stdio: 'inherit',
|
|
56
|
+
});
|
|
57
|
+
};
|
|
58
|
+
ShopifyApp.prototype.start = function (mode) {
|
|
59
|
+
var _this = this;
|
|
60
|
+
var tunnel = this.isQuickTunnel ? function () { return _this.tunnel.quick(); } : function () { return _this.tunnel.tunnel(); };
|
|
61
|
+
tunnel()
|
|
62
|
+
.then(function (url) {
|
|
63
|
+
var host = url.replace(/https?:\/\//g, '');
|
|
64
|
+
switch (mode) {
|
|
65
|
+
case constants_1.ERunMode['DEV']:
|
|
66
|
+
return _this.startDev(host);
|
|
67
|
+
case constants_1.ERunMode['PROD']:
|
|
68
|
+
return _this.startProd(host);
|
|
69
|
+
default:
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
})
|
|
73
|
+
.catch(function (err) {
|
|
74
|
+
throw err;
|
|
75
|
+
});
|
|
76
|
+
};
|
|
77
|
+
return ShopifyApp;
|
|
78
|
+
}());
|
|
79
|
+
exports.default = ShopifyApp;
|
package/package.json
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@fstacksoftware/shopify-dev",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"main": "dist/index.js",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"bin": {
|
|
7
|
+
"shopify-dev": "dist/index.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"dev": "ts-node src/index.ts",
|
|
11
|
+
"build": "rimraf ./dist && tsc",
|
|
12
|
+
"lint": "eslint src/**/*",
|
|
13
|
+
"lint:fix": "eslint src/**/* --fix"
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist"
|
|
17
|
+
],
|
|
18
|
+
"devDependencies": {
|
|
19
|
+
"@types/node": "^20.5.7",
|
|
20
|
+
"@typescript-eslint/eslint-plugin": "^6.5.0",
|
|
21
|
+
"@typescript-eslint/parser": "^6.5.0",
|
|
22
|
+
"eslint": "^8.48.0",
|
|
23
|
+
"rimraf": "^5.0.1",
|
|
24
|
+
"ts-node": "^10.9.1",
|
|
25
|
+
"typescript": "^5.2.2"
|
|
26
|
+
},
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"@fstacksoftware/tunnel": "^1.3.6",
|
|
29
|
+
"commander": "^11.0.0"
|
|
30
|
+
}
|
|
31
|
+
}
|