Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/afraid-foxes-build.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@halfdomelabs/ui-components': patch
---

Upgrade sonner to 1.7.4
7 changes: 7 additions & 0 deletions .changeset/six-candles-accept.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@halfdomelabs/project-builder-server': patch
'@halfdomelabs/project-builder-lib': patch
'@halfdomelabs/project-builder-web': patch
---

Rewrite saving/syncing logic to clean up flows for parsing and saving project definition
5 changes: 5 additions & 0 deletions .changeset/strange-toes-attend.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@halfdomelabs/project-builder-lib': patch
---

Refactor nameRefs to use resolveName for resolving name of entities
16 changes: 12 additions & 4 deletions packages/project-builder-lib/src/compiler/app-compiler-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,22 @@ export interface AppCompiler {
featureId: string,
children: Record<string, GeneratorBundle>,
) => void;
getChildrenForFeature: (featureId: string) => Record<string, GeneratorBundle>;
getChildrenForFeature: (
featureId: string,
) => Record<string, GeneratorBundle | GeneratorBundle[]>;
addRootChildren: (children: Record<string, GeneratorBundle>) => void;
getRootChildren: () => Partial<Record<string, GeneratorBundle>>;
getRootChildren: () => Partial<
Record<string, GeneratorBundle | GeneratorBundle[]>
>;
Comment thread
kingston marked this conversation as resolved.
}

export function createAppCompiler(): AppCompiler {
const children: Partial<Record<string, Record<string, GeneratorBundle>>> = {};
let rootChildren: Partial<Record<string, GeneratorBundle>> = {};
const children: Partial<
Record<string, Record<string, GeneratorBundle | GeneratorBundle[]>>
> = {};
let rootChildren: Partial<
Record<string, GeneratorBundle | GeneratorBundle[]>
> = {};

return {
addChildrenToFeature(featureId, newChildren) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import type {
DefinitionEntity,
DefinitionReference,
FixRefDeletionResult,
ZodRefPayload,
ResolvedZodRefPayload,
} from '@src/references/index.js';
import type {
ProjectDefinition,
Expand All @@ -22,6 +22,7 @@ import {
fixRefDeletions,
serializeSchemaFromRefPayload,
} from '@src/references/index.js';
import { prettyStableStringify } from '@src/utils';

/**
* Container for a project definition that includes references and entities.
Expand All @@ -30,14 +31,14 @@ import {
* such as the ability to fetch an entity by ID.
*/
export class ProjectDefinitionContainer {
refPayload: ZodRefPayload<ProjectDefinition>;
refPayload: ResolvedZodRefPayload<ProjectDefinition>;
definition: ProjectDefinition;
references: DefinitionReference[];
entities: DefinitionEntity[];
parserContext: SchemaParserContext;

constructor(
config: ZodRefPayload<ProjectDefinition>,
config: ResolvedZodRefPayload<ProjectDefinition>,
parserContext: SchemaParserContext,
public pluginStore: PluginImplementationStore,
) {
Expand Down Expand Up @@ -98,13 +99,14 @@ export class ProjectDefinitionContainer {
}

/**
* Serializes the configuration of the project definition such that all references are
* resolved to their names for easier reading.
* Serializes the project definition resolving references to their names for easier reading.
*
* @returns The serialized configuration of the project definition
* @returns The serialized contents of the project definition
*/
toSerializedConfig(): Record<string, unknown> {
return serializeSchemaFromRefPayload(this.refPayload);
toSerializedContents(): string {
return prettyStableStringify(
serializeSchemaFromRefPayload(this.refPayload),
);
}

/**
Expand Down Expand Up @@ -146,7 +148,7 @@ export class ProjectDefinitionContainer {
config,
),
context,
projectDefinitionSchemaWithContext._def.pluginStore,
projectDefinitionSchemaWithContext.pluginStore,
);
}
}
1 change: 0 additions & 1 deletion packages/project-builder-lib/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ export * from './definition/index.js';
export * from './feature-flags/index.js';
export * from './migrations/index.js';
export * from './parser/index.js';
export type * from './parser/types.js';
export * from './plugins/index.js';
export * from './references/index.js';
export * from './schema/index.js';
Expand Down
42 changes: 35 additions & 7 deletions packages/project-builder-lib/src/migrations/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,32 @@ export const SCHEMA_MIGRATIONS: SchemaMigration[] = [
migration009RenameRefs,
];

export function isMigrateableProjectDefinition(
projectDefinition: unknown,
): projectDefinition is ProjectDefinition {
return (
typeof projectDefinition === 'object' &&
!!projectDefinition &&
'schemaVersion' in projectDefinition
);
}

export class SchemaMigrationError extends Error {
public readonly migrationName: string;
public readonly cause: unknown;

constructor(migrationName: string, cause: unknown) {
super(
`Schema migration ${migrationName} failed: ${cause instanceof Error ? cause.message : String(cause)}`,
);
this.name = 'SchemaMigrationError';
this.migrationName = migrationName;
this.cause = cause;
}
}

export function runSchemaMigrations(config: ProjectDefinition): {
newConfig: ProjectDefinition;
migratedDefinition: ProjectDefinition;
appliedMigrations: SchemaMigration[];
} {
const schemaVersion = config.schemaVersion ?? 0;
Expand All @@ -25,15 +49,19 @@ export function runSchemaMigrations(config: ProjectDefinition): {
(m) => m.version > schemaVersion,
).sort((a, b) => a.version - b.version);

let newConfig = config;
let migratedDefinition = config;
for (const migration of unappliedMigrations) {
newConfig = {
...(migration.migrate(newConfig) as ProjectDefinition),
schemaVersion: migration.version,
};
try {
migratedDefinition = {
...(migration.migrate(migratedDefinition) as ProjectDefinition),
schemaVersion: migration.version,
};
} catch (cause) {
throw new SchemaMigrationError(migration.name, cause);
}
}

return { newConfig, appliedMigrations: unappliedMigrations };
return { migratedDefinition, appliedMigrations: unappliedMigrations };
}

export function getLatestMigrationVersion(): number {
Expand Down
Loading