@tywalk/pcf-helper
Version:
Command line helper for building and publishing PCF controls to Dataverse.
127 lines (126 loc) • 6.16 kB
JavaScript
;
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.defaultPrompt = void 0;
exports.buildProfileFromOptions = buildProfileFromOptions;
exports.runProfileInit = runProfileInit;
const readline_1 = __importDefault(require("readline"));
const color_logger_1 = __importDefault(require("@tywalk/color-logger"));
const configUtil_1 = require("./configUtil");
/** Default prompt implementation using Node's built-in readline. */
const defaultPrompt = (question, currentValue) => new Promise((resolve) => {
const rl = readline_1.default.createInterface({
input: process.stdin,
output: process.stdout,
});
const displayDefault = currentValue ? ` [${currentValue}]` : '';
rl.question(`${question}${displayDefault}: `, (answer) => {
rl.close();
const trimmed = answer.trim();
resolve(trimmed || currentValue || '');
});
});
exports.defaultPrompt = defaultPrompt;
/**
* Builds a Profile from the options, prompting for each field when interactive.
*
* Returns only the fields the user actually supplied — empty answers are not
* written to disk, so a skipped prompt produces no key in the profile.
*/
function buildProfileFromOptions(options_1) {
return __awaiter(this, arguments, void 0, function* (options, prompt = exports.defaultPrompt) {
const interactive = !options.nonInteractive;
const ask = (question, current) => __awaiter(this, void 0, void 0, function* () {
if (!interactive)
return current;
const answer = yield prompt(question, current);
return answer || undefined;
});
const environment = yield ask('Dataverse environment name', options.environment);
const publisherName = yield ask('Publisher display name', options.publisherName);
const publisherPrefix = yield ask('Publisher prefix (2-8 chars, e.g. "tyw")', options.publisherPrefix);
const profilePath = yield ask('Path to PCF solution folder (blank to skip)', options.path);
const template = yield ask('Control template (field|dataset; blank to skip)', options.template);
const framework = yield ask('Rendering framework (none|react; blank to skip)', options.framework);
// Session fields are only prompted when the user passed at least one,
// to keep the common path short.
const anySessionFlag = options.sessionUrl || options.sessionScript || options.sessionBundle;
let session;
if (anySessionFlag && interactive) {
const url = yield ask('Session: remote environment URL', options.sessionUrl);
const script = yield ask('Session: remote script to intercept', options.sessionScript);
const bundle = yield ask('Session: local bundle path', options.sessionBundle);
session = {};
if (url)
session.remoteEnvironmentUrl = url;
if (script)
session.remoteScriptToIntercept = script;
if (bundle)
session.localBundlePath = bundle;
if (Object.keys(session).length === 0)
session = undefined;
}
else if (anySessionFlag) {
// Non-interactive + some session flags passed — just use what was given.
session = {};
if (options.sessionUrl)
session.remoteEnvironmentUrl = options.sessionUrl;
if (options.sessionScript)
session.remoteScriptToIntercept = options.sessionScript;
if (options.sessionBundle)
session.localBundlePath = options.sessionBundle;
if (Object.keys(session).length === 0)
session = undefined;
}
const profile = {};
if (environment)
profile.environment = environment;
if (profilePath)
profile.path = profilePath;
if (publisherName)
profile.publisherName = publisherName;
if (publisherPrefix)
profile.publisherPrefix = publisherPrefix;
if (template)
profile.template = template;
if (framework)
profile.framework = framework;
if (session)
profile.session = session;
return profile;
});
}
/**
* Orchestrates the full `profile init` flow: collect fields (prompting when
* interactive), then write the profile to the target config file.
*/
function runProfileInit(options_1) {
return __awaiter(this, arguments, void 0, function* (options, prompt = exports.defaultPrompt) {
if (!options.name || !options.name.trim()) {
throw new Error('Profile name is required. Usage: profile init <name>');
}
const profile = yield buildProfileFromOptions(options, prompt);
const result = (0, configUtil_1.writeProfile)(options.name, profile, {
global: options.global,
setDefault: options.setDefault,
force: options.force,
});
const verb = result.replacedProfile ? 'Updated' : 'Created';
color_logger_1.default.log(`${verb} profile "${options.name}" in ${result.filePath}`);
if (options.setDefault) {
color_logger_1.default.log(`Set "${options.name}" as the default profile.`);
}
return result;
});
}