Skip to content
Open
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
6 changes: 4 additions & 2 deletions bin/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ load(
"pngquant_linux",
"pngquant_macos",
"valdi_compiler_companion_files",
"valdi_compiler_linux",
"valdi_compiler_macos",
)

filegroup(
Expand All @@ -18,8 +20,8 @@ native_binary(
name = "valdi_compiler",
src = select(
{
"@bazel_tools//src/conditions:darwin": "@valdi_compiler_macos//:valdi_compiler",
"@bazel_tools//src/conditions:linux_x86_64": "@valdi_compiler_linux//:valdi_compiler",
"@bazel_tools//src/conditions:darwin": valdi_compiler_macos(),
"@bazel_tools//src/conditions:linux_x86_64": valdi_compiler_linux(),
},
),
out = "valdi_compiler",
Expand Down
4 changes: 2 additions & 2 deletions bin/compiler/macos/valdi_compiler
Git LFS file not shown
10 changes: 10 additions & 0 deletions bzl/prebuilt_tools.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,16 @@ def pngquant_macos():
return "@valdi_pngquant_macos//:pngquant"
return "pngquant/macos/pngquant"

def valdi_compiler_macos():
if INTERNAL_BUILD:
pass
return "compiler/macos/valdi_compiler"

def valdi_compiler_linux():
if INTERNAL_BUILD:
pass
return "compiler/linux/valdi_compiler"

def valdi_compiler_companion_files():
if INTERNAL_BUILD:
return ["@valdi_compiler_companion//:all_files"]
Expand Down
23 changes: 0 additions & 23 deletions bzl/valdi/valdi_exported_library.bzl
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
load("@aspect_rules_js//npm:defs.bzl", "npm_package")
load("@build_bazel_rules_apple//apple:apple.bzl", "apple_xcframework")
load("//bzl:expand_template.bzl", "expand_template")
load("//bzl/android:collect_android_assets.bzl", "collect_android_assets")
load("//bzl/valdi:rewrite_hdrs.bzl", "rewrite_hdrs")
load("//bzl/valdi:suffixed_deps.bzl", "get_suffixed_deps")
load("//bzl/valdi:valdi_collapse_web_paths.bzl", "collapse_native_paths", "collapse_web_paths")
Expand Down Expand Up @@ -77,28 +76,6 @@ def valdi_exported_library(

java_deps = java_deps + get_suffixed_deps(deps, "_kt")

collect_android_assets(
name = "{}_android_assets".format(name),
valdi_deps = deps,
deps = java_deps,
output_target = source_set_select(
debug = "debug",
release = "release",
),
)

valdi_android_aar(
name = "{}_android".format(name),
java_deps = java_deps,
native_deps = [
"@valdi//valdi",
] + get_suffixed_deps(deps, "_native"),
additional_assets = [":{}_android_assets".format(name)],
excluded_class_path_patterns = android_excluded_class_path_patterns,
so_name = "lib{}.so".format(name),
tags = ["valdi_android_exported_library"],
)

package_name = web_package_name
if npm_scope:
package_name = npm_scope + "/" + package_name
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,46 @@ class PrependWebJSProcessor: CompilationProcessor {
}
}

let relativePath = item.relativeProjectPath
var relativePath = item.relativeProjectPath
// Strip TypeScript extensions (.tsx, .ts) from the path since compiled files are .js
// This ensures module.path matches what the module loader expects
if relativePath.hasSuffix(".tsx") {
relativePath = String(relativePath.dropLast(4))
} else if relativePath.hasSuffix(".ts") {
relativePath = String(relativePath.dropLast(3))
}

logger.debug("PrependWebJSProcessor: ========== Processing Web JS File ==========")
logger.debug("PrependWebJSProcessor: Output file path: \(finalFileOutput)")
logger.debug("PrependWebJSProcessor: relativeProjectPath (original): '\(item.relativeProjectPath)'")
logger.debug("PrependWebJSProcessor: relativeProjectPath (adjusted): '\(relativePath)'")
logger.debug("PrependWebJSProcessor: relativeProjectPath length: \(relativePath.count)")
logger.debug("PrependWebJSProcessor: sourceURL: \(item.sourceURL.absoluteString)")
logger.debug("PrependWebJSProcessor: bundleInfo.name: \(item.bundleInfo.name)")
logger.debug("PrependWebJSProcessor: outputURL.lastPathComponent: \(finalFile.outputURL.lastPathComponent)")

var newFile = finalFile.file
var contents: String? = try? newFile.readString()
let contentsLength = contents?.count ?? 0
logger.debug("PrependWebJSProcessor: File contents length: \(contentsLength)")

// Count how many require( calls are in the file
let requireCount = contents?.components(separatedBy: "require(").count ?? 1
logger.debug("PrependWebJSProcessor: Found \(requireCount - 1) 'require(' occurrences")

// Transform require( to customRequire( - this must happen for all web JS files
// Note: TypeScript with module: "commonjs" already transforms import() to Promise.resolve().then(() => require(...)),
// so we only need to transform require( to customRequire( and the import() transformation is handled automatically.
contents = contents?.replacingOccurrences(of: "require(", with: "customRequire(")
let prefix = "var customRequire = globalThis.moduleLoader.resolveRequire(\"\(relativePath)\");\n"

// Set up module.path for code that uses NavigationPage decorator
// The module variable is provided by webpack as a function parameter, so we just set the path property
// The module variable is declared in source code as: declare const module: { path: string; exports: unknown };
// Note: We use the adjusted relativePath (without .tsx/.ts extension) so module resolution works correctly
let moduleSetup = "module.path = \"\(relativePath)\";\n"
let prefix = "\(moduleSetup)var customRequire = globalThis.moduleLoader.resolveRequire(\"\(relativePath)\");\n"
logger.debug("PrependWebJSProcessor: Generated prefix (first 100 chars): \(String(prefix.prefix(100)))")
logger.debug("PrependWebJSProcessor: ==========================================")
if let data = (prefix + (contents ?? "" )).data(using: .utf8) {
newFile = .data(data)
}
Expand Down
17 changes: 16 additions & 1 deletion compiler/compiler/scripts/update_compiler.sh
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,14 @@ if [ -z "$bin_output_path" ]; then
usage
fi

# Convert to absolute path before changing directories
# This ensures the path remains correct after we cd to $BASE_PATH
ORIGINAL_PWD=$(pwd)
if [[ "$bin_output_path" != /* ]]; then
# Relative path - make it absolute from the original working directory
bin_output_path="$ORIGINAL_PWD/$bin_output_path"
fi

# Main
cd "$BASE_PATH"
VARIANT="release"
Expand Down Expand Up @@ -142,4 +150,11 @@ source src/composer/jenkins/jenkins_helpers.sh
mkdir -p "$OUT_DIR"
rm -f "$OUT_DIR/valdi_compiler"
cp "$OUTPUT_FILE_PATH" "$OUT_DIR/valdi_compiler"
)

# Verify the copy succeeded
if [ ! -f "$OUT_DIR/valdi_compiler" ]; then
echo "Error: Failed to copy compiler binary to $OUT_DIR/valdi_compiler" >&2
exit 1
fi

echo "All done."
109 changes: 102 additions & 7 deletions npm_modules/cli/src/commands/projectsync.ts
Original file line number Diff line number Diff line change
Expand Up @@ -192,14 +192,44 @@ async function collectTsConfigDirs(
};

const tsConfigDirs = new Map<string, TsConfigDir>();
let consolidatedModulesPath: string | undefined;

// First pass: detect if consolidated setup exists by checking for modules/tsconfig.json
// Look for any target under a modules/ directory and check if modules/tsconfig.json exists
for (const projectSyncOutput of projectSyncOutputs) {
if (projectSyncOutput.target.repo) {
continue;
}

const targetPath = bazelLabelToAbsolutePath(workspaceInfo, projectSyncOutput.target);
const modulesMatch = targetPath.match(/(.+[/\\]modules)[/\\]/);
if (modulesMatch) {
const potentialModulesPath = modulesMatch[1]!;
const consolidatedTsConfigPath = path.join(potentialModulesPath, 'tsconfig.json');
if (fsSync.existsSync(consolidatedTsConfigPath)) {
consolidatedModulesPath = potentialModulesPath;
break;
}
}
}

// Second pass: group modules into consolidated dir if detected
for (const projectSyncOutput of projectSyncOutputs) {
if (projectSyncOutput.target.repo) {
// Ignore external repo deps
continue;
}

const tsConfigDirPath = bazelLabelToAbsolutePath(workspaceInfo, projectSyncOutput.target);
const targetPath = bazelLabelToAbsolutePath(workspaceInfo, projectSyncOutput.target);

// If using consolidated setup and target is under modules/, use consolidated dir
let tsConfigDirPath: string;
if (consolidatedModulesPath && targetPath.startsWith(consolidatedModulesPath + path.sep)) {
tsConfigDirPath = consolidatedModulesPath;
} else {
tsConfigDirPath = targetPath;
}

let tsConfigDir = tsConfigDirs.get(tsConfigDirPath);
if (!tsConfigDir) {
tsConfigDir = { dir: tsConfigDirPath, matchedTargets: [] };
Expand Down Expand Up @@ -239,9 +269,19 @@ function computeTsCompilerOptions(
compilerOptions = {};
}

// Preserve jsx and lib if they exist, or set defaults
if (!compilerOptions.jsx) {
compilerOptions.jsx = 'preserve';
}
if (!compilerOptions.lib) {
compilerOptions.lib = ['dom', 'ES2019'];
}

compilerOptions.paths = {};
const rootDirs: string[] = [];
let valdiCoreTarget: TargetDescription | undefined;
const seenDependencies = new Set<string>();

for (const matchedTarget of matchedTargets) {
const targetRootDirs = matchedTarget.target.paths.map(p => relativePathTo(tsConfigDir, path.dirname(p)));

Expand All @@ -254,24 +294,75 @@ function computeTsCompilerOptions(
const selfName = matchedTarget.target.label.name ?? '';
const selfInclude = `${selfName}/*`;

const selfImportPaths = matchedTarget.target.paths.map(p => `${relativePathTo(tsConfigDir, p)}/*`);
// For consolidated setup, paths should be relative to modules/ directory
// For individual module setup, paths are relative to module directory
const selfImportPaths: string[] = [];
for (const targetPath of matchedTarget.target.paths) {
const relativePath = relativePathTo(tsConfigDir, targetPath);
selfImportPaths.push(`${relativePath}/*`);

// Add projectsync-generated paths if they exist
const targetDir = path.dirname(targetPath);
const projectsyncGeneratedDir = path.join(targetDir, '.valdi_build/projectsync/generated_ts', selfName);
if (fsSync.existsSync(projectsyncGeneratedDir)) {
const relativeProjectsyncPath = relativePathTo(tsConfigDir, projectsyncGeneratedDir);
if (!selfImportPaths.includes(`${relativeProjectsyncPath}/*`)) {
selfImportPaths.push(`${relativeProjectsyncPath}/*`);
}
}
}

compilerOptions.paths[selfInclude] = selfImportPaths;

for (const dependency of matchedTarget.dependencies) {
if (!dependency.label.name || compilerOptions.paths[dependency.label.name]) {
// Already present
if (!dependency.label.name) {
continue;
}

const dependencyKey = `${dependency.label.name}/*`;

// For consolidated setup, merge paths from all modules
// For individual setup, skip if already present
if (seenDependencies.has(dependencyKey) && !compilerOptions.paths[dependencyKey]) {
continue;
}

if (dependency.label.name === 'valdi_core') {
valdiCoreTarget = dependency;
}

const importPaths = dependency.paths.map(p => `${relativePathTo(tsConfigDir, p)}/*`);
const importPaths: string[] = [];
for (const depPath of dependency.paths) {
const relativePath = relativePathTo(tsConfigDir, depPath);
importPaths.push(`${relativePath}/*`);

// Add projectsync-generated paths for external dependencies if they exist
const depDir = path.dirname(depPath);
const depName = dependency.label.name;
if (depName) {
const projectsyncGeneratedDir = path.join(depDir, '.valdi_build/projectsync/generated_ts', depName);
if (fsSync.existsSync(projectsyncGeneratedDir)) {
const relativeProjectsyncPath = relativePathTo(tsConfigDir, projectsyncGeneratedDir);
if (!importPaths.includes(`${relativeProjectsyncPath}/*`)) {
importPaths.push(`${relativeProjectsyncPath}/*`);
}
}
}
}

const key = `${dependency.label.name}/*`;
compilerOptions.paths[key] = importPaths;
if (compilerOptions.paths[dependencyKey]) {
// Merge with existing paths
const existing = compilerOptions.paths[dependencyKey];
if (Array.isArray(existing)) {
compilerOptions.paths[dependencyKey] = [...new Set([...existing, ...importPaths])];
} else {
compilerOptions.paths[dependencyKey] = importPaths;
}
} else {
compilerOptions.paths[dependencyKey] = importPaths;
}

seenDependencies.add(dependencyKey);
}
}

Expand All @@ -284,6 +375,10 @@ function computeTsCompilerOptions(

compilerOptions.types = baseTsFiles.map(p => relativePathTo(tsConfigDir, removeTsFileExtension(p)));

// Ensure rootDirs includes current directory for consolidated setup
if (!rootDirs.includes('.')) {
rootDirs.unshift('.');
}
compilerOptions.rootDirs = rootDirs;

return compilerOptions;
Expand Down
4 changes: 4 additions & 0 deletions src/valdi_modules/src/valdi/coreutils/web/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,8 @@
"composite": true,
"allowJs": true
},
"exclude": [
"debug/**",
"release/**"
]
}
6 changes: 5 additions & 1 deletion src/valdi_modules/src/valdi/drawing/web/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@
"strict": true,
"skipLibCheck": true,
"composite": true,
"allowJs": true,
"allowJs": true
},
"exclude": [
"debug/**",
"release/**"
]
}
4 changes: 4 additions & 0 deletions src/valdi_modules/src/valdi/file_system/web/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,8 @@
"composite": true,
"allowJs": true
},
"exclude": [
"debug/**",
"release/**"
]
}
4 changes: 4 additions & 0 deletions src/valdi_modules/src/valdi/persistence/web/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,8 @@
"composite": true,
"allowJs": true
},
"exclude": [
"debug/**",
"release/**"
]
}
9 changes: 9 additions & 0 deletions src/valdi_modules/src/valdi/valdi_core/src/Device.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
getWindowWidth,
getTimeZoneDstSecondsFromGMT as nativeGetTimeZoneDstSecondsFromGMT,
isDesktop,
isWeb,
observeDarkMode as nativeObserveDarkMode,
observeDisplaySizeChange as nativeObserveDisplaySizeChange,
observeDisplayInsetChange as nativeObserveDisplayInsetChange,
Expand Down Expand Up @@ -65,6 +66,7 @@ const cacheDeviceLocales = new DeviceCache<string[]>(getDeviceLocales ?? (() =>
const cacheLocaleUsesMetricSystem = new DeviceCache<boolean>(getLocaleUsesMetricSystem ?? (() => false));
const cacheTimeZoneName = new DeviceCache<string>(getTimeZoneName ?? (() => 'unknown'));
const cacheIsDesktop = new DeviceCache<boolean>(isDesktop ?? (() => false));
const cacheIsWeb = new DeviceCache<boolean>(isWeb ?? (() => false));

/**
* Dark mode last cached value
Expand Down Expand Up @@ -134,6 +136,13 @@ export namespace Device {
return cacheIsDesktop.get();
}

/**
* Check whether the Device is running on the Web platform.
*/
export function isWeb(): boolean {
return cacheIsWeb.get();
}

/**
* Get whether the system is Android or iOS
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,5 @@ export function observeDisplayInsetChange(observe: () => void): DeviceCancelable
export function observeDisplaySizeChange(observe: () => void): DeviceCancelable;
export function observeDarkMode(observe: (isDarkMode: boolean) => void): DeviceCancelable;
export function isDesktop(): boolean;
export function isWeb(): boolean;
export const setBackButtonObserver: ((observer: (() => boolean) | undefined) => void) | undefined;
Loading