@builder.io/mitosis
Version:
Write components once, run everywhere. Compiles to Vue, React, Solid, and Liquid. Import code from Figma and Builder.io
89 lines (88 loc) • 4.23 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.updateStateCode = exports.getStateTypeForValue = exports.getStateSetterName = void 0;
const core_1 = require("@babel/core");
const function_1 = require("fp-ts/lib/function");
const capitalize_1 = require("../../../helpers/capitalize");
const replace_identifiers_1 = require("../../../helpers/replace-identifiers");
const strip_state_and_props_refs_1 = require("../../../helpers/strip-state-and-props-refs");
const transform_state_setters_1 = require("../../../helpers/transform-state-setters");
const getStateSetterName = (stateName) => `set${(0, capitalize_1.capitalize)(stateName)}`;
exports.getStateSetterName = getStateSetterName;
const getStateTypeForValue = ({ value, component, options, }) => {
var _a, _b, _c, _d;
// e.g. state.useContent?.blocks[0].id => useContent
const extractStateSliceName = (0, strip_state_and_props_refs_1.stripStateAndPropsRefs)(value).split('.')[0].split('?')[0];
const stateOverrideForValue = (_d = (_c = (_b = (_a = component.meta) === null || _a === void 0 ? void 0 : _a.useMetadata) === null || _b === void 0 ? void 0 : _b.solid) === null || _c === void 0 ? void 0 : _c.state) === null || _d === void 0 ? void 0 : _d[extractStateSliceName];
const stateType = stateOverrideForValue || options.state;
return stateType;
};
exports.getStateTypeForValue = getStateTypeForValue;
const getNewStateSetterExpression = (stateType) => ({ path, propertyName, }) => {
/**
* passes the value to the setter function
* ```ts
* // BEFORE
* state.count = newCount
* // AFTER
* setCount(newCount)
* ```
*/
const callValueSetter = (args) => core_1.types.callExpression(core_1.types.identifier((0, exports.getStateSetterName)(propertyName)), [args]);
switch (stateType) {
case 'signals':
return callValueSetter(path.node.right);
case 'store':
/**
* Wrap value in a reconcile() call for Stores updates
* ```ts
* // BEFORE
* state.count = newCount
* // AFTER
* setCount(reconcile(newCount))
* ```
*/
return callValueSetter(core_1.types.callExpression(core_1.types.identifier('reconcile'), [path.node.right]));
}
};
const updateStateSettersInCode = ({ options, component }) => (value) => {
const stateType = (0, exports.getStateTypeForValue)({ value, component, options });
switch (stateType) {
case 'mutable':
return value;
case 'store':
case 'signals':
try {
return (0, transform_state_setters_1.transformStateSetters)({
value,
transformer: getNewStateSetterExpression(stateType),
});
}
catch (error) {
console.error(`[Solid.js]: could not update state setters in ${stateType} code`, value);
throw error;
}
}
};
const updateStateGettersInCode = (options, component) => (0, replace_identifiers_1.replaceStateIdentifier)((name) => {
const stateType = (0, exports.getStateTypeForValue)({ value: name, component, options });
const state = component.state[name];
switch (stateType) {
case 'signals':
if (
// signal accessors are lazy, so we need to add a function call to property calls
(state === null || state === void 0 ? void 0 : state.type) === 'property' ||
// getters become plain functions, requiring a function call to access their value
(state === null || state === void 0 ? void 0 : state.type) === 'getter') {
return `${name}()`;
}
else {
return name;
}
case 'store':
case 'mutable':
return name;
}
});
const updateStateCode = ({ options, component, updateSetters = true, }) => (0, function_1.flow)(updateSetters ? updateStateSettersInCode({ options, component }) : function_1.identity, updateStateGettersInCode(options, component), (x) => x.trim());
exports.updateStateCode = updateStateCode;
;