/**
 * @since 4.0.0
 */
import * as Uuid from "uuid";
import * as DateTime from "../../DateTime.js";
import * as Effect from "../../Effect.js";
import * as Option from "../../Option.js";
import * as Predicate from "../../Predicate.js";
import * as Schema from "../../Schema.js";
import * as Getter from "../../SchemaGetter.js";
import * as Transformation from "../../SchemaTransformation.js";
import * as VariantSchema from "./VariantSchema.js";
const {
  Class,
  Field,
  FieldExcept,
  FieldOnly,
  Struct,
  Union,
  extract,
  fieldEvolve
} = /*#__PURE__*/VariantSchema.make({
  variants: ["select", "insert", "update", "json", "jsonCreate", "jsonUpdate"],
  defaultVariant: "select"
});
export {
/**
 * A base class used for creating domain model schemas.
 *
 * It supports common variants for database and JSON apis.
 *
 * @since 4.0.0
 * @category constructors
 * @example
 * ```ts
 * import { Schema } from "effect"
 * import { Model } from "effect/unstable/schema"
 *
 * export const GroupId = Schema.Number.pipe(Schema.brand("GroupId"))
 *
 * export class Group extends Model.Class<Group>("Group")({
 *   id: Model.Generated(GroupId),
 *   name: Schema.String,
 *   createdAt: Model.DateTimeInsertFromDate,
 *   updatedAt: Model.DateTimeUpdateFromDate
 * }) {}
 *
 * // schema used for selects
 * Group
 *
 * // schema used for inserts
 * Group.insert
 *
 * // schema used for updates
 * Group.update
 *
 * // schema used for json api
 * Group.json
 * Group.jsonCreate
 * Group.jsonUpdate
 *
 * // you can also turn them into classes
 * class GroupJson extends Schema.Class<GroupJson>("GroupJson")(Group.json) {
 *   get upperName() {
 *     return this.name.toUpperCase()
 *   }
 * }
 * ```
 */
Class,
/**
 * @since 4.0.0
 * @category extraction
 */
extract,
/**
 * @since 4.0.0
 * @category fields
 */
Field,
/**
 * @since 4.0.0
 * @category fields
 */
fieldEvolve,
/**
 * @since 4.0.0
 * @category fields
 */
FieldExcept,
/**
 * @since 4.0.0
 * @category fields
 */
FieldOnly,
/**
 * @since 4.0.0
 * @category constructors
 */
Struct,
/**
 * @since 4.0.0
 * @category constructors
 */
Union };
/**
 * @since 4.0.0
 * @category fields
 */
export const fields = VariantSchema.fields;
/**
 * @since 4.0.0
 * @category overrideable
 */
export const Override = VariantSchema.Override;
/**
 * A field that represents a column that is generated by the database.
 *
 * It is available for selection and update, but not for insertion.
 *
 * @since 4.0.0
 * @category generated
 */
export const Generated = schema => Field({
  select: schema,
  update: schema,
  json: schema
});
/**
 * A field that represents a column that is generated by the application.
 *
 * It is required by the database, but not by the JSON variants.
 *
 * @since 4.0.0
 * @category generated
 */
export const GeneratedByApp = schema => Field({
  select: schema,
  insert: schema,
  update: schema,
  json: schema
});
/**
 * A field that represents a sensitive value that should not be exposed in the
 * JSON variants.
 *
 * @since 4.0.0
 * @category sensitive
 */
export const Sensitive = schema => Field({
  select: schema,
  insert: schema,
  update: schema
});
/**
 * @since 4.0.0
 * @category optional
 */
export const optionalOption = schema => Schema.optionalKey(Schema.NullOr(schema)).pipe(Schema.decodeTo(Schema.Option(Schema.toType(schema)), Transformation.transformOptional({
  decode: oe => oe.pipe(Option.filter(Predicate.isNotNull), Option.some),
  encode: Option.flatten
})));
/**
 * Convert a field to one that is optional for all variants.
 *
 * For the database variants, it will accept `null`able values.
 * For the JSON variants, it will also accept missing keys.
 *
 * @since 4.0.0
 * @category optional
 */
export const FieldOption = /*#__PURE__*/fieldEvolve({
  select: Schema.OptionFromNullOr,
  insert: Schema.OptionFromNullOr,
  update: Schema.OptionFromNullOr,
  json: optionalOption,
  jsonCreate: optionalOption,
  jsonUpdate: optionalOption
});
/**
 * A schema for sqlite booleans that are represented as `0 | 1` in database
 * variants and `boolean` in JSON variants.
 *
 * @since 4.0.0
 * @category booleans
 */
export const BooleanSqlite = /*#__PURE__*/Field({
  select: Schema.BooleanFromBit,
  insert: Schema.BooleanFromBit,
  update: Schema.BooleanFromBit,
  json: Schema.Boolean,
  jsonCreate: Schema.Boolean,
  jsonUpdate: Schema.Boolean
});
/**
 * A schema for a `DateTime.Utc` that is serialized as a date string in the
 * format `YYYY-MM-DD`.
 *
 * @since 4.0.0
 * @category date & time
 */
export const Date = /*#__PURE__*/Schema.String.pipe(/*#__PURE__*/Schema.decodeTo(Schema.DateTimeUtc, {
  decode: /*#__PURE__*/Getter.dateTimeUtcFromInput().map(DateTime.removeTime),
  encode: /*#__PURE__*/Getter.transform(DateTime.formatIsoDate)
}));
/**
 * @since 4.0.0
 * @category date & time
 */
export const DateWithNow = /*#__PURE__*/VariantSchema.Overrideable(Date, {
  defaultValue: /*#__PURE__*/Effect.map(DateTime.now, DateTime.removeTime)
});
/**
 * @since 4.0.0
 * @category date & time
 */
export const DateTimeWithNow = /*#__PURE__*/VariantSchema.Overrideable(Schema.DateTimeUtcFromString, {
  defaultValue: DateTime.now
});
/**
 * @since 4.0.0
 * @category date & time
 */
export const DateTimeFromDateWithNow = /*#__PURE__*/VariantSchema.Overrideable(Schema.DateTimeUtcFromDate, {
  defaultValue: DateTime.now
});
/**
 * @since 4.0.0
 * @category date & time
 */
export const DateTimeFromNumberWithNow = /*#__PURE__*/VariantSchema.Overrideable(Schema.DateTimeUtcFromMillis, {
  defaultValue: DateTime.now
});
/**
 * A field that represents a date-time value that is inserted as the current
 * `DateTime.Utc`. It is serialized as a string for the database.
 *
 * It is omitted from updates and is available for selection.
 *
 * @since 4.0.0
 * @category date & time
 */
export const DateTimeInsert = /*#__PURE__*/Field({
  select: Schema.DateTimeUtcFromString,
  insert: DateTimeWithNow,
  json: Schema.DateTimeUtcFromString
});
/**
 * A field that represents a date-time value that is inserted as the current
 * `DateTime.Utc`. It is serialized as a `Date` for the database.
 *
 * It is omitted from updates and is available for selection.
 *
 * @since 4.0.0
 * @category date & time
 */
export const DateTimeInsertFromDate = /*#__PURE__*/Field({
  select: Schema.DateTimeUtcFromDate,
  insert: DateTimeFromDateWithNow,
  json: Schema.DateTimeUtcFromString
});
/**
 * A field that represents a date-time value that is inserted as the current
 * `DateTime.Utc`. It is serialized as a `number`.
 *
 * It is omitted from updates and is available for selection.
 *
 * @since 4.0.0
 * @category date & time
 */
export const DateTimeInsertFromNumber = /*#__PURE__*/Field({
  select: Schema.DateTimeUtcFromMillis,
  insert: DateTimeFromNumberWithNow,
  json: Schema.DateTimeUtcFromMillis
});
/**
 * A field that represents a date-time value that is updated as the current
 * `DateTime.Utc`. It is serialized as a string for the database.
 *
 * It is set to the current `DateTime.Utc` on updates and inserts and is
 * available for selection.
 *
 * @since 4.0.0
 * @category date & time
 */
export const DateTimeUpdate = /*#__PURE__*/Field({
  select: Schema.DateTimeUtcFromString,
  insert: DateTimeWithNow,
  update: DateTimeWithNow,
  json: Schema.DateTimeUtcFromString
});
/**
 * A field that represents a date-time value that is updated as the current
 * `DateTime.Utc`. It is serialized as a `Date` for the database.
 *
 * It is set to the current `DateTime.Utc` on updates and inserts and is
 * available for selection.
 *
 * @since 4.0.0
 * @category date & time
 */
export const DateTimeUpdateFromDate = /*#__PURE__*/Field({
  select: Schema.DateTimeUtcFromDate,
  insert: DateTimeFromDateWithNow,
  update: DateTimeFromDateWithNow,
  json: Schema.DateTimeUtcFromString
});
/**
 * A field that represents a date-time value that is updated as the current
 * `DateTime.Utc`. It is serialized as a `number`.
 *
 * It is set to the current `DateTime.Utc` on updates and inserts and is
 * available for selection.
 *
 * @since 4.0.0
 * @category date & time
 */
export const DateTimeUpdateFromNumber = /*#__PURE__*/Field({
  select: Schema.DateTimeUtcFromMillis,
  insert: DateTimeFromNumberWithNow,
  update: DateTimeFromNumberWithNow,
  json: Schema.DateTimeUtcFromMillis
});
/**
 * A field that represents a JSON value stored as text in the database.
 *
 * The "json" variants will use the object schema directly.
 *
 * @since 4.0.0
 * @category json
 */
export const JsonFromString = schema => {
  const parsed = Schema.fromJsonString(Schema.toCodecJson(schema));
  return Field({
    select: parsed,
    insert: parsed,
    update: parsed,
    json: schema,
    jsonCreate: schema,
    jsonUpdate: schema
  });
};
/**
 * @since 4.0.0
 * @category Uint8Array
 */
export const Uint8Array = Schema.Uint8Array;
/**
 * @since 4.0.0
 * @category uuid
 */
export const UuidV4WithGenerate = schema => schema.pipe(Schema.withConstructorDefault(Effect.sync(() => Uuid.v4({}, new globalThis.Uint8Array(16)))));
/**
 * A field that represents a binary UUID v4 that is generated on inserts.
 *
 * @since 4.0.0
 * @category uuid
 */
export const UuidV4Insert = schema => Field({
  select: schema,
  insert: UuidV4WithGenerate(schema),
  update: schema,
  json: schema
});
//# sourceMappingURL=Model.js.map