react-native-codegen
Version:
⚛️ Code generation tools for React Native
250 lines (247 loc) • 7.19 kB
JavaScript
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*
* @format
*/
;
function ownKeys(e, r) {
var t = Object.keys(e);
if (Object.getOwnPropertySymbols) {
var o = Object.getOwnPropertySymbols(e);
r &&
(o = o.filter(function (r) {
return Object.getOwnPropertyDescriptor(e, r).enumerable;
})),
t.push.apply(t, o);
}
return t;
}
function _objectSpread(e) {
for (var r = 1; r < arguments.length; r++) {
var t = null != arguments[r] ? arguments[r] : {};
r % 2
? ownKeys(Object(t), !0).forEach(function (r) {
_defineProperty(e, r, t[r]);
})
: Object.getOwnPropertyDescriptors
? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t))
: ownKeys(Object(t)).forEach(function (r) {
Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r));
});
}
return e;
}
function _slicedToArray(arr, i) {
return (
_arrayWithHoles(arr) ||
_iterableToArrayLimit(arr, i) ||
_unsupportedIterableToArray(arr, i) ||
_nonIterableRest()
);
}
function _nonIterableRest() {
throw new TypeError(
'Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.',
);
}
function _unsupportedIterableToArray(o, minLen) {
if (!o) return;
if (typeof o === 'string') return _arrayLikeToArray(o, minLen);
var n = Object.prototype.toString.call(o).slice(8, -1);
if (n === 'Object' && o.constructor) n = o.constructor.name;
if (n === 'Map' || n === 'Set') return Array.from(o);
if (n === 'Arguments' || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))
return _arrayLikeToArray(o, minLen);
}
function _arrayLikeToArray(arr, len) {
if (len == null || len > arr.length) len = arr.length;
for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
return arr2;
}
function _iterableToArrayLimit(r, l) {
var t =
null == r
? null
: ('undefined' != typeof Symbol && r[Symbol.iterator]) || r['@@iterator'];
if (null != t) {
var e,
n,
i,
u,
a = [],
f = !0,
o = !1;
try {
if (((i = (t = t.call(r)).next), 0 === l)) {
if (Object(t) !== t) return;
f = !1;
} else
for (
;
!(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l);
f = !0
);
} catch (r) {
(o = !0), (n = r);
} finally {
try {
if (!f && null != t.return && ((u = t.return()), Object(u) !== u))
return;
} finally {
if (o) throw n;
}
}
return a;
}
}
function _arrayWithHoles(arr) {
if (Array.isArray(arr)) return arr;
}
function _defineProperty(obj, key, value) {
key = _toPropertyKey(key);
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true,
});
} else {
obj[key] = value;
}
return obj;
}
function _toPropertyKey(arg) {
var key = _toPrimitive(arg, 'string');
return typeof key === 'symbol' ? key : String(key);
}
function _toPrimitive(input, hint) {
if (typeof input !== 'object' || input === null) return input;
var prim = input[Symbol.toPrimitive];
if (prim !== undefined) {
var res = prim.call(input, hint || 'default');
if (typeof res !== 'object') return res;
throw new TypeError('@@toPrimitive must return a primitive value.');
}
return (hint === 'string' ? String : Number)(input);
}
const _require = require('../../Utils'),
capitalize = _require.capitalize;
const _require2 = require('../../../parsers/flow/modules/utils'),
unwrapNullable = _require2.unwrapNullable,
wrapNullable = _require2.wrapNullable;
class StructCollector {
constructor() {
_defineProperty(this, '_structs', new Map());
}
process(structName, structContext, resolveAlias, nullableTypeAnnotation) {
const _unwrapNullable = unwrapNullable(nullableTypeAnnotation),
_unwrapNullable2 = _slicedToArray(_unwrapNullable, 2),
typeAnnotation = _unwrapNullable2[0],
nullable = _unwrapNullable2[1];
switch (typeAnnotation.type) {
case 'ObjectTypeAnnotation': {
this._insertStruct(
structName,
structContext,
resolveAlias,
typeAnnotation,
);
return wrapNullable(nullable, {
type: 'TypeAliasTypeAnnotation',
name: structName,
});
}
case 'ArrayTypeAnnotation': {
if (typeAnnotation.elementType == null) {
return wrapNullable(nullable, {
type: 'ArrayTypeAnnotation',
});
}
return wrapNullable(nullable, {
type: 'ArrayTypeAnnotation',
elementType: this.process(
structName + 'Element',
structContext,
resolveAlias,
typeAnnotation.elementType,
),
});
}
case 'TypeAliasTypeAnnotation': {
this._insertAlias(typeAnnotation.name, structContext, resolveAlias);
return wrapNullable(nullable, typeAnnotation);
}
case 'MixedTypeAnnotation':
throw new Error('Mixed types are unsupported in structs');
default: {
return wrapNullable(nullable, typeAnnotation);
}
}
}
_insertAlias(aliasName, structContext, resolveAlias) {
const usedStruct = this._structs.get(aliasName);
if (usedStruct == null) {
this._insertStruct(
aliasName,
structContext,
resolveAlias,
resolveAlias(aliasName),
);
} else if (usedStruct.context !== structContext) {
throw new Error(
`Tried to use alias '${aliasName}' in a getConstants() return type and inside a regular struct.`,
);
}
}
_insertStruct(structName, structContext, resolveAlias, objectTypeAnnotation) {
// $FlowFixMe[missing-type-arg]
const properties = objectTypeAnnotation.properties.map(property => {
const propertyStructName = structName + capitalize(property.name);
return _objectSpread(
_objectSpread({}, property),
{},
{
typeAnnotation: this.process(
propertyStructName,
structContext,
resolveAlias,
property.typeAnnotation,
),
},
);
});
switch (structContext) {
case 'REGULAR':
this._structs.set(structName, {
name: structName,
context: 'REGULAR',
properties: properties,
});
break;
case 'CONSTANTS':
this._structs.set(structName, {
name: structName,
context: 'CONSTANTS',
properties: properties,
});
break;
default:
structContext;
throw new Error(`Detected an invalid struct context: ${structContext}`);
}
}
getAllStructs() {
return [...this._structs.values()];
}
getStruct(name) {
return this._structs.get(name);
}
}
module.exports = {
StructCollector,
};